好久没写博客了,大概是与ReactNative大战半月已经有点疲惫了,说起集成微信三方登录,还记得上次实现功能还是刚参加工作时,用Mob的ShareSDK来集成实现的,该平台集成了数个主流平台的分享和登录功能,本来想继续抱着Mob大佬的大腿,后来觉得本项目也只集成一个微信登录而已,相比MobShareSDK,不需要再去申请额外的账号,所以最终还是决定入坑原生来将其实现,查阅了官方文档和相关资料,最后总算是将它完成了,不过相比Mob,确实封装不彻底,流程较为繁琐,而且官方文档对新手可能不太友好,所以决定来记录下相关流程和心得,ok,lets go!!!

话不多说,效果图走起来!(不要纠结是两个手机。。。)

第二个界面,我们把返回的字符串提取出昵称nickname和头像headurl,可以根据实际需求抽取字段,完成后续的操作。

下面详述实现流程

1.首先当然是去微信开放平台新建应用获取appId和secret

值得一提的是,因为审核周期过于长,所以等不及的小伙伴可以先把已经注册好的具有微信登录的app的id和secret值拿过来测试,之后审核通过后直接替换正式的id值即可,不过这里要注意:

1)测试demo的包名必须与那个已注册好的app的包名保持一致

2)测试demo的签名文件也必须与那个已注册好的app的签名文件保持一致

这样就没啥问题了,在微信开放平台那里,这就是两个相同的app,不会出什么幺蛾子。

2.接下来当然就是集成环境了

微信原生SDK的集成特别方便,在gradle里添加依赖即可

implementation 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'
implementation 'com.squareup.okhttp3:okhttp:3.4.1'

第一条依赖为微信原生SDK,第二条为Okhttp网络框架

在包名路径下,新建wxapi文件夹,再新建一个WXEntryActivity。(路径文件名必须保持一致)

打开WXEntryActivity

public class WXEntryActivity extends AppCompatActivity implements IWXAPIEventHandler 

重写两个方法。

@Override
public void onReq(BaseReq baseReq) {
}

//请求回调结果处理
@Override
public void onResp(BaseResp baseResp) {
}

点击

等待加载完毕,如无报错环境即搭载成功。

3.接下来就是实现功能了,打开MainActivity,在onCreate里注册应用

private void regToWx() {
    api = WXAPIFactory.createWXAPI(this, APP_ID, false);
    api.registerApp(APP_ID);
}

我们放一个触发请求登录的按钮

写请求方法。

if (!api.isWXAppInstalled()) {
    Toast.makeText(MainActivity.this, "您的设备未安装微信客户端", Toast.LENGTH_SHORT).show();
} else {
    final SendAuth.Req req = new SendAuth.Req();
    req.scope = "snsapi_userinfo";
    req.state = "wechat_sdk_demo_test";
    api.sendReq(req);
}

首先判断是否安装微信客户端,没有就文字提示,反之才进行请求。

4.打开WXEntryActivity

在onCreate方法里隐藏状态栏并获取wxapi

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getSupportActionBar().hide();
    // 隐藏状态栏
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    //接收到分享以及登录的intent传递handleIntent方法,处理结果
    iwxapi = WXAPIFactory.createWXAPI(this, "wx45ccf8958a0a24c7", false);
    iwxapi.handleIntent(getIntent(), this);
}

5.在onRep()方法里获取回调。

//请求回调结果处理
@Override
public void onResp(BaseResp baseResp) {
    //登录回调
    switch (baseResp.errCode) {
        case BaseResp.ErrCode.ERR_OK:
            String code = ((SendAuth.Resp) baseResp).code;
            //获取accesstoken
            getAccessToken(code);
            Log.d("fantasychongwxlogin", code.toString()+ "");
            break;
        case BaseResp.ErrCode.ERR_AUTH_DENIED://用户拒绝授权
            finish();
            break;
        case BaseResp.ErrCode.ERR_USER_CANCEL://用户取消
            finish();
            break;
        default:
            finish();
            break;
    }
}

根据返回码,如果请求成功会返回BaseResp.ErrCode.ERR_OK:相等的值,然后通过code和getAccessToken()方法再获取accessToken。

