Android:SNS客戶端開發一:OAuth認證方法 – Android移動開發技術文章_手機開發 Android移動開發教學課程

 

編寫微博客戶端,最重要的就是用戶授權方法。現在主流SNS社區開放API後,基本都采用OAuth認證進行授權。本文主要記錄新浪微博1.0a版本的OAuth認證。但是隨著2.0版本的逐漸普及,會在今後的加入2.0版本的方法。

 

     有關OAuth認證的理論及相應流程在這裡不做過多追述,各大網站上都已經寫的十分清晰,這裡主要寫下我自己的實現方法。對於OAuth認證,這裡采用signpost-oauth開源項目。

 

     首先編寫一個類,用於存儲認證過程中需要用到基本信息。

 

Java代碼 

public class SinaConstant {// 新浪OAuth輔助信息類  

 

    // 所分配的APP_KEY  

    public static final String CONSUMER_KEY = "";  

    // 所分配的APP_SECRET  

    public static final String CONSUMER_SECRET = "";  

    // 用於獲取未授權的request token  

    public static final String REQUEST_URL = "https://api.t.sina.com.cn/oauth/request_token";  

    // 用於獲取access token  

    public static final String ACCESS_URL = "https://api.t.sina.com.cn/oauth/access_token";  

    // 用於對未授權的request token進行授權  

    public static final String AUTHORIZE_URL = "https://api.t.sina.com.cn/oauth/authorize";  

    // 回調地址  

    public static final String OAUTH_CALLBACK_URL = "mysina://CallActivity";  

 

 

public class SinaConstant {// 新浪OAuth輔助信息類

 

       // 所分配的APP_KEY

       public static final String CONSUMER_KEY = "";

       // 所分配的APP_SECRET

       public static final String CONSUMER_SECRET = "";

       // 用於獲取未授權的request token

       public static final String REQUEST_URL = "https://api.t.sina.com.cn/oauth/request_token";

       // 用於獲取access token

       public static final String ACCESS_URL = "https://api.t.sina.com.cn/oauth/access_token";

       // 用於對未授權的request token進行授權

       public static final String AUTHORIZE_URL = "https://api.t.sina.com.cn/oauth/authorize";

       // 回調地址

       public static final String OAUTH_CALLBACK_URL = "mysina://CallActivity";

 

} 註:1、其中回調地址用於指向從新浪頁面授權後跳轉到頁面;2、對應的key和secret填寫新浪微博對應提供的app_key及app_secret

 

     建立一個Activity用於進行添加賬號的操作。將改Activity設置為單例模式

 

Xml代碼 

<activity 

            android:label="@string/app_name" 

            android:launchMode="singleInstance"            android:name=".AddUserActivity" > 

            <intent-filter > 

                <action android:name="android.intent.action.VIEW" /> 

                <category android:name="android.intent.category.DEFAULT" /> 

                <category android:name="android.intent.category.BROWSABLE" /> 

 

                <data 

                    android:host="CallActivity" 

                    android:scheme="mysina" /> 

            </intent-filter> 

        </activity> 

 

<activity

            android:label="@string/app_name"

            android:launchMode="singleInstance"            android:name=".AddUserActivity" >

            <intent-filter >

                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />

                <category android:name="android.intent.category.BROWSABLE" />

 

                <data

                    android:host="CallActivity"

                    android:scheme="mysina" />

            </intent-filter>

        </activity>註:1、android:launchMode="singleInstance"將該Activity設置為單例;2、data標簽與SinaConstant類中的回調地址對應,用於從瀏覽器回傳值時呼出該Activity

 

 

 

    建立AddUserActivity,對應代碼如下:

 

 

 

Java代碼 

public class AddUserActivity extends Activity {  

    /** Called when the activity is first created. */ 

    Context context;  

    private OAuthConsumer sinaconsumer;  

    private OAuthProvider sinaprovider;  

