Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Launching an Android Application from the Browser

I have looked at several Stack Overflow questions with similar titles to mine. Each is answered, and the original author seems satisfied, but when I try to replicate their results I come up empty handed. Obviously I'm doing something horribly wrong, but I can't seem to figure it out.

For reference, these are the questions that I've been looking at:

  • Launch Custom Android Application From Android Browser
  • Make a Link in the Android Browser Start Up My App
  • Android Dev Callback Url Not Working
  • Android Intent Filters: How Do You Use Intent Category Browsable Correctly

Ultimately, I want to use this to restart my application once the user has performed an OAuth authentication request. However, my real application is a bit too large to post here. For this question, I've put together a simple application, to show you what I've done. I have two activities. This is mostly because every example I've seen uses an activity using the VIEW action. I'd prefer to use the MAIN action, but I've used both here to show that I tried both.

AndroidManifest.xml (Original; see edited version below)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.example" android:versionCode="1" android:versionName="1.0-SNAPSHOT">
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
    <activity android:name=".HelloAndroidActivity">
        <intent-filter>
            <data android:scheme="ex1"/>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    <activity android:name=".CallbackActivity">
        <intent-filter>
            <data android:scheme="ex2"/>
            <action android:name="android.intent.action.VIEW"/>
        </intent-filter>
    </activity>
</application>

AndroidManifest.xml (Edited in response to comment)

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.example" android:versionCode="1" android:versionName="1.0-SNAPSHOT">
<application android:icon="@drawable/icon" android:label="@string/app_name" android:debuggable="true">
    <activity android:name=".HelloAndroidActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
    </activity>
    <activity android:name=".CallbackActivity">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
            <data android:host="www.this-so-does-not-exist.com" android:scheme="http" />
        </intent-filter>
    </activity>
</application>

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

HelloAndroidActivity.java

package org.example;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

public class HelloAndroidActivity extends Activity {

    private TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView) findViewById(R.id.textView);
    }

    @Override
    public void onResume() {
        super.onResume();
        Intent intent = getIntent();
        Uri data = intent.getData();
        if (data != null) {
            textView.setText("Hello Web!");
        }
    }

}

CallbackActivity.java

package org.example;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.widget.TextView;

public class CallbackActivity extends Activity {

    private TextView textView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView) findViewById(R.id.textView);
    }

    @Override
    public void onResume() {
        super.onResume();
        Intent intent = getIntent();
        Uri data = intent.getData();
        if (data != null) {
            textView.setText("Hello Web!");
        }
    }

}

This builds happily enough. Then, inside the browser, if I enter ex1://helloworld or ex2://helloworld I get different results depending upon how it is done. If I enter it in the url bar I get a google search for ex1://helloworld. If I do it via a redirect, I get "Web page not available". If I try to start the intent directly with something similar to:

    Intent intent = new Intent(Intent.ACTION_MAIN);
    ComponentName componentName = new ComponentName(
            "org.example",
            "org.example.HelloAndroidActivity");
    intent.setComponent(componentName);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setData(Uri.parse("ex1://helloworld"));
    intent.addCategory(Intent.CATEGORY_BROWSABLE);
    startActivity(intent);

I get the default "Hello my-example!". I'm not sure what I'm doing incorrectly. Any insights?

like image 221
Tim Avatar asked May 26 '11 13:05

Tim


People also ask

Can we open an Android app from browser?

Opening an installed app from a browser is known as “deep linking”, and with this guide you'll learn how to deep link into your Android app from the mobile web. We'll focus exclusively on how to trigger an app open from a website page, rather than from the click of a link inside other apps.

Can we open an mobile app from browser?

Just head on over to the Play Store in your browser and find the application. I highlighted the Application ID in the screenshot's address bar above. The Application Scheme is a little more tricky, but still quite doable. There are many ways to acquire the APK of an Android app.


1 Answers

You cannot use MAIN -- URLs in Android are only VIEWed from the browser or WebView.

Also, none of your Intent filters include the BROWSABLE category, so they will never work with the browser.

It is not recommended to invent your own schemes. You can use a regular HTTP scheme, for some domain that you control. This sample project demonstrates this. In particular, you can follow the pattern shown by this filter:

<intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:host="www.this-so-does-not-exist.com" android:scheme="http" />
</intent-filter>

replacing www.this-so-does-not-exist.com with something you own, and perhaps adding in a path to narrow the filter's scope. You can also see this technique used by the Barcode Scanner app from ZXing.

like image 108
CommonsWare Avatar answered Oct 18 '22 00:10

CommonsWare