Don't hardcode Chrome when opening custom tabs

Describe the problem you’re having:

In the Android app, The “Use quick preview” setting always opens Chrome custom tabs, even if you have a different default browser that also supports custom tabs.

If possible include steps to reproduce the problem:

  1. Install another browser that supports custom tabs (for example: Chrome Beta, Firefox Focus (Not the same as the regular Firefox, which doesn’t support custom tabs), or Samsung Internet).
  2. Set it as your default browser.
  3. Enable “Use quick preview” in settings.
  4. Open a link in the Android TTRSS app.
  5. Click the dots menu on the top right corner and notice that it says “Powered by Chrome” and not your default browser.

tt-rss version (including git commit id):

Tiny Tiny RSS Android app 1.213.

Platform (i.e. Linux distro, PHP, PostgreSQL, etc) versions:

Android 7.1.2, Nexus 5X.

Please provide any additional information below:

The Gmail app is an example of the expected correct behavior. Enable Gmail settings -> General Settings -> Open web links in Gmail, then open a link from an email and notice how the custom tabs it opens belong to your default browser, not Chrome.

this feature uses a client library (by google) which likely only supports chrome. the fact that this feature is literally called chrome custom tabs not whatever custom tabs is a pretty obvious clue imo.

before your next question no i’m not adding custom tab support for your bespoke browser.

Yeah, it’s called Chrome Custom Tabs, but it’s possible to implement the same protocol by different browsers. And like I said, the Gmail app does use the default browser somehow.

So anyway, I looked into it and i think the issue is this line (https://tt-rss.org/fox/tt-rss-android/blob/master/org.fox.ttrss/src/main/java/org/fox/ttrss/CommonActivity.java#L173 ) which uses a hardcoded package (com.android.chrome).

I also found a possible solution (https://gist.github.com/HellPie/d2216291dd46154798b9#file-chrometabsutils-java-L233 ), which requires mucking with PackageManager to find the default browser and then guess if it supports Custom Tabs or not. I totally understand if you don’t want to support this. And to be honest, it should’ve been the default behavior for CustomTabsClient anyway, but Google just can’t seem to be able to write sane APIs.

Looks like it’s in the documentation: Présentation des onglets personnalisés Android  |  Web on Android  |  Chrome for Developers

Preparing for other browsers

Remember the user may have more than one browser installed that supports Custom Tabs. If there’s more than one browser that supports Custom Tabs and none if them is the preferred browser, ask the user how she wants to open the link

/**
 * Returns a list of packages that support Custom Tabs.
 */	
public static ArrayList getCustomTabsPackages(Context context) {
    PackageManager pm = context.getPackageManager();
    // Get default VIEW intent handler.
    Intent activityIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.example.com"));
    // Get all apps that can handle VIEW intents.
    List resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
    ArrayList packagesSupportingCustomTabs = new ArrayList<>();
    for (ResolveInfo info : resolvedActivityList) {
        Intent serviceIntent = new Intent();
        serviceIntent.setAction(ACTION_CUSTOM_TABS_CONNECTION);
        serviceIntent.setPackage(info.activityInfo.packageName);
        // Check if this package also resolves the Custom Tabs service.
        if (pm.resolveService(serviceIntent, 0) != null) {
            packagesSupportingCustomTabs.add(info);
        }
    }
    return packagesSupportingCustomTabs;
}

well why not, i’ll try to add this when i’m back in town.

and yes the library should just work like that by default but lol google lol android etc

as usual for google the documentation is literal garbage

“here’s a way to get all browsers which implement custom tabs, you should use the preferred one, no we are not going to tell you how to figure out which one is preferred”

okay, time to snack overflow, as usual

5 minutes later

“You may want to check ResolveInfo#preferredOrder to check if the user has preference on one of the apps over the others. Also, if there’s no preferred app (or two apps have the same major preference level), you may want to ask the user to choose one, or go with reasonable defaults”

preferredOrder
added in API level 1
int preferredOrder
Order of result according to the user's preference. If the user has not set a preference for this result, the value is higher values are a higher priority.

oh god so they want me to sort this list by this field or something because some alpha ubersperg might have a cascading priority list of fucking browsers (i can’t even imagine how would you set something like that in android UI)

sorry boys gonna file this as “maybe later, when i’m too bored to function” for the time being, merge requests are welcome

thanks to https://git.tt-rss.org/git/tt-rss-android/pulls/3 new beta build with this should be up soon

i don’t have firefox installed so someone else will have to test if this actually works like it should

I just tried the beta and this feature works correctly. Thanks.

Tried the beta, seems to work as expected with Firefox Focus. Thanks Fox.

gonna push this to prod then

thank the guy who submitted the PR, i’d never bother myself

Thanks feuerplatz… :slight_smile:

I installed on 2 devices this AM and on both when I launch I just get a black screen. Samsung Galaxy 8+ and a Chromebook Android environment.

app doesn’t load at all? uhoh

looking by my crash reports its like everything is completely and utterly fucked on some devices

nice

e: 2017-11-21 (897 crashes, 29 unique installs) - posted crash to the PR

i’ve pushed an update which reverts this change to production, i guess we had to test it just a bit more lol

we’re at 1000 crashes now

It’s just a guess, but I think the crash happens when getCustomTabPackageName() returns null. Maybe check if it’s null and return "com.android.chrome" instead?

pls post this on the PR, not sure if author reads this thread

i think you’re right, if i set this manually to null i get the exact same exception on the avd

it’s probably this:

		if (packagesSupportingCustomTabs.isEmpty()) {
			s_customTabPackageName = null;

i’m not sure why would this list be empty (no chrome installed? who cares) but it’s fairly obvious that this function should either never return null or null value shouldn’t be used if returned, personally i would just default to chrome package in this case.

https://git.tt-rss.org/git/tt-rss-android/commit/bf5528dd5e245276af373b615d35c1f18b98f769

i wonder if i should wrap this in try-catch too just in case tbh

Can we get a beta release that enables this again?

yeah, sorry, i was busy with other stuff. i’ll try to put a beta up tomorrow.

new beta (1.230) should be up soon

sorry for the delay