zoukankan      html  css  js  c++  java
  • android开发我的新浪微博客户端OAuth认证过程中用WebView代替原来的系统自带浏览器

         

          前面的文章的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;
    }

    这样就完成了所有的实现了,这做虽然有点麻烦,但是彻底解决了以前存在的问题。

  • 相关阅读:
    汉诺塔
    破损的键盘
    解方程
    运输计划
    选学霸
    子集和的目标值
    棋盘染色2
    守卫者的挑战
    飞扬的小鸟
    攻克城堡
  • 原文地址:https://www.cnblogs.com/hll2008/p/2033481.html
Copyright © 2011-2022 走看看