关于微博授权的流程

微博授权V2.5,目前最新V3.0

Android SDK地址:https://github.com/sinaweibosdk/weibo_android_sdk

在应用中使用SSO授权时,首先需要做的是实例化授权类对象:

mWeiboAuth = new WeiboAuth(this, Constants.APP_KEY,
				Constants.REDIRECT_URL, Constants.SCOPE);
分别指定

APP_KEY:应用密钥

REDIRECT_URL:回调地址,创建应用时指定

SCOPE:权限接口

然后创建SSOHandler,并传入监听:

mSsoHandler = new SsoHandler(SSOAuthActivity.this, mWeiboAuth);
mSsoHandler.authorize(new AuthListener());
监听必须是实现WeiboAuthListener接口的类,这个里面主要是处理授权过程中的状态:

public abstract interface WeiboAuthListener
{
  public abstract void onComplete(Bundle paramBundle);

  public abstract void onWeiboException(WeiboException paramWeiboException);

  public abstract void onCancel();
}
提交:保存登陆信息的bundle

异常:获取异常信息,主要是web授权时

取消:截获触发取消授权的信息

在内部的授权流程中,采用SSO授权时,首先会检测微博客户端是否安装,主要方法是采用启动微博客户端的特定service:com.sina.weibo.remotessoservice。通过绑定本地的service并与其通信。

启动方式:

 private boolean bindRemoteSSOService(Context context, String packageName)
  {
    String tempPkgName = (TextUtils.isEmpty(packageName)) || (packageName.trim().equals("")) ? 
      "com.sina.weibo" : packageName;
    Intent intent = new Intent("com.sina.weibo.remotessoservice");
    intent.setPackage(tempPkgName);

    if (!context.bindService(intent, this.mConnection, 1)) {
      intent = new Intent("com.sina.weibo.remotessoservice");
      return context.bindService(intent, this.mConnection, 1);
    }

    return true;
  }

ServiceConnection对象:

private ServiceConnection mConnection = new ServiceConnection()
  {
    public void onServiceDisconnected(ComponentName name) {
      SsoHandler.this.mWeibo.anthorize(SsoHandler.this.mAuthListener);
    }

    public void onServiceConnected(ComponentName name, IBinder service)
    {
      RemoteSSO remoteSSOservice = RemoteSSO.Stub.asInterface(service);
      try {
        String ssoPackageName = remoteSSOservice.getPackageName();
        String ssoActivityName = remoteSSOservice.getActivityName();
        boolean singleSignOnStarted = SsoHandler.this.startSingleSignOn(ssoPackageName, ssoActivityName);

        if (!singleSignOnStarted)
          SsoHandler.this.mWeibo.anthorize(SsoHandler.this.mAuthListener);
      }
      catch (RemoteException e) {
        e.printStackTrace();
      }
    }
  };

在与service链接成功时就会继续使用SSO,当失败时会自动转成web授权。

在web授权中,主要是通过打开一个自定义的Dialog:

  public void anthorize(WeiboAuthListener listener)
  {
    authorize(listener, 1);
  }

  public void authorize(WeiboAuthListener listener, int type)
  {
    startDialog(listener, type);
  }

  private void startDialog(WeiboAuthListener listener, int type)
  {
    if (listener == null) {
      return;
    }

    LinkedHashMap requestParams = new LinkedHashMap();

    requestParams.put("client_id", this.mAuthInfo.mAppKey);
    requestParams.put("redirect_uri", this.mAuthInfo.mRedirectUrl);
    requestParams.put("scope", this.mAuthInfo.mScope);
    requestParams.put("response_type", "code");
    requestParams.put("display", "mobile");

    if (1 == type) {
      requestParams.put("packagename", this.mAuthInfo.mPackageName);
      requestParams.put("key_hash", this.mAuthInfo.mKeyHash);
    }

    String url = "https://open.weibo.cn/oauth2/authorize?" + Utility.packUrl(requestParams);
    if (!NetworkHelper.hasInternetPermission(this.mContext)) {
      UIUtils.showAlert(this.mContext, "Error", "Application requires permission to access the Internet");
    }
    else if (NetworkHelper.isNetworkAvailable(this.mContext)) {
      new WeiboDialog(this.mContext, url, listener, this).show();
    } else {
      String networkNotAvailable = ResourceManager.getString(this.mContext, 2);
      LogUtil.i("Weibo_web_login", "String: " + networkNotAvailable);
      UIUtils.showToast(this.mContext, networkNotAvailable, 0);
    }
  }
