1

sbt とjberkel/android-pluginを使用して、Scala と Akka で簡単な Android プロジェクトをセットアップしようとしています。android-plugin の入門チュートリアルに基づいて、簡単なアプリケーションを作成することに成功しました。また、Akka をプロジェクトに組み込むことができる ProGuard 構成を組み立てることもできました。

Akka 構成ファイルを追加したいのですが、それができません。私はそれをsrc/main/resourcesフォルダーに作成し、それがうまくいくことを期待していました。残念ながら、APK の組み立て中に、sbt は次のエラーで失敗します。

[trace] Stack trace suppressed: run last Akkdroid/android:package-debug for the full output.
[error] (Akkdroid/android:package-debug) 
[error] Using keystore: /home/ghik/.android/debug.keystore
[error] Packaging akkdroid-0.1.apk
[error] /data/Studia/S10/Mobilne/akkdroid/target/resources.apk:
[error] => res/layout/main.xml
[error] => AndroidManifest.xml
[error] => resources.arsc
[error] /data/Studia/S10/Mobilne/akkdroid/target/classes.dex => classes.dex
[error] /data/Studia/S10/Mobilne/akkdroid/target/classes.min.jar:
[error] => akkdroid.conf
[error] => library.properties
[error] => reference.conf
[error] => org/jboss/netty/container/spring/beans.xml
[error] /data/Studia/S10/Mobilne/akkdroid/src/main/resources/akkdroid.conf => akkdroid.conf
[error] 
[error] Error packaging /data/Studia/S10/Mobilne/akkdroid/target/akkdroid-0.1.apk: Duplicate files at the same path inside the APK
[error] Total time: 20 s, completed 2013-04-24 20:32:47

これらのメッセージから、akkdroid.confファイルが最初に (ProGuard によって?) にコピーされclasses.min.jar、後でsbt両方のリソースを含むパッケージをビルドしようとするclasses.min.jarsrc/main/resources、ファイルが 2 回表示されると推測しています。

残念ながら、これが発生する理由と修正方法はわかりません。

それが役立つ場合、これが私のsbtビルドファイルです(主にjberkelのテンプレートから生成されます):

import sbt._

import Keys._
import AndroidKeys._

object General {
  val settings = Defaults.defaultSettings ++ Seq(
    name := "Akkdroid",
    version := "0.1",
    versionCode := 0,
    scalaVersion := "2.10.1",
    platformName in Android := "android-10",
    javacOptions ++= Seq("-source", "1.6", "-target", "1.6")
  )

  val proguardSettings = Seq(
    useProguard in Android := true,
    proguardOption in Android :=
      """-keepclassmembers class * {
        |  ** MODULE$;
        | }
        |-keep public class akka.actor.LocalActorRefProvider {
        |public <init>(...);
        |}
        |-keep public class akka.remote.RemoteActorRefProvider {
        |public <init>(...);
        |}
        |-keep class akka.actor.SerializedActorRef {
        |*;
        |}
        |-keep class akka.remote.netty.NettyRemoteTransport {
        |*;
        |}
        |-keep class akka.serialization.JavaSerializer {
        |*;
        |}
        |-keep class akka.serialization.ProtobufSerializer {
        |*;
        |}
        |-keep class com.google.protobuf.GeneratedMessage {
        |*;
        |}
        |-keep class akka.event.Logging*
        |-keep class akka.event.Logging$LogExt{
        |*;
        |}
        |-keep class scala.Option
        |-keep class scala.Function1
        |-keep class scala.PartialFunction
        |-keep class scala.collection.SeqLike {
        |public protected *;
        |}
        |-keep class akka.**
        |-keepclassmembers class akka.**
        |-keep class org.omg.**
        |-keep class scala.Tuple2
        |-dontskipnonpubliclibraryclassmembers
        |-dontskipnonpubliclibraryclasses
      """.stripMargin
  )

  lazy val fullAndroidSettings =
    General.settings ++
      AndroidProject.androidSettings ++
      TypedResources.settings ++
      proguardSettings ++
      AndroidManifestGenerator.settings ++
      AndroidMarketPublish.settings ++ Seq(
      keyalias in Android := "change-me",
      libraryDependencies += "org.scalatest" %% "scalatest" % "1.9.1" % "test"
    )
}

object AndroidBuild extends Build {
  javacOptions ++= Seq("-target", "1.6")

  lazy val main = Project(
    "Akkdroid",
    file("."),
    settings = General.fullAndroidSettings ++ Seq(
      libraryDependencies += "com.typesafe.akka" % "akka-actor_2.10" % "2.1.2",
      libraryDependencies += "com.typesafe.akka" % "akka-remote_2.10" % "2.1.2"
    )
  )

  lazy val tests = Project(
    "tests",
    file("tests"),
    settings = General.settings ++
      AndroidTest.androidSettings ++
      General.proguardSettings ++ Seq(
      name := "AkkdroidTests"
    )
  ) dependsOn main
}

助けていただければ幸いです。Android や SBT の経験はほとんどありません。

4

2 に答える 2

1

私は同じ問題を抱えていました。これが最善の対処方法かどうかはわかりませんが、構成ファイルを Android プロジェクトのrawディレクトリに置きました。次に、それをオブジェクトに解析し、コンストラクターConfigに渡します。ActorSystem

object AkkaSystem {
  private var systemOption: Option[ActorSystem] = None

  def system(implicit context: Context): ActorSystem = synchronized {
    systemOption match {
      case None =>
        val reader = new InputStreamReader(
          context.getResources.openRawResource(R.raw.configuration)
        )
        systemOption = Option (
          ActorSystem("MySystem", ConfigFactory.parseReader(reader))
        )
        reader.close()
        systemOption.get
      case Some(existingSystem) => existingSystem
    }
  }
}

次に、ActivityクラスでそのAkkaSystemオブジェクトを使用して、構成済みを取得できますActorSystem

class MainActivity extends Activity {
  implicit val context = this

  private def mainActor = AkkaSystem.system.actorOf(Props[MainActor], "main")
}

そのようなコードをすべて回避できればContext、Android リソースを取得するために を渡す必要がなくなるという点に同意します。

于 2013-05-14T19:48:58.353 に答える