Android 一行代码即可将微信登陆集成到项目中

来源:互联网 发布:淘宝卖鞋子的好店平价 编辑:程序博客网 时间:2024/05/19 20:59

现在微信越来越火了,基本上每一个应用都会有一个微信登陆,于是跟同事商量着是不是写一个SDK出来,方便以后开发使用。写出来以后,本着开源的想法,还是分享给大家。本人的第二篇博客,如果哪里写的不好,请轻喷.....

废话不多说,直接进入整体。大家都知道,集成微信的功能,都要从微信开放平台上下载一个名为libammsdk.jar的文件,这个就不用多说了吧,大家上微信开放平台上下载就可以了。我自己封好的jar包链接如下:http://download.csdn.net/detail/q_probably/9714162

,大家只需要把这两个jar包放到自己的项目中,然后在项目的报名下新建一个wxapi的包名,然后在该报名下新建一个WXEntryActivity类,让这个类继承我的jar包中的WX_CallbackActivity类就可以了。要注意的是,这里的wxapi的包,必须建在主包名的下面。(一定要注意,不然不会走微信的回调)。然后在我们的配置文件中增加下面的代码:

<activity android:name=".wxapi.WXEntryActivity"    android:exported="true"/>

重点来了,在做完上述准备工作之后,我们只需要一行代码,就可以集成了,我将自己测试的Demo中的代码贴出来:

protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    textView = (TextView) findViewById(R.id.textview);    button = (Button) findViewById(R.id.button);    button.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View v) {            WeChatLogin.getWXInfo(MainActivity.this, "wxdc1e388c3822c80b", "3baf1193c85774b3fd9d18447d76cab0", new LoginInfoCallback() {                @Override                public void onSuccess(LOGIN login, final String s) {                   MainActivity.this.runOnUiThread(new Runnable() {                       @Override                       public void run() {                           textView.setText(s);                       }                   });                }                @Override                public void onError(LOGIN login, Throwable throwable) {                    textView.setText("错误了");                }            });        }    });}
其实很简单,我的MainActivity的布局文件中只有一个Button和一个Textview,当我点击Button的时候,就会调用WechatLogin这个类中的getWxInfo()方法,这个方法中有四个参数:第一个是 上下文,因为我在MainActivity中,所以我这里传的是MainActivity.this。第二个参数,是我们在微信开放平台注册的app_id了,这个不用多说吧。第三个参数跟第二个差不多,是和app_id对应的app_secret这个也不用多说。第四个参数呢,是我自己写的一个监听,当我们调起微信授权登陆页面点击确定登陆以后,最后会走到这个回调里面,然后我们就可以拿到微信得数据了。当然了,这里面肯定涉及到了网络请求,所以是在子线程中进行的,如果想要更新UI的话,还是需要在主线程中进行的,也就是runOnUiThread()方法了。除此之外,权限也是必不可少的嘛,

<uses-permission android:name="android.permission.INTERNET"/><uses-permission android:name="android.permission.READ_PHONE_STATE"/><uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
下面说一下大家可能遇到的问题,因为Android从6.0开始,权限就需要动态的去配置了,我在写的时候,为了省事,就将gradle文件做了以下的调整,

compileSdkVersion 22
minSdkVersion 16targetSdkVersion 22
compile 'com.android.support:appcompat-v7:22.0.0'
 这里大家可以看得懂吧,我把sdkversion限定在了22,这样就不会出现权限的问题了。如果你的是23,你需要自己去动态的处理一下权限了。

后面有时间的话,我会增加动态权限的申请,暂时就先这样了。


下面的话,我把思路和代码跟大家顺一下,如果你感兴趣的话,可以看一下,其实也没什么,里面稍微复杂的应该就是回调了,相信懂回调的朋友看起来会很简单:


