2012-10-01 69 views
11

我正在开发一个应用程序,它使用OAuth进行身份验证,但我在处理OAuth回调时遇到了一些问题。如何使用Intent过滤器处理OAuth URL回调(如果使用webview进行身份验证)?

认证

我的应用程序有一个的WebView作为登录屏幕,我获得一个网址加载权威性形式在我的网页流量。比方说,该网址是:

https://myoauthhost.com/oauth/auth?response_type=code&client_id=XXXXXXX&redirect_uri=YYYYYYYY&scope=ZZZZZZZZZZ 

,并在AUTH活动(AuthActivity.java),我有以下几点:

String authURL = https://myoauthhost.com/oauth/auth?response_type=code&client_id=XXXXXXX&redirect_uri=YYYYYYYY&scope=ZZZZZZZZZZ 
    myWebView.loadUrl(authURL); 
在manifest.xml

,对OAuth的回调我有以下处理:

<activity 
      android:name=".AuthActivity" 
      android:label="@string/app_name" 
      android:screenOrientation="portrait" > 

      <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="authprovider" 
        android:scheme="auth" /> 
      </intent-filter> 
</activity> 

的问题

当在webview中使用(使用loadURL()方法)时,此URL重定向到另一个包含REAL OAUTH WEB从(应该在Web视图中加载)的url。问题是,这个重定向在Android中自动启动意图选择:由于URL应该由网络浏览器处理,因此Android允许您选择手机上可用的网络浏览器之一打开URL。

因为这不是我想要的,我必须包括以下代码,以便重定向web视图中处理,但不启动Web浏览器(或其他):与此

myWebView.setWebViewClient(new WebViewClient()); 

所以代码,重定向处理“在web视图”,我有登录屏幕显示。

然后我可以输入凭证(例如:通过Twitter的oauth),但是当认证完成后,接收到回拨,但接下来应该处理回叫的活动(配置为在清单中接收回叫的AuthActivity)没有启动。相反,我在webview中显示一条消息,指出找不到url回调(在我们的例子中:authprovider:// auth/XXX?xxx = yyy,如清单中配置的那样)。

的原因可能是下面的代码:

myWebView.setWebViewClient(new WebViewClient()); 

前面介绍过,告诉Android web视图处理一切。所以,现在,由于回调url不是一个web网址,它处理它很麻烦,甚至无法启动可以处理它的intent。

问题

我怎样才能解决这个问题? 我应该可以让活动处理回调,但不要让webview尝试加载它。

任何帮助,将不胜感激提前

感谢

回答

0

嗯,首先,你可能需要调用由服务提供商提供的网址,如果有任何重定向存在,您会得到HTTP状态代码为3xx 。接下来,如果存在任何重定向,您可以尝试调用实际的URL。对于正常的HTTP响应,您将获得HTTP 2xx状态码。

+0

我有一个不同的情况,试图将OAuth与'AccountManager'和'android:launchMode =“singleInstance”'集成在一起。 – d370urn3ur

23

都在你的清单:首先,设置这些属性到你的活动,启动的WebView

android:launchMode="singleInstance" 

和意图过滤器添加到作为

<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:scheme="oauth-testing" /> 
</intent-filter> 

然后在你的代码,当用户点击登录按钮

mReqToken = mTwitter.getOAuthRequestToken(CALLBACK_URL); 
WebView webView = new WebView(this); 
webView.requestFocus(View.FOCUS_DOWN); 
webView.setOnTouchListener(new View.OnTouchListener() { 
    @Override 
    public boolean onTouch(View v, MotionEvent event) { 
     switch (event.getAction()) { 
      case MotionEvent.ACTION_DOWN: 
      case MotionEvent.ACTION_UP: 
      if (!v.hasFocus()) { 
       v.requestFocus(); 
      } 
      break; 
     } 
     return false; 
    } 
}); 
webView.loadUrl(mReqToken.getAuthenticationURL()); 
mainLayout.removeAllViews(); 
mainLayout.addView(webView); 

这里的回调网址是
private static final String CALLBACK_URL = "oauth-testing:///";
并且您正在创建动态Web视图并向用户显示。登录后,webview被关闭,代码来到onNewIntent()。登录后需要实现您的功能。

@Override 
protected void onNewIntent(Intent intent) { 
    super.onNewIntent(intent); 
    dealWithTwitterResponse(intent); 
} 
private void dealWithTwitterResponse(Intent intent) { 
    Uri uri = intent.getData(); 
    System.out.println("URI=" + uri); 
    if (uri != null && uri.toString().startsWith(CALLBACK_URL)) { 
     String oauthVerifier = uri.getQueryParameter("oauth_verifier"); 
     authoriseNewUser(oauthVerifier); 
    } 
} 

我知道我已经加了很多代码片段,其中一些可能是不相关的,但我希望这会帮助别人一天。

+0

不知道为什么这个答案没有被标记为接受! – Umair

0

由于您拥有WebView对象,所以您可以重载它,然后处理您在其中以wana导航到您的活动的URL,以这两种方式。

private class MyWebView extends WebViewClient{ 
      @TargetApi(Build.VERSION_CODES.N) 
      @Override 
      public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request) 
      { 
       Uri uri = request.getUrl(); 
       return shouldOverrideUrlLoading(uri.toString()); 
      } 

      private boolean shouldOverrideUrlLoading(final String url) 
      { 
       Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url); 
        //your code to handle the url for navigation will go here 
       try{ 
         if(url.contains("yourcondition")){ 
         //1st way to handle 
         Intent intent = new Intent(Intent.ACTION_VIEW); 
         intent.setData(Uri.parse(url)); 
         YourActivity.this.startActivity(intent); 
         }else{ 
          //2nd way 
         Intent intent = new Intent(YourActivity.this,NewActivity.class); 
         //you can set the data 
         intent.setData(Uri.parse(url)); 
         YourActivity.this.startActivity(intent); 
         } 
        }catch(ActivityNotFoundException e) {  
         Log.e(LOGTAG,"Could not load url"+url); 
        }      
       return false; 
       // return true; // this True means that application wants to leave the WebView and try to go to browser and handle the url itself, otherwise return false. 
      } 
    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url) 
    { 


     try { 
       if(url.contains("yourcondition")){ 
       //1st way to handle 
       Intent intent = new Intent(Intent.ACTION_VIEW); 
       intent.setData(Uri.parse(url)); 
       YourActivity.this.startActivity(intent); 
      }else{ 
      //2nd way 
      Intent intent = new Intent(YourActivity.this,NewActivity.class); 
      //you can set the data 
      intent.setData(Uri.parse(url)); 
      YourActivity.this.startActivity(intent); 
      } 

     } catch(ActivityNotFoundException e) { 

      Log.e(LOGTAG,"Could not load url"+url); 
     } 

     return false;  
    } 
} 

