Question

I have a Cordova/PhoneGap 2.0 based Android application, and I'm attemping to use intent-filters to register a custom protocol handler.

So my PhoneGap app launches, does its thing, and then later calls out to the Browser app to a remote web page (via navigator.app.loadUrl('http://example.com/') or window.open('http://example.com/')). A link on that remote web page in the Browser (myprotocol://do/stuff) will bring my app back to the foreground via the intent-filter for the data scheme. And via the WebIntents plugin I can get and parse this url in my app.

This is working in Android 4.0.4 on an HTC One X (and thus a 'Sense' version of Android).

The same code does not work on Android 4.0.4 or 4.1.1 on a Galaxy Nexus, or 4.0.1 on a Nexus S.

The odd issue I see on "stock" Android is that while the intent-filter is triggered, it launches a new view of the app, and IN the Android Browser. I can see it reloads the html page. It does not bring the existing app instance to the foreground as expected. Looking at logcat I see that this is actually the same I/Web Console process, but it's loaded the html again. There is no new log of 'Start proc'.

And oddly I now have two instances of my app displayed in the task manager. The original app instance is still there with my custom app icon. And the Browser process has its own Browser app icon, but is clearly running my app UI. I can switch and interact with each webview individually. It's almost like my process now has two web views - one in the app and a second web view now running in the Browser process.

I currently have something like this in AndroidManifest.xml:

<activity android:name="MyApp" android:label="@string/app_name" 
          android:screenOrientation="portrait"
          android:launchMode="singleTop"
          android:configChanges="orientation|keyboardHidden">

    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>

    <intent-filter>
      <data android:scheme="myprotocol" />
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.BROWSABLE" />
      <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>

</activity>

My App is using the WebIntents plugin and the NFC plugin, but I also see the same issue without them. I have also reproduced this issue in PhoneGap 1.8.1 and 1.9.0 as well.

I can also see via logging that for the HTC, DroidGap.onCreate() does not get called when the intent is triggered, but on the Nexus it does.

Am I doing something incorrect in hooking up the intent-filter this way?

How can I trigger the existing app instance to be called, instead of a new one in the browser, on stock Android 4.x?

Was it helpful?

Solution

Using android:launchMode="singleTask" rather than android:launchMode="singleTop" for the activity solved this for my scenario.

It appears that HTC simply handles this differently than default Android should.

Reading http://developer.android.com/guide/components/tasks-and-back-stack.html and viewing how, for example the Google Play Store App is launched by the Browser (in the Browser, in the Task list) on stock Android indicates the behavior I saw was intended, if a bit confusing.

I only have a single activity and intend for there to only be a single instance of my app, so "singleTask" here solved the issue.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top