转载请注明出处:http://blog.csdn.net/u010214991/article/details/49149793
记得第一次发博文的时候我写了一篇文章,题为“ Android使用官方API分享内容到QQ和微信(非第三方集成)”,里面介绍了如何使用各官方提供的SDK来实现分享功能。那么今天我们来讲讲如何通过新浪微博授权登录获取用户信息,大家都知道,现在很多软件除了本地注册登录之外,还增加了第三方登录功能,最常见的是直接授权QQ等软件来登录应用而无需自行注册,其原理更多的是通过开放协议OAuth获取第三方用户信息来达到此目的。本篇讲的正是基于OAuth认证来获取新浪微博用户信息。
一、准备工作
我们都知道,无论是分享到新浪微博,还是获取新浪微博的用户信息,都离不开一样东西,那就是新浪微博的APPID,APPID通过绑定我们应用程序的包名和签名进行识别,可以说它是我们跟新浪微博官方所提供接口进行交互的一个重要令牌,这一点跟QQ、微信接口等访问原理基本是一样的。那么问题来了,APPID到底怎么得到?答案就是你要到新浪微博开放平台http://open.weibo.com/注册一个帐号,填写并创建你的应用。如下图所示:
点击创建应用后会出现如下图所示页面,在这个页面中你必须要填写你的Android包名和Android签名,包名就是你应用程序AndroidManifest.xml文件中的package中的字符串,比如你新建了一个名称为“test”的项目,那么你的包名应该是com.example.test了。至于Android签名,你可以在该开放平台下载签名工具apk装到手机,然后打开该apk填写程序包名获取签名,也可以直接在开发工具eclispe中点击Window->Preferences->Android->Build查看,如下图所示,至于其它必要的填写信息,你自己去完善就可以了:
将所有信息填写完善后我们点击提交审核,注意,只有审核通过的应用才能调用他们提供的API。
二、工程准备
新建一个工程,包名要跟你上面填写的包名一致。新建完成后下载新浪微博SDK,下载完成后解压,将libs目录下的文件全部拷贝到你的工程libs目录下,将weiboSDKCore_3.1.2.jar包也拷贝到libs目录下,找到AccessTokenKeeper.java、UsersAPI.java、AbsOpenAPI.java文件并拷贝到你的包中,我把我的工程目录图贴出来,后面我会把整个示例源码放上来。
注意上面common中的SinaUserInfo.java是我自己建的,只是用来方便存和取用户信息而已。还有,别忘了在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.INTERNET"/>
三、动手写代码
几经波折,下面直接进入正题,贴代码
1、SinaUserInfo.java(前面说过,这个类非常简单,只是方便存取用户信息而已)
public class SinaUserInfo { private String uid;//用户ID private String name;//用户昵称 private String avatarHd;//用户头像url public SinaUserInfo() { super(); // TODO Auto-generated constructor stub } public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAvatarHd() { return avatarHd; } public void setAvatarHd(String avatarHd) { this.avatarHd = avatarHd; } }
2.MainActivity.java(这个是核心,先分步讲解,后面直接贴出完整代码)
在这个java文件中,授权登录并获取信息的具体流程是这样子的,首先通过我们之前审核通过的APPID来实例化IWeiboShareAPI:
weiboShareAPI = WeiboShareSDK.createWeiboAPI(context, SWB_APP_ID);
然后获取OAuth协议信息,并设置授权回调接口:
authInfo = new AuthInfo(context, SWB_APP_ID, SWB_REDIRECT_URL, SWB_SCOPE); ssoHandler = new SsoHandler(MainActivity.this, authInfo); ssoHandler.authorize(new AuthListener());
在授权回调接口当中,我们通过利用onComplete方法中的参数values来解析访问令牌accessToken,并通过AccessTokenKeeper这个类将accessToken保存,这样我们就完成了授权,紧接着我们开了一个线程,实例化UsersAPI并调用show()方法,这个方法有两个参数,由于我们是通过accessToken.getUid()也就是用户ID来获取用户信息的,所以这里的参数类型是long而不是String,如果你不转成long的话,他实际上是通过用户名来访问用户信息的,那么就会出现“com.weibo.sdk.android.WeiboException:
{"error":"User does not exists!","error_code":20003,"request":"/2/users/show.json"}”,也就是用户不存在的现象。
@Override public void onComplete(Bundle values) { // TODO Auto-generated method stub accessToken = Oauth2AccessToken.parseAccessToken(values); // 从Bundle中解析Token String phoneNum = accessToken.getPhoneNum();// 从这里获取用户输入的 电话号码信息 if (accessToken.isSessionValid()) { AccessTokenKeeper.writeAccessToken(MainActivity.this, accessToken); // 保存Token Toast.makeText(context, "授权成功", Toast.LENGTH_SHORT) .show(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub UsersAPI usersAPI = new UsersAPI(context, SWB_APP_ID, accessToken); usersAPI.show(Long.valueOf(accessToken.getUid()), new SinaRequestListener()); } }).start(); }else{ // 以下几种情况,您会收到 Code: // 1. 当您未在平台上注册的应用程序的包名与签名时; // 2. 当您注册的应用程序包名与签名不正确时; // 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。 String code = values.getString("code"); String message = "授权失败"; if (!TextUtils.isEmpty(code)) { message = message + "\nObtained the code: " + code;}Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } }
上面show方法中的第二个参数是新浪微博请求监听回调接口,我们可以在这个接口的onComplete方法中的参数respon中得到返回的json数据,
通过解析json数据就可以得到我们想要的新浪微博用户信息啦,到此整个流程也就结束了,以下是请求接口的部分代码。
public class SinaRequestListener implements RequestListener{ //新浪微博请求接口 @Override public void onComplete(String response) { // TODO Auto-generated method stub try { JSONObject jsonObject = new JSONObject(response); String idStr = jsonObject.getString("idstr");// 唯一标识符(uid) String name = jsonObject.getString("name");// 姓名 String avatarHd = jsonObject.getString("avatar_hd");// 头像
要想授权回调有效,别忘了在Activity中添加如下代码:
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if(ssoHandler != null){ ssoHandler.authorizeCallBack(requestCode, resultCode, data); } }
好了,下面直接贴出完整的代码:
import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.gdruichao.bbt.common.SinaUserInfo; import com.sina.weibo.sdk.api.share.IWeiboShareAPI; import com.sina.weibo.sdk.api.share.WeiboShareSDK; import com.sina.weibo.sdk.auth.AuthInfo; import com.sina.weibo.sdk.auth.Oauth2AccessToken; import com.sina.weibo.sdk.auth.WeiboAuthListener; import com.sina.weibo.sdk.auth.sso.SsoHandler; import com.sina.weibo.sdk.exception.WeiboException; import com.sina.weibo.sdk.net.RequestListener; public class MainActivity extends Activity implements OnClickListener{ private Context context; private IWeiboShareAPI weiboShareAPI; private final static String SWB_APP_ID = "3802299039"; private Button login; private AuthInfo authInfo; private SsoHandler ssoHandler; private Oauth2AccessToken accessToken; private TextView userinfo_tv; private SinaUserInfo userInfo; public static final String SWB_REDIRECT_URL = "https://api.weibo.com/oauth2/default.html";//新浪微博回调页面 public static final String SWB_SCOPE = "email,direct_messages_read,direct_messages_write," + "friendships_groups_read,friendships_groups_write,statuses_to_me_read," + "follow_app_official_microblog," + "invitation_write"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); context = this; weiboShareAPI = WeiboShareSDK.createWeiboAPI(context, SWB_APP_ID); userinfo_tv = (TextView) findViewById(R.id.userinfo_tv); login = (Button) findViewById(R.id.login); login.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub authInfo = new AuthInfo(context, SWB_APP_ID, SWB_REDIRECT_URL, SWB_SCOPE); ssoHandler = new SsoHandler(MainActivity.this, authInfo); ssoHandler.authorize(new AuthListener()); } public class AuthListener implements WeiboAuthListener{ @Override public void onCancel() { // TODO Auto-generated method stub Toast.makeText(context, "授权取消", Toast.LENGTH_LONG).show(); } @Override public void onComplete(Bundle values) { // TODO Auto-generated method stub accessToken = Oauth2AccessToken.parseAccessToken(values); // 从Bundle中解析Token String phoneNum = accessToken.getPhoneNum();// 从这里获取用户输入的 电话号码信息 if (accessToken.isSessionValid()) { AccessTokenKeeper.writeAccessToken(MainActivity.this, accessToken); // 保存Token Toast.makeText(context, "授权成功", Toast.LENGTH_SHORT) .show(); new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub UsersAPI usersAPI = new UsersAPI(context, SWB_APP_ID, accessToken); usersAPI.show(Long.valueOf(accessToken.getUid()), new SinaRequestListener()); } }).start(); } }else{ // 以下几种情况,您会收到 // 1. 当您未在平台上注册的应用程序的包名与签名时; // 2. 当您注册的应用程序包名与签名不正确时; // 3. 当您在平台上注册的包名和签名与您当前测试的应用的包名和签名不匹配时。 String code = values.getString("code"); String message = "授权失败"; if (!TextUtils.isEmpty(code)) { message = message + "\nObtained the code: " + code; } Toast.makeText(context, message, Toast.LENGTH_LONG).show(); } @Override public void onWeiboException(WeiboException e) {// TODO Auto-generated method stub Toast.makeText(context, "Auth exception : " + e.getMessage(),Toast.LENGTH_LONG).show(); } } public Handler handler = new Handler(){ public void handleMessage(Message msg) { if(msg.what == 1){ userinfo_tv.setText("用户id:"+userInfo.getUid()+"\n"+"用户名:"+userInfo.getName()+"\n"+"用户头像url:"+userInfo.getAvatarHd()); } }; }; public class SinaRequestListener implements RequestListener{ //新浪微博请求接口 @Override public void onComplete(String response) {// TODO Auto-generated method stub try { JSONObject jsonObject = new JSONObject(response); String idStr = jsonObject.getString("idstr");// 唯一标识符(uid) String name = jsonObject.getString("name");// 姓名 String avatarHd = jsonObject.getString("avatar_hd");// 头像 userInfo = new SinaUserInfo(); userInfo.setUid(idStr); userInfo.setName(name); userInfo.setAvatarHd(avatarHd); Message message = Message.obtain(); message.what = 1; handler.sendMessage(message); } catch (JSONException e) {// TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onWeiboException(WeiboException e) {// TODO Auto-generated method stubToast.makeText(context, "Auth exception : " + e.getMessage(),Toast.LENGTH_LONG).show(); Log.i("mylog", "Auth exception : " + e.getMessage()); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {// TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); if(ssoHandler != null){ ssoHandler.authorizeCallBack(requestCode, resultCode, data); } } }
四、activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <Button android:id="@+id/login" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="新浪微博登录获取用户信息" /> <TextView android:id="@+id/userinfo_tv" android:layout_width="match_parent" android:layout_height="match_parent" android:textSize="20dp" android:text="" /> </LinearLayout>
五、AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gdruichao.bbt" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="18" /> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.gdruichao.bbt.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- 新浪微博网页授权登录相关配置 --> <activity android:name="com.sina.weibo.sdk.component.WeiboSdkBrowser" android:configChanges="keyboardHidden|orientation" android:exported="false" android:windowSoftInputMode="adjustResize" > </activity> </application> </manifest>
其实也就加了个网络访问权限和新浪微博网页授权登录配置,防止用户没有新浪微博客户端的情况,如果你已经有新浪微博客户端了,可以不加这个网页授权这个配置,不过为了安全起见你还是加吧哈哈。
最后附上源码下载,Android授权第三方登录获取新浪微博用户信息,注意运行测试的时候要改成你自己的APPID和包名。好了,本篇到此结束了,欢迎有疑问或建议的童鞋热烈表白,咱们下期见!