                private OAuthRequestToken oauthtool;  

public void onCreate(Bundle savedInstanceState) {  

        super.onCreate(savedInstanceState);  

        setContentView(R.layout.usermanager);  

        sinaconsumer = new CommonsHttpOAuthConsumer(SinaConstant.CONSUMER_KEY,SinaConstant.CONSUMER_SECRET);//初始化用於OAuth認證的Consumer對象  

        sinaprovider = new CommonsHttpOAuthProvider(SinaConstant.REQUEST_URL,SinaConstant.ACCESS_URL, SinaConstant.AUTHORIZE_URL);//初始化用於OAuth認證的Provider對象               

        ImageButton adduser = (ImageButton) findViewById(R.id.addUserImage);this.context = this;          

        adduser.setOnClickListener(new OnClickListener() {  

            public void onClick(View v) {  

            System.out.println("OAuth認證新浪");  

                oauthtool = new OAuthRequestToken(context, sinaconsumer,sinaprovider);  

                oauthtool.execute();      

            }  

 

        });  

    }  

protected void onNewIntent(Intent intent) {//AddUserActivity為單例,再第二次開啟時加載該方法  

        super.onNewIntent(intent);  

        Uri uri = intent.getData();  

        String verifier = null;  

        verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);  

        try {                         

                                 sinaprovider.setOAuth10a(true);//設置OAuth版本號               

                      sinaprovider.retrieveAccessToken(sinaconsumer, verifier);//通過服務器返回的Verifier去獲取賬號對應的Token  

        SortedSet<String> user_ids = sinaprovider.getResponseParameters().get("user_id");  

        String user_id = user_ids.first();  

        String Token= sinaconsumer.getToken();  

        String TokenSecret = sinaconsumer.getTokenSecret();  

        System.out.println(userKey + "&*&" + userSecret);  

        } catch (Exception e) {  

            e.printStackTrace();  

        }  

 

public class AddUserActivity extends Activity {

       /** Called when the activity is first created. */

       Context context;

       private OAuthConsumer sinaconsumer;

       private OAuthProvider sinaprovider;

                private OAuthRequestToken oauthtool;

public void onCreate(Bundle savedInstanceState) {

              super.onCreate(savedInstanceState);

              setContentView(R.layout.usermanager);

              sinaconsumer = new CommonsHttpOAuthConsumer(SinaConstant.CONSUMER_KEY,SinaConstant.CONSUMER_SECRET);//初始化用於OAuth認證的Consumer對象

              sinaprovider = new CommonsHttpOAuthProvider(SinaConstant.REQUEST_URL,SinaConstant.ACCESS_URL, SinaConstant.AUTHORIZE_URL);//初始化用於OAuth認證的Provider對象                  

              ImageButton adduser = (ImageButton) findViewById(R.id.addUserImage);this.context = this;       

              adduser.setOnClickListener(new OnClickListener() {

                     public void onClick(View v) {

                     System.out.println("OAuth認證新浪");

                            oauthtool = new OAuthRequestToken(context, sinaconsumer,sinaprovider);

                            oauthtool.execute();      

                     }

 

              });

       }

protected void onNewIntent(Intent intent) {//AddUserActivity為單例,再第二次開啟時加載該方法

              super.onNewIntent(intent);

              Uri uri = intent.getData();

              String verifier = null;

              verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

              try {                                         

                                 sinaprovider.setOAuth10a(true);//設置OAuth版本號                    

                      sinaprovider.retrieveAccessToken(sinaconsumer, verifier);//通過服務器返回的Verifier去獲取賬號對應的Token

              SortedSet<String> user_ids = sinaprovider.getResponseParameters().get("user_id");

              String user_id = user_ids.first();

              String Token= sinaconsumer.getToken();

              String TokenSecret = sinaconsumer.getTokenSecret();

              System.out.println(userKey + "&*&" + userSecret);

              } catch (Exception e) {

                     e.printStackTrace();

              }

} 註:1、在OnNewIntent方法中,sinaprovider.retrieveAccessToken()需要與網路交互,最好采取異步操作,本代碼中忽略,異步方法可以參考在onClickListener監聽中的OAuthRequestToken。

 

 

 

我們可以在上面的代碼中看到,我們已經獲取到相應的Token及TokenSecret瞭。通過這2個值,我們技能對授權賬號進行操作,獲取賬號信息,發送微博,獲取微博,更新資料等。

 

 

 

在第一步認證中,用到瞭一個異步類OAuthRequestToken,代碼如下 :

 

Java代碼 

public class OAuthRequestToken extends AsyncTask<String, Void, String> {  

 

