android实现微信联合登录开发

随着现在社交app的越来越普及,微信,QQ,微博几乎成了我们每个人的手机必备,而且第三方应用也越来越多,不是每个用户都想为你的应用注册一个独立帐号的,所以联合登录也就显得尤为重要,成了我们不得不掌握的开发要点,但你要用微信等帐号实现联合登录,人家也有要求,就是你必须遵守OAuth2.0协议标准(https://oauth.net/2/)就行。

接下来我们就以android studio为平台,介绍下接入微信的整个流程:

这里有一个官方参考资料:https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317851&token=6bfe3acd2969037c7217667f24f8eeaf714e5113&lang

那么在接入之前,我们还有一些准备工作要做:

1):登录微信开放平台,完成账号申请:https://open.weixin.qq.com

2):提交app完成审核,并开通相应权限:

image.png

在提交app完成审核的过程中,我们需要提供app的包名与签名:

包名就是我们创建app时候的名称,可以通过manifest.xml和build.gradle中查看,如在manifest.xml中:

<?xml version="1.0" encoding="utf-8"?>
<manifest 
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yeejay.reader"
>

...

在build.gradle中:

defaultConfig {
    applicationId "com.yeejay.reader"
    ...
}

如果manifest.xml与build.gradle中不一致,将以build.gradle中的声明为准:

应用签名的获取会有一些麻烦,因为我们需要通过签名工具对我们的应用进行签名,如果不进行签名,每次安装apk时android平台会为我们生成默认签名,由于平台的不一致性,导致我们的apk装到不同的手机上签名不一致,最后导致无法正常使用微信登录与分享功能,所以我们要提前做好统一签名,整个签名流程如下:

(1)点击 build ---> Generate Signed Apk... ---> 选择app module ---> 填写生成keystore.jks的目录,密钥,有效期等信息;

(2)将生成的keystore.jks文件拷贝到project目录下的app目录下;

(3)在build.gradle文件中进行配置,代码如下:

signingConfigs {

    release {
        storeFile file('keystore.jks')
        storePassword 'xxx'
        keyAlias 'xxx'
        keyPassword 'xxx'
    }
}

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }

    debug {
        signingConfig signingConfigs.release
    }
}

将配置中的xxx改为生成keystore.jks时的密码信息;

(4)Sync同步下项目代码,完成后在右边的Gradle projects/app/build目录下双击assembleDebug或assembleRelease即可生成对应版本带有签名的apk。

(5)下载apk签名检测工具:
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&token=&lang=zh_CN
在最下面有一个签名生成工具,单击下载进行下载;

(6)将下载的apk签名工具安装到手机上,将之前生成的带有签名认证的apk也装到手机上,打开签名工具apk,如下图:

image.png

输入包名,点击按钮生成对应的数字签名;

(7) 将包名与数字签名注册到我们的app审核过程中;

(8)漫长的等待...,也许是两三天,也许一两个礼拜。当我们的应用申请通过时,微信开放平台会返回给我们APP_ID与APP_SECRET信息。

当应用审核通过后,就到我们的代码实施阶段了,不过在写代码之前,我们先来了解一下OAuth2.0它的一个认证流程:

image.png

整个过程的交互一共七个流程,当用户使用第三方应用请求微信登录时,此时会调起微信登录确认页面,并请求微信OAuth2.0进行授权,当用户确认登录时,这时微信平台会拉起我们的第三方应用,并将带有临时票据的信息返回给我们的第三方应用,当我们的应用拿到微信的临时票据时,我们就可以根据它的票据的code信息,再加上我们应用的appId与appSecret信息换取access_token。当然,为了用户帐号信息的保存,这个过程一般都是由我们的第三方应用的服务器完成的,我们只需要将我们的code传给我们的服务器,由服务器最终完成与微信平台的token换取。

接下来就是开始写代码了,首先我们需要下载微信的sdk包,在build.gradle中,添加下面一行代码:

dependencies {

...

compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'

...

}

sync,将会下载我们最新的sdk版本。如果下载失败我们也可以使用离线包,添加到app/lib目录中,并添加引用即可(由于前段时间jCenter下架了微信的sdk,导致开发的过程中发现不能直接使用,这时候可以考虑在lib中添加即可);

根据微信开发平台的官方要求,调起微信登录的处理逻辑必须放在我们应用的包名.wxapi目录下,否则会报错。这点可以参考微信提供的官方sdkDemo,https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419319167&token=&lang=zh_CN 在范例代码进行下载。不过这里下载的代码可能会因为编码的原因,导致汉语注释变成了混乱字符,后来将UTF-8编码改为GBK就OK了。

我们看一下代码的实现逻辑:

public class WXEntryActivity extends Activity implements IWXAPIEventHandler {

public static final String APP_ID = "xxxxxxxxxx";
public static final String APP_SECRET = "xxxxxxxxxx";
private static final String WEIXIN_SCOPE = "snsapi_userinfo";
private static final String WEIXIN_STATE = "login_wx";

private IWXAPI api;
private SendAuth.Req req;

private TextView loginWx;
private User user;
private String wxCode;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.login_wx);
    loginWx = (TextView) findViewById(R.id.login_wx);
    api = WXAPIFactory.createWXAPI(this, APP_ID, false);
    api.registerApp(APP_ID);

    try {
        api.handleIntent(getIntent(), this);
    } catch (NullPointerException e) {
        e.printStackTrace();
    }

    initListener();
}

