tags:

views:

235

answers:

1

Hi,

I'm working on an activity which other 3rd parties want to use in their own apps, via intents.

Right now this activity is catching urls via an intent filter, like this:

<activity android:name=".MyActivity">
  <intent-filter> 
    <action android:name="android.intent.action.VIEW"></action>
    <category android:name="android.intent.category.DEFAULT"></category>
    <category android:name="android.intent.category.BROWSABLE"></category>
    <data android:host="www.mysite.com" android:pathPrefix="/test/" android:scheme="http"></data>
  </intent-filter>
</activity>

The above works, whenever a user clicks a link in my app like:

"mysite.com/test/blah.html"

my app comes up as a choice, along with the browser, to open the link.

Now if a third party wants to use my app, I think they can use the above like this:

Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://mysite.com/test/somedata"));
startActivity(intent); 

While this would work, this probably won't give them the desired effect of jumping directly to my activity from theirs - the android chooser dialog will appear, asking if they want to open the intent data with the browser, or my app.

How can I let 3rd parties call my activity directly without broadcasting the intent like this? I'd like to make them still pass the same exact data scheme to me, but just let them open my activity directly.

Thank you

+1  A: 

You would most likely need for them to call your activity directly

Class yourClass = Class.forName("com.yourdomain.yourapp.YourClass");
Intent intent = new Intent(this, yourClass);

If they don't have a jar to link against. Otherwise, they could just use

Intent intent = new Intent(this, YourClass.class);    

And then put some extras in there. The whole concept of the browsable intent (along with the others) is to provide users with a choice of how they would like to view/use something. This is similar to what happens when you click "share" from the media viewer. The whole concept is to give them choice. If somebody wants to just start your activity, they will need to explicitly call it.

Edit: My reflection example above won't directly work unless the Dalvik class loader knows about your class (which it probably won't). You will actually need to specifically tell the VM to load a class from a foreign package. You can do that with the following code

Context foreignContext = createPackageContext("com.yourdomain.yourapp", Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
Class<?> yourClass = foreignContext.getClassLoader().loadClass("com.yourdomain.yourapp.YourClass");

Now that they have the class object, they can then fire the intent like before. So the complete code is something like

Context foreignContext = createPackageContext("com.yourdomain.yourapp", Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE);
Class<?> yourClass = foreignContext.getClassLoader().loadClass("com.yourdomain.yourapp.YourClass");
Intent intent = new Intent(this, yourClass);
startActivity(intent);
Chris Thompson
Ok, I don't understand how they would specify "YourClass" though in their source code - because wouldn't they need to have access to my activity's java file in their project to reference it like that? Thanks
If they were unable to link against your library, reflection could be used to get a handle on the class object. 'Class.forName(someFullyQualifiedClass)' returns a class object for the fully qualified class name. They would need to have knowledge of your class, but the compiler would not. I've updated my answer with sample code.
Chris Thompson
Thanks Chris, that works. Is it non-standard or a bad idea to let 3rd parties call my activity as above? It would still be nice to use intents, I just would like to define my intent in such a way that it doesn't also get fired by the Browser application too? For example, still broadcast an intent, but define it in such a way that no other app is likely to also be registered for it? Thank you
To be honest, I'm not sure I can give you an answer regarding the best practices. Personally, I don't think there's anything wrong with it given what you want to accomplish. In order to more or less guarantee that nobody else uses your intent (although you can't actually guarantee that...) you would need to define a custom intent. Check out this post: http://www.anddev.org/viewtopic.php?p=3435 Good luck!
Chris Thompson
Ok thanks - I am just playing around with it, seems I can add an extra custom category to my intent filter, so someone could add that category to more or less be sure to go directly to my activity without getting prompted for choices (unless someone writes their own activity with the same unique category name I come up with)Thanks
That's what I was thinking! Good luck
Chris Thompson