2012-10-01 14 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對象的控制權,那麼這是不是解決方案我會更新一次,我會解決這個問題。

相關問題