這篇文章給大家圖文詳解Android整合微信登入的步驟,透過文章整理的內容,大家只需要幾行程式碼就可以實現微信登入的功能了,剛興趣的朋友們下面來一起看看吧。
一、先在Application的onCreate中寫:
// GeneralAppliction.java public static IWXAPI sApi; @Override public void onCreate() { super.onCreate(); sApi = WXEntryActivity.initWeiXin(this, AppConst.WEIXIN_APP_ID); }
二、在需要登入的地方加入:
// MainActivity.java WXEntryActivity.loginWeixin(MainActivity.this, GeneralAppliction.sApi);
##三、下面對具體的整合步驟做詳細的描述。
整合步驟:
1、在開放平台註冊建立應用,申請登入權限 2、下載sdk,拷貝相關文件到專案工程目錄
3、全域初始化微信元件 4、請求授權登錄,取得code 5、透過code取得授權口設使用者資訊1. 在開放平台註冊創建應用,申請登入權限
#這一步其實不用怎麼講,無法就是在微信開放平台上註冊一個帳號,然後創建行動應用程式。要注意的是:套用簽章的部分
這裡套用簽章我使用的是線上的
key的
md5,關於這個需要注意的問題可以看:Android的簽章總結
2. 下載sdk,拷貝相關檔案到專案工程目錄開發工具包(SDK)的下載:可以使用微信分享、登入、收藏、付款等功能需要的程式庫以及檔案
範例Demo
如果wxapi這個資料夾放的位置不對,講無法登錄,微信sdk無法找到登入的Activity授權功能。然後在Man
est.
xml裡面加入:
<activity android:name=".wxapi.WXEntryActivity" android:theme="@android:style/Theme.Translucent.NoTitleBar" android:configChanges="keyboardHidden|orientation|screenSize" android:exported="true" android:screenOrientation="portrait" />3. 全域初始化微信元件
全域初始化微訊號元件,當然是Application的onCreate裡(當然Activity的onCreate也是可以的,為了全域使用微信api
物件方便操作):
@Override public void onCreate() { super.onCreate(); // 初始化微信组件 initWeiXin(); } public static IWXAPI sApi; private void initWeiXin() { sApi = WXEntryActivity.initWeiXin(this, AppConst.WEIXIN_APP_ID); }
為了同一業務的單一原則我把微信相關的都統一封裝到了wxapi包下和WXEntryActivity中:
#// 实现IWXAPIEventHandler 接口,以便于微信事件处理的回调
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {
private static final String WEIXIN_ACCESS_TOKEN_KEY = "wx_access_token_key";
private static final String WEIXIN_OPENID_KEY = "wx_openid_key";
private static final String WEIXIN_REFRESH_TOKEN_KEY = "wx_refresh_token_key";
private Gson mGson;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 微信事件回调接口注册
GeneralAppliction.sApi.handleIntent(getIntent(), this);
mGson = new Gson();
}
/**
* 微信组件注册初始化
* @param context 上下文
* @param weixin_app_id appid
* @return 微信组件api对象
*
/
public static IWXAPI initWeiXin(Context context, @NonNull String weixin_app_id) {
if (TextUtils.isEmpty(weixin_app_id)) {
Toast.makeText(context.getApplicationContext(), "app_id 不能为空", Toast.LENGTH_SHORT).show();
}
IWXAPI api = WXAPIFactory.createWXAPI(context, weixin_app_id, true);
api.registerApp(weixin_app_id);
return api;
}
/**
* 登录微信
*
* @param api 微信服务api
*/
public static void loginWeixin(Context context, IWXAPI api) {
// 判断是否安装了微信客户端
if (!api.isWXAppInstalled()) {
Toast.makeText(context.getApplicationContext(), "您还未安装微信客户端!", Toast.LENGTH_SHORT).show();
return;
}
// 发送授权登录信息,来获取code
SendAuth.Req req = new SendAuth.Req();
// 应用的作用域,获取个人信息
req.scope = "snsapi_userinfo";
/**
* 用于保持请求和回调的状态,授权请求后原样带回给第三方
* 为了防止csrf攻击(跨站请求伪造攻击),后期改为随机数加session来校验
*/
req.state = "app_wechat";
api.sendReq(req);
}
// 微信发送请求到第三方应用时,会回调到该方法
@Override
public void onReq(BaseReq req) {
switch (req.getType()) {
case ConstantsAPI.COMMAND_GETMESSAGE_FROM_WX:
break;
case ConstantsAPI.COMMAND_SHOWMESSAGE_FROM_WX:
break;
default:
break;
}
}
// 第三方应用发送到微信的请求处理后的响应结果,会回调到该方法
@Override
public void onResp(BaseResp resp) {
switch (resp.errCode) {
// 发送成功
case BaseResp.ErrCode.ERR_OK:
// 获取code
String code = ((SendAuth.Resp) resp).code;
// 通过code获取授权口令access_token
getAccessToken(code);
break;
}
}
}
第三方透過code取得access_token的時候需要用到,code的超時時間為10分鐘,一個code只能成功換取一次access_token即失效。 code的臨時性與一次保障了微信授權登入的
安全性性。第三方可透過使用https和state參數,進一步加強自身授權登入的安全性。
這樣
WXEntryActivity.loginWeixin(MainActivity.this, GeneralAppliction.sApi);
我們在onResp的回呼方法中取得了code,然後透過code取得授權口令access_token:
/**
* 获取授权口令
*/
private void getAccessToken(String code) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?" +
"appid=" + AppConst.WEIXIN_APP_ID +
"&secret=" + AppConst.WEIXIN_APP_SECRET +
"&code=" + code +
"&grant_type=authorization_code";
// 网络请求获取access_token
httpRequest(url, new ApiCallback<String>() {
@Override
public void onSuccess(String response) {
Logger.e(response);
// 判断是否获取成功,成功则去获取用户信息,否则提示失败
processGetAccessTokenResult(response);
}
@Override
public void onError(int errorCode, final String errorMsg) {
Logger.e(errorMsg);
showMessage("错误信息: " + errorMsg);
}
@Override
public void onFailure(IOException e) {
Logger.e(e.getMessage());
showMessage("登录失败");
}
});
}
/**
* 处理获取的授权信息结果
* @param response 授权信息结果
*/
private void processGetAccessTokenResult(String response) {
// 验证获取授权口令返回的信息是否成功
if (validateSuccess(response)) {
// 使用Gson解析返回的授权口令信息
WXAccessTokenInfo tokenInfo = mGson.fromJson(response, WXAccessTokenInfo.class);
Logger.e(tokenInfo.toString());
// 保存信息到手机本地
saveAccessInfotoLocation(tokenInfo);
// 获取用户信息
getUserInfo(tokenInfo.getAccess_token(), tokenInfo.getOpenid());
} else {
// 授权口令获取失败,解析返回错误信息
WXErrorInfo wxErrorInfo = mGson.fromJson(response, WXErrorInfo.class);
Logger.e(wxErrorInfo.toString());
// 提示错误信息
showMessage("错误信息: " + wxErrorInfo.getErrmsg());
}
}
/**
* 验证是否成功
*
* @param response 返回消息
* @return 是否成功
*/
private boolean validateSuccess(String response) {
String errFlag = "errmsg";
return (errFlag.contains(response) && !"ok".equals(response))
|| (!"errcode".contains(response) && !errFlag.contains(response));
}
#6. 在第5步判斷access_token是否存在與過期
#在回调的onResp方法中获取code后,处理access_token是否登录过或者过期的问题:
// 从手机本地获取存储的授权口令信息,判断是否存在access_token,不存在请求获取,存在就判断是否过期 String accessToken = (String) ShareUtils.getValue(this, WEIXIN_ACCESS_TOKEN_KEY, "none"); String openid = (String) ShareUtils.getValue(this, WEIXIN_OPENID_KEY, ""); if (!"none".equals(accessToken)) { // 有access_token,判断是否过期有效 isExpireAccessToken(accessToken, openid); } else { // 没有access_token getAccessToken(code); }
判断授权口令是否有效:
/** * 判断accesstoken是过期 * @param accessToken token * @param openid 授权用户唯一标识 */ private void isExpireAccessToken(final String accessToken, final String openid) { String url = "https://api.weixin.qq.com/sns/auth?" + "access_token=" + accessToken + "&openid=" + openid; httpRequest(url, new ApiCallback<String>() { @Override public void onSuccess(String response) { Logger.e(response); if (validateSuccess(response)) { // accessToken没有过期,获取用户信息 getUserInfo(accessToken, openid); } else { // 过期了,使用refresh_token来刷新accesstoken refreshAccessToken(); } } @Override public void onError(int errorCode, final String errorMsg) { Logger.e(errorMsg); showMessage("错误信息: " + errorMsg); } @Override public void onFailure(IOException e) { Logger.e(e.getMessage()); showMessage("登录失败"); } }); }
7. 如果access_token过期无效,就用refresh_token来刷新
/** * 刷新获取新的access_token * / private void refreshAccessToken() { // 从本地获取以存储的refresh_token final String refreshToken = (String) ShareUtils.getValue(this, WEIXIN_REFRESH_TOKEN_KEY, ""); if (TextUtils.isEmpty(refreshToken)) { return; } // 拼装刷新access_token的url请求地址 String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?" + "appid=" + AppConst.WEIXIN_APP_ID + "&grant_type=refresh_token" + "&refresh_token=" + refreshToken; // 请求执行 httpRequest(url, new ApiCallback<String>() { @Override public void onSuccess(String response) { Logger.e("refreshAccessToken: " + response); // 判断是否获取成功,成功则去获取用户信息,否则提示失败 processGetAccessTokenResult(response); } @Override public void onError(int errorCode, final String errorMsg) { Logger.e(errorMsg); showMessage("错误信息: " + errorMsg); // 重新请求授权 loginWeixin(WXEntryActivity.this.getApplicationContext(), GeneralAppliction.sApi); } @Override public void onFailure(IOException e) { Logger.e(e.getMessage()); showMessage("登录失败"); // 重新请求授权 loginWeixin(WXEntryActivity.this.getApplicationContext(), GeneralAppliction.sApi); } }); }
8. 使用access_token获取用户信息
/** * 获取用户信息 * / private void getUserInfo(String access_token, String openid) { String url = "https://api.weixin.qq.com/sns/userinfo?" + "access_token=" + access_token + "&openid=" + openid; httpRequest(url, new ApiCallback<String>() { @Override public void onSuccess(String response) { // 解析获取的用户信息 WXUserInfo userInfo = mGson.fromJson(response, WXUserInfo.class); Logger.e("用户信息获取结果:" + userInfo.toString()); } @Override public void onError(int errorCode, String errorMsg) { showMessage("错误信息: " + errorMsg); } @Override public void onFailure(IOException e) { showMessage("获取用户信息失败"); } }); }
通信部分
private OkHttpClient mHttpClient = new OkHttpClient.Builder().build(); private Handler mCallbackHandler = new Handler(Looper.getMainLooper()); /** * 通过Okhttp与微信通信 * * @param url 请求地址 * @throws Exception */ public void httpRequest(String url, final ApiCallback<String> callback) { Logger.e("url: %s", url); final Request request = new Request.Builder() .url(url) .get() .build(); mHttpClient.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, final IOException e) { if (callback != null) { mCallbackHandler.post(new Runnable() { @Override public void run() { // 请求失败,主线程回调 callback.onFailure(e); } }); } } @Override public void onResponse(Call call, final Response response) throws IOException { if (callback != null) { if (!response.isSuccessful()) { mCallbackHandler.post(new Runnable() { @Override public void run() { // 请求出错,主线程回调 callback.onError(response.code(), response.message()); } }); } else { mCallbackHandler.post(new Runnable() { @Override public void run() { try { // 请求成功,主线程返回请求结果 callback.onSuccess(response.body().string()); } catch (final IOException e) { // 异常出错,主线程回调 mCallbackHandler.post(new Runnable() { @Override public void run() { callback.onFailure(e); } }); } } }); } } } }); } // Api通信回调接口 public interface ApiCallback<T> { /** * 请求成功 * * @param response 返回结果 */ void onSuccess(T response); /** * 请求出错 * * @param errorCode 错误码 * @param errorMsg 错误信息 */ void onError(int errorCode, String errorMsg); /** * 请求失败 */ void onFailure(IOException e); }
总结
集成的详细描述就这样,至于获取的用户信息,小伙伴们应该知道后续自己业务的需求,该怎么处理了。以上就是本文的全部内容了,希望能对大家的学习或者工作带来一定的帮助,如果有疑问大家可以留言交流。
以上是圖文詳解Android整合微信登入的步驟的詳細內容。更多資訊請關注PHP中文網其他相關文章!