7

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:

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?

Community
  • 1
  • 1
Tim
  • 73
  • 1
  • 1
  • 4

2 Answers2

13

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.

CommonsWare
  • 910,778
  • 176
  • 2,215
  • 2,253
  • I've made the suggestions you suggested, but I still can't seem to get this working. When I type http://www.this-so-does-not-exist.com in the address bar I get: "Web page not available". – Tim May 27 '11 at 12:47
  • 1
    @Tim: I don't know if it will work from the address bar. The point is for it to work from a link. – CommonsWare May 27 '11 at 12:48
  • well there's the problem. Thank you for your help! – Tim May 27 '11 at 15:25
  • I have just checked ZXing app. It is not working as it is suggested. Could you please help me in this case... – Nirav Shah Mar 21 '13 at 13:49
  • @NiravShah: Please contact the ZXing team if you are having problems with the ZXing app. – CommonsWare Mar 21 '13 at 13:50
  • I'm trying your URLHandler demo on Android 4.3. It does not work in the sense that BROWSABLE VIEW intent for the mimeType "application/pdf" does not open URLHandler activity when a link to a pdf is clicked in a browser (Chrome and Dolphin was tested). For example, Chrome shows me a list of different apps which ready to process PDF, but your demo is not among them. What's the problem? Thanks in advance. – Stan Oct 19 '13 at 18:02
  • @Stan: Chrome tries to find something that handles the `http` scheme instead of the PDF MIME type. If you look at LogCat, you will see something like: `I/ActivityManager(1177): START u0 {act=android.intent.action.VIEW cat=[android.intent.category.BROWSABLE] dat=http://commonsware.com/Android/excerpt.pdf cmp=android/com.android.internal.app.ResolverActivity (has extras)}`. If you choose a Web browser in the chooser, it will initiate a download, then show a chooser with URLHandler in it, to view the downloaded file. – CommonsWare Oct 19 '13 at 18:33
  • Ok, I added http scheme and now it launches the demo for PDF. Thank you for the clarification. The problem is that I'm trying to customize the demo for processing files of other types actually. But specifing, for example, `image/*` or `image/png` does not work (browser shows the picture on its own). Should I know something more in order to make it work? I don't see any clues for this in the logs. – Stan Oct 19 '13 at 19:15
  • @Stan: You cannot force other apps to necessarily launch a third-party activity. Specifically, I would expect browser apps to handle on their own things that they know how to handle on their own: HTML, images, etc. – CommonsWare Oct 19 '13 at 19:16
  • @CommonsWare ....hello sir...by yours above code, i only understand to handle the data from the link...Can you please tell me that how can i create a link which contains my data...please help me...I want to create the link with data on button click event.. – Ravindra Kushwaha Nov 30 '15 at 13:37
0

Try this, if you want to start your application from browser I've done this yesterday

1) On localhost make the html page

<html>
<head>
</head>
<body>
<a href="yourownscheme://example.com/">Test link</a>
</body>
</html>

2) make a class

   import org.xml.sax.Parser;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class URLHandler extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);



    TextView uri=(TextView)findViewById(R.id.uri);
    TextView uri2=(TextView)findViewById(R.id.uri);


    if (Intent.ACTION_MAIN.equals(getIntent().getAction())) {
      String intentUri=(new Intent("yourownscheme://example.com/")).toUri(Intent.URI_INTENT_SCHEME).toString();



      uri.setText(intentUri);

    }
   }
  }

3) The manifest is below

<?xml version="1.0" encoding="utf-8"?>
<manifest android:versionCode="1"
          android:versionName="1.0"
          package="yourpackage name"
          xmlns:android="http://schemas.android.com/apk/res/android">

  <supports-screens android:largeScreens="true"
                    android:normalScreens="true"
                    android:smallScreens="false" />
  <application android:icon="@drawable/cw"
               android:label="@string/app_name">



      <activity
        android:name=".URLHandler"
        android:label="@string/app_name" 
        android:exported="true">
        <intent-filter>

            <data  android:scheme="yourownscheme://example.com/" />

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


  </application>
</manifest>

4) When you installed you'r application on emulator, open browser and go to localhost tap the link and your application, if it's installed gonna launch, othervice it would be error

Roman
  • 23
  • 4