想知道有没有人在Android中尝试使用新的Java 7语言特性? 我知道Android会读取Java生成的字节码并将其转换为dex文件。所以我的问题是,它能理解Java 7的字节码吗?
想知道有没有人在Android中尝试使用新的Java 7语言特性? 我知道Android会读取Java生成的字节码并将其转换为dex文件。所以我的问题是,它能理解Java 7的字节码吗?
build.gradle
方面的答案。Java 7的一小部分可以在Android中使用(注意:我只在4.1上进行了测试)。
首先,您不能使用Eclipse的ADT,因为它是硬编码的,只有Java编译器1.5和1.6才兼容。您可以重新编译ADT,但我发现除了重新编译整个Android外,没有简单的方法来做到这一点。
但您不需要使用Eclipse。例如,Android Studio 0.3.2, IntelliJ IDEA CE和其他基于javac的IDE支持编译到Android,并且您可以通过以下方式设置兼容性,甚至高达Java 8:
<>
)catch (Exc1 | Exc2 e)
)1_234_567
)0b1110111
)而这些特性目前还不能使用:
... "yet" :) 事实证明,尽管Android的库面向1.6版本,但是Android源代码确实包含了像AutoCloseable这样的接口,而传统的接口如Closeable也继承自AutoCloseable(虽然缺少了SafeVarargs)。我们可以通过反射来确认它们的存在。它们之所以被隐藏,仅仅是因为Javadoc使用了@hide
标签,这导致“android.jar”没有将它们包含在内。
已经有一个现有的问题 如何构建具有隐藏和内部API可用性的Android SDK? 关于如何获取这些方法。您只需要使用我们定制的“android.jar”替换当前平台的现有“android.jar”引用,那么许多Java 7 API将变得可用(该过程类似于Eclipse中的操作。检查项目结构→SDKs)。
除了AutoCloseable之外,以下Java 7库功能也被揭示:
基本上就是这样了。特别地,NIO 2.0并不存在,而Arrays.asList仍然不是@SafeVarargs。
nio2
和其他好玩意肯定是一个好消息。 - S.D.AutoCloseable
接口直到 ICS(或者可能是 HoneyComb)版本才存在。因此,即使您使用了打了补丁的 android.jar,在 2.x 系统上仍会收到 NoClassDefFoundError
错误。 - Idolon编辑:此篇文章撰写时,最新版本为Android 9和Eclipse Indigo。事情已经发生了改变。
是的,我尝试过。但这不是一个很好的测试,因为兼容性仅限于级别6,并且没有办法(至少没有简单的方法)真正使用Java 7:
接着,我安装了最新版本的Android SDK(编辑:Honeycomb,API13,当此帖子撰写时)。它找到了我的JDK 7并正确安装了。ADT也是如此。
但是,在尝试编译和运行Hello Word Android应用程序时,我有一个惊喜。兼容性设置为Java 6,没有办法强制它使用Java 7:
我已经让Hello World和其他更复杂的应用程序工作,它们使用了SQLite
、Listview
、Sensor
和Camera
,但这只证明了Java 7的兼容性处理似乎已经很好地与Android配合工作。
那么,有人尝试过使用好老的Ant来绕过上述的Eclipse限制吗?
无论如何,SDK都是设计用于Java 5或6的,正如在这里所解释的那样。
我们可以通过Java 7来实现一些工作,但这只是“偶然”能够工作。 DEX的构建可能正常工作,也可能不正常工作,而一旦DEX构建完成,它也可能正常工作或不正常工作。 这是因为使用未经资格认证的JDK会带来不可预测的结果。
即使有人成功地在纯Java 7下构建了Android应用程序,这也不能说明JDK是合格的。将同样的过程应用于另一个应用程序可能会失败,或者生成的应用程序可能存在与该JDK的使用相关的错误。不推荐此做法。
对于从事Web应用程序开发的人来说,这与在仅为Java 4合格的应用服务器上(例如Weblogic 8)部署在Java 5或6下构建的Web应用程序是完全相同的。这可能会起作用,但这不是可以推荐用于其他目的的东西。
dalvikvm.com的引用:
dx是包含在Android SDK中的一个工具,它将普通Java编译器编译的Java类的Java Class文件转换为另一种类文件格式(即.dex格式)。
这意味着,.java源文件并不重要,只有.class字节码文件才是关键。
据我所知,在Java 7中,只有invokedynamic被添加到JVM字节码中,其余部分兼容Java 6。Java语言本身并不使用invokedynamic。其他新功能,比如使用String的switch语句或多个catch仅仅是语法糖,并不需要字节码更改。例如,多个catch只是为每个可能的异常复制catch块。
唯一的问题应该是Java 7中引入的新类在Android中缺失,比如AutoCloseable,因此我不确定是否可以使用try-with-resources功能(有人尝试过吗?)。
对此有什么评论吗?我是否遗漏了什么?
Android需要编译器兼容级别5.0或6.0。找到'1.7'。请使用Android工具>修复项目属性。
为了进一步解释@KennyTM的答案,如果你的目标是4.0.3及以上版本(minSdkVersion=15),你可以通过向目标SDK android.jar中添加一些类来使用隐藏的API。
一旦这样做,您就可以在任何Closeable上使用try-with-resources,并在自己的类中实现AutoCloseable。
我制作了一个zip文件,其中包含所有需要修改android.jar中的类的源代码和二进制文件,以使这些API可用。您只需要解压缩它并将二进制文件添加到您的
android-sdk/platforms/android-NN/android.jar中即可。
您可以从这里下载:http://db.tt/kLxAYWbr
值得注意的是,在过去的几个月中,Elliott Hughes已经向Android代码库提交了一些内容:完成了AutoCloseable的结尾, 添加了SafeVarargs, 取消隐藏了各种API, 修复了Throwable的受保护构造函数和在dx中添加了对版本51类文件的支持。因此,终于有了一些进展。
编辑(2014年4月):
随着SDK 19的发布,无需使用补丁程序将android.jar与其他API一起使用。
在针对4.0.3及以上版本(minSdkVersion=15)的应用程序中,在Android Studio中使用try-with-resources的最佳方法是将以下compileOptions
添加到您的build.gradle
中:
android {
compileSdkVersion 19
buildToolsVersion '19.0.3'
defaultConfig {
minSdkVersion 15
targetSdkVersion 19
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
Android Studio会抱怨此API级别无法使用try-with-resources,但我的经验是可以的。该项目将在4.0.3及以上版本的设备上构建和运行,没有任何问题。我已经在安装了500k+设备的应用程序中使用过,没有遇到任何问题。
如果您想忽略此警告,请将以下内容添加到您的 lint.xml
文件中:
<issue id="NewApi">
<ignore regexp="Try-with-resources requires API level 19"/>
</issue>
custom_rules.xml
文件中即可:
custom_rules.xml:
<project name="custom_android_rules">
<property name="java.target" value="1.7" />
<property name="java.source" value="1.7" />
</project>
看起来用纯粹的ant让它工作有点笨拙。
但对我来说,它起作用了:http://www.informit.com/articles/article.aspx?p=1966024
<property name="java.source" value="1.5" />
行(而不是您项目中的那个!)。对我来说,它在/opt/android-sdk-update-manager/tools/ant/build.xml中。 - Mateusz Kowalczykcustom_rules.xml
覆盖这些属性,参见我在这里的回答:https://dev59.com/Mmw05IYBdhLWcg3wmCwo#24608415 - Flow有些人可能会对我发现的这个git项目感兴趣,它似乎可以在Android上运行Java 7。 https://github.com/yareally/Java7-on-Android
然而,如果我将其添加到我目前正在工作的项目中,风险太大了。因此,我会等待Google正式支持Java 7。