您的位置:首页 > 移动开发 > 微信开发

android 同时实现微信分享和微信登录功能

2015-12-01 18:39 1101 查看

    Android应用实现微信登录与分享

    1. 闲话(可直接无视

    项目慢慢的推进,逐渐的做到了微信第三方登录的功能模块了。其实我想说Orz,我等这一天等了好久了,想做个微信验证登录都等了两个多星期咧(其实是我们这边出了点问题),先要申请微信开放平台的帐号,在里面创建一个应用,通过审核之后再交300软妹币,是的,你没有听错,上交300软妹币(听说会成为传说中的认证开发者)才可以获得应用第三方登录的权限,否则只能够分享到盆友圈。中间也是遇到了一些小问题,微信那边的文档写的也不是特别的清楚,还有一些关于微信分享到朋友圈和好友方面的,下面就把问题和解决方法给大家呈上来。

    2. 概述

    在之前只有微信分享的功能,到后来慢慢的发展出了微信登录的模块,分享的功能比较好做,按照微信给的文档构造好需要传递的信息,再调用微信分享接口,即可跳转至微信的页面进行分享了。登录的功能比分享稍微复杂,需要和微信服务器进行至少三次的数据交换(第一步获取code, 第二步通过code获取access_token以及其他的凭证, 第三步再通过access_token来调用微信的接口)。

    3. 正文

    3.1 appId申请

    如需帐号申请,请跟随链接移步,注册一个帐号后在管理中心—>移动应用找到创建移动应用。 



    进入后在里面填写各种需要的信息,要注意的是这里的应用审核通过后,应用名称不允许修改,所以各位给自己心爱的应用选一个好听的名字咯(貌似都被注册光了)。 



    下一步后,会看到要填写应用官网,应用下载地址,应用签名,应用包名等资料。



    应用包名就是项目文件AndroidManifest.xml文件里面的
package="com.ldx.microtravelnotes"
这个东西。获取应用签名需要先在手机上面安装好应用的release签名版app,再安装一个微信提供的签名生成工具,这个工具安装在手机上后,输入app的应用包名,即可生成应用签名,填写后提交给微信,等待审核的通过。 



    通过审核之后,会得到微信分配给申请app的appId和appSecret,以及一些能够免费使用的权限(例如分享至微信朋友圈等),如果需要微信验证登录,则要上交300软妹币,成为传说中的验证开发者才可以使用。

    在开始做登录和分享之前,还需要下载微信提供的SDK开发包,将这个包导入到项目的libs文件夹里面,再add as library就可以正常的使用了。还需要注意的一点就是要在AndroidManifest.xml文件里面加入如下的权限:
<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    3.2 微信分享

    既然微信登录那边还需要再次验证开发者,我们就先来说说微信分享的实现步骤吧,其实小达在做分享的时候还是挺顺利的(相对于登录来说)。实现微信分享功能分为以下几个步骤:

第一步

利用appId(注册后会得到)将app注册到微信

public static IWXAPI api;
private void registerToWx() {
api = WXAPIFactory.createWXAPI(this, AppConstant.APP_ID, false);
api.registerApp(AppConstant.APP_ID);
}


    上面的AppConstant.APP_ID即字符串常量,也就是申请得到的appId,将这些代码放在应用启动时候的Activity或者Application类里面,onCreate()方法调用的时候,顺带的调用registerToWx(),小达这边是有一个在app启动时候绑定的一个Application类,放在了onCreate()里面,贴上一小部分代码,
AndroidManifest.xml
<application
android:name=".global.MTNApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">

public class MTNApplication extends CommonApplication {
public static IWXAPI api; private void registerToWx() { api = WXAPIFactory.createWXAPI(this, AppConstant.APP_ID, false); api.registerApp(AppConstant.APP_ID); }

@Override
public void onCreate() {
super.onCreate();
registerToWx();
}
}


    当然也可以写在Activity的onCreate()方法里面,个人觉得放在欢迎页面里面也不错哦。

第二步

在需要分享的位置编写如下代码

private void shareArticleToWx(final int flag) {
if (!MTNApplication.api.isWXAppInstalled()) {
AppData.showToast("您还未安装微信客户端");
return;
}
WXWebpageObject webPage = new WXWebpageObject();
webPage.webpageUrl = ArticleApi.getDisplayArticleUrl(mArticleId, mArticleTemp);
WXMediaMessage msg = new WXMediaMessage(webPage);
msg.title = "笔记";
msg.description = mArticleTitle;
msg.setThumbImage(loadedImage);
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.transaction = String.valueOf(System.currentTimeMillis());
req.message = msg;
req.scene = flag == 0 ? SendMessageToWX.Req.WXSceneSession : SendMessageToWX.Req.WXSceneTimeline;
MTNApplication.api.sendReq(req);
}


    上面的代码也就是按照微信给的结构,构造了一个微信分享信息,在这个微信分享信息中,可以设置点击跳转的url,这条分享信息的标题等,其中有一个flag参数,这个参数是用来确定分享给朋友圈(flag == 1)还是分享给好友(flag == 0)的。最后通过一个已经注册过的IWXAPI类的实例来发送出分享请求。

第三步

创建一个供微信调用的Activity

    创建这个Activity的位置不能随便放,需要在包名下面创建一个新的文件夹wxapi,再在这个文件夹下创建WXEntryActivity.java文件。项目的结构如图,一定不要放错了,因为微信可能无法调用: 


 

创建完成之后还需要在AndroidManifest.xml文件中对WXEntryActivity进行设置:
android:exported="true"


    创建的WXEntryActivity.java继承自Activity,实现IWXAPIEventHandler接口,该接口即处理微信和app通信的不同event:
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {

//这两个参数在文档中没有找到,可能是瞎了,,,自己在代码里面找了会才找到,这两个常量代表了微信返回的消息类型,是对登录的处理还是对分享的处理,登录会在后面介绍到
private static final int RETURN_MSG_TYPE_LOGIN = 1;
private static final int RETURN_MSG_TYPE_SHARE = 2;

private static final String TAG = "WXEntryActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wxentry);

//如果没回调onResp,八成是这句没有写
MTNApplication.api.handleIntent(getIntent(), this);
}

//微信发送消息给app,app接受并处理的回调函数
@Override
public void onReq(BaseReq baseReq) {

}

//app发送消息给微信,微信返回的消息回调函数,根据不同的返回码来判断操作是否成功
@Override
public void onResp(BaseResp resp) {
switch (resp.errCode) {
case BaseResp.ErrCode.ERR_AUTH_DENIED:
case BaseResp.ErrCode.ERR_USER_CANCEL:
showToast("微信失败");
break;

case BaseResp.ErrCode.ERR_OK:
switch (resp.getType()) {
case RETURN_MSG_TYPE_SHARE:
showToast("微信分享成功");
finish();
break;
}
break;
}
}
}


    微信分享到这里就做完了,需要上面的三个步骤即可实现,需要注意的是第二步构造分享信息,以及第三步在设置微信回调页面的时候。

    3.3 微信登录

    在上面微信分享的基础上,再来做微信登录的功能。微信登录前的准备工作和微信分享一样,先将app注册到微信端,app也是通过WXEntryActivity来处理返回的消息。分下面几个步骤进行:

第一步

注册app到微信

    这一步的工作和前面是一样的,如果这个已经完成了,直接跳到下一步。

第二步

发送code请求到微信

    在需要微信登录的地方添加上一个按钮,用来点击后调用微信登录页面。之前开始不知道微信验证登录的界面是什么情况,还以为要自己写好,其实是微信那边已经写好了的界面(并非我们的WXEntryActivity),我们只需要在自己的app这边发送请求就会自动跳转到微信的页面。发送code请求的代码如下:

if (!MTNApplication.api.isWXAppInstalled()) {
AppData.showToast("您还未安装微信客户端");
return;
}
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "diandi_wx_login";
MTNApplication.api.sendReq(req);


    上面构造并通过注册好了的api发送了一个请求,请求中scope是固定的形式,用来请求微信验证登录,官方解释:
授权作用域(scope)代表用户授权给第三方的接口权限,第三方应用需要向微信开放平台申请使用相应scope的权限后,使用文档所述方式让用户进行授权,经过用户授权,获取到相应access_token后方可对接口进行调用。如获取用户个人信息则填写snsapi_userinfo


    参数state是可以自定义的,官方解释:
用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验


    效果大概是这样的: 

    这个页面就是WXEntryActivity,上面加了一个按钮,用来点击之后执行上面的那一段代码, 



    点击之后,向微信发送了请求,会自动跳转到微信的界面,也就是下面的这张图片,这个界面是微信已经写好了的,我们就不用操心了。 



    小达实验了一下,先开始将这个微信验证登录的按钮放在了WXEntryActivity.java中,点击了微信界面登录之后会返回到WXEntryActivity界面中去,后来又想了下,如果不放在WXEnrtyActivity中会怎么样,于是另外写了一个Activity专门用来登录,结果是从微信确认登录之后又返回了WXEnrtyActivity,所以个人认为还是直接放在WXEnrtyActivity里面比较好。反正去了总是要回到这个界面进行处理的。

第三步