private void initListener() {
    loginWx.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            sendAuth();
        }
    });
}

private void sendAuth() {
    req = new SendAuth.Req();
    req.scope = WEIXIN_SCOPE;
    req.state = WEIXIN_STATE;
    api.sendReq(req);
}

@Override
public void onReq(BaseReq baseReq) {
}

@Override
public void onResp(BaseResp baseResp) {
    int type = baseResp.getType();
    if (type == 1) {
        // 登录
    SendAuth.Resp sendAuthResp = (SendAuth.Resp) baseResp;
    wxCode = sendAuthResp.code;
    String state = ((SendAuth.Resp) baseResp).state;
    int errCode = baseResp.errCode;
    Intent intent = new Intent(WXEntryActivity.this, HomeActivity.class);
    intent.putExtra("login", "login");
    intent.putExtra("wxCode", wxCode);
    startActivity(intent);
    YeeUtils.animOpenActivity(this);
    finish();
    } 
}
    
@Override
public void finish() {
    super.finish();
    YeeUtils.animCloseActivity(this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    api.unregisterApp();
}
}

要实现微信登录的功能,我们的代码就必须实现IWXAPIEventHandler接口,实现onReq()与onResp()接口,首先我们要在activity创建的时候需要进行一些初始化的操作,这个照写就是:

api = WXAPIFactory.createWXAPI(this, APP_ID, false);
api.registerApp(APP_ID);

try {
    api.handleIntent(getIntent(), this);
} catch (NullPointerException e) {
    e.printStackTrace();
}

当我们进行微信登录时,整个认证流程也就从sendAuth()开始了,当调起微信登录并确认后,这个时候微信sdk会调起我们的当前activity并触发onResp()回调,并传回code信息,这时候我们就可以将接下来的处理交给我们的服务器,由它完成对微信token的换取。

当然如果你想自己实现对微信token的获取以及接下来的操作,也是可以的,不过不建议这样使用,下面就是获取token的代码:

private void getResult(String code) {
    String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
            + APP_ID
            + "&secret="
            + APP_SECRET
            + "&code="
            + code
            + "&grant_type=authorization_code";
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, null, new SuccessResponse(), new ErrorListener());
    StudyApplication.getInstance().newRequestQueue(this).add(request);
}

class SuccessResponse implements Response.Listener<JSONObject> {

    @Override
    public void onResponse(JSONObject response) {
 
        if (null != response) {
            String openid = null;
            try {
                openid = response.getString("openid")
                        .toString().trim();
            String access_token = response
                    .getString("access_token").toString().trim();          
               SharePreferenceHelper.putValue(getApplicationContext(), "access_token", access_token);
                getUID(openid, access_token);
            }
            catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }
}

通过这一步那么我们就拿到了用户的token信息,使用token我们就可以获取到用户信息,包括昵称,性别,头像,地址等信息,我们接下来看getUid()中的实现:

private void getUID(final String openId, final String accessToken) {
    String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId;
    JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, null, new UIDSuccessResponse(), new ErrorListener());
    StudyApplication.getInstance().newRequestQueue(this).add(request);
    }

class UIDSuccessResponse implements Response.Listener<JSONObject> {

        @Override
        public void onResponse(JSONObject response) {
            if (response == null) {
                return;
            }
            String nickname = null;
            nickname = response.optString("nickname");
            String unionid = response.optString("unionid");
            String headUrl = response.optString("headimgurl");
            SharePreferenceHelper.putValue(getApplicationContext(), "nickname", nickname);
            SharePreferenceHelper.putValue(getApplicationContext(), "photourl", headUrl);
            SharePreferenceHelper.putValue(getApplicationContext(), "uin", unionid);
            if (user == null) {
                user = new User();
            }
            user.setUin(unionid);
            user.setNickName(nickname);
            user.setHeadImgUrl(headUrl);

            ...
        }
    };

当拿到用户的私人信息后,我们就完成了整个流程,但这些信息不应该由我们自己处理,所以当需要获取用户信息时,我们应该请求我们自己的服务器,然后由服务器再去请求微信服务器,这样的流程才是安全可靠的。

除了微信登录,微信sdk还集成了微信好友分享,朋友圈分享,小程序分享(比较早的版本是没有的...)等功能,分享内容包括图片,文本,网页等,这就看我们的需求了,分享这块我就不写了,大家可以参考下官方的sdkDemo关于分享的代码。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,973评论 25 707
  • 转载需要著名出处: 之前写过微信登录分享支付第一版: 前言 大部分的app都有接入第三方sdk的需求。例如第三方登...
    Android开发666阅读 6,454评论 3 38
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,646评论 18 139
  • 第2天·21天OH卡魔法美颜瘦身课#玩卡不卡·每日一抽# 每一位都可以通过这张卡片觉察自己: 1、直觉他叫什么名字...
    听味十足的故事阅读 197评论 0 0
  • 如果阳光不那么高远我愿意摘取一篮每天把它种在地里施肥、除草、浇水直到收获 如果大地不这么广袤我愿择取一隅种些粮食和...
    郭安安阅读 322评论 11 15