借助于Mono For Android技术,.Net开发者也可以使用自己熟悉的C#语言以及.Net来开发Android应用。由于Mono For Android把Android SDK中绝大部分类库都已经实现,基本直接参考Java开发Android的书就可以掌握Mono for android技术。
对于有项目技术决策权的团队,如果项目组成员对Java不熟悉,那么可以使用自己熟悉的.Net来开发Android应用,比如我的一个学生使用Mono For Android开发了一款应用(应学生要求,应用的名字保密),3月份一个月就入账41万元。当然是否赚钱和工具关系不大,这里贴出这个案例只是为了告诉大家:Mono For Android是可以完成你的需求的
有一个非常重要的问题,做Android开发的时候还会使用一些第三方的jar包。jar是java的技术,那么在Mono for android中需要怎样使用这些jar呢? 需要一个把jar绑定到dll的过程。
下面以一个典型的Mono For android调用百度地图sdk来讲解一下这个过程:
第一步:创建jar的绑定程序集
Mono for android提供了Java Binding Library用来自动化的创建绑定(或者说包装)jar的.Net程序集,这样就可以通过调用程序集中的包装类来调用jar中的类了。
首先从百度地图网站上下载百度地图的SDK;
接着在Visual Studio的点击主菜单【文件】→【新建】→【项目】,在对话框中选择Mono for Android下的“Java Binding Library”,给项目取一个名字,比如“BaiduMapSDK”;
接下来把baidumapapi_v2_1_1.jar放到Jars文件夹下,选中jar文件,在属性视图中将“生成操作”属性设置为“EmbeddedJar”,生成解决方案。我们就会发现在bin/Debug文件夹下就生成了BaiduMapSDK.dll这个包装程序集,细心的朋友应该发现了在obj\Debug\generated\src下生成的cs代码就是对jar的封装调用。
第二步:引用绑定程序集
点击主菜单【文件】→【新建】→【项目】,在对话框中选择Mono for Android下的“Android Application”创建一个Android项目,比如取名为“MapTest”。
在项目上点右键选择【添加引用】→【项目】,在项目列表中选择第一步创建的“BaiduMapSDK”。
如果是普通的全部都是用java代码写的jar,那么这样就可以用了,但是百度地图SDK中是包含使用C/C++写的Native代码(如果SDK包中除了jar文件之外还有.so文件,那么就说明有一部分代码是非Java的Native代码)的,因此还需要把libapp_BaiduMapApplib_v2_1_1.so、libvi_voslib.so这两个库文件放到MapTest项目中,并且把so文件的“生成操作”设置为“AndroidNativeLibrary”,否则运行的时候会提示加载不到Library。
在MapTest项目中创建一个libs文件夹,并且在libs文件夹下创建一个armeabi文件夹,然后把libapp_BaiduMapApplib_v2_1_1.so、libvi_voslib.so放到这个文件夹下。如果运行到armeabi-v7a CPU下,还需要同样创建一份armeabi-v7a文件夹;同样如果运行在x86CPU下则同样需要创建x86文件夹(但是百度地图SDK的so暂时不支持X86CPU)。
第三步:调用百度地图SDK
在axml中添加地图视图控件:MapView
<com.baidu.mapapi.map.MapView android:id="@+id/bmapsView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true" />
反编译BaiduMapSDK.dll我们会发现,这个程序集中把命名空间、类名、方法名等都改成了.Net的命名规则,比如MapView类在java中的包名是com.baidu.mapapi.map,但是在dll程序集中命名空间变成了Com.Baidu.Mapapi.Map(首字母大写)。
因为layout文件是给android引擎使用的,而程序集中的类只是对java类的的包装,所以注意在layout文件中控件节点的命名空间要使用java中的命名规则com.baidu.mapapi.map.MapView,而不是Com.Baidu.Mapapi.Map.MapView。
在Activity的OnCreate中SetContentView之前添加下面的代码来初始化百度地图SDK,否则会报错“com.baidu.platform.comjni.map.basemap.JNIBaseMap.Create”:
BMapManager mBMapMan = new BMapManager(this.Application);
mBMapMan.Init("我的Key", null);
注意把“我的Key”替换成从百度地图网站上申请的应用Key。
当然还没有结束,因为还需要增加百度地图SDK需要的权限,至少添加如下的权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
程序运行之后百度地图就显示出来了。
当然如果仔细查看生成的DLL,你可能会发现所有的方法的参数名字全部都是p0、p1、p2,而不是有意义的参数名。
这是怎么回事呢?不像.Net的MSIL中把参数名也写入了IL代码,Java中方法名是没有写入.class 的,因此工具也无法通过jar文件分析出参数的名字,所以“Java Binding Library”生成的程序集的方法的参数名都是p0、p1、p2这样无意义的参数名,能否命名为有意义的参数名呢?关于这个问题可以参考官方文档《Binding a Java Library (.jar),Consuming Java Libraries from C#》 中“Fixing Up Parameter Names”这段内容,里面提到了可以编辑Metadata.xml文件来为参数取名字。
但是这个为参数命名的过程很枯燥,按理来说,如果我们拿到了jar对应的java源文件,那么Mono For Android应该可以根据java源代码来知道参数的名字,但是貌似这个还没有实现。我有一个思路,使用Eclipse的JDT中的Java源码分析类ASTParser(用法参考:http://lym6520.iteye.com/blog/747840 和http://blog.csdn.net/flying881114/article/details/6187503 )来分析jar对应的java源文件,然后自动生成Metadata.xml文件。工作很忙,暂时没时间实现这个想法,希望有园子里的大牛能实现,造福广大Monoer!