前言
上个周到现在一直在忙年前的优化任务,领导都是越到年底越想激发你的潜力,任务一个一个地来,干完了就能回家。作为一个刚刚进入这家公司的Android独苗,接触陌生的代码并且周围人没办法提供帮助的情况下在这么短时间开发几个功能,还是挺费神的。等到现在才完全收工,有时间闲下来去总结一下上个周把我折磨得死去活来的小妖精们。(示例大部分依旧是kotlin)
微信三方登录
集成微信的三方登陆过程不难,但是中间有好多大坑官方没有说明白。我们先从头看开始讲,遇到的坑就放在后面详细探讨一下。
-
注册微信开放平台用户,申请应用。
这一步应该不用说太多,就是简单的注册流程。不过在Android应用这,app的签名是通过微信提供的签名工具获取的:GenSignature,在这里面输入本机已经安装的应用包名,就能获取到这个应用的签名。填上就行了。审核上面说是七个工作日,其实几个小时就行了。
-
引入第三方包,初始化
引入三方包,老规矩
com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+
在项目的gradle文件中引用这个地址,更新一下就可以使用了。
然后进行初始化,一般要放在Application里面进行:
val appID = "wxecb9abc374b780c2"
val api: IWXAPI = WXAPIFactory.createWXAPI(this, appID, true)
private fun initWx() {
api.registerApp(appID)
}
当然这一步很多人直接放在需要调用登陆的Activity或者Fragment里面进行,不过咱们这里防止以后还需要加微信其他功能,就放在这里了。
-
接下来就是在Activity或者Fragment里面的操作。
private fun startWxLogin() { val appID = "wxecb9abc374b780c2" val api: IWXAPI = WXAPIFactory.createWXAPI(this, appID, true) if (!api.isWXAppInstalled) { showShort("您还未安装微信") } else { val req = SendAuth.Req() req.scope = "snsapi_userinfo" req.state = "zhys_wxlogin" api.sendReq(req) } }
这个方法就是调起微信的操作,将这个方法放进相应的点击事件里面就好了。req.scope固定为这个,req.state自定。
-
接下来需要新建一个类用于接收微信传回来的信息。因为在微信官网注册了包名和签名,所以微信是通过用绝对路径的方式将信息传到这个类里面,这个类有严格的命名规则。必须是包名的一级子目录下新建一个文件夹:wxapi,在这个文件夹下新建名为WXEntryActivity的类,官网给出的规则必须是:包名.wxapi.WXEntryActivity,比如说官网注册为com.androidproject.test,那么这个类的包名就应该是com.androidproject.test.wxapi.WXEntryActivity。下面是这个类的基本写法
class WXEntryActivity : Activity(), IWXAPIEventHandler {
private var mWeixinAPI: IWXAPI? = null
private val RETURN_MSG_TYPE_LOGIN = 1
private val RETURN_MSG_TYPE_SHARE = 2
public override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mWeixinAPI = WXAPIFactory.createWXAPI(this, WEIXIN_APP_ID, true)
mWeixinAPI!!.handleIntent(this.intent, this)
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
mWeixinAPI!!.handleIntent(intent, this)//必须调用此句话
}
//微信发送的请求将回调到onReq方法
override fun onReq(req: BaseReq) { LogUtils.d("onReq")
}
//发送到微信请求的响应结果
override fun onResp(resp: BaseResp) {
LogUtils.d("onResp")
when (resp.errCode) {
BaseResp.ErrCode.ERR_OK -> {
LogUtils.d("ERR_OK")
//发送成功
val sendResp = resp as SendAuth.Resp
val code = sendResp.code
EventBus.getDefault().post(code,"wxCode")
finish()
}
BaseResp.ErrCode.ERR_USER_CANCEL -> {
if (resp.type == RETURN_MSG_TYPE_SHARE){
showShort("分享失败")
}else{
showShort("登陆失败")
}
LogUtils.e("ERR_USER_CANCEL")
}
BaseResp.ErrCode.ERR_AUTH_DENIED -> LogUtils.e("ERR_AUTH_DENIED")
else -> {
showShort("微信登陆错误")
LogUtils.d("微信登陆错误"+" "+resp.errCode+resp.errStr)
finish()
}
}//发送取消
//发送被拒绝
//发送返回
}
companion object {
private val APP_SECRET = "305c1e604e79f7e9b4c9a617c67c345c"
val WEIXIN_APP_ID = "wxecb9abc374b780c2"
private val uuid: String? = null
}
}
- 这里我们只用到了微信返回的code,然后发送给后端,后端再集成微信三方登录的功能获取我们的用户信息,如果是想取到相关用户信息也是可以取到的。
好了,到现在为止,微信的基本用法就这么多,下面来讲一下我在微信集成的时候遇到的坑。
一开始,我按照官网一步步写完运行之后发现微信调起界面只是一闪而过,调起瞬间又关闭,然后在WXEntryActivity这个类中debug也没有触发。显然,微信没有找到这个类。于是我检查了包名,和官网一模一样,然后我又检查签名,发现debug模式安装和打包安装的签名是不一样的。这就很坑,于是我得出结论,之后打包之后再测试吧。但是!!!!改了签名之后还是不行,网上查找解决办法都说包名不对。可是我左看右看包名完全一致啊,然后这个问题困扰了我一天。到了晚上回到家精疲力尽的时候,想要做最后一博,就去试验各种方法。然后我发现了这个代码之前设计的是在不同环境下打包添加不同的后缀,
applicationIdSuffix ".develop"
这个时候你们肯定以为我在这个地方犯了低级错误,去找和官网注册的相同后缀的包名问题就解决了(我倒是希望如此),事实证明问题并不是那么简单。
找到相同包名以为可以松一口气的时候,绝望地发现还是不行。我这个时候就感觉肯定和这行代码有关系,网上成功的案例都是绝对固定的包名。于是我注释掉这行代码,将微信注册的包名换成没有后缀的形式,果然成功了。(内心一万个草泥马奔腾而过)。虽然成功了,但是这个项目不能这么继续做下去,因为之后还要做QQ登陆,腾讯开放平台的包名是不能修改的,而且还用了其他的第三方SDK,会影响其他功能。我就只能更改目录结构,硬生生把那个后缀写死在里面。然后切出另外一个分支,维持原有的目录结构,保证其他功能可以在测试环境测试。
微信登陆的坑:
-
注意包名是否一致
-
debug运行的签名和打包签名不一致(集成之后如果出现微信返回ERR=-6的错误,多半是签名不一致,就是这个原因。也有可能是之前微信运行过错误的签名,就会记录到微信缓存中,需要清除缓存或者直接卸载重装)
-
//applicationIdSuffix ".develop" //signingConfig signingConfigs.release
不能使用这两行代码(后面这个是我实验出来的),比较懊恼的是至今不知道其原因,希望有缘人看到这篇文章可以解答一下。
QQ三方登录
接下来我们讲一下QQ三方登录,QQ三方登录其实很简单,我在这个地方绊倒纯粹是经验不足。
QQ三方登陆的SDK还是用的依赖lib包的形式实现。在官网下载它的lib包,引入后就可以使用了。
-
首先在你需要调用的地方进行实例化:
val mTencent: Tencent = Tencent.createInstance("你的appid", applicationContext)
然后进行拉起QQ登陆:
mTencent.login(this, "all", BaseUiListener())
这里的BaseUiListener是自己去写的接收qq的回调。需要自己去写一下.
-
编写QQ回调
public class BaseUiListener implements IUiListener { //注意测试需要在腾讯开放平台注册调试者QQ号 @Override public void onComplete(Object response) { try { // String openId = ((JSONObject) response).getString("openid"); // String expires = ((JSONObject) response).getString("expires_in"); String token = ((JSONObject) response).getString("access_token"); LogUtils.d(((JSONObject) response).getString("access_token")); EventBus.getDefault().post(token,"qqToken"); } catch (JSONException e) { e.printStackTrace(); } } @Override public void onError(UiError e) { LogUtils.d("code:" + e.errorCode + ", msg:" + e.errorMessage + ", detail:" + e.errorDetail); } @Override public void onCancel() { LogUtils.d("onCancel"); } }
这里我只需要qq的accessToken,所有就取了这个值,其他的个人信息也可以取到。
QQ需要注意的点就是在测试环境下需要去腾讯开放平台注册调试者QQ号,不然的话只会不断地重新拉起没有反应。(奇怪的是,ios不用注册也可以收到,因为这个我一直没注意这个问题)。
至此,微信QQ三方登陆的坑就算填完了,这些坑耽误了我太长时间,不过也值得。下面再讲一个和主题无关的小坑:
我中间还用了百度的离线语音合成,但是出现一个问题,打正式的包的时候语音就无法读出。我就去锁定了打包的那几行代码得出以下结论:
// minifyEnabled false
// shrinkResources false
这两行不能随便加上,收缩资源和缩小文件会去删掉它认为没用的资源文件。极大可能会误删,所以导致了离线语音不可用。
最后总结
前段时间时间太紧张了,博客也没更,自己维护的项目也没做,后面再慢慢跟上吧。踩过的这些坑虽然耗时长,但是涨了不少经验,以后就不会犯错了。