Issue
I'm building a basic web browser with the android webview component and recently added support for opening links in relevant external apps e.g. if you're on a page and click a youtube link, the youtube app is opened instead of navigating to the web page.
This works fine accept for when an app is freshly installed and you click on a link for the first time (I suspect my app isn't the default browser at this point). Then it always prompts if you want to open it in another app, even if the only other relevant apps are other browsers, which isn't a great user experience as the user is already in the browser they want to open the link in otherwise they wouldn't be using it.
So I need to be able to distinguish between a link that has a dedicated installed app (e.g. it's found a wikipedia app for wikipedia links) vs a link that there are no dedicated apps for and is suitable for any browser to open.
Here's the relevant code in MyWebViewClient.shouldOverrideUrlLoading()
...
Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
if(intent!=null){
PackageManager packageManager = context.getPackageManager();
ResolveInfo info = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (info != null) {
String suggestedPackageName = info.activityInfo.applicationInfo.packageName;
String intentAction = intent.getAction();
final boolean packageMatchesThisBrowser = (MY_PACKAGE_NAME).equals(suggestedPackageName);
final boolean isUrlAttempt = UrlHelper.isUrlAttempt(url);
final boolean areSuggestedAppsOnlyBrowsers = false; // ????
final boolean canItBeOpenedInThisBrowser = isUrlAttempt;
if(canItBeOpenedInThisBrowser && (packageMatchesThisBrowser || areSuggestedAppsOnlyBrowsers)){
return false; // allow the url to load normally in the current web view
}else {
// Else we have a dedicated app link (e.g. tel://, whatsapp://, intent://) or app supported links like (e.g. https://youtube.com/...)
context.startActivity(intent);
return true; // Launched the activity successfully so block webview from loading
}
} else {
// ...
}
}
Solution
Thanks to JensV I think I came up with a working solution. At least it seems to be able to distinguish between dedicated apps for links (Instagram, wikipedia etc) vs general purpose apps like other browsers.
public boolean areResolvedActivitiesOnlyBrowsers(Context context, Intent uriIntent) {
PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> resolvedActivityList;
final String scheme = uriIntent.getScheme();
if (scheme == null || (!scheme.equals("http") && !scheme.equals("https"))) {
return false;
}
// Find all activities that could open the URI intent
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
resolvedActivityList = packageManager.queryIntentActivities(uriIntent, PackageManager.MATCH_ALL);
}else{
resolvedActivityList = packageManager.queryIntentActivities(uriIntent, 0);
}
// Check each activity for a match with the path part of the URI, if
for (ResolveInfo activityResolveInfo : resolvedActivityList) {
final int match = activityResolveInfo.match;
boolean matchesPath = (match & IntentFilter.MATCH_CATEGORY_PATH) > 0;
if(matchesPath){
return false;
}
}
return true;
}
Answered By - MeatPopsicle
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.