2012-10-01 34 views
11

Estoy desarrollando una aplicación que usa OAuth para la autenticación, pero tengo un pequeño problema con las devoluciones de llamada de OAuth.¿Cómo se manejan las devoluciones de llamada URL OAuth con filtros de intención si la autenticación se realiza con webview?

la autentificación

Mi aplicación tiene una vista web como la pantalla de inicio de sesión y me da una URL para cargar el formulario de autenticación en mi vista web. Digamos que la URL es:

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

y en la actividad de autenticación (AuthActivity.java), Tengo el siguiente:

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

en el manifest.xml, Tengo el siguiente de devolución de llamada oauth manipulación:

<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> 

EL PROBLEMA

Esta url cuando se usa en la vista web (con el método loadURL()) redirige a otra URL que contiene REAL OAUTH WEB DE (que debe cargarse en la vista web). El problema es que esta redirección inicia automáticamente la selección de intento en Android: dado que la URL debe ser manejada por un navegador web, Android le permite elegir uno de los navegadores web disponibles en el teléfono para abrir la url.

Dado que esto no es lo que quiero, tengo que incluir el siguiente código para que el cambio de dirección se maneja dentro de la vista web, pero no se inicia un navegador web (o lo que sea):

myWebView.setWebViewClient(new WebViewClient()); 

así que con esto código, la redirección se maneja "dentro de la vista web" y tengo la pantalla de inicio de sesión mostrada.

Puedo ingresar las credenciales (por ejemplo: oauth a través de Twitter) pero cuando se realiza la autenticación, se recibe la devolución de llamada pero luego se activa la actividad que se encarga de la devolución (AuthActivity configurado para recibir una devolución de llamada en el manifiesto) no está lanzado. En cambio, tengo la vista web que muestra un mensaje que dice que no se puede encontrar la devolución de llamada url (en nuestro caso: authprovider: // auth/XXX? Xxx = yyy como se configuró en el manifiesto).

La razón puede ser que el siguiente código:

myWebView.setWebViewClient(new WebViewClient()); 

presentado anteriormente, dice que el androide vista web se encarga de todo. Entonces, como la url de devolución de llamada no es una url web, tiene problemas para manejarla y ni siquiera puede lanzar la intención que puede manejarla.

LA PREGUNTA

¿Cómo puedo solucionar este problema? Debería poder dejar que la actividad maneje la devolución de llamada pero no permitir que la vista web intente cargarla.

cualquier ayuda se agradece

gracias de antemano

Respuesta

0

Bueno, en primer lugar es posible que necesite llamar a la URL que es proporcionada por el proveedor de servicios, si hay alguna redirigir existes obtendrá el código de estado HTTP 3xx . A continuación, puede intentar llamar a la URL real si existe alguna redirección. Para la respuesta HTTP normal, obtendrá el código de estado HTTP 2xx.

+0

Tuve un caso diferente, tratando de integrar OAuth con 'AccountManager' y' android: launchMode = "singleInstance" 'trabajado para mí. – d370urn3ur

23

primer lugar en su manifiesto, establecer estas propiedades a su actividad que pone en marcha la vista Web

android:launchMode="singleInstance" 

y añadir un filtro intención de que a medida que

<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> 

después en su código cuando el usuario hace clic en el botón de inicio de sesión

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); 

Aquí la URL de devolución de llamada es
private static final String CALLBACK_URL = "oauth-testing:///";
y está creando una vista web dinámica y mostrando al usuario. Y después de iniciar sesión, la vista web se cierra y el código llega al onNewIntent(). Debe implementar su funcionalidad después de iniciar sesión allí.

@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); 
    } 
} 

Sé que he añadido una gran cantidad de fragmento de código, algunos de los cuales puede no ser relevante, pero espero que ayude a alguien algún día.

+0

no estoy seguro de por qué esta respuesta no está marcada como aceptada. – Umair

0

Como tiene el Objeto de WebView para que pueda sobrecargarlo y luego manejar la url en la que va a navegar a su Actividad, de estas dos maneras.

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;  
    } 
} 

puede establecer el mWebView.setWebViewClient(new WebViewClient()); que es defecto pero por simplemente añadiendo un WebViewClient personalizado predeterminado sólo permitirá la vista Web para manejar cualquier sí mismo es decir, las direcciones URL cargados dentro de la web View en lugar de navegador.

pero si se sobrecarga por pasando por encima class MyWebView como mWebView.setWebViewClient(new MyWebView()); entonces se puede controlar la carga de la url misma cosa u puede 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;  

    }}); 

En caso de que no tiene el control del objeto en vista web, entonces esto no es la solución la actualizaré una vez que resolveré esto.

Cuestiones relacionadas