Как обрабатывать обратные вызовы URL-адресов OAuth с помощью фильтров Intent, если проверка подлинности выполняется с помощью webview?
Я разрабатываю приложение, использующее OAuth для аутентификации, но у меня есть небольшая проблема с обработкой обратных вызовов OAuth.
АУТЕНТИФИКАЦИЯ
Мое приложение имеет веб-просмотр в качестве экрана входа в систему, и мне предоставляется URL-адрес для загрузки формы
ПРОБЛЕМА
Этот 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-адресом сети, он имеет проблемы с его обработкой и не может даже запустить намерение, которое может справиться с ним.
ВОПРОС
Как я могу решить эту проблему?
Я должен уметь управлять обработкой обратного вызова, но не позволять веб-обозревателю загружать его.
любая помощь будет оценена
заблаговременно
Ответы
Ответ 1
Прежде всего в вашем манифестах, установите эти свойства в свою активность, которая запускает 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);
}
}
Я знаю, что добавил много фрагментов кода, некоторые из которых могут быть неактуальными, но я надеюсь, что когда-нибудь это поможет кому-то.
Ответ 2
Ну, сначала вам может понадобиться вызывать URL-адрес, предоставленный вашим поставщиком услуг, если есть какая-либо переадресация, вы получите код статуса HTTP 3xx. Затем вы можете попытаться вызвать фактический URL-адрес, если существует какая-либо переадресация. Для нормального ответа HTTP вы получите код состояния 2x 2xx.
Ответ 3
Поскольку у вас есть объект 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-адреса, т.е. в веб-браузере, а не в браузере.
но если вы перегрузитесь, пройдя выше 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, это не решение, которое я обновлю после того, как я его разрешу.