参考资料
1.Android接入指南(微信官方):
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=1417751808&token=&lang=zh_CN
2.Android开发第三方登录–微信登录
https://blog.csdn.net/pkandroid/article/details/72974552?utm_source=itdadao&utm_medium=referral
3.Android 微信登录
https://blog.csdn.net/pkandroid/article/details/72974552?utm_source=itdadao&utm_medium=referral
4.EventBus框架简单使用
https://www.jianshu.com/p/f9ae5691e1bb
5.Android 一个改善的okHttp封装库
https://blog.csdn.net/lmj623565791/article/details/49734867/
6.微信token的存储(未实现,仅了解)
https://www.csdn.net/article/2014-08-15/2821220-weixin
https://www.cnblogs.com/penglei-it/p/wx_yh.html
EventBus是一种用于Android的发布/订阅事件总线。它有很多优点:简化应用组件间的通信;解耦事件的发送者和接收者;避免复杂和容易出错的依赖和生命周期的问题;很快,专门为高性能优化过等等。
如果,当前没有微信登录权限,可以使用官方demo的appid和包名及签名来进行练习,这就意味着你需要修改自己应用程序的包名。
Android Studio如何在debug模式下进行签名测试
signingConfigs {
debug {
storeFile file("../debug.keystore")
}
}
或者
File--ProjectStructure--app--Signing添加签名文件--Build Types进行添加设置即可
代码
码云:https://gitee.com/zhangtao3/android_thirdlogin
准备
微信开放平台申请appid,认真正确填写包名和签名(至少保证在调用微信登录之前包名和签名一定要是正确的),微信登录需要认证开发者才能申请开通,认证开发者需付费。
>>>签名生成工具<<<
开始
1.添加依赖
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'(包含统计功能)
implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
2.AndroidManifest添加权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
3.在MyApplication注册到微信
private void initWeiXin() {
// 通过WXAPIFactory工厂,获取IWxApi实例
wxApi = WXAPIFactory.createWXAPI(MyApplication.getAppContext(), GlobalData.WX_APP_ID, true);
// 将应用的AppID注册到微信
wxApi.registerApp(GlobalData.WX_APP_ID);
}
4.发送请求或响应到微信(微信登录)
private void loginWeixin() {
if (MyApplication.wxApi.isWXAppInstalled() && MyApplication.wxApi.isWXAppSupportAPI()) {
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";//应用授权作用域
req.state = "wechat_sdk_demo";//用于保持请求和回调的状态,授权请求后原样带回给第三方。
MyApplication.wxApi.sendReq(req);
} else {
ToastUtils.showShortToast("未安装微信");
}
}
5.接收微信的请求及返回值(接受登录回调),参照接入指南操作3步即可
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注意:
//第三方开发者如果使用透明界面来实现WXEntryActivity,需要判断handleIntent的返回值,如果返回值为false,则说明入参不合法未被SDK处理,应finish当前透明界面,避免外部通过传递非法参数的Intent导致停留在透明界面,引起用户的疑惑
try {
boolean result = MyApplication.wxApi.handleIntent(getIntent(), this);
if (!result) {
Log.d(GlobalData.TAG, "参数不合法,未被SDK处理,退出");
finish();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
MyApplication.wxApi.handleIntent(data, this);
}
//
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
MyApplication.wxApi.handleIntent(intent, this);
finish();
}
@Override
public void onReq(BaseReq baseReq) {
Log.d("wx_onReq", baseReq.toString());
}
@Override
public void onResp(BaseResp baseResp) {
String result = new Gson().toJson(baseResp);
Log.d(GlobalData.TAG, "wx_onResp:" + result);
switch (baseResp.errCode) {
case BaseResp.ErrCode.ERR_OK:
//发送EventBus事件
String code = ((SendAuth.Resp) baseResp).code;
EventBus.getDefault().post(new MessageEvent(code));
break;
case BaseResp.ErrCode.ERR_USER_CANCEL:
// 取消
break;
case BaseResp.ErrCode.ERR_AUTH_DENIED:
// 拒绝
ToastUtils.showShortToast("取消微信登录");
break;
default:
break;
}
finish();
}
}
6.在完成步骤五之前,需要在MainAvtivity注册EventBus,就收EventsBus
// 注册EventBus
EventBus.getDefault().register(this);
// 接受EventBus
@Subscribe(threadMode = ThreadMode.MAIN)
public void Event(MessageEvent messageEvent) {
// 获取微信授权code
String code = messageEvent.getMessage();
// 获取token,openid
// 获取个人信息
getWxToken(code);
}
7.获取token
// 通过code获取access_token
private void getWxToken(String code) {
Map<String, String> params = new HashMap<>();
params.put("appid", GlobalData.WX_APP_ID);
params.put("secret", GlobalData.WX_APP_SECRET);
params.put("code", code);
params.put("grant_type", "authorization_code");
//{"access_token":"11_-T4RsKGs8-SXKCtdYUkaHpx5AZyTCmaQRk6SWR0ZcwKYjcvY0eDJljhx683N1aNJ2j0bO8ndnu8ZuQGTlooPxB8dR8iK_g81sggRH6ZhPEA",
// "expires_in":7200,"refresh_token":"11_Vn-rr9i57WDrH4YjxWg_R1qdRfXZusmAwXvl7WSJfvGeMRYx215dKbtWKFh9LA0Bothg6mIRTp_yJjuP3cbBaEhjoZAhT_l3aHnJGGpnAUc",
// "openid":"xxx","scope":"snsapi_userinfo","unionid":"xxx"}
OkHttpUtils.getInstance().getRequestAsync(GlobalData.WX_GET_TOKEN, params, new OkHttpUtils.MyOkHttpCall() {
@Override
public void success(Call call, Response response) throws IOException {
// response.body()只可调用一次
final String resultString = response.body().string();
Log.d(GlobalData.TAG, "http_wx_getToken: " + resultString);
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject resultObj = new JSONObject(resultString);
if (resultObj.getString("access_token") != null) {
String access_token = resultObj.getString("access_token");
String openid = resultObj.getString("openid");
getWxUserInfo(access_token, openid);
} else {
Log.e(GlobalData.TAG, "run_err: " + resultObj.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
8.获取个人信息
// 获取用户个人信息(UnionID机制)
private void getWxUserInfo(String access_token, String openid) {
Map<String, String> params = new HashMap<>();
params.put("access_token", access_token);
params.put("openid", openid);
//{"openid":"xxx","nickname":"Animal_1","sex":1,"language":"zh_CN","city":"Xi'an","province":"Shaanxi","country":"CN",
// "headimgurl":"http:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/DYAIOgq83erSSvDC5t1xWD7CiaicGFtZptRtwPKP969ygibS212MnSG72Cv9XoehOKCSQBIepsjYp3ricDPGzic923g\/132",
// "privilege":[],"unionid":"xxxxx"}
OkHttpUtils.getInstance().getRequestAsync(GlobalData.WX_GET_USER_INFO, params, new OkHttpUtils.MyOkHttpCall() {
@Override
public void success(Call call, Response response) throws IOException {
// response.body()只可调用一次
final String resultString = response.body().string();
Log.d(GlobalData.TAG, "http_wx_getUserInfo: " + resultString);
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
JSONObject resultObj = new JSONObject(resultString);
if (resultObj.getString("nickname") != null) {
tv_result.setText("微信nickname:" + resultObj.getString("nickname"));
} else {
Log.e(GlobalData.TAG, "run_err: " + resultObj.toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
});
}
结束
参照网上资源基本就可以很快实现,我一开始没有正确的应用签名,导致一直吊不起微信授权页面,纠结了好久,网上的解决方案是清理缓存或者卸载微信重新尝试,我使用的模拟器,重新安装后依旧没有授权页面,画面一闪而逝,但是各种数据都能拿到,好在正确填写签名后,别人的可以正常使用。所以也就这样了。