您的位置 首页 java

「Android」微信登录,一篇文章搞定

申请账号

去微信开放平台申请账号

使用方法是把这个APP安装到手机,然后把要获取签名的APP使用发布版签名安装到同一个手机,然后输入包名点击下图的获取。

签名和包名填写到页面底部的这里↓

然后在页面顶部复制这个AppID,这个东西是不会变的,复制一次就行了,下面的AppSecret可用可不用。

因为微信的登录回调写得很智障,用户昵称头像之类的东东,你和后台,谁去管微信要,谁就要用到这个AppSecret

自动给debug包签名

如果不想每次都手动签名,可以使用gradle脚本自动签名。 在APP的build.gradle下android中加入

signingConfigs {
 debug {
 keyAlias 'aaa'//库中对应的签名文件
 keyPassword '123456'//签名密码
 storeFile file('D:/AndroidProjects/xxx.jks')//签名库文件路径和名称,强烈建议存在项目目录里
 storePassword '123456'//签名库密码
 }
 }
 

导入lib

跟我念:Gradle大法好!微信支付和微信登录都在这一个包里,导入就完事了

//微信SDK
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
 

登录代码(写到你的登录界面里)

先实例化一个微信 api 对象

Java

private IWXAPI api;
//实例化全局微信api对象,可以写到Activity的onCreate里也可以把整个对象放在 Application 里全局使用
 api = WXAPIFactory.createWXAPI(this, "你的AppID", false);
 api.registerApp("你的AppID");
 

Kotlin

lateinit var api: IWXAPI
//实例化全局微信api对象,可以写到Activity的onCreate里也可以把整个对象放在Application里全局使用
 api = WXAPIFactory.createWXAPI(this, "你的AppID", false)
 api.registerApp("你的AppID")
 

然后是登录方法

Java

private void login(IWXAPI api) {
 if (!api.isWXAppInstalled()) {
 ToastUtils.showShort("您还未安装微信客户端!");//这里是一句Toast,可以用你自己的Toast工具类替换
 return;
 }
 SendAuth.Req req = SendAuth.Req();
 req.scope = "snsapi_userinfo";
 req.state = "wechat_sdk_demo_test";
 api.sendReq(req);
 finish();
 }
 

Kotlin

private fun login(api: IWXAPI) {
 if (!api.isWXAppInstalled) {
 ToastUtils.showShort("您还未安装微信客户端!")//这里是一句Toast,可以用你自己的Toast工具类替换
 return
 }
 val req = SendAuth.Req()
 req.scope = "snsapi_userinfo"
 req.state = "wechat_sdk_demo_test"
 api.sendReq(req)
 finish()
 }
 

直接调用这个方法就可以请求微信登录,回调写的下面提到的Activtiy里。

对,没错,回调写到其他Activity里,是不是很扯淡?不知道他微信的SDK开发人员脑子里是不是进了硫酸(╯‵□′)╯︵┻━┻写出这种神仙操作逻辑。

创建wxapi的Activity

在你的包名下建一个子package叫wxapi,这个名字不能改,然后在里面新建

WXEntryActivity -> 微信登录/微信分享回调

WXPayEntryActivity -> 微信支付回调

他们都继承Activity实现IWXAPIEventHandler接口

注册回调Activity

<!-- 微信回调STRART -->
 <activity
 android:name=".wxapi.WXEntryActivity"
 android:configChanges="keyboardHidden|orientation|screenSize"
 android:exported="true"
 android:theme="@android:style/Theme.Translucent.NoTitleBar" />
 <!--/*微信支付*/-->
 <activity
 android:name=".wxapi.WXPayEntryActivity"
 android:exported="true"
 android:launchMode="singleInstance"
 android:theme="@style/AppSplash">
 <!-- 微信支付 -->
 < intent -filter>
 <action android:name="android.intent.action.VIEW" />
 <category android:name="android.intent.category.DEFAULT" />
 <data android:scheme="在这里填写AppID" />
 </intent-filter>
 </activity>
 

style内容

 <style name="AppSplash" parent="Theme.AppCompat.Light.NoActionBar">
 <!-- 设置启动背景透明 -->
 <item name="android:windowIsTranslucent">true</item>
 <!-- 设置启动不要Title -->
 <item name="android:windowNoTitle">true</item>
 </style>
 

本篇讲微信登录,支付用的WXPayEntryActivity如果你的项目没用到可以不写也没关系。

在WXEntryActivity和刚才一样拿一个WXAPI对象,创建过程是一毛一样的这里就省略不写了,如果你一开始是写在Application里面的现在直接拿来用就好了。

不同的是这次要在onCreate和onNewIntent里加上

setIntent(intent);//onNewIntent还要在前面加这句,onCreate不用
api.handleIntent(intent, this);
 

然后重写onReq(请求发出)和onResp(请求返回)两个方法

发出的地方(onReq)打个日志就好

Toast.makeText(this, " openid  = " + req.openId, Toast.LENGTH_SHORT).show();
 

接收返回的地方(onResp)我们来搞事情

Java