在弹出对话框之前,进行网络判断,
应用是否授予网络权限

网络可用,弹出对话框

网络不可用的提示

接下来就要看WeiboDialog类,它继承自Dialog。先看构造方法:

  public WeiboDialog(Context context, String authUrl, WeiboAuthListener listener, WeiboAuth weibo)
  {
    super(context, theme);
    this.mAuthUrl = authUrl;//授权地址
    this.mListener = listener;//监听
    this.mContext = context;//上下文
    this.mWeibo = weibo;//WeiboAuth对象
  }
主要是一些实例化操作。

  protected void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);

    initWindow();

    initLoadingDlg();

    initWebView();

    initCloseButton();
  }
在oncreate中,是进行界面的初始化,主要的地方是在webview。

webview中有这样一句:

this.mWebView.setWebViewClient(new WeiboWebViewClient(null));
来进行事件处理。

private class WeiboWebViewClient extends WebViewClient
  {
    private boolean isCallBacked = false;

    private WeiboWebViewClient() {
    }
    public boolean shouldOverrideUrlLoading(WebView view, String url) { LogUtil.i("WeiboDialog", "load URL: " + url);

      if (url.startsWith("sms:")) {
        Intent sendIntent = new Intent("android.intent.action.VIEW");
        sendIntent.putExtra("address", url.replace("sms:", ""));
        sendIntent.setType("vnd.android-dir/mms-sms");
        WeiboDialog.this.getContext().startActivity(sendIntent);
        return true;
      }
      return super.shouldOverrideUrlLoading(view, url);
    }

    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl)
    {
      LogUtil.d("WeiboDialog", "onReceivedError: errorCode = " + errorCode + 
        ", description = " + description + 
        ", failingUrl = " + failingUrl);
      super.onReceivedError(view, errorCode, description, failingUrl);

      if (WeiboDialog.this.mListener != null) {
        WeiboDialog.this.mListener.onWeiboException(new WeiboDialogException(description, errorCode, failingUrl));
      }
      WeiboDialog.this.dismiss();
    }

    public void onPageStarted(WebView view, String url, Bitmap favicon)
    {
      LogUtil.d("WeiboDialog", "onPageStarted URL: " + url);
      if ((url.startsWith(WeiboDialog.this.mWeibo.getAuthInfo().getRedirectUrl())) && 
        (!this.isCallBacked)) {
        this.isCallBacked = true;
        WeiboDialog.this.handleRedirectUrl(url);
        view.stopLoading();
        WeiboDialog.this.dismiss();

        return;
      }

      super.onPageStarted(view, url, favicon);

      if ((!WeiboDialog.this.mIsDetached) && (WeiboDialog.this.mLoadingDlg != null) && (!WeiboDialog.this.mLoadingDlg.isShowing()))
        WeiboDialog.this.mLoadingDlg.show();
    }

    public void onPageFinished(WebView view, String url)
    {
      LogUtil.d("WeiboDialog", "onPageFinished URL: " + url);
      super.onPageFinished(view, url);
      if ((!WeiboDialog.this.mIsDetached) && (WeiboDialog.this.mLoadingDlg != null)) {
        WeiboDialog.this.mLoadingDlg.dismiss();
      }
      WeiboDialog.this.mWebView.setVisibility(0);
    }
  }
在页面开始加载时的方法中有一个判断:

 if ((url.startsWith(WeiboDialog.this.mWeibo.getAuthInfo().getRedirectUrl())) && 
        (!this.isCallBacked)) {
        this.isCallBacked = true;
        WeiboDialog.this.handleRedirectUrl(url);
        view.stopLoading();
        WeiboDialog.this.dismiss();

        return;
      }
因为最早的时候在创建应用时给定了一个回调页的地址,当要加载的页面地址开头是回调页时,就开始进行解析用户信息和授权信息,因为在这个返回的的url中包含四个参数:

access_token,remind_in,expires_in,uid。

