scala+maven开发android程序

[align=center][size=x-large]scala+maven开发android程序[/size]
[size=large]Shiva Wu[/size]
[/align]

[b]转载请注明出处[/b]

[size=medium][b]0、前言[/b][/size]

刚刚入了一个android手机,想玩一玩开发。

本想用eclipse了事,如果只用java的话,eclipse的adt确实很不错,还有可视化的界面设计。无奈scala-ide太不给力,卡的要命,而且根本不能正常识别scala写出来的Activity,无奈放弃。

[quote]参考[url]http://blog.caokee.com/index.php/2010/11/11/scala-android-eclipse/[/url]
大部分都是这个思路,不过我没搞明白scala-android.jar是神马,感觉应该已经停止更新了,有没有2.8的新特性不好说。
[/quote]

IDEA也尝试了一下,IDEA的scala插件一向是最稳定的,不过IDEA本身实在是慢,而且启动模拟器程序部署不上去,打开模拟器之后IDEA就一直在Waiting for device中,不知道什么情况,估计linux下没这个问题。

以上问题如果谁知道怎么办麻烦告知。

还有一篇用ant做scala on android开发的文章,[url]http://chneukirchen.org/blog/archive/2009/04/programming-for-android-with-scala.html[/url],很专业。

言归正传。

emacs的scala-mode+ensime还是很不错的,可以和sbt、maven结合。于是决定尝试maven。

顺便说,maven-scala-plugin的continuous build在windows下有问题,但是ensime本身提供了这个功能,所以也没有关系。

[quote][url]http://riddell.us/AndroidWithEmacsOnUbuntu.html[/url]
此人写了一个简单的android-mode,可以作为参考,不过如果使用maven就不用这么麻烦了。

[url]https://github.com/jberkel/android-plugin[/url]
这里还有一个sbt-android-plugin,没有试用,对sbt不熟悉。[/quote]