@ Override 
private void onResp(BaseResp resp) {
 String result = "";
 switch (resp.errCode) {
 case BaseResp.ErrCode.ERR_USER_CANCEL:
 result = "操作取消";
  break ;
 case BaseResp.ErrCode.ERR_AUTH_DENIED:
 result = "请求被拒绝";
 break;
 default:
 result = "未知错误";
 break;
 }
 }
 switch (resp.type) {
 case 1:{
 if (resp.errCode == BaseResp.ErrCode.ERR_OK) {
 SendAuth.Resp resp2 = (SendAuth.Resp) resp;
 val code = resp2.code;
 result = "登录成功";
 getAccessToken(code);//如果你家后台要昵称头像啥的用户信息你还要用这个code去请求微信的接口,否则在这里直接返回code给后台即可
 }
 break;
 }
 case 2: {
 if (resp.errCode == BaseResp.ErrCode.ERR_OK) {
 result = "分享成功";
 }
 }
 }
 ToastUtil.showShort(result);
 Logger.d(result);
}
 

Kotlin

override fun onResp(resp: BaseResp) {
 when (resp.errCode) {
 BaseResp.ErrCode.ERR_USER_CANCEL -> result = "操作取消"
 BaseResp.ErrCode.ERR_AUTH_DENIED -> result = "请求被拒绝"
 else -> {
 result = "未知错误"
 }
 }
 when (resp.type) {
 1 -> {
 if (resp.errCode == BaseResp.ErrCode.ERR_OK) {
 val code = (resp as SendAuth.Resp).code
 result = "登录成功"
 getAccessToken(code)//如果你家后台要昵称头像啥的用户信息你还要用这个code去请求微信的接口,否则在这里直接返回code给后台即可
 }
 }
 2 -> {
 if (resp.errCode == BaseResp.ErrCode.ERR_OK) {
 result = "分享成功"
 }
 }
 }
 ToastUtil.showShort(result)
 Logger.d(result)
 }
 

如果你家后台只要code的话,到这里为止就结束了,把getAccessToken那个方法换成http请求发给你家后台就行了。

如果你还想拿微信的昵称和头像的话,请继续往下看。

用code调微信接口拿token

Java+OkHttp3

private void getAccessToken(String code) {
 // String url = "";
 String url = "";
 OkHttpClient mOkHttpClient = new OkHttpClient();
 ///< Post方式也可以...
 // RequestBody body = new FormBody.Builder()
 // .add("appid", "替换为你的appid")
 // .add("secret", "替换为你的app密钥")
 // .add("code", code)
 // .add("grant_type", "authorization_code")
 // .build();
 url += "?appid=" + "替换为你的appid" + "&secret=xxxxxxxx"
 + "&code=" + code + "&grant_type=authorization_code";
 final Request request = new Request.Builder()
 .url(url)
 //.post(body)
 .build();
 Call call = mOkHttpClient.newCall(request);
 call.enqueue(new Callback() {
 @Override
 public void onFailure(Call call, IOException e) {
 finish();
 }
 @Override
 public void onResponse(Call call, Response response) throws IOException {
 String json = response.body().string();
 AccessToken accessToken = JSONObject.parseObject(json, new TypeReference<AccessToken>() {
 });
 getUserInfo(accessToken.getAccess_token(), accessToken.getOpenid());
 }
 });
 }
 

Kotlin+Kolley

/**
 * @param code 根据code再去获取AccessToken
 */
 private fun getAccessToken(code: String) {
 // String url = "";
 ///< Post方式也可以...
 // RequestBody body = new FormBody.Builder()
 // .add("appid", "替换为你的appid")
 // .add("secret", "替换为你的app密钥")
 // .add("code", code)
 // .add("grant_type", "authorization_code")
 // .build();
 Http.post {
 // url += ("?appid=" + "替换为你的appid" + "&secret=xxxxxxxx"
// + "&code=" + code + "&grant_type=authorization_code")
 url = ""
 params {
 "appid" - "你的AppID"
 "secret" - "你的Secret"
 "code" - code//你拿到的code
 "grant_type" - "authorization_code"
 }
 onSuccess { byts ->
 var result = byts.toString(Charset.defaultCharset())
 if (TextUtils.isNotEmpty(result)) {
 val model: WXTokenModel = StringNullAdapter.gson.fromJson(result)
 getUserInfo(model.access_token, model.openid)
 }
 }
 onFail { error ->
 var message = error.message
 ToastUtil.showShort(message)
 }
 }
 }
 

其中用到的

kolley是一个仅支持Kotlin的轻量级网络请求框架

StringNuallAdapter是一个解析json时即使遇到空也不会崩溃的第三方库仅支持Kotlin

implementation 'com.ohmerhe.kolley:kolley:0.3.1'
implementation 'com.github.mfangtao:FTLibary:2.0.2'
 

WXTokenModel

JavaBean

public class WXTokenModel{
 private String access_token = "";
 private int expires_in = 0;
 private var openid: String = "";
 private String refresh_token = "";
 private String scope: = "";
 
 //getter/setter略
}
 

Kotlin data class

data class WXTokenModel(
 var access_token: String = "",
 var expires_in: Int = 0,
 var openid: String = "",
 var refresh_token: String = "",
 var scope: String = ""
)
 

