Android app defaults - two handling activities, setting default activity - android

I'm doing something like custom browser with 2 options: View or Download page. Manifest file looks something like this:
<activity android:name=".ViewActivity" .... >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http" />
<data android:scheme="https" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
<activity android:name=".DownloadActivity" .... >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<data android:scheme="http" />
<data android:scheme="https" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
</activity>
When I open URL I can select what to do. Everything works fine until I select DownloadActivity and confirm with ALWAYS -> it sets app defaults (Open by default). And next time when I click on link, URL is handled by ViewActivity (just because it is first declared in Manifest file - I tried to swap activities in manifest).
Can you help me how to fix it a set the default Activity (not Application) for opening URL? And when I set Download as ALWAYS so it will be always downloading and if I set View as ALWAYS it will be always Viewed. Is it possible? Or is there any other possible solution?
Thanks

I'm not 100% sure, but I think it is a limitation of how android stores "default" (by clicking on ALWAYS) and dispatches url to intent filter.
Android stores just which application should be open by clicking on ALWAYS, and not which Activity, because Activities can be renamed, deleted etc. So imagine you as the android system has to lookup how to open http://foo.com for an app. You have to look at the in the internal lookup table for the "default" (by clicking on ALWAYS) and then determine that the app with the package com.example.myapp should be open.
Now imagine that rather than just the package name of the app you would store the concrete Activity com.example.myapp.DownloadActivity. That would be dangerous as hell, because DownloadActivity could have been renamed, deleted or even just the intent filter could has been removed from DownloadActivity between setting DownloadActivity as "default" and an update of your app that has introduced that change.
The only thing the android operating system gets notified is when an app has been installed or uninstalled, but not if an activity of an app has been renamed or deleted etc.
Hence is not possible for android to guarantee that it can keep the mapping from http://foo.com to com.example.myapp.DownloadActivity up to date.
Therefore, Android is just launching the app with package com.example.myapp for `http://foo.com and then let the app dispatch it internally to the first Intent filter that matches from your apps manifest.
As already said, I'm not 100% sure, but to me it seems reasonable ...

Related

Intent-filter - Open NEW application, not embedded one

I don't know if it's really understandable.
When i'm clicking on a llink in a mail, I can open this link with my application and that's perfeclty what I want.
<intent-filter>
<data android:scheme="https" android:host="xxx.xxx.com"/>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.BROWSABLE"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
BUT
When i'm opening my application like that, and I check the opened application, I see that my application is "inside" Gmail task, like that
But, when i'm opening the link with Chrome for exemple, Chrome is opening in his own task, like that
How can my application open in her own task and NOT inside Gmail's one ?
you have to set a specific andorid:launchMode to your activity:
android:launchMode="singleTask"
or
android:launchMode="singleInstance"
placed in the declaration of your activity in the AndroidManifest.xml will do it.
take a look also at this article that explain how android handles tasks and activities

Launching custom Android application from Android browser / Chrome

First of all, my question is extremely similar to this, this and this. The Android documentation for what I'm trying to achieve is here. I couldn't get this to work using these resources so please don't mark this as duplicate as it is not.
I have a website and an Android application. The user will be able to scan QR codes that contain links like http://mywebsite.com/map/. When the user tries to open this link, I want Android to show him a chooser dialog where he can choose to open that link using my application. If my application is not installed, it should proceed to the specified website.
I know Chrome allows this by opening the chooser dialog when the user navigates to that address. For example, try downloading the Stack Exchange app and going to this question in Chrome. It will show this:
I have added the following code in AndroidManifest.xml after following the suggestion in the above-mentioned answers:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="mywebsite.com"
android:path="/map"
android:scheme="http" />
<data
android:host="mywebsite.com"
android:path="/animals"
android:scheme="http" />
<data
android:host="mywebsite.com"
android:path="/articles"
android:scheme="http" />
</intent-filter>
Also, I have tried adding android:mimeType="text/plain" to data but it didn't help.
The problem is that when I go to http://mywebsite.com/map or http://mywebsite.com/map/ Chrome just opens the webpage without showing the chooser dialog.
I would like to mention:
following the Android documentation, I have added this code inside one of the activity structures in AndroidManifest.xml. As I am not sure this is the perfect place to add it, I have also tried adding it outside the application structure and directly inside the application structure but it didn't work
this is the only code I have implemented for this to work. If something else is needed please let me know. From what I understand, adding a href to the webpage is only needed when using custom schemas
I do not want to use a custom schema in order to achieve this
I am developing on a Nexus 4, running Android 4.4.2 (latest)
You need to set it up like this :
<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="example.com"
android:pathPrefix="/someresource/"
android:scheme="http" />
<data
android:host="www.example.com"
android:pathPrefix="/someresource/"
android:scheme="http" />
</intent-filter>
Notice that in your case, you would need to use android:pathPrefix instead of android:path.
Just to be sure, you should reset the preferences for your app in case you have accidentally set it to always open the link in chrome rather than show the chooser dialog. Once "Always" is used to open the matching uri, it will never show the chooser.
Second, you can have as many data elements in the intent filter as your want, but it is not necessary to repeat information. You can do the same thing like this:
<data android:host="mywebsite.com"/>
<data android:scheme="http"/>
<data android:path="/map"/>
<data android:path="/animals"/>
<data android:path="/articles"/>
But note that for the path, you can just use a wildcard
<data android:path="/.*"/>
Consider adding an additional
<data android:host="www.mywebsite.com"/>
And finally you may not want to show the chooser dialog but open a specific app intent/activity directly. On your website, if you detect the android user agent, you can create a link url this way:
<a href="intent://mywebsite.com/articles#Intent;package=com.myapp;scheme=http;end;"/>
See here for more details How do I open any app from my web browser (Chrome) in Android? What do I have to do with the A Href link?
Note that with this method if the app is not installed the user will be taken to the Google Play store for the specified app package.
If you are still having problems, check your intent filter priority. http://developer.android.com/guide/topics/manifest/intent-filter-element.html
In my case site URL is: http://www.example.org/mobile/
so putting these code into AndroidManifest.xml inside activity
<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.example.org"
android:pathPrefix="/mobile/"
android:scheme="http" />
</intent-filter>
Here,
scheme -> Protocol of particular site
host-> Exact site url with WWW
pathprefix - > Your site's sub path if available
Now,
You can search with chrome / etc android browser'search box like example then open chosen dialog ..!!

Reading a custom file launched using Box

We have developed an Android app which is used for rendering files of our custom file type (.vds). I am able to launch my app for all the files (.vds file) which are stored on local storage, but if the files is stored on Box and I try to access them using the Box Android App then I am facing issues. I have created the following intent filter:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="file" />
<data android:host="*" />
<data android:pathPattern=".*\\.vds" />
The problem is that in the corresponding activity I am able to get the intent, but if I try to read the URI (as our rendering logic is based upon file location) it gives me a path which doesn't exists on the SD card. What happens if we try to open a file using Box Android Native App? Where is the file downloaded and how should the downloaded file be accessed?
This may solve ur problem. Add the bellow intent filter.
<activity android:name=".Activity"
android:screenOrientation="portrait"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.EDIT"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:pathPattern="*.snowdragon"/>
<data android:mimeType="text/snowdragon"/>
</intent-filter>
</activity>
As noted above I've run into the same problem. While I've not found what I would consider to be The Right Solution(TM) I do have a couple of things to add that might be useful to others:
First, I've discovered that if I download the file in Box (not the same as mark for offline) then clicking the item in either the download result dialog or in the subsequent notification that appears at the bottom of the app works. Once you've dismissed that notification however, there does not seem to be a way to get back to the downloaded file from within Box.
Second, and let me qualify this by saying that I've not looked very closely at it yet but I think one could use the filename info in the intents for non-existent files to retrieve the file via the Box API, either directly from the cloud or possibly via API call to retrieve offline items. I'm wondering if this is actually what Box is trying to get us to do with these bogus file paths, considering that they are so blatantly bogus:
12-04 10:09:29.318: INFO/ActivityManager(607): START u0
{act=android.intent.action.VIEW dat=file:///non_existent_dummy_folder/foo.abcdef typ=application/abcdef cmp=com.foo.bar/.app.FooViewer}

Android: using intent filter to launch app doesn't work

I know this question is asked and answered many times on SO, but I just couldn't get it to work. Here is my manifest file (I have 3 activities, I'm showing the only one that I want to be displayed when associated):
<activity
android:name=".MyActivity"
android:label="#string/app_name"
android:theme="#style/HoloDarkTheme" >
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.ACTION_SEND" />
<action android:name="android.intent.action.EXTRA_TEXT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.action.BROWSABLE" />
<category android:name="android.intent.action.DEFAULT" />
<data android:scheme="http" />
<data android:host="example.com" />
</intent-filter>
</activity>
When I launch a browser and go to "example.com", my app isn't launched. Is there something wrong with the above XML?
Not sure if relevant, but this activity uses MediaPlayer to play videos. Also, I'm using SDK version 11.
I figured it out. It's simply a case of typo. Instead of this,
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.action.BROWSABLE" />
<category android:name="android.intent.action.DEFAULT" />
I needed to replace "android.intent.action" with "android.intent.category" in the last two lines:
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
I'm adding this answer here because this thread is one of the top hits when googling "intent filter to launch app from http not working". I suppose the root cause for me could also be considered a typo, but I'm going to call it an "Android documentation defect".
There's a line way toward the bottom of this page that breaks down a URI as:
<scheme>://<host>:<port>/<path>
This breakdown indicates that the "://", ":" and "/" will be added for me so I used the following data in my intent-filter:
<data android:scheme="http" />
<data android:host="my.school.edu" />
<data android:path="thingy" />
I then sent myself an SMS with the following text: "my.school.edu/thingy", which was recognized by my SMS client (Hangouts) as a web address, so it made it clickable. However, clicking on it just gave me a choice of browsers, my app was a no-show.
So I removed the host and the path, and my app launched for any link (or at least every one I tried). I put the host back in and it still worked. Put the path back and we're back to not working. On a whim I decided to prepend a slash to the path:
<data android:path="/thingy" />
...et voilĂ ! There's my app in amongst the browsers! So the error in my view is Android's doc that suggests that the slash is inserted automagically. :) It apparently is not.
More Info: I'm using the HTTP scheme because that's what gets made clickable in SMS and email messages, giving me a free ride to that point.
And note that if you specify a unique host (and path), and the user selects "Always" when choosing your app from the list, future taps on your link will bypass that choice dialog and go straight to your app, which is nice.
Make sure you have the internet permission in your manifest.
I doubt that you can override the http scheme to point back to your app.

How can I start the next matching activity if my app is the default one

I have an activity that works as a hook for various intents. Specifically, the VOICE_COMMAND and CALL_PRIVILEGED. (It is a requirement to use these.)
<activity android:name=".MyActivity"
android:enabled="true">
<intent-filter>
<action android:name="android.intent.action.VOICE_COMMAND" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.CALL_PRIVILEGED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="tel" />
</intent-filter>
</activity>
I ask the user to set my app as the default action for these intents so they don't have to select it every time. This is also a requirement.
The problem is that in certain cases I want my activity to work transparently and pass the intent to the dialer or other app. This should be selectable by the user. I achieved this by using getPackageManager().setComponentEnabledSetting(myCompName, isEnabled, PackageManager.DONT_KILL_APP) on my activity in certain places of the code.
Is there a more elegant way to do this? I tried startNextMatchingActivity(getIntent()) but that does not start anything (returns false). Does this mean that if there is a default action, then everything else is ignored from the intent resolution?
Currently (on Android 2.3) there seems to be no other way of forwarding the intent than doing it manually. Additionally, to send CALL_PRIVILEGED intent the app must have special permissions that only system apps have. (The app will receive not allowed exceptions otherwise.)
All in all, the intent must be converted to some other intent that my app can send and start the next activity manually by retrieving the list of applicable activities from the PackageManager.queryIntentActivities() API.

Categories

Resources