[b]使用的系统环境:[/b]
[table]
|System| Windows 7|
|Maven|3.0|
|Scala|2.8.1|
|[url=http://proguard.sf.net]Proguard[/url]| 4.4|
|[url=http://code.google.com/p/maven-android-plugin]maven-android-plugin[/url]| 2.8.3|
|[url=http://pyx4me.com/pyx4me-maven-plugins/proguard-maven-plugin/]proguard-maven-plugin[/url]|2.0.4|
[/table]

[size=medium][b]1、生成archetype[/b][/size]

archetype参考了java的,具体看这里:
[url]https://github.com/akquinet/android-archetypes[/url]

这里使用简单的quickstart,执行
[code]
mvn archetype:generate -DarchetypeGroupId=de.akquinet.android.archetypes -DarchetypeArtifactId=android-quickstart -DarchetypeVersion=1.0.4 -DgroupId=com.ga -DartifactId=hello -Dversion=1.0-SNAPSHOT
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building Maven Stub Project (No POM) 1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] >>> maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom >>>
[INFO]
[INFO] <<< maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom <<<
[INFO]
[INFO] --- maven-archetype-plugin:2.0:generate (default-cli) @ standalone-pom ---
[INFO] Generating project in Interactive mode
[INFO] Archetype repository missing. Using the one from [de.akquinet.android.archetypes:android-quickstart:1.0.4] found in ca
talog remote
[INFO] Using property: groupId = com.ga
[INFO] Using property: artifactId = hello
[INFO] Using property: version = 1.0-SNAPSHOT
[INFO] Using property: package = com.ga
[INFO] Using property: platform = 7
Confirm properties configuration:
groupId: com.ga
artifactId: hello
version: 1.0-SNAPSHOT
package: com.ga
platform: 7
Y: :
[WARNING] Don't override file D:\Temp\hello\pom.xml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.052s
[INFO] Finished at: Mon Jan 17 16:50:10 CST 2011
[INFO] Final Memory: 5M/10M
[INFO] ------------------------------------------------------------------------
[/code]

还说不要改动pom.xml,这里只好无视了。

[size=medium][b]2、加入scala nature[/b][/size]

[quote]参考了davidB的scala-archetype-simple,[url]https://github.com/davidB/scala-archetype-simple[/url]
[/quote]

1、首先在pom.xml加入scala-library依赖,将原来的dependencies tag改成

<properties>
<encoding>UTF-8</encoding>
<scala.version>2.8.1</scala.version>
</properties>

<repositories>
<repository>
<id>scala-tools.org</id>
<name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.google.android</groupId>
<artifactId>android</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
</dependencies>


2、加上scala-plugin的依赖,在build标签中:

<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/scala</testSourceDirectory>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.0</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
<configuration>
<args>
<arg>-make:transitive</arg>
<arg>-dependencyfile</arg>
<arg>${project.build.directory}/.scala_dependencies</arg>
</args>
</configuration>
</execution>
</executions>
</plugin>
</plugins>


3、由于我用2.2的系统,所以把platform标签改成8。

4、下面删掉原来的HelloAndroidActivity.java,创建HelloAndroidActivity.scala。
[code]
package com.ga

import android.app.Activity
import android.os.Bundle
import android.util.Log

class HelloAndroidActivity extends Activity {
override def onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
}
}
[/code]

这个时候使用mvn compile编译应该是通过的,前提是Android SDK已经装好,可能还要在环境变量里面设置一下ANDROID_HOME。

[size=medium][b]3、打包发布[/b][/size]

这个时候使用mvn package,经过漫长的等待之后,应该会出现错误。

究其原因,dx.bat不能正确打包scala-library,主要集中在scala.actors和scala.concurrency。这里有一个issue提交,[url]http://code.google.com/p/android/issues/detail?id=7147[/url],2.7.7版本是正常的,可能2.8.1改动了代码就又有问题了。

Anyway,即使能够正确运行,打出来的包的大小也是很恐怖的。所以要减肥。

这里使用proguard 4.4,虽然最新版是4.5.1,但是maven repo上没有更新,不知道为什么,如果想用最新版可以将相应的版本install的本地仓库上。

[quote]参考maven-android-plugin的一篇wiki,[url]http://code.google.com/p/maven-android-plugin/wiki/ProGuard[/url],以及这个页面下面的Scala Sample,但是那个是错误的,以下方法解决了其问题。
[/quote]

首先在pom.xml里面加入proguard-maven-plugin的依赖,这个插件也很久没有更新,有些功能上的缺陷,留待后面谈。

<plugin>
<groupId>com.pyx4me</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.0.4</version>
<executions>
<execution>
<phase>process-classes</phase>
<goals>
<goal>proguard</goal>
</goals>
</execution>
</executions>
<configuration>
<maxMemory>512m</maxMemory>
<injar>android-classes</injar>
<inFilter>
!scala/Enumeration**,!scala/collection**
</inFilter>
<libs>
<lib>${java.home}/lib/rt.jar</lib>
</libs>
<exclusions>
<exclusion>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
</exclusion>
</exclusions>
<!--<proguardInclude>${basedir}/proguard.conf</proguardInclude>-->
</configuration>
<dependencies>
<dependency>
<groupId>net.sf.proguard</groupId>
<artifactId>proguard</artifactId>
<version>4.4</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</plugin>


比较一下上面的代码和wiki页面上的不同。
[list=1]
[*]使用版本4.4
[*]将-Xmx参数设到512m,实际不需要,下面解释。
[*]加入了scala-library的exclusion。这个原因是,android-plugin会把整个scala-library解压到classes里面,但这个jar包还在依赖中,所以也会以libraryjars的形式输入给proguard,会导致大片的duplicated classes definition,而且读入两遍之后会出现OutOfMemoryError,这也是2的目的。这里把它从libraryjars中排除就彻底解决了这个问题。
[*]去掉了keep class等,把它放到了一个新的文件中,这样更容易配置,因为插件给出的设置选项还是有限。其次,wiki上的配置是错误的,会把scala-library整个精简掉,导致程序崩溃。下载附件中的proguard.conf,和pom.xml放在一起,如果想要使用其他文件名,参见上面注释的proguardInclude。
[*]加入了scala.Enumeration和scala.collection的filter,前者会生成大把莫名其妙的warning,而且Enumeration已经是不推荐使用的类了;后者由于太大了,为了减小体积。此条为个人喜好,不加也没有问题。
[/list]

这个时候执行mvn package就可以看到生成的hello-1.0-SNAPSHOT.apk,大小为70k,还算可以。

启动一个模拟器,然后mvn android:deploy就可以部署上去了。实际还可以直接部署到真机上,windows用一个usb driver,官网有下,还没有尝试过。

放一张截图。

[img]http://dl.iteye.com/upload/attachment/392402/db0e1d3c-64af-3360-bbbe-971c67785066.jpg[/img]

[size=medium][b]4、优化[/b][/size]
上面的过程实际还可以优化,一个完整的mvn clean package android:deploy还是要花上将近一分钟的时间。

主要还是集中在proguard的打包上,而且这也涉及到发布程序的时候的大小。

[quote]proguard的官网上给出了很多例子,[url]http://proguard.sourceforge.net/index.html#/manual/examples.html[/url],其中包括一个scala的。但是这个会造成不必要的依赖,所以在本文中只使用了其一部分。[/quote]

目前想到的可以加速的几点:
[list=1]
[*]每次android-plugin都会把所有的依赖库解压一遍,这个非常慢,可以作为一个feature request提出来,对于库依赖这个插件没有处理好。
[*]rt.jar的读取也是很慢的,可以在rt.jar加入过滤(java/**,javax/**),这个也是官网推荐的。但是由于proguard-maven-plugin不支持这个选项,所以可以把-libraryjars rt.jar(filter)加入到proguard.conf里面,去掉上面的libs标签。有一利就有一弊,这样的话就不能跨平台,因为rt.jar的路径是固定的。
[*]filter掉一部分scala-library,篇头提到的scala-android.jar应该也是做了同样的事情。甚至可以直接做一个精简的jar出来install到本地仓库上,这样也可以减小第一条浪费的时间。前面也提到actors和concurrency不能被dx正确打包,所以估计这两个特性是不能用了。collection虽然很强大,但是本身也太大了,如果注重效率还是用java的容器吧。
[*]proguard还有obfuscate和optimize特性可以用,都能减小大小,不过optimize可能会让程序崩溃。上面的程序obfuscate后变成50K,可以运行。optimize后40K,但是会崩溃,可能需要调整一些细微的参数。
[/list]

如果有更好的方法建议欢迎讨论。 :D
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值