1. 程式人生 > >Android授權登入新浪微博獲取使用者個人資訊

Android授權登入新浪微博獲取使用者個人資訊

記得第一次發博文的時候我寫了一篇文章,題為“”,裡面介紹瞭如何使用各官方提供的SDK來實現分享功能。那麼今天我們來講講如何通過新浪微博授權登入獲取使用者資訊,大家都知道,現在很多軟體除了本地註冊登入之外,還增加了第三方登入功能,最常見的是直接授權QQ等軟體來登入應用而無需自行註冊,其原理更多的是通過開放協議OAuth獲取第三方使用者資訊來達到此目的。本篇講的正是基於OAuth認證來獲取新浪微博使用者資訊。

一、準備工作

我們都知道,無論是分享到新浪微博,還是獲取新浪微博的使用者資訊,都離不開一樣東西,那就是新浪微博的APPID,APPID通過繫結我們應用程式的包名和簽名進行識別,可以說它是我們跟新浪微博官方所提供介面進行互動的一個重要令牌,這一點跟QQ、微信介面等訪問原理基本是一樣的。那麼問題來了,APPID到底怎麼得到?答案就是你要到新浪微博開放平臺註冊一個帳號,填寫並建立你的應用。如下圖所示:

點選建立應用後會出現如下圖所示頁面,在這個頁面中你必須要填寫你的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和包名。好了,本篇到此結束了,歡迎有疑問或建議的童鞋熱烈表白,咱們下期見!