10

I had an app that used to open the phone browser, where the user would be redirected to my webapp, where after a certain user action, the webapp redirects back to the app using intent filters

 <application>     
<activity
                android:name="com.xyz.sdk.SomeActivity"
                android:allowTaskReparenting="true"
                android:configChanges="keyboardHidden|orientation|keyboard|screenSize"
                android:launchMode="singleTask"
                android:noHistory="true"
                android:theme="@android:style/Theme.NoTitleBar">
                <intent-filter>
                    <data android:scheme="someString-${applicationId}" />
                    <action android:name="android.intent.action.VIEW" />
                    <category android:name="android.intent.category.DEFAULT" />
                    <category android:name="android.intent.category.BROWSABLE" />
                </intent-filter>
            </activity>
 </application>

Recently I migrated to using Chrome Custom Tabs instead of browser (Webview is not an option due to security concerns)

Unfortunately, when redirecting back to app in chrome custom tabs the chrome custom tab does not auto close. Even though i can verify via logs that the app has received the response, the custom tab remains open and stays on top, so the user cant see whats happening on the app, until he closes the app.

One workaround i found to this was to set the NEW_TASK flag while initiating my custom tab, but that makes my app and the custom tab show up as two separate apps which is the entire reason I moved away from browsers in the first place.

In summary: I have App A, which opens a custom tab, the webapp opened in the custom tab redirects back to App A using intent filters, but the vustom tab does not close and remains on top until the user manuall closes it.

I have tried setting the NO_HISTORY flag for the custom tab intent but it made no difference.

custom tab code:

   CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
                         .setShowTitle(true)
                         .setToolbarColor(getToolBarColor())
                         .setStartAnimations(this, android.R.anim.slide_in_left, android.R.anim.slide_out_right)
                         .setExitAnimations(this, android.R.anim.slide_in_left, android.R.anim.slide_out_right)
                         .build();
                 customTabsIntent.intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
                 customTabsIntent.launchUrl(this, Uri.parse(url));
                 customTabsIntent.launchUrl(this, Uri.parse(url));

UPDATE I have realized that if the intent filter redirect back to a different app, then the custom tab closes successfully (provided its a singletop activity and no history is set to true) But in my case, we need to redirect back to the same activity from which custom tabs was invoked.

Vardaan Sharma
  • 1,125
  • 1
  • 10
  • 21

2 Answers2

13

I also faced the same issue, but in my case its now working.

I launched the custom tab with FLAG_ACTIVITY_NO_HISTORY and FLAG_ACTIVITY_CLEAR_TOP.

customTabsIntent.intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
customTabsIntent.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

And launchMode of my activity was "singleTop".

<activity
    android:name=".SomeActivity"
    android:theme="@style/SomeTheme"
    android:configChanges="keyboardHidden|orientation|screenSize"
    android:noHistory="true"
    android:launchMode="singleTop" >
    <intent-filter>
        <data android:scheme="intent" />
        <data android:scheme="myFile" />
        <data android:scheme="myScheme" />
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
</activity>

An important update by @bkant:

I was able to get this to work by changing the launch mode from 'singleTop' to either 'singleTask' or 'singleInstance'. In this mode, the redirect will come to the same Activity via 'onNewIntent'.

mdrafiqulrabin
  • 1,657
  • 5
  • 28
  • 38
  • i made the manifest changed like you suggested, still no effect – Vardaan Sharma Mar 01 '17 at 12:03
  • 1
    I was able to get this to work by changing the launch mode from 'singleTop' to either 'singleTask' or 'singleInstance'. In this mode, the redirect will come to the same Activity via 'onNewIntent'. – bkant Oct 23 '17 at 11:46
  • got it working :) did not have to make any manifest changes. Just was careful of how the activity stack was and adding the flags fixed it. – Vardaan Sharma Jan 30 '18 at 08:21
  • @VardaanSharma Can u pls explain me what you did. – sver Feb 10 '20 at 08:14
1

This problem can exist in Xamarin too and the answer applies to issue when using Xamarin.Forms. It can be applied by modifying the Activity attribute. Modify the code to match LaunchMode = LaunchMode.SingleTask

Here is a modified example of Xamarain.Auth from https://developer.xamarin.com/samples/xamarin-forms/WebServices/OAuthNativeFlow/

namespace OAuthNativeFlow.Droid
{
     [Activity(Label = "CustomUrlSchemeInterceptorActivity", NoHistory = true, LaunchMode = LaunchMode.SingleTask)]
     [IntentFilter(
         new[] { Intent.ActionView },
         Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
         DataSchemes = new[] { "<insert custom URL here>" },
         DataPath = "/oauth2redirect")]
     public class CustomUrlSchemeInterceptorActivity : Activity
     {
         protected override void OnCreate(Bundle savedInstanceState)
         {
             base.OnCreate(savedInstanceState);

             // Convert Android.Net.Url to Uri
             var uri = new Uri(Intent.Data.ToString());

             // Load redirectUrl page
             AuthenticationState.Authenticator.OnPageLoading(uri);

             Finish();
         }
     }
 }
samuel.molinski
  • 1,119
  • 10
  • 24