Как обращаться с намерением://по URL-адресу webView?
В настоящее время я разрабатываю приложение для Android с webView
. На некотором urls
мне нужно использовать метод shouldOverrideUrlLoading
, который довольно прямолинейный:
if(url.startsWith("something")){
//do something
return true;
}
Моя проблема:
Некоторые urls
, например, в поиске google, имеют следующую схему URL
:
intent://en.m.wikipedia.org/wiki/Test_cricket#Intent;scheme=http;package=org.wikipedia;S.browser_fallback_url=https%3A%2F%2Fwww.google.pt%2Fsearchurl%2Fr.html%23app%3Dorg.wikipedia%26pingbase%3Dhttps%3A%2F%2Fwww.google.pt%2F%26url%3Dhttps%3A%2F%2Fen.m.wikipedia.org%2Fwiki%2FTest_cricket;S.android.intent.extra.REFERRER_NAME=https%3A%2F%2Fwww.google.pt;launchFlags=0x8080000;end
Я пробовал использовать:
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity(browserIntent);
Но у меня есть ошибка:
10-15 15:18:15.546: W/System.err(29086): android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=intent://en.m.wikipedia.org/wiki/Test_cricket }
Как мне обращаться с такой схемой URL
?
ОБНОВЛЕНИЕ:
Следуя комментариям @CommonsWare, я попытался использовать parseUri()
в Intent
для создания Intent object
из URL
, а затем попробуйте startActivity()
, что-то вроде:
Intent myIntent = new Intent().parseUri(url, Intent.URI_INTENT_SCHEME);
startActivity(myIntent);
Но я все еще получаю:
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=http://en.m.wikipedia.org/wiki/Test_cricket flg=0x8080000 pkg=org.wikipedia (has extras) }
Возможно, у меня неверные инструкции, или я просто не могу построить Intent
как указано @CommonsWare. Любые советы о том, как построить Intent
?
Ответы
Ответ 1
Структура URL-адреса этого намерения описана здесь https://developer.chrome.com/multidevice/android/intents.
Поэтому мы можем справиться с этим во внутреннем WebView следующим образом:
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("intent://")) {
try {
Context context = view.getContext();
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
if (intent != null) {
view.stopLoading();
PackageManager packageManager = context.getPackageManager();
ResolveInfo info = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (info != null) {
context.startActivity(intent);
} else {
String fallbackUrl = intent.getStringExtra("browser_fallback_url");
view.loadUrl(fallbackUrl);
// or call external broswer
// Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(fallbackUrl));
// context.startActivity(browserIntent);
}
return true;
}
} catch (URISyntaxException e) {
if (GeneralData.DEBUG) {
Log.e(TAG, "Can't resolve intent://", e);
}
}
}
return false;
}
Ответ 2
Ответ товарища - тот, который нужно использовать.
То, как мне удалось решить это, не изящно, но оно работает.
Сначала мы проверяем, если URL startsWith
с intent://
и содержит scheme=http
, если это так, то мы получим значение сразу после намерения:// everything until#
и передать его в Intent.ACTION_VIEW
, если нет, то return false
(игнорировать нажмите).
Я протестировал это решение с несколькими результатами поиска в Google, например, Twitter, facebook, google maps и wikipedia, и он работал безупречно.
@Override
public boolean shouldOverrideUrlLoading( WebView view, String url) {
if(url.startsWith("intent://") && url.contains("scheme=http")){
url = Uri.decode(url);
String bkpUrl = null;
Pattern regexBkp = Pattern.compile("intent://(.*?)#");
Matcher regexMatcherBkp = regexBkp.matcher(url);
if (regexMatcherBkp.find()) {
bkpUrl = regexMatcherBkp.group(1);
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://"+bkpUrl));
startActivity(myIntent);
return true;
}else{
return false;
}
}
return false;
}
Если у вас есть лучшее решение, я бы хотел его услышать.
Спасибо всем за поддержку, особенно CommonsWare.