Windows下Scala编程环境的构建:Scala on Android开发
概述
开发Android应用程序,大家都已知是使用Java编程语言,为何要用Scala?有什么意义?
学习函数式编程,比Scala编程语言更加“更正苗红”的函数式编程语言有其它的选择,为何要选择Scala编程语言?
首先,用Scala开发Android app,已经有很多人这样做了,绝非什么新鲜事;其次,个人非常不喜欢Java编程语言,感觉不自由,抽象层次还是偏低,等等,而Scala语言就没有Java的那些问题,对于提高产能和效率,应该比Java更好;再次,Android应用程序的开发,实际是在JVM上做开发,JVM Langauge其实有很多,只不过Scala是其中呼声较高,前途光明的一个。
Scala实际不仅仅是函数式编程语言,它是一种支持多范型开发的编程语言,同时支持描述式和命令式的编程思想。使用它,首先,有利于对二者的比较,容易理解函数式开发的思想;其次,按照Anders Hejlsberg的说法,多范型和并发的支持是编程语言发展的趋势,Scala很好的支持了这个说法,所以我选择了Scala。在学习和掌握了Scala之后,可以进一步的学习那些比较纯粹的函数式编程语言,那是后话了。
那么Scala on Android,可以有2种理解:
1)开发的是Scala应用程序,Android其实主要是提供一套GUI框架,这样可以理解成Scala在智能手机领域的的应用。
2)开发的是Android应用程序,只是把JAVA语言换成另一种效率更高的JVM编程语言Scala,以提高Android app的开发能力和效率。最终还是打包为运行在android机器上的apk。
本文是按照第二种理解,说明如何使用IntelliJ IDEA Community进行Scala on Android的开发。
基础
1,Android的开发环境已经配置好,并正常进行IDEA下Android app的开发。
上图是相关环境变量的配置。注意ANDROID_HOME和ANDROID_SDK_HOME的区别,后者是用来指明avd创建的路径的。
2,Android的项目编译,是使用Ant管理的,要熟悉Ant的用法。
3,除了IDE提供的ant,我们还需要自己在Console下运行ant,还有proguard,所以单独安装一份。
http://proguard.sourceforge.net/ 4.8
http://ant.apache.org/ 1.8.4
它们没有MSI安装文件,解压缩zip,并配置PATH:
构建思路
1,按照对Scala on Android的2种理解,其实有2个方式来构建:
1)首先创建一个Scala项目,然后使其支持Android的开发。
2)首先创建一个Android项目,然后使其支持使用Scala语言。
而且Scala项目和Android项目的创建,又都有2种方式:
1)使用Console工具
2)使用IDE
所以总共就有4种方式来构建Scala on Android。结合前面几篇文章的说明,可以先确定一点:优先使用IDE。所以结果就变成了2个方式:
1)用IDEA先创建一个Scala项目,然后使其支持Android。
2)用IDEA先创建一个Android项目,然后使其支持Scala。
后文分别说明这2种方式。
2,参考网上的资料:
1) http://chneukirchen.org/blog/archive/2009/04/programming-for-android-with-scala.html
此文比较早,说明了比较早期的做法,也说明了下scala的lib如何转换成dex格式的。还需要额外拷贝scala的lib到项目的目录中,然后修改build.xml。
2) http://lampwww.epfl.ch/~michelou/android/
这个网站要近一些,这里很有价值,其中不仅有文档说明,还有把Android sample的代码转换成scala的示例代码,可以帮助大家学习如何进行Scala on Android的实际开发。相比上一个链接,这里是完整的解决方案。不过遗憾的是,它并没有及时更新,最近的也是10个月之前,无法在最新的Android sdk环境下(Android tools r21.1)直接使用。这里的解决方案是针对Scala 2.9.x + Android tools r19的环境,对于最新的Scala 2.10.x以及Android tools r21.1的环境,都没有说明。
通过这个链接,可以得到那些从Android Java code转换成 Scala code的示例项目的。
其中,https://github.com/michelou/android-examples/tree/master/hello-android/configs/ant中的build-scala.xml是关键,它是本文后续改进的基础。
3) http://yinghau76.github.com/2012/12/08/trying-scala-on-android/
这个链接是最近的更新了。在上一个链接的基础上,提供了一个mac-shim.xml,配合build-scala.xml(2个链接中是一样的),可以支持Android tools r21.1。其实这个脚本并不只是如它的网页上所说,用来解决Linux和MacOS之间的兼容问题, 它实际是解决了Android tools r19中的ant build.xml升级到r21.1后的兼容问题,因为build-scala.xml中使用的一些路径和变量,是基于r19中的Ant build.xml的,到了r21.1中的Ant build.xml,已经变化,后文会解释。
但是,这个链接中的内容,还是没有提供从Scala 2.9.x升级到2.10.x的解决方案,以及如何在IntelliJ IDEA中调试的问题。
本文就是在这些前辈的基础上,进一步把Scala on Android的构建脚本,升级到适应最新的Scala和Android开发环境中。下面,以图文的方式demo下,如何使用IDEA构建、调试一个简单的Scala On Android的项目。
先Scala,后Android
1,新建一个Scala项目,命名为 HelloScalaOnAndroid,由于上一篇中设置了Global Libraries,所以这里自动使用Existent Library。
2,打开project structure(别说这个还不知道怎么操作哦,上一篇已经讲过了),增加Android facet。这相当于Eclipse中Add xxx nature的功能。
然后修改Project SDK为Android,这里选择4.0.3:
检查下现在project modules:
现在这个Scala项目已经支持2种facets了,已经是一个Android + Scala的混合项目。OK退出。
在IDEA中的这些配置,其实不影响Scala On Android项目的编译,但涉及在IDEA中的编码以及调试。编译是由Ant来负责的,IDEA只是要调用它。
3,创建AndroidManifes.xml文件,以及Android project所需要的目录结构和文件,比如res目录和文件。这一步纯手工。
4,下面,使用cygwin,在命令行下运行android update project生成Android项目所需的配置文件:
这样我们得到4支文件,这样一个Android Project的基本结构就可以了。
5,创建一个Scala class,表示一个Android activity。按照AndroidManifest.xml中的Package和Activity命名:
并修改代码如下:
6,下面,创建debug configuration。选择Android Application类型,命名,选择Module。注意到默认的Before launch是Make。
到此,从Scala项目开始,建立起来一个Scala on Android项目的基本结构,不过现在build,是肯定会失败的。(这里涉及IDEA的Make是如何工作的,暂时没有分析。)
接下去,就是如何把参考链接中的解决方案用上了。不过,先看完如何从Android项目入手,构建一个Scala on Android项目。
先Android,后Scala
1,创建一个Android项目,同样命名为 HelloScalaOnAndroid。(如果在同一个目录下,要先删除上一节创建的同名项目哦)
简单直接,一个完整的Android Project就OK了,比手动调用android update project创建的,还多出了一个ant.properties。还多了一些子目录:assets, libs。
2,增加Scala facet。还是通过project structure:
然后:
这里选择Global libraries中的scala 2.10.0 compiler。然后是:
增加对Scala library的依赖:
OK退出后, IDEA会有一个bubble提示,是关于Scala的"Configure type-aware highlighting for the project"的,推荐Enable它。
4,修改一个地方,这样后面支持可以安装到android 2.3.3的 emulator target上,当然也可以不改。
5,因为debug configuration也是自动创建好的,所以只需要把Java Code修改成Scala Code。右击com.example.HelloScalaOnAndroid,创建一个Scala class,命名为MyActivity,修改内容,然后删掉同名的MyActivity.java(要把safe delete disable掉)。
至此,从Android项目入手,一个Scala On Android项目同样准备好了,当然也是不能build的。同样的错误。
小结
1,无论是从创建Scala项目,还是Android项目入手,最终殊途同归,一个Scala on Android项目的结构其实是一样的。
2,通过比较,还是从Android入手,省事。
3,在IDEA上选择的Scala Compiler & Library的版本,其实不影响它的编译,只是涉及在IDEA中编码时使用的Scala的语言功能。当然,也应跟编译系统中的设定一致为好。
4,这部分只是使用IDEA搭建了一个Scala on Android项目的基础,不是难点,下面暂时离开IDEA,重点说明下编译系统的 改进,最后再回到IDEA,看下如何在IDEA中进行debug。
编译
1,下面,根据链接http://yinghau76.github.com/2012/12/08/trying-scala-on-android/中的内容,获取一些文件:
1) mac-shim.xml
并且,参考build.xml, ant.properties中的写法。
2,新建一个config子目录,将下载的mac-shim.xml、build-scala.xml和proguard-template.cfg放入其中,然后修改build.xml和ant.properties文件,指定Scala和proguard的根目录。新建一个config子目录,主要用来统一管理这些脚本。
以及,config/build-scala.xml,把94,95行的2处从"basedir"改成"config.dir"。
3,打开cygwin,在项目的根目录下,试运行:
Great! 成功了。可见,在最新的Android tools r21.1和Scala 2.9.2的环境下,这些脚本完全可以用。
4,下面,尝试运行到emulator上:
Great! 运行也正常的。
分析
1,可以尝试先把config/mac-shim.xml文件移除,再重新ant debug,此时是肯定会出错的(最好自己做一下,看看是什么错误信息)。所以mac-shim.xml中的内容是怎么得来的呢?
2,在 build-scala.xml的commit message中,得知 updage for r19,其实就是Android tools r19,而现在已经到r21.1了。所以,只要对比下2个版本的 Ant build.xml,就可知了。r19的版本可以从:http://dl-ssl.google.com/android/repository/tools_r19-windows.zip得到。相对路径在ANDROID_HOME/tools/ant/build.xml。
经过对比以及移除mac-shim.xml后尝试build的出错信息,可知从r19到r21.1:
1)project.libraries.jars改为project.all.jars.path。
2)android.target.classpath改为project.target.class.path。
3)extensible.classpath和extensible.libs.classpath是r21.1中缺少的,需要Porting。
3,buils-scala.xml还需要一个变量proguard.dir,这个变量可以设置在任何地方:ant.properties、build.xml、build-scala.xml、mac-shim.xml、local.properties、project.properties中。考虑与Scala On Android脚本的关联性,放在ant.properties,以及build-scala.xml、mac-shim.xml是合适的。本文就是放在ant.properties。
下面,更换Scala的版本,看看在2.10.x上,有什么表现。
支持Scala 2.10.x
1,修改ant.properties,设置scala.dir到2.10.1-RC3。(先把Scala 2.10.1-RC3下载好,放在一个目录下)
2,重新试运行ant:
Oops!Fail~ 这次应该是Scala升版,有了什么变化,导致build-scala.xml不匹配了。经过查找,需要修改build-scala.xml:
再次运行ant:
又出错了~ 这次是proguard的template脚本有问题。proguard会shrink Scala的libraries,shrink后导致一些符号找不到引用了。再次修改,按照下面的diff,删除那些相关的内容:
再次run ant,发现还有can't find referenced class sun.misc.Unsafe的错误,网上有人认为这是Scala的bug,其实应该是proguard的事情。继续修改proguard-template.cfg文件,增加这些内容:
这次,终于编译通过了!
这些对proguard-template.cfg的改动,实际上就是阻止对Scala 2.10.x中的这些class进行obscure和 shrink,以保证找到引用。
到目前为止,可以支持Scala 2.10.x版本了! 编译系统全部构建完毕!接下来,回到IDEA,看看如何Debug。
在IDEA中Debug
上面已经提到,使用IDEA中的Make是无法编译成功的,更无法进行调试了。上一大节,我们构建好了编译系统。现在,只要使IDEA调用Ant来进行编译即可。
1, IDE最右边的一列上的“Ant Build”,就是用来设置用Ant管理项目编译的。现在看起来,内容为空。通过“+”按钮,把build.xml文件导入,然后就会出现许多build targets了。
可见,最下面的2个就是build-scala.xml中增加的目标。黑体是ant的 primary targets,灰色的不是。
2,重新设置Debug configuration。在Before launch中选择Run Ant target。
选择build-scala.xml中的target,-post-compile-scala:
OK后,返回。然后把原来的Make删除。
OK退出。
3,下面我们来尝试运行Debug,现在code里加个断点。
启动emulator后,Fail了!
从结果上来看,IDEA需要out\production\HelloScalaOnAndroid\下的一个apk,但实际上Ant是在bin\下生成的apk,所以要么将其copy到out下的指定目录,要么在IDEA中指明从bin下去拿apk。
1)解决方法一:打开project structure,在android module下的compiler页中,设置APK path:
将其设置为bin\HelloScalaOnAndroid-debug.apk。OK退出。
2)解决方法二:修改Ant脚本,增加一个build target,这里新建一个xml文件,然后在build.xml中导入:
实际上就是把HelloScalaOnAndroid-debug.apk拷贝并重命名为HelloScalaOnAndroid.apk。
然后再次修改下debug configuration,把上面设置的-post-compile-scala改成debug-for-intellij。
4,无论哪种方法,这次重新Debug,终于可以了~
至此,使用IDEA构建和调试Scala on Android的开发环境已全部完毕。
总结
1,相比2种Scala on Android的项目构建方式,从Android项目入手,要比从Scala项目入手要方便、直接一些。
2,对于前辈们总结出来的解决方案,一定要耐心分析它们在新的版本环境中无法再工作的原因,细致分析之后,总能找到解决方法。
3,IDEA虽然可以调用Ant脚本,但还是不能直接辨认它的生成路径,做为一个Android项目,调试时,还是按照默认的APK Path去拿apk。
本文所示代码仓库
1,根据前辈的解决方案,我自己整理的Ant脚本,以及示例项目的代码,已放到gitcafe和bitbucket中。
gitcafe:https://gitcafe.com/leo.l.cao/HelloScalaOnAndroid
bitbucket:https://bitbucket.org/leolcao/helloscalaonandroid
注意它们都有一个submodule,clone时要带参数。我修改的那些ant和proguard脚本,放在一个单独的仓库中。
gitcafe:https://gitcafe.com/leo.l.cao/scala-on-android-scripts
bitbucket:https://bitbucket.org/leolcao/scala-on-android-scripts
BTW,克隆了HelloScalaOnAndroid的项目后,别忘了在本地运行"android update project -p .",因为local.properties是需要在本地生成的。
2,说明下我的改动:
1)将本文的build-scala.xml改名为build-scala_2.9.2_r19.xml,它是其它文件的基础。
2)将本文的mac-shim.xml改名为build-scala_r19_patch_to_r21.xml。
3)文件命名中,2.9.2不仅支持Scala 2.9.2,还支持2.9.3;而r21也不仅支持Android tools r21,也支持r21.1。
4)build-scala_*_r21.xml中的内容,已经整合了build-scala_r19_patch_to_r21.xml的内容,所以如果使用它们,可以不再使用build-scala_r19_patch_to_r21.xml。
5)因为现在Android Tools最新的版本就是r21.1,开发一般都是在最新的版本环境中的,所以可以直接拿build-scala_*_r21.xml使用,具体哪一个,要看使用的Scala的版本是2.9.x还是2.10.x。
6)build-scala_2.10.0_*.xml中的内容,是针对Scala 2.10.x的版本所做的更新。与2.9.x的版本不兼容。
7)将本文的proguard-template.cfg改名为proguard-template_2.9.2.cfg,表示只支持Scala 2.9.x版本;若想使用Scala 2.10.x,需要用proguard-template_2.10.0.cfg。
结束语
至此,Windows下使用IDEA构建Scala on Android的开发环境,就全部完成了。至于如何使用Eclispe进行构建,我打算日后有时间再补上,不过Eclipse下的plugins要比IDEA丰富,而且我还没有彻底使用Eclipse构建过,所以不保证什么时间,若没有什么特别需要注意的地方,网上也能找到可用的参考,或许我就不写了。我个人偏向于IDEA,计划写Eclipse的部分,是想让这个系列更完整。
正如系列开篇时所说,这些内容只是适合初学者,至于函数式编程的深入理解,以及Scala语言的深入使用,都不是本文所涉及的。作为基础部分,能帮到有意学习这些内容的朋友,已感高兴,任何看法和建议,可以邮件联系。谢谢~
返回索引