I am trying to programmatically add and remove application shortcuts from the app drawer. I understand the app drawer knows which applications should be presented by using an intent filter with the LAUNCHER category.
I would like to be able to add/remove shortcuts to specific activities in my application, according to dynamic conditions, which is why I can't have them simply in my manifest file.
Thank you.
As far as I know, this is not possible. Unfortunately, with the current Android API level there is no way to add IntentFilters to Activity objects through code. Check out this doc on intent filters. Relevant quote:
An intent filter is an instance of the IntentFilter class. However, since the Android system must know about the capabilities of a component before it can launch that component, intent filters are generally not set up in Java code, but in the application's manifest file (AndroidManifest.xml) as elements. (The one exception would be filters for broadcast receivers that are registered dynamically by calling Context.registerReceiver(); they are directly created as IntentFilter objects.)
Related
We have an app with an Activity that can be started in two ways:
From another Activity - always with some extra data filled in
From deep linking
As far as I can see this is always working just fine. We either get the Intent.ACTION_VIEW with a data URI, or we get some string extras.
However, we have a very few instances where action is Intent.ACTION_MAIN and there are no extra data.
The toString() of the Intent is as follows (class name changed):
Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10400000 cmp=com.example.OurActivity }
Intent.getExtras() returns null, Intent.getDataString() returns null.
In which cases can this happen? Why is the category for the Activity Intent.CATEGORY_LAUNCHER? How can we get the data needed to show the user the right contents?
launchMode is not specified for the Activity. The only IntentFilter in AndroidManifest.xml is for the deep linking (and not the launcher category).
The issue happens on Android 4-6 on a wide range of devices.
Edit: Forgot to mention the flags:
As the print out suggests the flags for the Intent are FLAG_ACTIVITY_NEW_TASK and FLAG_ACTIVITY_BROUGHT_TO_FRONT. I suppose that could be relevant here.
I believe, I nailed it:
There're launchers, like Nova Launcher which allows users to start with any of app's Activities, instead of the normal flow:
For example, you can add a shortcut on your desktop to start Gmail client with Account setup Activity.
And in this case, Activity is being started with empty Extras and technically it becomes a launcher's Activity.
Now that AndroidManifest.xml is manipulated by the build system, it often happens that libraries that you include also add things to the manifest, which I suspect may be happening here.
Although you state that there is only one IntentFilter in the manifest, have you actually checked the installed app to see what its manifest says (rather than relying on what you think you put in your source code)?
Various apps are available in the Play Store to show you the manifest of an installed app - including App Detective (which I wrote).
We specify current activity and start activity for an intent and we call it through the method startService(). So why do we need to mention that activity in manifest again?
Indexing (what can your app do?)
I can answer at least part of the why for Activities. The manifest is also where you declare your IntentFilter which is how the system understands what your application does. i.e. should your activity be an illegible choice when the user is trying to take a picture? choose a file? share a piece of text? In addition to that the IntentFilter also tells the Launcher application that you would like to have your activity included in the Applications drawer.
Configuring (what is your main activity?)
There are also several configuration options that you can set on Activities which have to be done in the manifest i.e. SingleTop. Without the declaration in the manifest there would be no place to declare these configurations.
Time Saving (where can the system find your service?)
The manifest file is used by the system to know what kind of components do the application have. Without registering your Activities/Services/Receivers/Content Providers the system would have to scan and parse the whole apk every time someone wants to use a specific component to find it. This would be really slow, that's why there is the AndroidManifest.xml, which is a small file, and it can be parsed fast to find the required component.
Sources: Why do Activities/Services need to be explicitly added to the Android manifest? why acitivies have to be registered in manifest file
Each android application you build will include a file called
AndroidManifest.xml which is placed in the root of the project
hierarchy. So why is it important? Because it lets you define the
structure and metadata of your android application and its components.
http://simpledeveloper.com/android-application-manifest-file/
background:
i've noticed that for regular activities within, it is possible for any application to open the activities of my app .
question:
is it possible to allow only my own app (or apps , or package) to send and receive intents inside the same scope , so that other application won't be able to receive them or interfere with the flow of the app?
example:
suppose i have a broadcastReceiver that listens to some kind of intent , but this intent is only meant to be used by another service/activity that resides either inside my app , or inside another app that i've created , but i don't want others to be able to use this intent.
please help me.
setPackage()
Set an explicit application package name that limits the components this Intent will resolve to. If left to the default value of null, all components in all applications will considered. If non-null, the Intent can only match the components in the given application package.
or you can use setSelector() , but not both.
suppose i have a broadcastReceiver that listens to some kind of intent , but this intent is only meant to be used by another service/activity that resides either inside my app , or inside another app that i've created , but i don't want others to be able to use this intent.
In addition to Reno's fine answer, for your specific requirement quoted above, use LocalBroadcastManager. Not only do you get the security you seek, but it is more efficient. LocalBroadcastManager is available in the Android Support package and AFAIK should work going back to Android 1.6. Here is a sample project using LocalBroadcastManager.
Is there an app or another possibility to watch for ALL Intents and Broadcast flowing in an android system?
Maybe another app which uses a special intent (not the standart ones) you want to use or broadcast yourself.
You can't listen to every Intent.
If you are worried that someone else uses your intent use your package name as prefix.
For example if you are willing to have an intent with the action SERVER_UPDATE, use: com.nitromouse.appname.SERVER_UPDATE
why not? Just list all permitted intents in the intent filters section. If you find that intimidating, write a program to write the xml menifest (or may be pay someone for typing)?
Oh.. dont forget to add all required permissions also...
What's the proper way for other people to reuse my Activities? Should they hard code the intent actions in their app or is it customary to provide them with a jar file enumerating my app's intent actions? Is there a less tightly-coupled way to lookup the intent actions?
First of all, take a look at openintents.org and see if there's any match to what your activity does.
Secondly, documentation is always a good idea.
Having the intent details hardcoded in their applications should work just fine. After all, the intents are part of your public interface and shouldn't change.
Your applications manifest should announce what sorts of things your activity can handle, via intent-filters. Outside users can read the manifest to determine what actions you support, and invoke them via action intents.
See intents and intent filters for more details.