I have a custom button in a sticky notification.
I used to attach a PendingIntent to it for receiving button clicks:
Intent intent = new Intent();
intent.setAction("com.example.app.intent.action.BUTTON_CLICK");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 2000, intent, PendingIntent.FLAG_UPDATE_CURRENT);
contentViewExpanded.setOnClickPendingIntent(R.id.button, pendingIntent);
When i run this code on Oreo , i get BroadcastQueue: Background execution not allowed in logcat and don't receive button click.
I registered receiver with manifest:
<receiver
android:name=".BroadcastReceiver.NotificationActionReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.example.app.intent.action.BUTTON_CLICK"/>
</intent-filter>
</receiver>
I also tried registering receiver in my code:
NotificationActionReceiver mMyBroadcastReceiver = new NotificationActionReceiver();
IntentFilter filter = new IntentFilter("com.example.app.intent.action.BUTTON_CLICK");
mContext.registerReceiver(mMyBroadcastReceiver, filter);
This works but only when the app is visible to user.
Thanks for help
Never use an implicit Intent when an explicit Intent will work.
Replace:
Intent intent = new Intent();
intent.setAction("com.example.app.intent.action.BUTTON_CLICK");
with:
Intent intent = new Intent(this, NotificationActionReceiver.class);
And remove the <intent-filter> from the NotificationActionReceiver <receiver> element.
I ran into this issue as well on Android 8 - Oreo, but given my library project requirements, I don't have the explicitly named BroadcastReceiver class implementation, that the end-client will declare in it's AndroidManifest.
Solution:
Specify the application package on the Intent using setPackage(String).
Example:
// Application unique intent action String
final String receiverAction = getApplicationContext().getPackageName()
+ BaseLibraryReceiver.ACTION_SUFFIX;
// No need for Class definition in the constructor.
Intent intent = new Intent();
// Set the unique action.
intent.setAction(receiverAction);
// Set the application package name on the Intent, so only the application
// will have this Intent broadcasted, thus making it “explicit" and secure.
intent.setPackage(getApplicationContext().getPackageName());
...
From the Android Broadcasts: Security considerations and best practices docs.
In Android 4.0 and higher, you can specify a package with
setPackage(String) when sending a broadcast. The system restricts the
broadcast to the set of apps that match the package.
Here’s an example of the BroadcastReceiver declared (or merged) in to the end-client application’s AndroidManifest:
<receiver
android:name=“com.subclassed.receiver.ReceiverExtendedFromLibrary"
android:exported="false"
android:enabled="true">
<intent-filter>
<action android:name="${applicationId}.action.MY_UNIQUE_ACTION"/>
</intent-filter>
</receiver>
Since my example revolves around a library project that broadcasts an Intent, I’ve decided to keep the <intent-filter> and <action /> in the <receiver> declaration. Otherwise, there would be non-unique broadcast actions being fired, which could lead to potential issues where multiple applications receive the wrong broadcast. This is mostly a safety precaution. Of course you still need to check the action in the implementation of the BroadcastReceiver.
Hope someone finds this helpful!
Related
I am having problem receiving broadcast sent from android library module in app module.
I create an explicit broadcast with action and component name. And send this broadcast from android lib module.
val intent = Intent()
intent.action = "com.example.action.SOME_ACTION"
intent.component = ComponentName("com.example", "com.example.MyReceiver")
sendBroadcast(intent)
To receive this broadcast, I created a receiver and registered it in manifest.
<receiver
android:name=".MyReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.example.action.SOME_ACTION" />
</intent-filter>
</receiver>
This receiver prints received event, but unfortunately, I am not receiving any broadcast. Am I missing anything? Or is it supposed to be this way, i.e. You cannot receive broadcast sent from the library?
try to do like this, this is working for me
register receiver where you want to receive using this code
IntentFilter filter = new IntentFilter();
filter.addAction("myCustomAction");
registerReceiver(receiver, filter);
send a broadcast from different lib like this
Intent intent = new Intent("myCustomAction");
intent.putExtra("value", 0);
intent.setComponent(null);
context.sendBroadcast(intent);
now no need to register a receiver in AndroidManifest.xml
set ComponentName to null because ComponentName is
The name of the application component to handle the
intent, or null to let the system find one for you.
i am implementing the google Awareness API in an android app, but none of the samples, nor the guides, shows how to listen to the api events while the app is down or in the background.
I wrote a global receiver based on the answer here
<receiver android:name=".MyFenceReceiver" >
<intent-filter>
<action android:name="android.intent.action.FENCE_RECEIVER_ACTION" />
</intent-filter>
</receiver>
However, since it is not working, i suspect i don't know the correct intent filter for intercepting the Awarness events.
Does anyone know the correct intent filter, or if this is not my issue, how can i intercept the API events while the app is down or in the background with a global receiver?
Ok so the answer eventually was that you have to register this receiver in the manifest and give it your own intent filter like this:
Intent intent = new Intent(Constants.Requests.FENCE_RECEIVER_ACTION);
mPendingIntent =
PendingIntent.getBroadcast(BaseActivity.this, 0, intent, 0);
// The broadcast receiver that will receive intents when a fence is triggered.
where "FENCE_RECEIVER_ACTION" is this:
// The intent action which will be fired when your fence is triggered.
public final static String FENCE_RECEIVER_ACTION =
BuildConfig.APPLICATION_ID + "FENCE_RECEIVER_ACTION";
And in the manifest you put in the receiver like this:
<receiver android:name=".FenceReceiver" >
<intent-filter>
<action android:name="'YOUR_PACKGE_NAME_HERE'FENCE_RECEIVER_ACTION" />
</intent-filter>
</receiver>
There is no need to unregister the receiver anywhere.
I'm trying to set up one class for receiving sms and sent status.
This is how my manifest looks for this task:
<receiver android:name=".SmsListener" android:permission="android.permission.BROADCAST_SMS" android:exported="true">
<intent-filter android:priority="5822">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
<action android:name="android.provider.Telephony.SMS_SENT" />
</intent-filter>
</receiver>
I get received messages, but don't get SENT messages, is something wrong with my Manifest declarations?
PendingIntent _pendingIntent;
Intent _intent = new Intent();
_intent.setClass(ParkingOptionsActivity.this, SmsListener.class); // SmsListener extends BroadcastReceiver
_intent.putExtra("test","test");
_pendingIntent = PendingIntent.getActivity(ParkingOptionsActivity.this, 0, _intent, 0);
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(phoneNumber, null, "test message", _pendingIntent, null);
You need to obtain your PendingIntent with getBroadcast() instead of getActivity(), since you want to send a broadcast to your BroadcastReceiver, not start an Activity.
In your current code, you can simply change that one line:
_pendingIntent = PendingIntent.getBroadcast(ParkingOptionsActivity.this, 0, _intent, 0);
Furthermore, the "android.provider.Telephony.SMS_SENT" action is not present in the SDK currently, and there is no system broadcast when an SMS is sent. Your app doesn't really need that <action> in the manifest entry, since the Intent is explicitly targeting your Receiver class.
If you do plan to use that action for something else - e.g., differentiating broadcasts in onReceive(), receiving implicit broadcasts from other apps, etc. - then you might consider changing it to use something other than the android.provider.Telephony package name, so as not to cause potential unwanted behavior or confusion in the future. Using your own app's package name is the norm, I would say.
I have a service that supposed to upload photos in the background. But when I try to start it, it doesn't start. In the logcat I've noticed that I get a warning Implicit intents with startService are not safe : Intent { .....}. I've already tripled checked that the action string is the same in the manifest and what I'm starting with. My code :manifest :
<service android:name=".photosupload.services.PhtosUploadService"
android:exported="false" android:process=":uploadPhotosServiceProcess">
<intent-filter>
<action android:name="com.yoovi.app.photosupload.services.action.START_UPLOAD" />
</intent-filter>
</service>
starting service code :
Intent i = new Intent(PhtosUploadService.ACTION_START_UPLOAD);
i.putExtra(PhtosUploadService.ALBUM_ID, albumID);
context.startService(i);
You need to understand implicit and explicit intents.
Explicit intent means you need to specify the exact class from which the intent will be serviced.
Your code should be similar to
Intent i = new Intent();
i.setClass(this, photosupload.services.PhtosUploadService.class);
If you want to send implicit intent to a service - Please Change to android:exported="true" in manifest.
I have an application developed for jelly bean, where I schedule an event to be executed in the future using Alarm manager. The scheduled event executes as expected as long as the application runs in the foreground or in the background. But once I force close the application under taskmanager, I am no longer able to receive the broadcast from the alarm manager.
As suggested by various posts and blogs i tried using Intent.Flag_Include_Stopped_Packages. But it was of no use. Including this flag in the intent works only for sendBroadcast(intent). But in case of an alarm manager where pending intent is used,it does not work.
My code to schedule the alarm
Intent intent = new Intent("com.dummy.intent");
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(),dummyId, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.set(AlarmManager.RTC_WAKEUP, scheduledAlarm.getTimeInMillis(), pi);
My mainfest
<receiver android:name="com.example.androidScheduling.alarmReceiver"
android:enabled="true"
android:exported="true"
android:process=":remote">
<intent-filter>
<action android:name="com.dummy.intent"></action>
</intent-filter>
</receiver>
Can someone please help me out?
I even tried including android:process = ":remote" for the receiver in manifest. But even that did not help.
I think you have not spelled correctly the intent's action name in manifest and programmatically .
In pro-grammatically
Intent intent = new Intent("com.dummy.intent");
Manifest file-
<intent-filter>
<action android:name="com.custom.intent"></action>
</intent-filter>
The action name to intent and declared in manifest must require same.
Hope this helpful to you