利用微信返回的code去请求access_token

    第二步拿到的code还不算完呢,这个code的声明周期只有五分钟,而且每个code只可以用一次,切记请勿重复使用,否则就会出现
{"errcode":40029,"errmsg":"invalid code"}
这种问题了。也是构造一个请求发送给微信,可以直接接在获取code之后,立马把这个请求发送出去,因为是属于微信登录的中间操作。通过code请求access_token的接口如下:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

参数说明

参数必须说明
appid应用唯一标识,在微信开放平台提交应用审核通过后获得
secret应用密钥AppSecret,在微信开放平台提交应用审核通过后获得
code填写第一步获取的code参数
grant_type填authorization_code
    问我在那里获取微信返回的code?肯定是在WXEntryActivity里面咯,前面提到了这个activity是专门用来给微信调用的,附上WXEnrtyActivity.java里面的代码:
public class WXEntryActivity extends Activity implements IWXAPIEventHandler {

private Button checkLogin;

private static final int RETURN_MSG_TYPE_LOGIN = 1;
private static final int RETURN_MSG_TYPE_SHARE = 2;

private static final String TAG = "WXEntryActivity";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_wxentry);
checkLogin = (Button) findViewById(R.id.check_login);
checkLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!MTNApplication.api.isWXAppInstalled()) {
AppData.showToast("您还未安装微信客户端");
return;
}
final SendAuth.Req req = new SendAuth.Req();
req.scope = "snsapi_userinfo";
req.state = "diandi_wx_login";
MTNApplication.api.sendReq(req);
}
});

//如果没回调onResp,八成是这句没有写
MTNApplication.api.handleIntent(getIntent(), this);
}

//微信直接发送给app的消息处理回调
@Override
public void onReq(BaseReq baseReq) {

}

//app发送消息给微信,处理返回消息的回调
@Override
public void onResp(BaseResp resp) {
switch (resp.errCode) {

case BaseResp.ErrCode.ERR_AUTH_DENIED:
case BaseResp.ErrCode.ERR_USER_CANCEL:
if (RETURN_MSG_TYPE_SHARE == resp.getType()) AppData.showToast("分享失败");
else AppData.showToast("登录失败");
break;
case BaseResp.ErrCode.ERR_OK:
switch (resp.getType()) {
case RETURN_MSG_TYPE_LOGIN:
//拿到了微信返回的code,立马再去请求access_token
String code = ((SendAuth.Resp) resp).code;

//就在这个地方,用网络库什么的或者自己封的网络api,发请求去咯,注意是get请求

break;

case RETURN_MSG_TYPE_SHARE:
AppData.showToast("微信分享成功");
finish();
break;
}
break;
}
}
}


    请求返回回来的参数形式如下:
{
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid":"o6_bmasdasdsad6_2sgVt7hMZOPfL"
}


官方给出的参数列表:
参数说明
access_token微信接口调用凭证
expires_inaccess_token接口调用凭证超时时间,单位(秒)
refresh_token用户刷新access_token
openid授权用户唯一标识
scope用户授权的作用域,使用逗号(,)分隔
unionid只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。
    微信验证登录到这里就差不多了,验证的主要目的就是拿到微信给的这个access_token,用来调用微信的各种接口,可以获取用户的基本信息等等。下面就来说说在做的过程中遇到了那些坑的地方(其实就是在自己坑自己Orz)。

    4. 填坑环节

    在做微信登录模块的时候,遇到了一些小的问题如下,现在给出一些小的建议:
请求登录,没有回调,可能是由于WXEntryActivity的onCreate()方法里面没有处理intent。 
MTNApplication.api.handleIntent(getIntent(), this);

获取到code之后,一个code的寿命只有5分钟,而且只能用一次,如果重复利用就会出现{“errcode”:40029,”errmsg”:”invalid code”}的情况。
应用签名:XXXXX 包名:com.X.X这两个一定不能写反咯,写反就死翘翘了,写反了也会{“errcode”:40029,”errmsg”:”invalid code”}。
拿到code后,如果需要通过自己的服务器向微信发送获取access_token的请求,也要注意code只能用一次(当然不算你给自己服务器的那次),如果你们后台还承担着微信公众号的事务,则要小心不要将微信公众号的appid和app_secret与微信开放平台上的弄混了,否则也会返回{“errcode”:40029,”errmsg”:”invalid code”}。

    以上就是对微信登录以及分享的一些小心得,拿出来和大家分享一下,有什么错误的地方还望多多指教。

上一篇下一篇

发表评论

查看评论

1楼u0130662922015-11-19
10:33

我想问一下,那我要弄个按钮退出登录的话这个怎么写?

更多评论(1)



回顶部


移动版|桌面版

©1999-2012, CSDN.NET, All Rights Reserved
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息