I have created a BroadcastReceiver to detect SDCard mount and unmount
event, however, I am not able to receive any events at all:
here's the AndroidManifest.xml:
<receiver android:enabled="true" android:label="SDCardMountReceiver" android:exported="true" android:name="xxx.broadcasts.SDCardBroadcastReceiver">
<intent-filter>
<action android:name="android.content.Intent.ACTION_MEDIA_MOUNTED"></action>
<!-- or <action android:name="android.content.Intent.ACTION_MEDIA_UNMOUNTED" />--></intent-filter>
</receiver>
And the SDCardMountReceiver class:
public class SDCardBroadcastReceiver extends BroadcastReceiver {
public SDCardBroadcastReceiver() {
super();
System.err.println("constructor");
}
public void onReceive(Context context, Intent intent) {
Log.d("SDCardBroadCastReceiver", "receive " + intent.getAction());
System.err.println("jonathan receive " + intent.getAction());
}
}
You also need to set the data scheme to "file".
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<data android:scheme="file" />
</intent-filter>
Reference: android-developers thread
The Intent javadoc specifies a different action:name value.
Use "android.intent.action.MEDIA_MOUNTED" instead of "android.content.Intent.ACTION_MEDIA_MOUNTED"
If you register a broadcast receiver programmatically, you must also set the scheme to "file".
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_MEDIA_MOUNTED);
filter.addAction(Intent.ACTION_MEDIA_REMOVED);
filter.addDataScheme("file");
mContext.registerReceiver(mExternalStorageReceiver, filter);
Related
I searched the web for alot of time and I don't understand why my custom broadcast
isn't working.
<receiver
android:name=".myservice.MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED" />
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED" />
<action android:name="android.intent.action.BATTERY_CHANGED"/>
<action android:name="android.intent.action.SCREEN_ON" />
<action android:name="android.intent.action.SCREEN_OFF" />
</intent-filter>
</receiver>
I don't it not recieve when I reconnet and disconnect the charger.
I did this for making thing simpale
public class MyReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(context,"Battery", Toast.LENGTH_SHORT).show();
Log.i("Recive", "Yes");
}
}
From docs:
ACTION_BATTERY_CHANGED
Broadcast Action: This is a sticky broadcast containing the charging state, level, and other information about the battery. See BatteryManager for documentation on the contents of the Intent.
You cannot receive this through components declared in manifests, only by explicitly registering for it with Context.registerReceiver(). See ACTION_BATTERY_LOW, ACTION_BATTERY_OKAY, ACTION_POWER_CONNECTED, and ACTION_POWER_DISCONNECTED for distinct battery-related broadcasts that are sent and can be received through manifest receivers
So, you cannot use this BroadcastReceiver decalred in Manifest, only registering explicitly from your context.
Also, your power connection BroadcastReceiver seems correct. Try to separate it into another BroadcastReceiver, maybe action ACTION_BATTERY_CHANGED is interfering with other actions.
This is my declared BroadcastReceiver which I use and it's working in my app.
<receiver android:name=".PowerConnectionBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
</intent-filter>
</receiver>
PowerConnectionBroadcastReceiver
public class PowerConnectionBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "PowerRcvr";
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_POWER_CONNECTED)) {
Log.d(TAG, "Device is charging");
} else if (action.equals(Intent.ACTION_POWER_DISCONNECTED)) {
Log.d(TAG, "Device is NOT charging");
} else {
Log.d(TAG, "Unable to check if device is charging or not");
}
}
}
NOTE: This code is working on Android 8 with targetSdkVersion 25 or lower.
In targetSdkVersion 26 or higher most of BroadcastReceivers doesn't work through Manifest due to background limitations. Here are documentation (thanks to Pawel) about that. So your IntentFilters wont work. To keep it working you can download your targetSdkVersion to 25 or lower.
To put it simply; BroadcastReceiver Works when defined in Manifest but it works with a short Delay and it doesn't Always trigger unless Registered Manually.
Here is the BroadcastReceiver I created to capture event when date changes (day is passed):
public class BootBroadcastReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, intent.getAction(), Toast.LENGTH_LONG).show();
switch (intent.getAction()){
case Intent.ACTION_TIME_TICK:
case Intent.ACTION_TIME_CHANGED:
case Intent.ACTION_TIMEZONE_CHANGED:
case Intent.ACTION_DATE_CHANGED:
case Intent.ACTION_BOOT_COMPLETED:
Log.d("BroadcastReceiver", intent.getAction().toString());
}
}
}
Here registered in Manifest, It works but has a short delay and also doesn't always trigger:
<receiver android:name=".Receivers.BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.TIME_TICK" />
<action android:name="android.intent.action.TIME_SET" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
But when registered manually via my background service it works just fine:
public class ApplicationService extends Service{
...
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_DATE_CHANGED);
intentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
intentFilter.addAction(Intent.ACTION_TIME_CHANGED);
intentFilter.addAction(Intent.ACTION_TIME_TICK);
registerReceiver(new BootBroadcastReceiver(), intentFilter);
return START_STICKY;
}
}
To investigate this issue further I created two similar app which in one BroadcastReceiver registered in Manifest and in the other one receiver is registered Manually via Service.
In the Manifest one all events are triggered few second after Manual one..
Try this :
<receiver android:name=".Receivers.BootBroadcastReceiver">
<intent-filter
android:enabled="true"
android:exported="true">
<action android:name="android.intent.action.TIME_TICK" />
<action android:name="android.intent.action.TIME_SET" />
<action android:name="android.intent.action.TIMEZONE_CHANGED" />
<action android:name="android.intent.action.DATE_CHANGED"/>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
I guess you can have multiple each one having its action.
https://developer.android.com/guide/components/intents-filters.html
The documentation says that "An app component should declare separate filters for each unique job it can do." This would allow finer grained detail for different actions
The answer was hidden in Intent documentation:
ACTION_TIME_TICK Added in API level 1
public static final String ACTION_TIME_TICK
Broadcast Action: The current time has changed. Sent every minute. You
cannot receive this through components declared in manifests, only by
explicitly registering for it with
Context#registerReceiver(BroadcastReceiver, IntentFilter).
To simply put, you can't receive TIME_TICK through registering the BroadcastReceiver in manifest, it has to be registered in your application components (Service, Activity, etc.)
Define a BootBroadcastReceiver anywhere in Activity/Fragment like this:
mBootBroadcastReceiver = new BootBroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG," BootBroadcastReceiver"); //do something with intent
}
};
mIntentFilter=new IntentFilter("action_name");
Now register the BootBroadcastReceiver in onResume() and Unregister in onPause()
#Override
protected void onResume() {
super.onResume();
registerReceiver(mBootBroadcastReceiver, mIntentFilter);
}
#Override
protected void onPause() {
if(mReceiver != null) {
unregisterReceiver(mBootBroadcastReceiver);
mBootBroadcastReceiver = null;
}
super.onPause();
}
add permission in your Manifest.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="ANDROID.PERMISSION.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
I have 2 applications. One of them is doing broadcast custom strings continously and the other one is receiving. I have to be notified and delete some datas in the reciever application when the broadcaster application is deleted. Is there a method like onDelete() or something like that? How can I do this?
Yeah! There's an intent called ACTION_PACKAGE_REMOVED that you can listen for.
Add this inside <application> in your manifest: (don't forget to change the package name)
<receiver android:name="com.arjnklc.receiverapp.UninstallReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<data android:scheme="package" />
</intent-filter>
</receiver>
Then you need to create the class mentioned above.
public class UninstallReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if(intent.getData().getSchemeSpecificPart() == "com.arjnklc.broadcasterapp")
cleanUpEverything();
}
}
Not exactly sure when you want to do but from what I understand, you want your second application to know when the first application is deleted?
If that's the case, do this:
In AndroidManifest.xml, you MUST have a new BroadcastReceiver because this receiver used a different data scheme:
<receiver
android:name=".PackageReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
Then your BroadcastReceiver:
public class PackageReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_PACKAGE_REMOVED)) {
Log.d(TAG, "ACTION_PACKAGE_REMOVED");
String data = intent.getData().toString();
// data string has the package name
// if that is your package name, your first app was uninstalled
}
}
}
Just make sure, it's a separate BroadcastReceiver. It can not be combined with any other Receiver or the other actions will stop working.
Hope this works.
I added a receiver to listen when app is installed. But it is not working. Here is my code in AndroidManifest.xml
<receiver android:enabled="true"
android:exported="true"
android:name="com.bsp.iqtest.reiceiver.IQTestReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
Here is my code in MainActivity (launcher activity) , function onCreate.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
IQTestReceiver br = new IQTestReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addDataScheme("package");
registerReceiver(br, intentFilter);
}
Here is my code in IQTestReceiver (this class is written in other file)
public class IQTestReceiver extends BroadcastReceiver {
public IQTestReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
String packageName=intent.getData().getEncodedSchemeSpecificPart();
Log.e("HELLO",packageName);
}
}
I set a breakpoint in onReceive function , but it doesn't run when i debug.
Thanks for your helping.
You can not receive PACKAGE_ADDED or PACKAGE_REPLACED for your own app, if that is what you're trying.
"Broadcast Action: A new application package has been installed on the device. The data contains the name of the package. Note that the newly installed package does not receive this broadcast."
See http://developer.android.com/reference/android/content/Intent.html
set your broadcasrt in manifest like this
<receiver
android:name=".IQTestReceiver"
android:exported="true"
android:enabled="true">
<intent-filter>
<action android:name="check_values"/>
</intent-filter>
</receiver>
and send the broadcast like this.....Intent it1=new Intent(Intent.ACTION_USER_PRESENT);
it1.setAction("check_values");
it1.putExtra("data_key1",message);
sendBroadcast(it1);
and in on receive would be like this....
#Override
public void onReceive(Context context, Intent intent)
{
data1=intent.getStringExtra("data_key1");
System.out.println("ffffff11" + data1);
}
I want to write a BroadcastReceiver to receive the application install action. But it failed, so I test if my receiver is well or not. So custom a intent, it also filed. below is my code. Please help me correct it.
public class MyInstallReceiver extends BroadcastReceiver {
// public MyInstallReceiver() {
// }
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Intent Detected.", Toast.LENGTH_LONG).show();
Log.d("receiver", "Intent Detected");
if (intent.getAction (). equals ("android.intent.action.PACKAGE_ADDED")) {
String packageName = intent.getDataString ();
//System.out.println ("installed:" + packageName + "package name of the program");
Log.d("receiver","installed:" + packageName + "package name of the program");
}
}
}
custom intent
public void installAPK(View v){
startActivity(intent);
Intent intent = new Intent();
intent.setAction("com.tutorialspoint.CUSTOM_INTENT");
sendBroadcast(intent);
Log.d("receiver", "Intent sent");
}
Manifest.xml
<receiver
android:name=".MyInstallReceiver"
android:enabled="true"
android:exported="true" >
<Intent-filter>
<action android:name = "android.intent.action.PACKAGE_ADDED"/>
<action android:name = "android.intent.action.PACKAGE_REMOVED"/>
<action android:name="com.tutorialspoint.CUSTOM_INTENT">
</action>
<Data android:scheme = "package" />
</Intent-filter>
</receiver>
enter code here
I don't know about correct spelling in your manifest, but this code is definitely works very well:
<receiver android:name=".MyInstallReceiver">
<intent-filter>
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<action android:name="android.intent.action.PACKAGE_ADDED" />
<data android:scheme="package"/>
</intent-filter>
</receiver>
Every application install/uninstall will trigger this receiver.
Everythong looks good, expect a typo in your manifest. It should be <intent-filter> and not <Intent-filter>