Android应用实现微信登录与分享
2015-08-05 11:57
274 查看
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 |
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_in | access_token接口调用凭证超时时间,单位(秒) |
refresh_token | 用户刷新access_token |
openid | 授权用户唯一标识 |
scope | 用户授权的作用域,使用逗号(,)分隔 |
unionid | 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段。 |
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”}。
以上就是对微信登录以及分享的一些小心得,拿出来和大家分享一下,有什么错误的地方还望多多指教。
相关文章推荐
- 微信红包程序 java
- AKTabBarController:类似微信的第三方库
- 如何获取别人微信文章中的图片
- 微信服务号和订阅号的区别
- 只是一个爱的小程序
- java微信公众平台开发三(多图文素材界面)
- 【微信分享】李滔:搜狐基于Spark的新闻和广告推荐实战
- java微信公众平台开发四(上传素材)
- Android之自定义AlertDialog和PopupWindow实现(仿微信Dialog)
- 微信公众号开发学习
- 微信智能硬件
- Android 高仿微信实时聊天 基于百度云推送
- 高仿微信朋友圈评论popwindow
- 【微信支付】开发遇到的一些问题一些弯路
- 【微信支付】开发遇到的一些问题一些弯路
- 微信JS SDK开发 共享问题小结
- php 判断是否在微信浏览器中打开
- 判断是否在微信浏览器中打开
- 利用Qt来实现一个时钟小程序
- 微信企业号开发:接收消息和事件