I've seen several different apps (like NFC TagInfo and NFC TagInfo by NXP) that have an option to autostart (or show up in the "select app" list) when a tag is touched only if that option is set in the preferences, and otherwise it seems like the intent filter is totally ignored by the system.
How can this be done in an Android application?
Full answer is to use an <activity-alias> in the app's manifest, like this:
<activity-alias
android:name=".ActivityAlias"
android:targetActivity=".YourActualActivity"
android:enabled="false" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity-alias>
YourActualActivity is the class for which you want to be able to turn on or off the intent filter. As you do not want to disable the complete activity, you use an activity-alias in which you put the intent filter that you want to enable (here it's disabled by default).
In your PreferenceActivity you set up a listener that is called when the particular setting is changed. It then does something like this:
getPackageManager().setComponentEnabledSetting(
new ComponentName("your.package.name", "your.package.name.ActivityAlias"),
changedBooleanPreference ? PackageManager.COMPONENT_ENABLED_STATE_DISABLED :
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
Here changedBooleanPreference is the setting that has been changed.
Note that it may take some time before the package manager has made the change effective. It depends on the Android version when and how fast that happens (and perhaps also on the CPU speed of the device).
You can disable the component that has the <intent-filter> you wish to have ignored, by using PackageManager and setComponentEnabledSetting().
Related
I am developing a launcher app for android and for that i need my app to get notified for the system broadcast with actions like ACTION_PACKAGE_REMOVED, ACTION_PACKAGE_CHANGED, etc that impacts the activities available for launch with the user(to be displayed by my app).
Broadcast for package installed, package removed, package updated & package disabled/enabled are working as usual but the problem is when whole of the package is disabled like through Titanium backup or some similar app its get notified to my Broadcast receiver through system broadcast invoked having action Intent.ACTION_PACKAGE_CHANGED but when an app component like an activity is disabled individually from apps like MyAndroidTools it does not get notified to my Broadcast receiver i.e no broadcast(broadcast with Intent.ACTION_PACKAGE_CHANGED) is received from the system to my app due to disabling individual app component.
Here is my Manifest declaration of Broadcast receiver with requisite intent filter:
<receiver android:name=".LauncherBroadcastReceiver">
<intent-filter android:priority="100">
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_CHANGED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
Everything is working as intented but only when whole of the package is disabled or enabled but not when a single component(say activity) is disabled or enabled.
There is definately some way of doing it as i have test checked it with some other launchers i.e. when a single component is disabled it gets reflected(disappeared in app drawer) in the launcher & vice versa for enabling the component. So those launchers are receiving this info may be some listener or broadcast.
`<receiver android:name=".LauncherBroadcastReceiver" exported="true" enabled="true">`
One probable solution(not ideal) for my problem is to get the list of disabled launchable activites in Activity onResume method and than update to reflect the changes.
To get the list of disabled launchable activities:
Query package manager for all launchable activities(including disabled ones)
Intent mainLaunchIntent = new Intent(Intent.ACTION_MAIN);
mainLaunchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
mainLaunchIntent.addFlags(PackageManager.MATCH_DISABLED_COMPONENTS);
List<ResolveInfo> activitiesInformationList = packageManager.queryIntentActivities(mainLaunchIntent, 0);
Query package manager for only enabled launchable activities
Intent mainLaunchIntent = new Intent(Intent.ACTION_MAIN);
mainLaunchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> activitiesInformationList = packageManager.queryIntentActivities(mainLaunchIntent, 0);
List(1-2) will be the list of disabled activities. I haven't tested the same since not ideal for me would like to wait for more answers but if some1 found the same helpful can use it.
What needs to be done to make your app appear as an option app.
For eg, when I select an image file, android shows me a list of applications to open the file with, like Gallery,Photos etc.
I want that android also shows my app in this list.
How to achieve this? I am unable to understand which android classes to use for it? Or do I need to modify manifest file to add some specific intents?
By defining intent filter you can achieve this. You can register your Android components via intent filters for certain events.If a component does not define one, it can only be called by explicit intents. The key for this registration is that your component registers for the correct action, mime-type and specifies the correct meta-data.
Eg.
<activity android:name=".BrowserActivitiy"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"/>
</intent-filter>
</activity>
Above code will register an Activity for the Intent which is triggered when someone wants to open a webpage.
Source: http://www.vogella.com/tutorials/AndroidIntent/article.html
How do I build an intent and the Manifest so that I can invoke an activity with my application as an implicit intent.
The idea is that I am writing some general code that I wish to use in a number of applications.
This code is held in an Android library and is linked to the using application.
This general code opens an activity and does some work.
Once it is done (user clicks a button) it needs to transfer to an activity that is specific to this application.
As per my understanding on your questions,
You can declare your activity with specified implicit intent in your application's manifest file..
For example: If you want to make a application for view Image with your application and you have to use that application on your device which can allow other activity to view image using implicit intent action.VIEW so ,just
<activity android:label="#string/app_name" android:name=".MyImageViewerActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN">
<category android:name="android.intent.category.LAUNCHER">
</category></action></intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW">
<category android:name="android.intent.category.DEFAULT">
<data android:mimetype="image/*">
</data></category></action></intent-filter>
</activity>
In the above code we can see that intent-filter has following properties.
a. action: type for which this activity will respond for.Like this activity will respond for view action.
b. category: implicit intents are divided in categories.Like this activity is in default category.
c. data: Specify more information about intent-filter. Like this activity will handle file of mimeType “image/*”.
And when you install this application in your device and click on any image file, you will see a choice dialog that offer you to select between default application and your application. Just select your application to see the image.
For more info with example look at this What is intent filter in android?
Tutorial: Registering via Intentfilter
I think you can use intent-filters. I didn't use it for such things, but I hope that will help you.
Idea is that you can call your activity not by name, but by it's action (that is setted in intent-filter in your Manifest)
Instead of declaring a pre-determined launcher activity in my manifest using an intent filter:
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
Could I, instead, be given programmatic control over the activity which gets run when the application launches?
I'm not able to find anywhere in the documentation which says I must use the intent filter approach... but I also don't see any discussion of the alternative(s).
http://developer.android.com/guide/topics/fundamentals/activities.html
http://developer.android.com/guide/topics/intents/intents-filters.html
Thanks.
As far as I know, it's not possible. Android creates or sets up the hard link of the App icons to their respective activities by looking at the manifest. If you don't set it, you will not find any icons/shortcuts for your app after you install it.
I test the intent-filter android:priority="0" and intent-filter android:priority="20" by android.intent.category.HOME. I list the information below,
<activity android:name=".TestHomeActivity"
android:label="#string/app_name">
<intent-filter android:priority="0">
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
When finishing system booting, it always pops up a dialog (ResolveActiivty) for choose preferred activity for this intent...
Can anyone can help this? is it error usage for android:priority?
Thanks!
I haven't actually seen android:priority being taken into account when the system is resolving intents. I just tried setting a priority on an intent-filter that I use, but the system still gave me the resolution popup dialog, no matter what value I set my intent-filter's priority to.
I guess you'll just have to select the home screen activity you want to use (i.e. yours) and select the "Use by default..." checkbox.
android:priority is only used on OrderedBroadcast intents, not the order of resolution for non-ordered broadcasts. Users select the default activity for a given action, which is why the dialog pops up. So, yes, you are using priority incorrectly.
From your snippet, it seems that You are trying to launch your application. Priority is the one that should be given to the parent component w.r.t handling intents of the type described by the filter.
It provides information about the ability of an activity to respond to an intent that matches the filter, relative to other activities.It also controls the order in which broadcast receivers are executed to receive broadcast messages.
Use this attribute only if you really need to impose a specific order in which the broadcasts are received, or want to force Android to prefer one activity over others.
The value must be an integer, such as
"100". Higher numbers have a higher
priority.
// non-privileged applications can never define a priority > 0 (PKMS)