android開發我的新浪微博客戶端-OAuth認證過程中用WebView代替原來的系統自帶瀏覽器

本文轉自: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文件如下:

<?xml version="1.0" encoding="utf-8"?>
<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控件顯示用戶認證的網頁,代碼實現如下:

//Url類似:http://api.t.sina.com.cn/oauth/authenticate?oauth_token=71c6df7fd0b4e1e5c491faa90b654fdf&from=xweibo
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進行認證網頁顯示,代碼如下:

super.onCreate(savedInstanceState);
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().setJavaScriptEnabled(true);
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方法添加如下代碼:

wv.addJavascriptInterface(new JavaScriptInterface(), "Methods");
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

class 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代碼如下:

<head><head>
<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方法代碼如下:

public String getPin(String html)
{
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;
}

這樣就完成了所有的實現了,這做雖然有點麻煩,但是徹底解決了以前存在的問題。

發佈了30 篇原創文章 · 獲贊 61 · 訪問量 22萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章