Intereting Posts
   

如何使用Intentfilter处理OAuth URLcallback(如果使用webview进行身份validation)?

我正在开发一个应用程序使用OAuth身份validation,但我有一个小问题处理OAuthcallback

authentication

我的应用程序有一个webview作为login屏幕,我被给了一个url加载auth窗体在我的webview。 假设这个url是:

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

并在身份validation活动(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中,我有以下的oauthcallback处理:

 <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中使用这个URL(使用loadURL()方法)redirect到包含REAL OAUTH WEB FROM (应该在web视图中加载)的另一个url。 问题是这个redirect会自动启动Android中的意图select :由于URL应该由Web浏览器处理,因此Android允许您select手机上可用的Web浏览器之一来打开URL。

由于这不是我想要的,我必须包含下面的代码,以便在webview中处理redirect,但不启动Web浏览器(或其他):

 myWebView.setWebViewClient(new WebViewClient()); 

所以使用这个代码,redirect处理“在web视图”,我有login屏幕显示。

然后我可以input证书(例如:通过Twitter的oauth),但是当authentication完成时,接收到callback,但是接下来应该处理callback的活动(configuration为在清单中接收callback的AuthActivity)不会启动。 相反,我有webview显示一个消息说,urlcallback(在我们的例子中:authprovider:// auth / XXX?xxx = yyyconfiguration在清单中)无法find。

原因可能是下面的代码:

 myWebView.setWebViewClient(new WebViewClient()); 

之前介绍过,告诉Android,webview处理一切。 所以现在,由于callbackurl不是一个web url,所以处理起来很麻烦,甚至无法启动可以处理的intent。

问题

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

任何帮助,将不胜感激

提前致谢

首先在清单中,将这些属性设置为启动WebView的活动

 android:launchMode="singleInstance" 

并为此添加一个意图filter

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

然后在你的代码中当用户点击loginbutton时

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

这里的callbackurl是
private static final String CALLBACK_URL = "oauth-testing:///";
你正在创build一个dynamic的web视图并显示给用户。 login后,webview被closures,代码进入onNewIntent() 。 login后需要实现您的function。

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

我知道我已经添加了很多代码片断,其中一些可能不相关,但是我希望有一天它可以帮助别人。

那么,首先你可能需要调用你的服务提供者提供的URL,如果存在任何redirect,你将得到HTTP状态代码3xx。 接下来,如果存在任何redirect,您可以尝试调用实际的URL。 对于正常的HTTP响应,您将获得HTTP 2xx状态码。

因为你有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将只允许WebView处理任何加载的URL本身,即在WebView而不是浏览器。

但是如果你通过传递class MyWebViewmWebView.setWebViewClient(new MyWebView()); 那么你可以控制的url加载相同的东西你可以存档

 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对象,那么这不是我解决这个问题的解决scheme。