Android Can';在活动中找不到方法
我从Scala+Android开始(并使用sbt Android插件)。我正在尝试将按钮操作连接到按钮,而不使用活动实现View.OnClickListener 由于找不到该方法,因此按钮单击在运行时失败。我正在处理的文档说,我只需要声明一个公共void方法来查看操作,并在布局中使用该方法名称 我做错了什么 MainActivity.scalaAndroid Can';在活动中找不到方法,android,scala,sbt,Android,Scala,Sbt,我从Scala+Android开始(并使用sbt Android插件)。我正在尝试将按钮操作连接到按钮,而不使用活动实现View.OnClickListener 由于找不到该方法,因此按钮单击在运行时失败。我正在处理的文档说,我只需要声明一个公共void方法来查看操作,并在布局中使用该方法名称 我做错了什么 MainActivity.scala package net.badgerhunt.hwa import android.app.Activity import android.os.Bu
package net.badgerhunt.hwa
import android.app.Activity
import android.os.Bundle
import android.widget.Button
import android.view.View
import java.util.Date
class MainActivity extends Activity {
override def onCreate(savedInstanceState: Bundle) = {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
}
def calculate(button: View): Unit = println("calculating with %s ...".format(button))
}
res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/button"
android:text=""
android:onClick="calculate"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
更新
考虑到这可能是sbt android插件的一个错误,我加倍确保编译后该方法存在。使用javap
Compiled from "MainActivity.scala"
public class net.badgerhunt.hwa.MainActivity extends android.app.Activity implements scala.ScalaObject{
public net.badgerhunt.hwa.MainActivity();
public void calculate(android.view.View);
public void onCreate(android.os.Bundle);
public int $tag() throws java.rmi.RemoteException;
}
sbt android插件包括一个ProGuard任务,它去除了所有未使用的代码。非常酷的东西,有助于真正精简生成的.apk文件,但不幸的是,回调方法通常不会在代码中引用,因此,通过defalt,ProGuard将抛出它们。 要亲自查看,请尝试在MainActivity类上使用javap,但将类路径设置为target/your\u scala\u version/classes.min.jar。 您需要告诉proguard要明确保留的内容。sbt android插件的默认设置中已经有一组-keep选项,但这是特定于您的项目的,因此您必须在project/build/YourProjectName.scala中编辑项目定义。查看sbt android插件和lok的代码,了解proguardTask定义。您必须覆盖该选项,并添加其他保留选项。这就是我所做的:
import sbt._
import java.io._
import proguard.{Configuration=>ProGuardConfiguration, ProGuard, ConfigurationParser}
import sbt._
import Process._
trait Defaults {
def androidPlatformName = "android-1.6"
}
class TestAndro2(info: ProjectInfo) extends ParentProject(info) {
override def shouldCheckOutputDirectories = false
override def updateAction = task { None }
lazy val main = project(".", "testAndro2", new MainProject(_))
class MainProject(info: ProjectInfo) extends AndroidProject(info) with Defaults {
val scalatest = "org.scalatest" % "scalatest" % "1.0" % "test"
override def proguardTask = task {
val args = "-injars" :: mainCompilePath.absolutePath+File.pathSeparator+
scalaLibraryJar.getAbsolutePath+"(!META-INF/MANIFEST.MF,!library.properties)"+
(if (!proguardInJars.getPaths.isEmpty) File.pathSeparator+proguardInJars.getPaths.map(_+"(!META-INF/MANIFEST.MF)").mkString(File.pathSeparator) else "") ::
"-outjars" :: classesMinJarPath.absolutePath ::
"-libraryjars" :: libraryJarPath.getPaths.mkString(File.pathSeparator) ::
"-dontwarn" :: "-dontoptimize" :: "-dontobfuscate" ::
"-dontwarn" :: "-dontoptimize" :: "-dontobfuscate" :: "-printseeds" ::
"""-keep public class com.test.android.MainActivity {
public void calculate(android.view.View);
}""" ::
"-keep public class * extends android.app.Activity" ::
"-keep public class * extends android.app.Service" ::
"-keep public class * extends android.appwidget.AppWidgetProvider" ::
"-keep public class * implements junit.framework.Test { public void test*(); }" :: proguardOption :: Nil
val config = new ProGuardConfiguration
new ConfigurationParser(args.toArray[String], info.projectPath.asFile).parse(config)
new ProGuard(config).execute
None
}
}
}
基本上
,我添加了-printseeds和一个-keep选项来保留MainActivity的calculate()方法-printseeds有利于调试,因为它告诉proguard打印保留的类和方法的名称。
ProGuard有大量的配置选项,您在构建项目时需要关注它们,因为有很多模糊的情况,ProGuard在默认情况下不会做正确的事情
import sbt._
import java.io._
import proguard.{Configuration=>ProGuardConfiguration, ProGuard, ConfigurationParser}
import sbt._
import Process._
trait Defaults {
def androidPlatformName = "android-1.6"
}
class TestAndro2(info: ProjectInfo) extends ParentProject(info) {
override def shouldCheckOutputDirectories = false
override def updateAction = task { None }
lazy val main = project(".", "testAndro2", new MainProject(_))
class MainProject(info: ProjectInfo) extends AndroidProject(info) with Defaults {
val scalatest = "org.scalatest" % "scalatest" % "1.0" % "test"
override def proguardTask = task {
val args = "-injars" :: mainCompilePath.absolutePath+File.pathSeparator+
scalaLibraryJar.getAbsolutePath+"(!META-INF/MANIFEST.MF,!library.properties)"+
(if (!proguardInJars.getPaths.isEmpty) File.pathSeparator+proguardInJars.getPaths.map(_+"(!META-INF/MANIFEST.MF)").mkString(File.pathSeparator) else "") ::
"-outjars" :: classesMinJarPath.absolutePath ::
"-libraryjars" :: libraryJarPath.getPaths.mkString(File.pathSeparator) ::
"-dontwarn" :: "-dontoptimize" :: "-dontobfuscate" ::
"-dontwarn" :: "-dontoptimize" :: "-dontobfuscate" :: "-printseeds" ::
"""-keep public class com.test.android.MainActivity {
public void calculate(android.view.View);
}""" ::
"-keep public class * extends android.app.Activity" ::
"-keep public class * extends android.app.Service" ::
"-keep public class * extends android.appwidget.AppWidgetProvider" ::
"-keep public class * implements junit.framework.Test { public void test*(); }" :: proguardOption :: Nil
val config = new ProGuardConfiguration
new ConfigurationParser(args.toArray[String], info.projectPath.asFile).parse(config)
new ProGuard(config).execute
None
}
}
}