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获取授权口令access_token

6、在第5步判断access_token是否存在和过期

7、如果access_token过期无效,就用refresh_token来刷新

8、使用access_token获取用户信息

1. 在开放平台注册创建应用,申请登录权限

这一步其实不用怎么讲,无法就是在微信开放平台上注册一个账号,然后创建移动应用。

需要注意的是:应用签名的部分

此处应用签名我使用的是线上的key的md5,关于这个需要注意的问题可以看:Android的签名总结

2. 下载sdk,拷贝相关文件到项目工程目录

开发工具包(SDK)的下载:可以使用微信分享、登录、收藏、支付等功能需要的库以及文件

示例Demo

下载后把libammsdk.jar文件拷贝到AS工程的libs目录,并把示例Demo里源文件目录下的wxapi目录整个拷贝到,工程目录的src下的根包下:

如果wxapi这个文件夹放的位置不对,讲无法登录,微信sdk无法找到登录的Activity授权功能。然后在Manifest.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); }

4. 请求授权登录,获取code

为了同一业务的单一原则我把微信相关的都统一封装到了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是啥玩意:

第三方通过code进行获取access_token的时候需要用到,code的超时时间为10分钟,一个code只能成功换取一次access_token即失效。code的临时性和一次保障了微信授权登录的安全性。第三方可通过使用https和state参数,进一步加强自身授权登录的安全性。

这样客户端使用的地方只要:

WXEntryActivity.loginWeixin(MainActivity.this, GeneralAppliction.sApi);

5. 通过code获取授权口令access_token

我们在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); }

总结

集成的详细描述就这样,至于获取的用户信息,小伙伴们应该知道后续自己业务的需求,该怎么处理了。以上就是本文的全部内容了,希望能对大家的学习或者工作带来一定的帮助,如果有疑问大家可以留言交流。

时间: 2024-09-20 14:46:26

Android集成微信登录的步骤详解的相关文章

Android集成微信登录的步骤详解_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 WXEntryActivi

Laravel搭建后台登录系统步骤详解_php实例

本文实例讲述了Laravel搭建后台登录系统的方法.分享给大家供大家参考,具体如下: 今天想用laravel搭建一个后台系统,就需要最简单的那种,有用户登录系统,试用了下,觉得laravel的用户登录这块做的还真happy.当然,前提就是,你要的用户管理系统是最简单的那种,就是没有用户权限,能登录就好. 我这里就不用默认的user表做例子了,那样很容易和laravel的一些默认设置混淆. 首先确认,后台的用户表,我设计表叫做badmin,每个管理员有用户名(username),有昵称(nickn

修改Android中hosts文件的步骤详解

前言 在开发的时候我们可能会需要修改Android的hosts文件.Android的hosts文件路径是/system/etc/hosts,在修改该文件前首先需要Android手机获取root权限.至于如何root你的手机,这里就不加详述,可以自行在网络上查找,很多也很简单. 本文将要阐述的是如何在命令行下通过adb程序访问root过的手机,把hosts拖到电脑上修改,然后再复制回手机来实现修改hosts的方法. 下面就开始具体的步骤: C:\tools>adb pull /system/etc

Laravel搭建后台登录系统步骤详解

本文实例讲述了Laravel搭建后台登录系统的方法.分享给大家供大家参考,具体如下: 今天想用laravel搭建一个后台系统,就需要最简单的那种,有用户登录系统,试用了下,觉得laravel的用户登录这块做的还真happy.当然,前提就是,你要的用户管理系统是最简单的那种,就是没有用户权限,能登录就好. 我这里就不用默认的user表做例子了,那样很容易和laravel的一些默认设置混淆. 首先确认,后台的用户表,我设计表叫做badmin,每个管理员有用户名(username),有昵称(nickn

Android 实现微信登录详解_Android

前言  分享到微信朋友圈的功能早已经有了,但微信登录推出并不久,文档写的也并不是很清楚,这里记录分享一下.  正文  一.准备   注册.认证步骤自己来.微信开放平台:https://open.weixin.qq.com  二. 代码   2.1 唤起微信登录    参考官网文档:资源中心/移动应用开放/接入指南/Android接入指南 private IWXAPI mWeixinAPI; private void loginWithWeixin() { if (mWeixinAPI == nu

《Android 网络开发与应用实战详解》——2.2节解析Android SDK实例

2.2 解析Android SDK实例 Android 网络开发与应用实战详解 在Android安装后的目录中有一个名为"samples"的子目录,在里面保存了SDK中的几个演示实例.这些实例从不同的方面展示了SDK的特性.例如"android-3"目录中的实例文件结构如图2-8所示. 在本节的内容中,将引领读者浏览图2-8中各个实例的效果. 1.HelloActivity 这和编程语言中的Hello Word程序类似,是一个Android平台上的最简单程序,运行后

《Android 网络开发与应用实战详解》——1.3节搭建Android应用开发环境

1.3 搭建Android应用开发环境 Android 网络开发与应用实战详解 "工欲善其事,必先利其器"出自<论语>,意思是要想高效地完成一件事,需要有一个合适的工具.对于安卓开发人员来说,开发工具同样至关重要.作为一项新兴技术,在进行开发前首先要搭建一个对应的开发环境.而在搭建开发环境前,需要了解安装开发工具所需要的硬件和软件配置条件. 注意 Android开发包括底层开发和应用开发,底层开发大多数是指和硬件相关的开发,并且是基于Linux环境的,例如开发驱动程序.应用

Android 布局学习之——Layout(布局)详解二(常见布局和布局参数)

  [Android布局学习系列]   1.Android 布局学习之--Layout(布局)详解一   2.Android 布局学习之--Layout(布局)详解二(常见布局和布局参数)   3.Android 布局学习之--LinearLayout的layout_weight属性   4.Android 布局学习之--LinearLayout属性baselineAligned的作用及baseline      Layout Parameters(布局参数):            在XML文

115网盘怎么用 115网盘下载方法步骤详解

  115网盘怎么用呢?115网盘是大家都很喜欢使用的网络硬盘.下面,绿茶小乐哥就为大家带来115网盘下载方法步骤详解,感兴趣的就一起来看下吧. 115网盘是什么? 115网盘是目前流行的网络硬盘,和它属于同一类的还有百度云.360云盘和腾讯微云等,曾几何时人们主要是通过U盘转移数据,现在随着网盘兴起,大部分人都采用网盘存储数据.同传统硬盘和U盘相比,安全,便捷和免费是网盘的杀手锏特色.115网盘凭借出色的使用体验.高容量存储(2TB).丰富的功能.海量的资源和对所有主流离线下载方式的支持(你懂