作過新浪微博第三方登陸的朋友都清楚,他們的官方文檔寫的真心糟糕,添加新應用也很麻煩。我也是一邊看文檔,一邊看demo,摸爬滾打才實現第三方登陸的功能。今天和你們分享一個完整的開發流程,從申請開發者帳號,到集成SDK,到代碼編寫。ps:我所使用的是SDK版本是weiboSDKCore_3.1.2java
第一步:申請開發者帳號,官網http://open.weibo.com android
登陸或註冊新浪微博帳號web
而後建立新應用,建立的時候要注意幾點:express
拿到APPID,個人應用->應用信息->基本信息apache
個人應用->應用信息->基本信息app
包名是指AndroidManifest.xml文件裏面package屬性對應的內容less
簽名必須經過官方提供的MD5簽名工具生成,可百度搜索,我這裏也有連接http://pan.baidu.com/s/1qWlD1LE ide
大概長這個樣兒,對照着簽名填寫到官網的Android簽名那欄就好。函數
點擊個人應用->應用信息->高級信息,填寫回調地址,這個是受權成功後調用的地址,後續再代碼編寫的時候會用到,必須保持一致,可使用http://www.sina.com工具
添加測試帳號,
第二步:集成SDK,
到官網下載最新的SDK文件,
或者用我這裏提供的
http://pan.baidu.com/s/1sjFxEbz
把目錄weibo_android_sdk-master\libs下的6個文件夾拷貝到工程的libs文件中,
和weibo_android_sdk-master目錄下的weiboSDKCore_3.1.2.jar複製到libs文件中
而後再選中weiboSDKCore_3.1.2.jar右鍵Build Path->Add to Build Path
至此集成已經成功一半
修改AndroidManifest.xml文件,添加如下代碼
<activity android:name="com.sina.weibo.sdk.component.WeiboSdkBrowser" android:configChanges="keyboardHidden|orientation" android:exported="false" android:windowSoftInputMode="adjustResize" > </activity> <service android:name="com.sina.weibo.sdk.net.DownloadService" android:exported="false" > </service>
添加權限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
這樣SDK算是集成完畢了
第三步:代碼編寫
我主要是參考官方demo來寫的,關鍵是三個java文件
LoginActivity,集中調用新浪微博API的類,實現了第三方受權,登陸,退出,登陸時顯示用戶信息的功能
package com.example.thirdpartyloginafc; import java.text.SimpleDateFormat; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.text.TextUtils; import android.text.method.ScrollingMovementMethod; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; 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; public class LoginActivity extends Activity implements OnClickListener { private AuthInfo mAuthInfo; private Button btnweibo; private Button btnlogout; private TextView tv; private String nickname=""; /** 封裝了 "access_token","expires_in","refresh_token",並提供了他們的管理功能 */ private Oauth2AccessToken mAccessToken; /** 注意:SsoHandler 僅當 SDK 支持 SSO 時有效 */ private SsoHandler mSsoHandler; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initweibologin(); initViews(); initEvents(); initData(); } private void initData() { // TODO Auto-generated method stub // 從 SharedPreferences 中讀取上次已保存好 AccessToken 等信息, // 第一次啓動本應用,AccessToken 不可用 mAccessToken = AccessTokenKeeper.readAccessToken(this); if (mAccessToken.isSessionValid()) { updateTokenView(true); } } private void initViews() { btnweibo = (Button) findViewById(R.id.btn_weibo_login); btnlogout = (Button) findViewById(R.id.btnlogout); tv = (TextView) findViewById(R.id.content); // 獲取 Token View,並讓提示 View 的內容可滾動(小屏幕可能顯示不全) tv.setMovementMethod(new ScrollingMovementMethod()); } private void initEvents() { btnweibo.setOnClickListener(this); btnlogout.setOnClickListener(this); } /** * 進行微博受權初始化操做 */ private void initweibologin() { // TODO Auto-generated method stub // 初始化受權類對象,將應用的信息保存 mAuthInfo = new AuthInfo(this, Constants.APP_KEY, Constants.REDIRECT_URL, Constants.SCOPE); mSsoHandler = new SsoHandler(LoginActivity.this, mAuthInfo); } /** * 當 SSO 受權 Activity 退出時,該函數被調用。 * * @see {@link Activity#onActivityResult} */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // SSO 受權回調 // 重要:發起 SSO 登錄的 Activity 必須重寫 onActivityResults if (mSsoHandler != null) { mSsoHandler.authorizeCallBack(requestCode, resultCode, data); } } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btn_weibo_login:// SSO 受權, ALL IN ONE // 若是手機安裝了微博客戶端則使用客戶端受權,沒有則進行網頁受權 mSsoHandler.authorize(new AuthListener()); break; case R.id.btnlogout:// 用戶登出 nickname = ""; AccessTokenKeeper.clear(getApplicationContext()); mAccessToken = new Oauth2AccessToken(); updateTokenView(false); break; default: break; } } /** * 微博認證受權回調類。 1. SSO 受權時,須要在 {@link #onActivityResult} 中調用 * {@link SsoHandler#authorizeCallBack} 後, 該回調纔會被執行。 2. 非 SSO * 受權時,當受權結束後,該回調就會被執行。 當受權成功後,請保存該 access_token、expires_in、uid 等信息到 * SharedPreferences 中。 */ class AuthListener implements WeiboAuthListener { @Override public void onCancel() { // TODO Auto-generated method stub Toast.makeText(LoginActivity.this, "取消受權", Toast.LENGTH_LONG) .show(); } @Override public void onComplete(Bundle values) { // TODO Auto-generated method stub // 從 Bundle 中解析 Token mAccessToken = Oauth2AccessToken.parseAccessToken(values); if (mAccessToken.isSessionValid()) { nickname = "用戶名:" + String.valueOf(values .get("com.sina.weibo.intent.extra.NICK_NAME")); // 顯示 Token updateTokenView(false); // 保存 Token 到 SharedPreferences AccessTokenKeeper.writeAccessToken(LoginActivity.this, mAccessToken); Toast.makeText(LoginActivity.this, "受權成功", Toast.LENGTH_SHORT) .show(); // Toast.makeText( // LoginActivity.this, // "頭像地址:" // + String.valueOf(values // .get("com.sina.weibo.intent.extra.USER_ICON")), // Toast.LENGTH_LONG).show(); Toast.makeText(LoginActivity.this, nickname, Toast.LENGTH_LONG) .show(); } else { // 如下幾種狀況,您會收到 Code: // 1. 當您未在平臺上註冊的應用程序的包名與簽名時; // 2. 當您註冊的應用程序包名與簽名不正確時; // 3. 當您在平臺上註冊的包名和簽名與您當前測試的應用的包名和簽名不匹配時。 String code = values.getString("code"); String message = "受權失敗"; if (!TextUtils.isEmpty(code)) { message = message + "\nObtained the code: " + code; } Toast.makeText(LoginActivity.this, message, Toast.LENGTH_LONG) .show(); } } @Override public void onWeiboException(WeiboException e) { // TODO Auto-generated method stub Toast.makeText(LoginActivity.this, "Auth exception : " + e.getMessage(), Toast.LENGTH_LONG) .show(); } } /** * 顯示當前 Token 信息。 * * @param hasExisted * 配置文件中是否已存在 token 信息而且合法 */ private void updateTokenView(boolean hasExisted) { String date = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss") .format(new java.util.Date(mAccessToken.getExpiresTime())); String format = getString(R.string.weibosdk_demo_token_to_string_format_1); tv.setText(String.format(format, mAccessToken.getToken(), date)); String message = String.format(format, mAccessToken.getToken(), date); if (hasExisted) { message = getString(R.string.weibosdk_demo_token_has_existed) + "\n" + message; } message += "\n" + nickname; tv.setText(message); } }
package com.example.thirdpartyloginafc; /* * Copyright (C) 2010-2013 The SINA WEIBO Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import com.sina.weibo.sdk.auth.Oauth2AccessToken; /** * 該類定義了微博受權時所須要的參數。 * * @author SINA * @since 2013-10-07 */ public class AccessTokenKeeper { private static final String PREFERENCES_NAME = "com_weibo_sdk_android"; private static final String KEY_UID = "uid"; private static final String KEY_ACCESS_TOKEN = "access_token"; private static final String KEY_EXPIRES_IN = "expires_in"; private static final String KEY_REFRESH_TOKEN = "refresh_token"; /** * 保存 Token 對象到 SharedPreferences。 * * @param context * 應用程序上下文環境 * @param token * Token 對象 */ public static void writeAccessToken(Context context, Oauth2AccessToken token) { if (null == context || null == token) { return; } SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); Editor editor = pref.edit(); editor.putString(KEY_UID, token.getUid()); editor.putString(KEY_ACCESS_TOKEN, token.getToken()); editor.putString(KEY_REFRESH_TOKEN, token.getRefreshToken()); editor.putLong(KEY_EXPIRES_IN, token.getExpiresTime()); editor.commit(); } /** * 從 SharedPreferences 讀取 Token 信息。 * * @param context * 應用程序上下文環境 * * @return 返回 Token 對象 */ public static Oauth2AccessToken readAccessToken(Context context) { if (null == context) { return null; } Oauth2AccessToken token = new Oauth2AccessToken(); SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); token.setUid(pref.getString(KEY_UID, "")); token.setToken(pref.getString(KEY_ACCESS_TOKEN, "")); token.setRefreshToken(pref.getString(KEY_REFRESH_TOKEN, "")); token.setExpiresTime(pref.getLong(KEY_EXPIRES_IN, 0)); return token; } /** * 清空 SharedPreferences 中 Token信息。 * * @param context * 應用程序上下文環境 */ public static void clear(Context context) { if (null == context) { return; } SharedPreferences pref = context.getSharedPreferences(PREFERENCES_NAME, Context.MODE_APPEND); Editor editor = pref.edit(); editor.clear(); editor.commit(); } }
package com.example.thirdpartyloginafc; public class Constants { public static final String APP_KEY = "本身的id"; public static final String REDIRECT_URL = "與網頁對應的回調地址; public static final String SCOPE = "email,direct_messages_read,direct_messages_write," + "friendships_groups_read,friendships_groups_write,statuses_to_me_read," + "follow_app_official_microblog," + "invitation_write"; }
運行結果
受權成功
官方開放了三種登陸方式,第一種是經過客戶端登陸,第二種是經過web登陸,第三種是先嚐試經過客戶端登陸,若是沒有安裝客戶端,就經過web登陸,這裏使用的是第三種方式
本例子的代碼:http://pan.baidu.com/s/1nttlgt7
導入工程以後,記得修改Constants裏面的APP_KEY和REDIRECT_URL,有問題歡迎交流!!