private void getAccessToken(String code) {
    createProgressDialog();
    //获取授权
    StringBuffer loginUrl = new StringBuffer();
    loginUrl.append("https://api.weixin.qq.com/sns/oauth2/access_token")
            .append("?appid=")
            .append("wx45ccf8958a0a24c7")
            .append("&secret=")
            .append("e9c071f3326663856bc6cf02c2d6b657")
            .append("&code=")
            .append(code)
            .append("&grant_type=authorization_code");
    Log.d("urlurl", loginUrl.toString());

    OkHttpClient okHttpClient = new OkHttpClient();
    final Request request = new Request.Builder()
            .url(loginUrl.toString())
            .get()//默认就是GET请求,可以不写
            .build();
    Call call = okHttpClient.newCall(request);
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.d("fan12", "onFailure: ");
            mProgressDialog.dismiss();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            String responseInfo= response.body().string();
            Log.d("fan12", "onResponse: " +responseInfo);
            String access = null;
            String openId = null;
            try {
                JSONObject jsonObject = new JSONObject(responseInfo);
                access = jsonObject.getString("access_token");
                openId = jsonObject.getString("openid");
            } catch (JSONException e) {
                e.printStackTrace();
            }
            getUserInfo(access, openId);
        }
    });
}

这里我们在请求之前新建一个progressDialog,避免长时间白屏(因为在进行多次网络请求)造成卡死的假象

private void createProgressDialog() {
    mContext=this;
    mProgressDialog=new ProgressDialog(mContext);
    mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);//转盘
    mProgressDialog.setCancelable(false);
    mProgressDialog.setCanceledOnTouchOutside(false);
    mProgressDialog.setTitle("提示");
    mProgressDialog.setMessage("登录中,请稍后");
    mProgressDialog.show();
}

如果请求成功,我们通过JSON解析获取access和token值,再通过getUserInfo(access, openId)方法获取用户信息

private void getUserInfo(String access, String openid) {
    String getUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access + "&openid=" + openid;
    OkHttpClient okHttpClient = new OkHttpClient();
    final Request request = new Request.Builder()
            .url(getUserInfoUrl)
            .get()//默认就是GET请求,可以不写
            .build();
    Call call = okHttpClient.newCall(request);
    call.enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            Log.d("fan12", "onFailure: ");
            mProgressDialog.dismiss();
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            String responseInfo= response.body().string();
            Log.d("fan123", "onResponse: " + responseInfo);
            SharedPreferences.Editor editor= getSharedPreferences("userInfo", MODE_PRIVATE).edit();
            editor.putString("responseInfo", responseInfo);
            editor.commit();
            finish();
            mProgressDialog.dismiss();
        }
    });
}

请求成功时,后台会返回一串用户信息的字符串,我们把字符串塞到SharedPreference缓存中,finish掉这个界面

6.回到MainActivity,重写onResume()。

@Override
protected void onResume() {
    super.onResume();
    SharedPreferences sp= getSharedPreferences("userInfo", MODE_PRIVATE);
    String responseInfo= sp.getString("responseInfo", "");

    if (!responseInfo.isEmpty()){
        try {
            JSONObject jsonObject = new JSONObject(responseInfo);
            nickname = jsonObject.getString("nickname");
            headimgurl = jsonObject.getString("headimgurl");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        tv.setText("昵称:"+ nickname+ "\n"+ "头像:"+ headimgurl);
        SharedPreferences.Editor editor= getSharedPreferences("userInfo", MODE_PRIVATE).edit();
        editor.clear();
        editor.commit();
    }
}

这里我们从缓存中的用户信息字符串中获取有用的信息,根据实际需求完成相应的操作即可。

值得一提的是,完成后续的相应操作后,我们要把该缓存清空,否则每次该界面可见都会自动完成相应的后续操作。

 

至此全部完成,没有demo的博客都是耍流氓,demo附上

友情提示:因为不可描述的原因,本demo已经把APPID和APPSECRET移除,故无法调起微信客户端,主要看流程代码即可!

(2020.6.18记 鉴于很多童鞋因为积分不够无法下载,故本demo的下载积分已设置为0,希望能帮到更多童鞋~~~)

(2020.9.2记 鉴于我设置免费积分下载的资源频繁被自动设置30多分,故本人已经将demo传到码云(类似github)上,有需求的小伙伴可以自行下载)

CSDN下载链接:资源下载

码云(类似github)下载链接:资源下载

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