用token调微信接口拿用户信息

Java+OkHttp3

private void getUserInfo(String access_token, String openid) {
 // String url = "";
 String url = "";
 OkHttpClient mOkHttpClient = new OkHttpClient();
 RequestBody body = new FormBody.Builder()
 .add("access_token", access_token)
 .add("openid", openid)
 .build();
 final Request request = new Request.Builder()
 .url(url)
 .post(body)
 .build();
 Call call = mOkHttpClient.newCall(request);
 call.enqueue(new Callback() {
 @Override
 public void onFailure(Call call, IOException e) {
 finish();
 }
 @Override
 public void onResponse(Call call, Response response) throws IOException {
 String json = response.body().string();
 WXUserInfo wxUserInfo = JSONObject.parseObject(json, new TypeReference<WXUserInfo>() {
 });//至此昵称头像全部到手,传给你家后台吧
 finish();
 }
 });
 }
 

Kotlin+kolley

private fun getUserInfo(access_token: String, openid: String) {
 // String url = "";
 Http.post {
 url = ""
 params {
 "access_token" - access_token
 "openid" - openid
 }
 onSuccess { byts ->
 var result = byts.toString(Charset.defaultCharset())
 if (TextUtils.isNotEmpty(result)) {
 val model: WXUserInfo = StringNullAdapter.gson.fromJson(result)
 sendThird(openid, model.headimgurl, model.nickname)//至此昵称头像全部到手,传给你家后台吧
 }
 }
 onFail { error ->
 var message = error.message
 ToastUtil.showShort(message)
 }
 }
 }
 

WXUserInfo

JavaBean

public class WXUserInfo(
 private String city = "";
 private String country = "";
 private String headimgurl = "";
 private String nickname = "";
 private String openid= "";
 private List<String> privilege = ArrayList();
 private String province "";
 private int sex 0;
 private String unionid "";
 
 //getter/setter略
)
 

Kotlin data class

data class WXUserInfo(
 var city: String = "",
 var country: String = "",
 var headimgurl: String = "",
 var nickname: String = "",
 var openid: String = "",
 var privilege: MutableList<String> = ArrayList(),
 var province: String = "",
 var sex: Int = 0,
 var unionid: String = ""
)
 

微信登录奇怪的调用链导致的问题

这里的调用链是你的登录界面→微信的登录界面→微信的回调界面,你会发现在这个跳转中由于微信的登录界面这个东东屁都不给你返回,你的登录界面不能通过onActivtiyResult之类的方法去拿登录结果,登录结果被传给了微信的回调界面。

你的登录界面完完全全就是个请求发送器,发送请求之后就没用了,所以在api.sendReq(req)这行下面通常都会加一句finish()让登录界面出栈,避免用户在APP玩了一圈想退出的时候退回到了栈底的登录界面。

当然这样一来会导致一个问题,那就是用户在微信授权的界面点退出直接就没有栈底元素了直接回桌面了,但是这种情况一样会走到WXEntryActivity里,所以解决办法就是在WXEntryActivity里当resp.errCode != BaseResp.ErrCode.ERR_OK的时候手动去启动一下我们自己的登录界面。

关于集成 友盟 的登录方案

如果你的项目使用了友盟分享的话,就不用导入一开始说的那个库了,取而代之的是下面这个库

implementation 'com.umeng.umsdk:share-wx:6.9.4'
 

然后在Application的onCreate中加上

UMConfigure.init(this, "友盟AppKey", "Umeng", UMConfigure.DEVICE_TYPE_PHONE, "友盟MessageSecret");
PlatformConfig.setWeixin("微信AppID", "微信AppSecret");
 

调用改为 Java

private UMShareAPI umShareAPI;
private UMAuthListener umAuthListener;//这东西的方法直接空实现即可,因为它的回调微信不会走。是方法空实现,不是对象留空
//onCreate中
umShareAPI = UMShareAPI.get(this);
//调用登录
umShareAPI.getPlatformInfo(this, SHARE_MEDIA.WEIXIN, umAuthListener);//微信登录
 

Kotlin

lateinit var umShareAPI: UMShareAPI
lateinit var umAuthListener: UMAuthListener//这东西的方法直接空实现即可,因为它的回调微信不会走。是方法空实现,不是对象留空
//onCreate中
umShareAPI = UMShareAPI.get(this)
//调用登录
umShareAPI.getPlatformInfo(this, SHARE_MEDIA.WEIXIN, umAuthListener)//微信登录
 

最后

谢谢大家阅读都这里,想看更多技术文章可以给我加个关、。

我从事Android开发快十年了,今年年初我花两个月的时间收录整理了一套知识体系,此外,还有面试专题、架构视频,如果有想法深入的系统化的去学习的,可以关注我,我会把我收录整理的资料都送给大家,帮助大家更快的提升。

私信【架构】

关注+转发+私信,让更多需要的朋友们都可以免费看到、领到。

文章来源:智云一二三科技

文章标题:「Android」微信登录,一篇文章搞定

文章地址:https://www.zhihuclub.com/180389.shtml

关于作者: 智云科技

热门文章

网站地图