Intent.ACTION_PACKAGE_CHANGED - Broadcast for App component disabled not received - android

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.

Related

Get notified when PlayStore adds app icon to home screen

Does PlayStore send any broadcast message with "com.android.launcher.action.INSTALL_SHORTCUT" action, when it adds app shortcut to home screen before/after the app get installed?
I heard of the following method:
Add <uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" /> to manifest.xml
Extend BroadcastReceiver class, then override onReceive() method
Is it true that the above 2 steps will let app get notified when Play Store add app shortcut to home screen?
Here I don't think there is any listener available to listen shortcuts directly. but you could go through some tricky way like :
1) Listen to application install using listener. you could achieve it by registering following way :
<receiver android:name=".apps.AppListener">
<intent-filter android:priority="999">
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_INSTALL"/>
<data android:scheme="package"/>
</intent-filter>
2) In your AppListener broadcast receiver whenever you will get it triggered, keep delay of 5 to 10 second and perform action to get all installed applications using :
List<ApplicationInfo> packs = pm.getInstalledApplications(0);
Now you have all installed packages, iterate through them and callgetLaunchIntentForPackage() on each item
If a valid intent is returned, that means it exists on launcher, else if it returns null, the package doesn't launch from home screen.
REASON : Home screens shortcuts are subset of the launcher apps :)

How to open Activity via intent-filter and what is the use of intent-filter?

I'm working with activities I know how to open activities via intent, but I want to know how can I open activity via intent-filter and what is the role of intent-filter to open activities.
How many ways to open the activity?
Activity can even be launched via IntentFilter
try this out
Basically when you install your app, Android system will register the activity with corresponding action, when you declare your activity with custom action, Android system stores the activity with the respective activity. When you launch the intent with your custom action. The system will find the receiving activity and launch it it there is only one activity matching it, if there are more than one Activity receiving that action, System will ask the user to choose which activity to complete the action.
declare activity in manifest as
<activity
android:name=".YourActivity" >
<intent-filter>
<action android:name="your.custom.ACTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
then you can start this activity by just calling
startActivity(new Intent("your.custom.ACTION"));
An IntentFilter is used with BroadcastReceivers.
The BroadcastReceiver then gets activated when any intent that fits through the filter arrives in the system.
This is generally used to send messages between activities, between different applications, or from the server to the application.
See BroadcastReceiver documentation:
http://developer.android.com/reference/android/content/BroadcastReceiver.html
or this tutorial:
http://www.vogella.com/tutorials/AndroidBroadcastReceiver/article.html

Handle NFC intents only when preference is set

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().

How do I complete the actual uninstall/removal of my android app using an uninstall activity?

I added an activity with an intent filter to intercept the uninstall of my app so I can add some additional processing/cleanup when a user uninstalls my app. My activity get called just fine but I seem unable to complete the removal of the package from the device.
<activity
android:name=".Uninstall"
android:label="#string/app_name">
<intent-filter>
<action android:name="android.intent.action.DELETE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="package" />
</intent-filter>
</activity>
When I use the package manager to try to complete the uninstall it just pops up the same chooser dialog.
Intent intent = new Intent(Intent.ACTION_DELETE, Uri.fromParts("package", Uninstall.this.getPackageName(), null));
startActivity(intent);
If I am providing an alternative uninstall activity for my app how do I complete the actual uninstall of the apk from the device?
Thanks.
You should take a look at the reference documentation for your intents. The intent ACTION_DELETE has to do with the deletion of items from a container, and not of applications/packages. The intent that handles the removal of applications/packages is ACTION_PACKAGE_REMOVED but as the documentation states:
An existing application package has been removed from the device. The data contains the name of the package. The package that is being (un)installed does not receive this Intent.
So the short answer to your question is that it cannot be done. If you play by the book, you don't need to perform additional tasks at uninstall time.

Hide an application from Android application list

Is there any way to hide an application icon from Android applications list ? The application should be downloaded from Market and opened some GUI for configuring my application. I don't want to see any icon of my application in applications list. User should not be able to run it.
By the way I know some way:
remove this line from manifest category android:name="android.intent.category.LAUNCHER"
But it is not worked for me, because the GUI is not shown.
Thanks very much !
Removing the launcher category is correct.
Try adding android.intent.category.DEFAULT to the intent filter to be able to call the activity.
Thanks for replay.
I found a way to hide application icon from application list;
PackageManager pm = getApplicationContext().getPackageManager();
pm.setComponentEnabledSetting(getComponentName(), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
But in time of application reinstalling occurs error "Activity class does not exist" and it is not possible to reinstall application without uninstalling it. .... what's the problem ?
There is also variant of Launcher Pro. But this is an application. My app should be downloaded from Android Market and there is no guarantee that all users have Launcher Pro.
I want programmatically hide application icon from application list. The method with PackageManager works for me ... but there is a problem regarding reinstalling. It is important when you want to update the application from Market.
I have found a way for this to work when you reinstall the app.
Add a broadcast receiver with intent filter action android.intent.action.PACKAGE_ADDED.
In the onReceived method you must activate your disabled component :
ComponentName componentToEnable = new ComponentName(context, Your_disabled_class.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(componentToEnable, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
Complete AndroidManifest.xml for receiver:
<receiver android:name="PackageChangeReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_REPLACED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package"/>
</intent-filter>
</receiver>

Categories

Resources