Awareness API global receiver intent filter - android

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.

Related

Receiving broadcast from notification on Android Oreo

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!

Broadcast Receiver not getting triggered

This should be fairly easy but I somehow can't get a Broadcast receiver's onReceive method triggered. Details below:
App B provides a broadcast receiver.
Manifest:
<receiver android:name=".MyNotificationReceiver">
<intent-filter>
<action android:name="com.go.foo.A_ACTION" />
</intent-filter>
</receiver>
Java:
public class MyNotificationReceiver extends BroadcastReceiver {
private final String TAG= "MyNotificationReceiver";
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "this is not shown" , Toast.LENGTH_LONG).show();
}
}
App A is Broadcast Sender App:
Java
Intent intent = new Intent();
intent.setAction("com.go.foo.A_ACTION");
sendBroadcast(intent);
Log.d(TAG, "broadcast intent sent...");
I can see the log statement that the broadcast is sent but the receiver's onReceive() callback is not getting triggered. Am I doing something wrong?
Interesting why it's not working. Try this one out. I know the default values of exported and enabled are true. But still have a try at it.
<receiver android:name=".MyNotificationReceiver" android:enabled="true" android:exported="true">
<intent-filter>
<action android:name="com.go.foo.A_ACTION" />
</intent-filter>
</receiver>
Learned something new today. As of Android 4.1, the system no longer sends broadcasts to app components without an activity. The broadcast received started working after I added an activity in the manifest.

Why broadcast receiver is called even no intent filter specified?

As in title, broadcast receiver get called even no intent filter is specified in android manifest or in code. Even I specify concrete intent action in manifest like:
<receiver
android:icon="#drawable/ic_action_network_wifi_on"
android:name=".receivers.WifiReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
The receiver get called when no airplane mode change.
Any ideas appreciated.

PACKAGE_ADDED BroadcastReceiver doesn't work

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

how to tell the application it was started from boot up of the device?

Hi I'm writing a application for android that is started from boot up and i wondered if there was a way of telling the application it was started from the boot up of the device? i need it to do something different if the application was manual started (i.e not when the device was started). i am using a BroadcastReceiver to start the application when the device starts.
You could either make two different broadcast receivers one that has ACTION_BOOT_COMPLETED for the intent filter, and another that has the other intent filter that you would use.
Or create one broadcastreceiver that has two intent filters like:
<receiver android:name=".BatteryReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<intent-filter>
<action android:name="SOMETHING_ELSE"/>
</intent-filter>
</receiver>
and then in the onReceiver do:
if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)){
// do code for phone just powered on
} else {
// do code for phone is already on
}
EDIT:
The above assumes that you use the BroadcastReceiver under two circumstances, which may not be the case judging from your question.
So if you are starting an Activity (or service), then in the BroadcastReceiver code, you could do:
Intent i = new Intent(context, MyClass.class);
i.putExtra("STARTED_FROM_BOOT", true);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
Then in the activity, you could do:
if (getIntent().hasExtra("STARTED_FROM_BOOT")){
// do your code for when started from boot.
}
Let me know if I need to add anything.
yes, hook a broadcastreceiver with a on boot completed intent in the manifest and when the device boots up that receiver will be fired and you can do whatever you want there
<receiver android:name=".BatteryReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>

Categories

Resources