趁着失业了,闲着没事儿学习了下Xamarin.Android binding,在以往的开发中,我相信不少人都遇到过binding的坑,也不例外,php
在作这个工做前,我上网搜索了一下关于binding的文章,也有,可是比较少,并且文章都是一两年前,不少SDK都更新了不少代了,java
按照他们以前的一些作法就会有问题。node
我尝试绑定了微信SDK、支付宝SDK、百度地图SDK,在大神帮助下,一步一步绑定成功了。android
并且我相信这几个SDK在开发中用到的几率也仍是很大的,因此特此分享下绑定遇到的坑,也为了更好的记录本身遇到的问题。git
话很少说,直接上代码。github
1.准备工做:下载百度android开发包,毕竟工欲善其事必先利其器,地址:http://lbsyun.baidu.com/sdk/download?selected=mapsdk_basicmap,mapsdk_searchfunction,mapsdk_lbscloudsearch,mapsdk_calculationtoolapi
2.开发环境,这里就不讲解开发环境搭建了。我这儿的环境的是VS2017+win10,后续的两个绑定都是如此。浏览器
3.Binding:微信
3.1 新建安卓bingding工程
3.2 将下载的压缩包解压,而后把里面的jar包以及so文件放到如下目录
这里的so文件就是为不一样的cup架构提供的指令集
3.3 接下来就是设置jar、so文件的属性,按照以下设置
3.4接下来就是编译,不出意外会出现如下错误
错误的意思就是字段名称和类名重复了才致使编译不过,那么接下来怎么办呢,这就须要咱们手动配置这些字段名称,毕竟VS再智能也会有绑定不对的时候啊!
打开文件Metadata.xml文件,加入如下代码。
<attr path="/api/package[@name='com.baidu.location']/class[@name='Address']/field[@name='address']" name="name">AddressInfo</attr> <attr path="/api/package[@name='com.baidu.mapapi']/class[@name='VersionInfo']/field[@name='VERSION_INFO']" name="name">VersionInformation</attr> <attr path="/api/package[@name='com.baidu.platform.comapi.map']/class[@name='B']/field[@name='b']" name="name">BField</attr> <attr path="/api/package[@name='com.baidu.platform.comapi.map']/class[@name='E']/field[@name='e']" name="name">EField</attr>
这里的意思呢就是讲这些字段名称重命名,Metadata.xml还能够去除某些类或字段,设置某些函数的返回值之类的。Metadata.xml更多的用法的话,能够参考https://developer.xamarin.com/guides/android/advanced_topics/binding-a-java-library/customizing-bindings/java-bindings-metadata/。主要全是英文,我英文能力也差,估计翻译出来你们都会吐槽,还不如本身看。
而后再编译就没有问题了,说一下,百度地图我编译的环境是在jdk1.8+安卓目标平台7.0下编译的。
而后我照着百度地图提供的DEMO写了个示例
关键代码:
SDKInitializer.Initialize(ApplicationContext); SetContentView(Resource.Layout.Main); mapView = FindViewById<MapView>(Resource.Id.mapView); currentLocationMode = LocationMode.Normal; var baiduMap = mapView.Map; //定义Maker坐标点 LatLng point = new LatLng(30.691359, 104.052236); //构建Marker图标 BitmapDescriptor bitmap = BitmapDescriptorFactory.FromResource(Resource.Drawable.marker); //构建MarkerOption,用于在地图上添加Marker OverlayOptions option = new MarkerOptions().InvokePosition(point).InvokeIcon(bitmap); //在地图上添加Marker,并显示 baiduMap.AddOverlay(option); baiduMap.MyLocationEnabled = true;更多的用法的话,参照百度地图的API
代码的话,别急,会在最后给出GITHub的地址。
效果图:
在调用百度地图的时候,须要配置你的APK签名的sha1值,调试的时候呢,都是用的这个目录下的 C:\Users\HuShuai\AppData\Local\Xamarin\Mono for Android
debug.keystore来签名的,而后须要获取它的sha1值,推荐一个好用的工具,并且很是简单的,详情请看: http://bbs.lbsyun.baidu.com/forum.php?mod=viewthread&tid=106461&qq-pf-to=pcqq.group.
能够经过命令行来获取 Keytool -list -v -keystore "C:\Users\用户名\AppData\Local\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android。
可是这个有时候好像不太管用, 好比我就没有获取到,不如第一种方式简单暴力。
有了前面的百度地图绑定示例,后面的两个绑定基本都相似了,无非就是修修改改编译不过的问题。
SDK下载地址:https://doc.open.alipay.com/doc2/detail.htm?treeId=54&articleId=104509&docType=1
But支付宝稍微有点儿不同:
一开始编译的话,应该会提示如下错误
所有提示不能强制转换类RpcException为java.lang.object
按照上一个绑定的经验来绑定的话,彻底懵逼了,根本无法弄。But能够这样
将转换的地方,直接修改为 this.Handle
相似下面这样
接下来就是把里面转换的地方都改完,而后把里面的内容所有复制,新建一个名字为RpcException的类
而后把内容粘贴进去,新建的类放在 Additions 这个文件夹中。
而后就是在Metadata.xml里面加入一下代码
<remove-node path="/api/package[@name='com.alipay.android.phone.mrpc.core']/class[@name='RpcException']" />这里的意思呢就是删除banding自动给咱们生成的类,而咱们的 Additions 文件夹呢则是存放用户自定义的内容,在编译的时候则会把咱们添加的内容一块儿编译进去。
而后就是本身写了一个支付demo,只能跳转到支付界面以及调用H5页面支付界面,没有测试是否可以真的支付成功,主要是没有若是要测试的话,还须要部署套测试环境才行。若是那位测试能够支付的话,请给博主留言,谢谢了。
调用H5支付页面的话,须要在AndroidManifest.xml文件中加入如下节点:
<activity android:name="com.alipay.sdk.app.H5PayActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind"></activity> <activity android:name="com.alipay.sdk.auth.AuthActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind"></activity>效果图:
微信SDK下载地址:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=11_1
仍是按照以前的操做,将jar文件复制到 Jars 文件夹里,设置编译属性为 EmbeddedJar
这里呢说一下博主在绑定过程当中 遇到的坑:
一开始编译的时候,提示名称重复,我心想so easy,这难道不我啊,毕竟有两个绑定的经验了,而后就再Metadata.xml添加了以下两句代码:
<attr path="/api/package[@name='com.tencent.mm.opensdk.modelbase']/class[@name='BaseResp']/field[@name='errCode']" name="managedName">errCode</attr> <attr path="/api/package[@name='com.tencent.mm.opensdk.modelmsg']/class[@name='WXMediaMessage']/field[@name='mediaObject']" name="managedName">mediaObject</attr>
并且也如预期同样编译成功了,心想这不是多难啊。而后就想照着这个 文章 这样写个支付Demo,写着写着,准备用到 PayReq 这个类的时候,结果发现如何引用都找不到它,这就尴尬了。
我反编译看了下微信SDK源码,
我发现是有这个类的,可是为何绑定没有呢? 我又在绑定项目工程下的目录去查看了生成的类文件,结果也没有叫作 PayReq 的类
What ? 这咋办呢,而后看了下警告信息,发现是这个类不能正确映射,而后就缺失了,可是这咋办呢?翻了一下午的Xamarin论坛,又全是英文,也没有找到什么有效的解决办法,But 我最前面说认识了个大佬啊,不懂就请教啊。
大佬告诉我你这错误缘由多是 JDK版本 设置的太高的缘由,让我改为 JDK1.7,目标编译框架设置成6.0试试
大佬就是大佬,一针见血的找到问题,剩下的就是两个小问题,重命名就搞定了,到此编译成功!
<attr path="/api/package[@name='com.tencent.mm.opensdk.modelbase']/class[@name='BaseResp']/field[@name='errCode']" name="managedName">errCode</attr> <attr path="/api/package[@name='com.tencent.mm.opensdk.modelmsg']/class[@name='WXMediaMessage']/field[@name='mediaObject']" name="managedName">mediaObject</attr>
可是又遇到一个奇葩问题,在实例化 PayReq 对象时,VS仍是找不到这个类,我用ILSpay看了生成的类,是有这个的 !
But并不能影响什么,由于仍是能够编译成功!!!
并且若是我将编译好的dll 文件单独放到 安卓工程里面去引用的话,编译是没有问题的,这个时候VS也能知道这个类,在对象浏览器中也能看到这个类,我试过将两个工程里面的obj、bin目录下的文件都删除,而后从新编译,结果仍是这个问题,直接引用这个binding工程找不到PayReq这个类,可是却能编译成功。不知道是否是VS17的一个Bug,若是那位园友遇到过这个问题,也能够留言说一下。
微信支付后回调Activity 代码:
using System; using Android.App; using Android.Content; using Android.OS; using Com.Tencent.MM.Opensdk.Modelbase; using Com.Tencent.MM.Opensdk.Openapi; using Android.Util; using Android.Widget; using Com.Tencent.MM.Opensdk.Constants; namespace XamarinWeiXinDemo { /// <summary> /// 微信支付回调Activity /// </summary> public class WXPayEntryActivity : Activity, IWXAPIEventHandler { private IWXAPI api; public void onCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); //SetContentView(R.layout.pay_result); //布局是能够自定义 api = WXAPIFactory.CreateWXAPI(this, "App_ID"); api.HandleIntent(Intent, this); } protected override void OnNewIntent(Intent intent) { base.OnNewIntent(intent); Intent = intent; api.HandleIntent(intent, this); } public void OnReq(BaseReq p0) { } public void OnResp(BaseResp p0) { Log.Debug("微信支付回调", "onPayFinish, errCode = " + p0.errCode); if (p0.Type == ConstantsAPI.CommandPayByWx) { //0 成功 展现成功页面 //-1 错误 可能的缘由:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其余异常等。 //-2 用户取消 无需处理。发生场景:用户不支付了,点击取消,返回APP。 if (p0.errCode == 0) { //支付成功逻辑 Toast.MakeText(this, "支付成功", ToastLength.Long).Show(); } else { //支付失败 Toast.MakeText(this, "支付失败", ToastLength.Long).Show(); } Finish(); } } } }
三个绑定demo都已经传至GitHub
百度地图:https://github.com/HuUncle/Xamarin.Android-BaiDuMapSDKBinding
微信:https://github.com/HuUncle/Xamarin.Android-WeiXinSDKBindingDemo
支付宝:https://github.com/HuUncle/Xamarin.Android-AlipaySDKBindingDemo
若是以为对你有帮助,请帮我点个赞,你的推荐是我学习的动力。
转载请注明出处 IT胡小帅: http://www.cnblogs.com/CallMeUncle/p/6562440.html