public class WX_CallbackActivity extends Activity implements IWXAPIEventHandler {    private static LoginReqCallback _reqCallbrack;    private static IWXAPI iwxapi;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        iwxapi.handleIntent(getIntent(),this);    }    @Override    public void onReq(BaseReq baseReq) {    }    @Override    public void onResp(BaseResp baseResp) {        int errorCode = baseResp.errCode;        switch (errorCode) {            case BaseResp.ErrCode.ERR_OK:                //用户同意                String code = ((SendAuth.Resp) baseResp).code;                if (_reqCallbrack != null) {                    _reqCallbrack.complete(code);                }                finish();                break;            case BaseResp.ErrCode.ERR_AUTH_DENIED:                //用户拒绝                if (_reqCallbrack != null) {                    _reqCallbrack.denied();                }                break;            case BaseResp.ErrCode.ERR_USER_CANCEL:                //用户取消                if (_reqCallbrack != null) {                    _reqCallbrack.cancel();                }                break;            default:                break;        }    }    /**     * 向微信发送登陆请求     * @param reqCallbrack 请求的回调     * @param app_id 在微信开放平台注册的app id     * */    public static void sendReq(Context context,String app_id, LoginReqCallback reqCallbrack) {        iwxapi = WXAPIFactory.createWXAPI(context,app_id,true);        iwxapi.registerApp(app_id);        if( !iwxapi.isWXAppInstalled()){            Toast.makeText(context, "请先安装微信应用", Toast.LENGTH_SHORT).show();            return;        }        _reqCallbrack = reqCallbrack;        SendAuth.Req req = new SendAuth.Req();        req.scope = "snsapi_userinfo";        req.state = "wechat_sdk_demo_test";        iwxapi.sendReq(req);    }}

这里面就是让大家继承的那个activity的所有代码了,在这里我实现了IWXAPIEventHandler接口,在微信得官方文档上是WXEntryActivity实现的该接口,按照继承的思想,是一样的拉。在这里,除了必须要实现的onReq和onResp方法外,我写了一个sendReq()方法,参数分别是context上下文,app_id,和一个回调接口,该接口中有三个方法,如下所示

public interface LoginReqCallback {    public void complete(String code);    public void denied();    public void cancel();}
其中的三个方法分别对应,用户授权,拒绝和取消。在该类里面,首先我拿到了sendReq()方法传过来的回到接口,并将它赋给我类中的成员变量,这样当用户点击不同的操作的时候,会在onResp方法中,调用接口的不同方法,来将用户进行的操作传递给实现该接口的方法中,如果用户同意,我们就可以拿到code了。


import android.content.Context;import android.util.Log;import android.widget.Toast;import com.llk.wechatlogin.activity.WX_CallbackActivity;import com.llk.wechatlogin.data.WeChatTokenEntity;import com.llk.wechatlogin.llk_enum.LOGIN;import com.llk.wechatlogin.llk_interface.HttpCallbackListener;import com.llk.wechatlogin.llk_interface.LoginInfoCallback;import com.llk.wechatlogin.llk_interface.LoginReqCallback;import com.llk.wechatlogin.utils.HttpUtil;import org.json.JSONException;import org.json.JSONObject;/** * Created by QQY on 2016/12/16 0016. * 微信登陆,调用微信客户端登陆 */public class WeChatLogin {    public WeChatLogin(){}    /**     * 获取微信授权,得到微信用户的信息     *     * */    public static void getWXInfo(final Context context, final String app_id, final String app_secret, final LoginInfoCallback loginInfoCallback) {        WX_CallbackActivity.sendReq(context,app_id, new LoginReqCallback() {            @Override            public void complete(String code) {                Toast.makeText(context,"用户同意",Toast.LENGTH_SHORT).show();                Log.e("---------->","用户同意");                getToken(app_id,app_secret,code,loginInfoCallback);            }            @Override            public void denied() {                Toast.makeText(context,"用户拒绝",Toast.LENGTH_SHORT).show();                loginInfoCallback.onError(LOGIN.WEIXIN,new Throwable("您已拒绝"));            }            @Override            public void cancel() {                Toast.makeText(context,"用户取消",Toast.LENGTH_SHORT).show();                loginInfoCallback.onError(LOGIN.WEIXIN,new Throwable("成功取消"));            }        });    }    /**     * 根据code获取token     * @param code 微信登陆必须的code     * @param loginInfoCallback 获取微信用户信息的回调     * */    private static void getToken(String app_id, String app_secret, String code, final LoginInfoCallback loginInfoCallback) {        final String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" +                app_id + "&secret=" + app_secret + "&code=" + code + "&grant_type=authorization_code";        //发送网络请求        HttpUtil.sendHttpRequest(url, new HttpCallbackListener() {            @Override            public void onFinish(String response) {                try {                    JSONObject jsonObject = new JSONObject(response);                    if (jsonObject.optInt("errcode",-1) == -1) {                        WeChatTokenEntity entity = new WeChatTokenEntity();                        entity.access_token=jsonObject.optString("access_token","");                        entity.openid=jsonObject.optString("openid","");                        //调用获取微信信息的方法                        getInfo(entity,loginInfoCallback);                    }                } catch (JSONException e) {                    e.printStackTrace();                }            }            @Override            public void onErrot(Exception e) {                loginInfoCallback.onError(LOGIN.WEIXIN,new Throwable("请求异常"));            }        });    }    /**     *获取微信用户信息     * @param entity Token相关实体类     * @param loginInfoCallback     回调接口     * */    private static void getInfo(WeChatTokenEntity entity, final LoginInfoCallback loginInfoCallback) {        Log.e("------------>toiken",entity.access_token);        String accessToken = entity.access_token;        String openId = entity.openid;        final String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId;        HttpUtil.sendHttpRequest(url, new HttpCallbackListener() {            @Override            public void onFinish(String response) {                try {                    JSONObject json = new JSONObject(response);                    if (json.optInt("errcode",-1) == -1) {                        if (loginInfoCallback != null) {                            Log.e("------------->",response);                            loginInfoCallback.onSuccess(LOGIN.WEIXIN,response);                        }else {                            if (loginInfoCallback != null) {                                loginInfoCallback.onError(LOGIN.WEIXIN,new Throwable("请求异常"));                            }                        }                    }                } catch (JSONException e) {                    if (loginInfoCallback != null) {                        loginInfoCallback.onError(LOGIN.WEIXIN,new Throwable("请求异常"));                    }                }            }            @Override            public void onErrot(Exception e) {                loginInfoCallback.onError(LOGIN.WEIXIN,new Throwable("请求异常"));            }        });    }}

在上面我们说过,只需要调用WechatLogin中degetWxInfo()方法就可以,这个方法中的参数,大家自己看代码就可以了,我就不多说了。在这个方法的一开始,我们调用了

WX_CallbackActivity.sendReq(context,app_id, new LoginReqCallback()
方法,这里new 出了一个LoginReqCallback()接口,这样就对应上上面所说的了,当用户授权以后,我们实现的complete()方法就可以拿到code了,拿到code以后,我们调用了getToken()方法来获取token。大家可以看到,我们在getWXInfo()方法传进来的LoginInfoCallback接口会一直传到最后面的getInfo()方法中,另外HttpCallBackListener回调接口是我们在向微信请求数据的监听回调,在我们发送网络请求的时候,也就是
 HttpUtil.sendHttpRequest(url, new HttpCallbackListener() 

这一行代码。该接口中两个方法,分别对应请求成功和请求失败,当我们请求成功以后,我们调用了从最上面的getWXInfo()方法中一直传过来的LoginInfoCallback接口中的onSuccess()方法,将我们请求到的数据传出去。这样我们在最开始调用getWXInfo()方法时候new 出来的 LofinInfoCallback接口实现的两个方法中,就可以拿到数据了。

基本的思路就是这样了,我把剩下的代码都给大家贴出来

/** * Created by QQY on 2016/12/17 0017. * 网络请求的回调 */public interface HttpCallbackListener {    void onFinish(String response);    void onErrot(Exception e);}
public interface LoginInfoCallback {    void onSuccess(LOGIN type, String response);    void onError(LOGIN type, Throwable text);}
public enum LOGIN {    WEIXIN,    SINA_WEIBO,    QQ,    PHONE_NUMBER}
public class WeChatTokenEntity {    public String access_token ;                  // 接口调用凭证    public long expires_in;         //接口调用凭证超时时间,单位(秒)    public String refresh_token ;                 // 用户刷新access_token    public String  openid ;                        // 授权用户唯一标识    public String scope ;                         // 用户授权的作用域,使用逗号(,)分隔    public String unionid;         // 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。}

public class HttpUtil {    /**     * 发送一个网络请求的方法     * @param address 要访问的地址     * @param listener 回调接口     * */    public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {        //网络请求为耗时操作,在子线程中运行        new Thread(new Runnable() {            @Override            public void run() {                HttpURLConnection connection = null;                try {                    URL url = new URL(address);                    connection = (HttpURLConnection) url.openConnection();                    connection.setRequestMethod("GET");                    connection.setConnectTimeout(8000);                    connection.setReadTimeout(8000);                    connection.setDoInput(true);                    connection.setDoOutput(true);                    InputStream in = connection.getInputStream();                    BufferedReader reader = new BufferedReader(new InputStreamReader(in));                    StringBuilder response = new StringBuilder();                    String line;                    while ((line = reader.readLine()) != null) {                        response.append(line);                    }                    if (listener != null) {                        //回调onFininsh()方法                        listener.onFinish(response.toString());                    }                } catch (MalformedURLException e) {                    listener.onErrot(e);                } catch (IOException e) {                    listener.onErrot(e);                } finally {                    if (connection != null) {                        //断开连接                        connection.disconnect();                    }                }            }        }).start();    }}

其中,大家看到了,有一个枚举,因为后面我们还要把微博、QQ登陆都封转一下,所以就可以通过枚举来区分到底是哪一种登陆,从而在LoginInfoCallback接口的两个回调方法中,就可以区分不同平台的数据了,就不用每一个登陆方式都写一个接口回调了。但是,每一个平台的登陆,还是要对应一个不同的方法的。


好了,就到这里了,如果大家有什么疑问的话,可以留言问我。我看到的话会尽量帮大家解决。重申一下,本人写的第二篇博客,写的不好的地方,希望大家理解,如果不喜欢实在想喷的话,请轻喷。




1 0