I'm developing a launcher application, I just added a broadcast receiver I will use to update the app list. I initially tried to receive ACTION_PACKAGE_ADDED and ACTION_PACKAGE_REMOVED as they seemed enought for the job, however none where fired so I added all other package-related actions I deemed useful and tried to register for them both in the activity:
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
intentFilter.addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
intentFilter.addAction(Intent.ACTION_PACKAGE_INSTALL)
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED)
val rec = AppsInstallationsReceiver()
registerReceiver(rec, intentFilter)
and manifest:
<receiver android:name=".core.installed_apps.AppsInstallationsReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_FULLY_REMOVED" />
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
The receiver itself is nothing special:
class AppsInstallationsReceiver : BroadcastReceiver() {
override fun onReceive(p0: Context?, p1: Intent?) {
//TODO
}
}
turns out I only receive PACKAGE_FULLY_REMOVED and only if it's registered in the manifest.
Now this is good enought, but I need a way to know when new apps are installed. Since this is a launcher app this feature is critical. Why am I not receiving anything? the activity of course still exists the background since it is used as launcher.
First of all, you should be aware about the Implicit Broadcast Limitations introduced from Android 8.0 and above.
The broadcasts you registered come under the catergory of restricted broadcasts (except ACTION_PACKAGE_FULLY_REMOVED). So, you won't receive these events when you register the actions from manifest. So, remove the receiver entry from manifest.
The alternative solution to this would be to register these broadcasts programatically - which you have already done.
The only thing missing here is to add intentFilter.addDataScheme("package") before registering the receiver.
Hoping this should resolve your issue.
Related
Registering broad cast
IntentFilter filter1 = new IntentFilter();
filter1.addAction(Intent.ACTION_PACKAGE_REMOVED);
filter1.addAction(Intent.ACTION_PACKAGE_ADDED);
filter1.addDataScheme("package"); // add addDataScheme
pkgRemoveReceiver=new ApplicationUninstallReceiver();
registerReceiver(pkgRemoveReceiver, filter1);
Permission in manifest
<receiver android:name="com.pcclean.app.receivers.ApplicationUninstallReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_INSTALL" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
Broadcast receiver
public class ApplicationUninstallReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
}
}
I'm not getting any call in on receive method.
I cannot see much wrong with code. A minor point though. The manifest file is missing the PACKAGE_REMOVED filter. Inside <intent-filter> of receiver in manifest file, add
<action android:name="android.intent.action.PACKAGE_REMOVED" />
Dynamically registering a BroadcastReceiver will have the disadvantage that notification will be received only if your app is running ( or in background ). Since you have already added the receiver in your manifest, there is no need to register it dynamically again. Also a correction in terminology - PACKAGE_ADDED and PACKAGE_REMOVED are not permissions exactly. There is no special permission required to receive notification on app install/uninstall.
Of lesser importance - I hope you are not attempting to receive a notification on the removal of your application itself. You will not get a notification on install/removal of your application itself(1).
I have an android Application that (among other things) show notifications on an Android Wear device.
This is done by having a class in the Wear module extend WearableListenerService. In the Wear module, I also have a class that extends BroadcastReceiver.
The scenario here is:
- Run the application from Android Studio
- Use the phone application so that a Notification is shown on the Wear device
- Restart the Wear device
Now what I want is that if I make the phone show another notification, it should appear on the wearable. So is not the case, because the WearableListenerService is not started...
So I let the BroadcastManager listen to ACTION_BOOT_COMPLETED events:
#Override
public void onReceive(Context context, final Intent intent) {
Log.d(TAG, "onReceive!");
if(intent==null)
return;
if(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Log.d(TAG, "Action boot completed");
ComponentName c = context.startService(new Intent(context, OngoingNotificationListenerService.class));
Log.d(TAG, "returned " + c);
return;
}
.
.
.
And in my Manifest file:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
.
.
.
<receiver android:name=".ActionsReceiver" android:enabled="true" android:exported="false">
<intent-filter>
<action android:name="com.XX.receiver.action_pause" />
<action android:name="com.XX.receiver.action_resume" />
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Now the problem is that my application doesn't receive the BOOT_COMPLETED action. I have checked the log and seen that the other listeners on the watch receives this event after a reboot, but not mine.
I have seen several posts about this, for example
Android BOOT_COMPLETED not received when application is closed
I think this might be quite similar to my problem.
My android wear app doesnt have a "mainactivity" that a user can start - it's ONLY the listener service and receiver. Although, I quickly implemented a main activty with a launcher intent, so that I could launch the app from the launcher on the watch. This didn't affect the situtation at all. Once the watch is restarted, it wont show a notification from my app until I reinstall it from android studio.
So have I missed something important? Is my WearableListenerService supposed to start itself without my interaction when the watch is restarted? (It doesn't...) Or does it have anything to do with that this is a developer version of the app?
(Note: I have also tried shut down and then start - no difference)
Try adding <category android:name="android.intent.category.DEFAULT" /> as a child of you <intent-filter>
You need to add your service to your wear module's manifest and add the BIND_LISTENER DATA_CHANGED action to it:
To listen to data items and messages on a path of /prefix, the new syntax looks like this (according to the android tools site):
<service android:name=".ExampleWearableListenerService">
<intent-filter>
<action android:name="com.google.android.gms.wearable.DATA_CHANGED" />
<action android:name="com.google.android.gms.wearable.MESSAGE_RECEIVED" />
<data android:scheme="wear" android:host="*" android:pathPrefix="/prefix" />
</intent-filter>
</service>
Suppose I want to define a receiver for my own widget and I want it to handle my own broadcast org.test.mywidget.MY_ACTION along with the APPWIDGET_xxx system broadcasts, what is the correct way to define it, if I want it to handle my own broadcast only if it is sent from the same app package? I tried the following XML code but in this way the APPWIDGET_DELETE action was no more delivered to the widget provider:
<receiver
android:name="MyWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/my_widget_info" />
</receiver>
<receiver
android:name="MyWidgetProvider"
android:exported="false">
<intent-filter>
<action android:name="org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE" />
</intent-filter>
</receiver>
The XML above has the problem I've mentioned (no DELETED events delivered) and it also does not seem good to me, since the receiver is redefined.. So I compacted everything as follows:
<receiver
android:name="MyWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/my_widget_info" />
</receiver>
This works, APPWIDGET_UPDATE, APPWIDGET_DELETE and my own broadcast are all delivered but now I have a question: are now other apps able to deliver a broadcast intent with the action org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE to my widget, since the android:exported value is set to true by default? Maybe I'm missing some basic concept related to this exported value, so I would be glad if some of you can make me understand everything better :)
if I want it to handle my own broadcast only if it is sent from the same app package?
You do not need, or even want, an action string if it is all going to be within your own package. Just use the Intent constructor that takes a Java class object as the second parameter, and use that for sending broadcasts to be picked up by the receiver.
I tried the following XML code but in this way the APPWIDGET_DELETE action was no more delivered to the widget provider
That is because there is no <intent-filter> referencing that action string in your code.
are now other apps able to deliver a broadcast intent with the action org.test.mywidget.FORCE_SMALL_WIDGET_UPDATE to my widget, since the android:exported value is set to true by default?
Yes. Of course, third party apps can send APPWIDGET_UPDATE broadcasts, or even hack an Intent that identifies your component directly, and you will receive those as well.
I suspect that the right answer, in your case, is to simply implement a second BroadcastReceiver, one with no <intent-filter>, that handles operations that you solely want to be within your package. Or, if you do not need to use a PendingIntent for this BroadcastReceiver, consider LocalBroadcastManager from the Android Support package.
I have a broadcast receiver registered in Manifest:
<application ...>
<receiver android:name="com.some.pkg.NewAppReceiver" >
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
</intent-filter>
</receiver>
</appcication>
And the receiver:
public class NewAppReceiver extends BroadcastReceiver {
private static final String TAG = "NewAppReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Intent: " + intent.getAction());
}
}
And nothing is received when I install APK manually or from the Android Market. Why?
Did you run the app that contains this broadcastReceiver before installing the other apps?
Starting at some API version, broadcastReceivers will not work till you execute the app. Put an activity and execute it.
Also , don't forget to add the following into the broadcastReceiver:
<data android:scheme="package" />
EDIT: On Android 8 and above, if your app targets API 27 or more, it will work partially, so you have to register to those events in code and not in manifest. Here's a list of intents that are still safe to use in manifest: https://developer.android.com/guide/components/broadcast-exceptions.html .
The rest should be used in code. More info here
Since android.intent.action.PACKAGE_ADDED is a System Intent (note that your own app will not receive it at its installation), your BroadcastReceiver will receive messages from sources outside your app. Thus, check you did NOT put: android:exported="false"
You also may need to add:
<data android:scheme="package" />
So, your BroadcastReceiver in your AndroidManifest.xml should look like this:
<application ...>
<receiver android:name=".NewAppReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
</appcication>
If it still doesn't work, you may try to put an higher priority, such as: android:priority="1000"
Take a look at: http://developer.android.com/guide/topics/manifest/receiver-element.html
Registering receiver from manifest would not work from API 26(android 8). Because it had performance impact on older versions.
But we can register receiver from java code and receive updates of removed and added applications.
val intentFilter = IntentFilter()
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED)
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED)
intentFilter.addDataScheme("package")
registerReceiver(YourBroadcastReceiver(), intentFilter)
Are you trying to receive the intent in the application you are installing? The documentation for ACTION_PACKAGE_ADDED says:
Note that the newly installed package does not receive this broadcast.
Another possibility is that this intent might not be delivered to components registered via the manifest but only manually (as described in an answer by Mark Murphy to Stack Overflow question Can't receive broadcasts for PACKAGE intents).
If you try to receive some other package it must be worked.
(As #Savvas noted) If you try to receive your own package's addition you can't receive it. Even if your broadcast receiver has action.PACKAGE_ADDED, receiver's onReceive method isn't triggered.
In this case your best bet is saving this data. By using sharedPreferences, add a key something like "appIsWorkedBefore", and on your launcher Activity's onCreate method set this variable as "true". And you can make your works with respect to this Boolean.
This intent action is no longer available for applications.
This is a protected intent that can only be sent by the system.
https://developer.android.com/reference/android/content/Intent#ACTION_PACKAGE_ADDED
I'm currently trying to catch states for ACTION_SCO_AUDIO_STATE_CHANGED as specified by:
http://developer.android.com/reference/android/media/AudioManager.html#ACTION_SCO_AUDIO_STATE_CHANGED
I have registered the intent on my manifest but I'm not getting anything when connecting to a bluetooth device. Any particular permission I need or something?
Manifest:
<receiver android:name="com.app.receiver.BluetoothReceiver">
<intent-filter>
<action android:name="android.media.SCO_AUDIO_STATE_CHANGED" />
<action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
<action android:name="android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED" />
<action android:name="android.bluetooth.device.action.BOND_STATE_CHANGED" />
</intent-filter>
</receiver>
I can't get any of the calls from BOND_STATE_CHANGED, SCO_AUDIO_STATE_CHANGED or ACL_DISCONNECT_REQUESTED. The other intents I'm receiving them just fine.
Thanks,
-Jona
It's probably a broadcast intent that cannot be received using the Manifest. You'll have to setup a BroadcastReceiver object and register it to receive the broadcast. The Receiver must be active in order to receive the intent.
Some broadcasts intents work like this while others are allowed to be caught via the manifest.
The other possibility is that the receiver requires a permission that you aren't requesting.
This is an important note from the SDK about Context.registerReceiver().
Note: this method cannot be called from a BroadcastReceiver component; that is, from a BroadcastReceiver that is declared in an application's manifest. It is okay, however, to call this method from another BroadcastReceiver that has itself been registered at run time with registerReceiver(BroadcastReceiver, IntentFilter), since the lifetime of such a registered BroadcastReceiver is tied to the object that registered it
<uses-permission android:name="android.permission.BROADCAST_STICKY"