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
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);
}

总结

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

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, 微信授权登录
, 微信集成
集成微信登录
android集成微信登录、android集成qq登录、装修流程步骤详解图、装修流程步骤详解、热血江湖结婚步骤详解,以便于您获取更多的相关知识。

时间: 2024-10-13 23:21:13

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 Bluetooth蓝牙技术使用流程详解_Android

在上篇文章给大家介绍了Android Bluetooth蓝牙技术初体验相关内容,感兴趣的朋友可以点击了解详情. 一:蓝牙设备之间的通信主要包括了四个步骤 设置蓝牙设备 寻找局域网内可能或者匹配的设备 连接设备 设备之间的数据传输 二:具体编程实现 1. 启动蓝牙功能 首先通过调用静态方法getDefaultAdapter()获取蓝牙适配器BluetoothAdapter,如果返回为空,则无法继续执行了.例如: BluetoothAdapter mBluetoothAdapter = Blueto

android之SeekBar控件用法详解_Android

MainActivity.java package com.example.mars_2400_seekbar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.app.Activity; import android.os.Bundle; import a

android之RatingBar控件用法详解_Android

MainActivity.java package com.example.mars_2500_ratingbar; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBar; import android.support.v4.app.Fragment; import android.app.Activity; import android.os.Bundle; import

Android消息处理机制Looper和Handler详解_Android

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理. Handler:处理者,负责Message的发送及处理.使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等. MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行.当然,存放Message并非实际意义的保存,而是将Message以链表的方

Android开发之TabActivity用法实例详解_Android

本文实例讲述了Android开发之TabActivity用法.分享给大家供大家参考,具体如下: 一.简介 TabActivity继承自Activity,目的是让同一界面容纳更多的内容.TabActivity实现标签页的功能,通过导航栏对各个页面进行管理. 二.XML布局文件 注意: 1.TabActivity的布局文件要求以TabHost作为XML布局文件的根. 2.通常我们采用线性布局,所以<TabHost> 的子元素是 <LinearLayout>. 3.<TabWidg

Android编程之json解析实例详解_Android

本文实例分析了Android编程之json解析的方法.分享给大家供大家参考,具体如下: JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换.JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为. – Json.org JSON Vs XML 1.JSON和XML的数据可读性基本相同 2.JSON和XML同样拥有丰富的解析手段 3.

Android实现屏幕锁定源码详解_Android

最近有朋友问屏幕锁定的问题,自己也在学习,网上找了下也没太详细的例子,看的资料书上也没有有关屏幕锁定程序的介绍,下个小决心,自己照着官方文档学习下,现在做好了,废话不多说,先发下截图,看下效果,需要注意的地方会加注释,有问题的朋友可以直接留言,我们共同学习交流,共同提高进步!直接看效果图: 一:未设置密码时进入系统设置的效果图如下:   二:设置密码方式预览: 三:密码解密效果图 四:九宫格解密时的效果图 下面来简单的看下源码吧,此处讲下,这个小DEMO也是临时学习下的,有讲的不明白的地方请朋友