Intereting Posts
Как выйти из приложения программно с помощью нажатия кнопки Как я могу воспользоваться кнопкой «Очистить кеш» от Android Android: программно анимация между изображениями в виджетах галереи Ошибка чтения данных из InputStream в Bluetooth на Android Андроид Сбор мусора Android GridView (GC_EXTERNAL_ALLOC) <1K чрезмерно, вызывая очень изменчивый интерфейс Частный просмотр устарел в Android WebView по API 17. Какая альтернатива? Программно вернуться к предыдущему фрагменту в стопке Android Studio изменяет прозрачность объектов изображения Проект с path ': mypath' не найден в корневом проекте 'myproject' Команда изменения скорости не работает, когда аудио-поток отсутствует в видео – ffmpeg «Не удалось получить системную библиотеку для проекта» после обновления до Android SDK 2.3 и ADT 8.0 Как нарисовать границу в верхней части линейного макета Почему Android использует Ints вместо Enums Хранить длинную стоимость в базе данных android

Как обрабатывать обратные вызовы URL-адресов OAuth с помощью фильтров Intent, если проверка подлинности выполняется с помощью webview?

Я разрабатываю приложение, использующее OAuth для аутентификации, но у меня есть небольшая проблема с обработкой обратных вызовов OAuth.

АУТЕНТИФИКАЦИЯ

У моего приложения есть веб-просмотр в качестве экрана входа в систему, и мне предоставляется URL-адрес для загрузки формы auth в моем веб-просмотре. Предположим, что URL-адрес:

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> 

ПРОБЛЕМА

Этот URL-адрес при использовании в webview (с методом loadURL ()) перенаправляет на другой URL-адрес, содержащий REAL OAUTH WEB FROM (который должен быть загружен в webview). Проблема в том, что это перенаправление автоматически запускает выбор намерений в Android: поскольку URL-адрес должен обрабатываться веб-браузером, Android позволяет вам выбрать один из доступных веб-браузеров на телефоне, чтобы открыть URL-адрес.

Поскольку это не то, что я хочу, я должен включить следующий код, чтобы перенаправление обрабатывалось в веб-просмотре, но не запускает веб-браузер (или что-то еще):

 myWebView.setWebViewClient(new WebViewClient()); 

Поэтому с этим кодом перенаправление обрабатывается «внутри веб-просмотра», и у меня отображается экран входа в систему.

Затем я могу ввести учетные данные (например: oauth через Twitter), но когда аутентификация завершена, возвращается обратный вызов, но затем не запускается действие, которое должно обрабатывать обратный вызов (AuthActivity, настроенный для приема обратного вызова в манифесте). Вместо этого у меня есть веб-представление, отображающее сообщение о том, что обратный вызов url (в нашем случае: authprovider: // auth / XXX? Xxx = yyy, как указано в манифесте) не может быть найден.

Причина может заключаться в следующем:

 myWebView.setWebViewClient(new WebViewClient()); 

Представленный ранее, сообщает Android, что webview обрабатывает все. Итак, теперь, поскольку URL-адрес обратного вызова не является URL-адресом сети, он имеет проблемы с его обработкой и даже не может запустить намерение, которое может справиться с этим.

ВОПРОС

Как я могу решить эту проблему ? Я должен уметь управлять обработкой обратного вызова, но не позволять webview пытаться его загрузить.

Любая помощь будет оценена

заранее спасибо

Solutions Collecting From Web of "Как обрабатывать обратные вызовы URL-адресов OAuth с помощью фильтров Intent, если проверка подлинности выполняется с помощью webview?"

Прежде всего в вашем манифестах, установите эти свойства в свою деятельность, которая запускает 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); 

Здесь URL-адрес обратного вызова
private static final String CALLBACK_URL = "oauth-testing:///";
И вы создаете динамический веб-просмотр и показываете пользователю. И после входа в веб-просмотр закрывается, и код приходит к 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); } } 

Я знаю, что добавил много фрагментов кода, некоторые из которых могут быть неактуальными, но я надеюсь, что когда-нибудь это поможет кому-то.

Ну, сначала вам может понадобиться позвонить по URL-адресу, предоставленному вашим поставщиком услуг, если существует какая-либо переадресация, вы получите код состояния HTTP 3xx. Затем вы можете попытаться вызвать фактический URL-адрес, если существует какая-либо переадресация. Для обычного HTTP-ответа вы получите код состояния 2x 2xx.

Поскольку у вас есть объект WebView, чтобы вы могли его перегрузить, а затем обрабатывать URL-адрес, по которому вы wana переходите к своей Деятельности, этими двумя способами.

 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 MyWebView например mWebView.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, это не решение, которое я обновлю после того, как я разрешу это.