本文轉自:http://www.cnblogs.com/hll2008/archive/2011/04/30/2033481.html
前面的文章的OAuth認證過程在獲取oauth_verifier碼是是通過調用android系統帶的瀏覽器進行用戶授權認證的, 具體見:android開發我的新浪微博客戶端-用戶授權頁面功能篇(3.2)。
當初的實現是這樣:
1、首先在AndroidManifest.xml中配置給AuthorizeActivity添加如下配置<data android:scheme="myapp" android:host="AuthorizeActivity" /> ,這樣在瀏覽器中通過地址myapp://AuthorizeActivity啓動AuthorizeActivity這個Activity.
2、在用android系統帶的瀏覽器顯示用戶授權頁面的時候,把"myapp://AuthorizeActivity"作爲url參數CallBackUrl=myapp://AuthorizeActivity,這樣當用戶輸入完賬號和密碼會請求myapp://AuthorizeActivity?oauth_verifier=123456這個地址,這個時候就自然啓動了AuthorizeActivity這個Activity.
3、當AuthorizeActivity被啓動的時候,在onNewIntent方法中通過Uri uri = intent.getData();獲取oauth_verifier值123456。
這樣的實現有個弊端:
就是當用戶認證是選擇用uc等第三方的瀏覽器進行用戶認證時,當用戶輸入賬號密碼後點擊授權按鈕後不會跳轉到AuthorizeActivity這個Activity,只有用android自帶的瀏覽器纔沒有問題。其實這個是個比較嚴重的問題了大多數的用戶都會用uc等第三方的瀏覽器了,這樣導致認證不能正常進行。
最近在嘗試iphone下的oauth認證的時候發現一個很好的思路,那就是不要用系統帶的瀏覽器而且在自己的程序中嵌入一個WebView在這個WebView控件中完成用戶授權認證而不再使用額外的瀏覽器。今天抽了空把在iphone下的實現思路搬到了android下,做了如下的嘗試。
現在的實現是這樣:
1、首先上面的那3點都可以不需要了,該刪除的刪除。
2、新建一個名爲WebViewActivity的ViewActivity,在這個ViewActivity就只有一個WebView控件
Layout文件如下:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<WebView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:id="@+id/web">
</WebView>
</ScrollView>
3、修改OAuth過程在獲取(Request Token和Request Secret)後,啓動WebViewActivity,在這個WebViewActivity的WebView控件顯示用戶認證的網頁,代碼實現如下:
String Url=getAuthenticationURL();
Intent intent = new Intent(MainActivity.this, WebViewActivity.class);
Bundle b=new Bundle();
b.putString("url", url);
intent.putExtras(b);
startActivity(intent);
4、在WebViewActivity中onCreate方法中獲取上面傳過來的url進行認證網頁顯示,代碼如下:
setContentView(R.layout.webview);
WebView wv =(WebView) findViewById(R.id.web);
Intent i=this.getIntent();
if(!i.equals(null)){
Bundle b=i.getExtras();
if(b!=null){
if(b.containsKey("url")){
String url = b.getString("url");
//這行很重要一點要有,不然網頁的認證按鈕會無效
wv.getSettings().setSupportZoom(true);
//wv.getSettings().setDefaultZoom(WebSettings.ZoomDensity.FAR);
wv.getSettings().setBuiltInZoomControls(true);
wv.loadUrl(url);
}
}
}
5、上面Url參數中我們並沒有提供CallBackUrl參數,這個時候當用戶輸入賬號和密碼點擊授權後會顯示pin碼(oauth_verifier值)頁面,而不在會跳轉,頁面如下:
6、上一步中已經在WebView顯示出了授權碼,我們接下來要做的就是獲取這個授權碼176048,這個既然是顯示在WebView中的網頁,那麼我們獲取當前的這個WebView顯示的html代碼然後從中提取出授權碼不就可以了。獲取html代碼是通過調用javascript實現的,不難就解釋了看具體代碼,在onCreate方法添加如下代碼:
WebViewClient wvc=new WebViewClient()
{
@Override
public void onPageFinished(WebView view,String url)
{
view.loadUrl("javascript:window.Methods.getHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
super.onPageFinished(view, url);
}
};
wv.setWebViewClient(wvc);
添加類JavaScriptInterface
{
public void getHTML(String html)
{
String pin= getPin(html);
//這裏就獲取到了我們想要的pin碼
//這個pin碼就是oauth_verifier值,用來進一步獲取Access Token和Access Secret用
Log.e("pin", pin);
}
}
7、這樣我們就獲取到了當前WebView的html代碼,接下來就是提取html中的授權碼,html代碼如下:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width">
<title>應用授權 - 新浪微博</title>
<link href="http://timg.sjs.sinajs.cn/t35/style/css/open/open_third.css" rel="stylesheet" type="text/css">
</head><body>
<div class="opthBg">
<div class="opthTopBg"><div class="opthHead"><a href="http://weibo.com" class="newlogo"></a></div></div>
<div class="opthBox">
<div class="opthCen">
<br><br>
<font size="4"><b>獲取到授權碼:176048</b></font>
<br><br>
<div class="opthBottom">
<div class="lf"></div>
<div class="rt">
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
function canchange()
{
document.forms['authZForm'].from.value='turnuser';
document.forms['authZForm'].action.value='';
document.forms['authZForm'].submit();
}
</script>
</body></head>
提取授權碼用正則實現的,java方法代碼如下:
{
String ret="";
String regEx="[0-9]{6}";
Pattern p=Pattern.compile(regEx);
Matcher m=p.matcher(html);
boolean result=m.find();
if(result)
{
ret= m.group(0);
}
return ret;
}
這樣就完成了所有的實現了,這做雖然有點麻煩,但是徹底解決了以前存在的問題。