access_token代表口令信息,remind_in和expires_in都代表过期时间,uid代表被授权用户id。

 private void handleRedirectUrl(String url)
  {
    Bundle values = Utility.parseUrl(url);

    String errorType = values.getString("error");
    String errorCode = values.getString("error_code");
    String errorDescription = values.getString("error_description");

    if ((errorType == null) && (errorCode == null))
      this.mListener.onComplete(values);
    else
      this.mListener.onWeiboException(
        new WeiboAuthException(errorCode, errorType, errorDescription));
  }
Utility中提供了解析url的方法。

至于其中的另外一个条件:

(!this.isCallBacked)
我的理解是:因为返回的url的状态码是301,意思是客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL,也就是回调页,这个时候要做的判断就是,这个页面的url开头也是回调页,所以就要用isCallbacked进行阻止,意思是已经回调过了,就不会再去解析它了,其实里面也是空的,还有一点就是,解析过一次,这个webview就会被关掉,这个变量可能是防止解析出错延时做的措施。

接下来,解析到的信息就被放进了bundle,在判断其中信息无误后调用onComplete(value)。







/** * 测试新浪微博API * @author syn * @date 2010/12/22 */ public class TestActivity extends Activity { private static final String BASE_URL = "http://api.t.sina.com.cn/"; //API接口 private static final String CONSUMER_KEY = "270793661"; //你申请的Key private static final String HEADER_AUTHO = "Authorization"; //Authorization private static final String HEADER_BASIC = "Basic "; //Basic private static final String ERROR = "MyError"; //错误 List<myTest> myTestList; /** * 测试用的类,用于解析JSON,因为只是测试,所以乱写一下 */ public class myTest { private Date created_at; //返回微博发布的时间 private String text; //微博内容 private User user; //微博用户信息 public myTest(JSONObject object) throws JSONException //解析JSON文件 { text=""; user=null; created_at=new Date(object.getString("created_at")); text=object.getString("text"); user=new User(object.getJSONObject("user")); } } @Override public void onCreate(Bundle savedInstanceState) { String tailUrl="statuses/public_timeline.json"; //我要获得的是最新的公共微博 String response=getResponse(tailUrl, MainActivity.loginUser);//调用提交函数,此函数是核心部分 super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.test); TextView textView01=(TextView)findViewById(R.id.test); if(response.startsWith(ERROR)) textView01.setText("error"); else { JSONArray array; try { array = new JSONArray(response); for (int i = 0; i < array.length(); i++) { myTest mytest= new myTest(array.getJSONObject(i)); //myTestList.add(mytest); String content="Content:"+mytest.text+" Author:"+mytest.user.getNike()+" Date:"+mytest.created_at; textView01.setText(content); } } catch (JSONException e) { e.printStackTrace(); } } } /** * 此函数提交URL,返回访问结果 * @param tailUrl json或者xml的url * @param user 用户的一个对象 * @return 提交结果 */ private static String getResponse(String tailUrl,User user) { String httpUrl=BASE_URL+tailUrl; ArrayList<NameValuePair> postParams=new ArrayList<NameValuePair>(); postParams.add(new BasicNameValuePair("source",CONSUMER_KEY)); //封装入APP Key try { HttpPost httpRequest = new HttpPost(httpUrl); httpRequest.setEntity(new UrlEncodedFormEntity(postParams,HTTP.UTF_8)); //把参数放入Entity httpRequest.addHeader(HEADER_AUTHO, HEADER_BASIC+user.encodeBase64NamePass()); //这里就是给用户的用户名和密码加密,然后放入http头 httpRequest.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE,false); HttpClient httpclient = new DefaultHttpClient(); HttpResponse httpResponse = httpclient.execute(httpRequest); //提交 int statusCode=httpResponse.getStatusLine().getStatusCode(); //获得结果码200是正确 if ( statusCode== HttpStatus.SC_OK) { String strResult = EntityUtils.toString(httpResponse.getEntity()); Log.e("WeiboKu", "strResult :"+strResult); return strResult; } else { Log.e("WeiboKu", "strResult Error:"+statusCode); return ERROR+String.valueOf(statusCode); } } catch (Exception e) { Log.e("WeiboKu", "getResponse Exception:"+e.getMessage()); return ERROR+e.getMessage().toString(); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值