可以设置mWebView.setWebViewClient(new WebViewClient());这是默认的,而是由 只需添加一个默认的自定义WebViewClient将只允许web视图来处理web视图,而不是浏览器中的任何加载网址本身即。

但如果你通过将上述class MyWebViewmWebView.setWebViewClient(new MyWebView());超载,那么你可以控制的URL一样的东西加载U可以achive

myWebView.setWebViewClient(new WebViewClient(){ 

       @TargetApi(Build.VERSION_CODES.N) 
       @Override 
       public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request) 
       { 
        Uri uri = request.getUrl(); 
        return shouldOverrideUrlLoading(uri.toString()); 
       } 

       private boolean shouldOverrideUrlLoading(final String url) 
       { 
        Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url); 
         //your code to handle the url for navigation will go here 
        try{ 
          if(url.contains("yourcondition")){ 
          //1st way to handle 
          Intent intent = new Intent(Intent.ACTION_VIEW); 
          intent.setData(Uri.parse(url)); 
          YourActivity.this.startActivity(intent); 
          }else{ 
           //2nd way 
          Intent intent = new Intent(YourActivity.this,NewActivity.class); 
          //you can set the data 
          intent.setData(Uri.parse(url)); 
          YourActivity.this.startActivity(intent); 
          } 
         }catch(ActivityNotFoundException e) {  
          Log.e(LOGTAG,"Could not load url"+url); 
         }      
        return false; 
        // return true; // this True means that application wants to leave the WebView and try to go to browser and handle the url itself, otherwise return false. 
       } 

    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url) 
    { 

     try { 
      if(url.contains("yourcondition")){ 
      //1st way to handle 
      Intent intent = new Intent(Intent.ACTION_VIEW); 
      intent.setData(Uri.parse(url)); 
      YourActivity.this.startActivity(intent); 
      }else{ 
      //2nd way 
       Intent intent = new Intent(YourActivity.this,NewActivity.class); 
      //you can set the data 
      intent.setData(Uri.parse(url)); 
      YourActivity.this.startActivity(intent); 
      }  
     } catch(ActivityNotFoundException e) { 

      Log.e(LOGTAG,"Could not load url"+url); 
     } 

     return false;  

    }}); 

如果你没有的WebView对象的控制权,那么这是不是解决方案我会更新一次,我会解决这个问题。

相关问题