    private OAuthConsumer consumer;  

    private OAuthProvider provider;  

 

    private Context context;  

    private ProgressDialog pd;  

 

    public OAuthRequestToken(Context context, OAuthConsumer consumer,  

            OAuthProvider provider) {  

        this.context = context;  

        this.consumer = consumer;  

        this.provider = provider;  

    }  

 

    @Override 

    protected String doInBackground(String… params) {  

        // TODO Auto-generated method stub  

        // if(type.equalsIgnoreCase("sina")){  

 

        try {  

            Uri uri = null;  

            // retrieveRequestToken的第二個參數是回調URL  

            final String url = provider.retrieveRequestToken(consumer,SinaConstant.OAUTH_CALLBACK_URL);  

            System.out.println(consumer.getToken());  

            uri = Uri.parse(url);  

            context.startActivity(new Intent(Intent.ACTION_VIEW, uri));  

        } catch (Exception e) {  

            // TODO Auto-generated catch block  

            e.printStackTrace();  

            return null;  

        }  

 

          

        return "success";  

    }  

 

    @Override 

    protected void onPostExecute(String result) {  

        // TODO Auto-generated method stub  

        super.onPostExecute(result);  

        pd.dismiss();  

        if(result == null){  

            Toast.makeText(context, "網絡異常,請稍後重試", Toast.LENGTH_LONG).show();  

        }  

          

    }  

 

    @Override 

    protected void onPreExecute() {  

        // TODO Auto-generated method stub  

        super.onPreExecute();  

        pd = new ProgressDialog(context);  

        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);  

        pd.setMessage("正在加載");  

        pd.show();  

    }  

 

 

public class OAuthRequestToken extends AsyncTask<String, Void, String> {

 

       private OAuthConsumer consumer;

       private OAuthProvider provider;

 

       private Context context;

       private ProgressDialog pd;

 

       public OAuthRequestToken(Context context, OAuthConsumer consumer,

                     OAuthProvider provider) {

              this.context = context;

              this.consumer = consumer;

              this.provider = provider;

       }

 

       @Override

       protected String doInBackground(String… params) {

              // TODO Auto-generated method stub

              // if(type.equalsIgnoreCase("sina")){

 

              try {

                     Uri uri = null;

                     // retrieveRequestToken的第二個參數是回調URL

                     final String url = provider.retrieveRequestToken(consumer,SinaConstant.OAUTH_CALLBACK_URL);

                     System.out.println(consumer.getToken());

                     uri = Uri.parse(url);

                     context.startActivity(new Intent(Intent.ACTION_VIEW, uri));

              } catch (Exception e) {

                     // TODO Auto-generated catch block

                     e.printStackTrace();

                     return null;

              }

 

             

              return "success";

       }

 

       @Override

       protected void onPostExecute(String result) {

              // TODO Auto-generated method stub

              super.onPostExecute(result);

              pd.dismiss();

              if(result == null){

                     Toast.makeText(context, "網絡異常,請稍後重試", Toast.LENGTH_LONG).show();

              }

             

       }

 

       @Override

       protected void onPreExecute() {

              // TODO Auto-generated method stub

              super.onPreExecute();

              pd = new ProgressDialog(context);

              pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);

              pd.setMessage("正在加載");

              pd.show();

       }

 

} OAuth認證,在本文中是通過調用系統瀏覽器到新浪微博指定地址進行授權,如果使用UCWeb之類的瀏覽器可能會出現無法回調的異常。所以建議使用WebView來實現授權頁面。相應的方法會在後面寫到

 

作者 river418

發佈留言