In android there are 3 kinds of Intents,
Intent,
Sticky Intent,
Pending intent.
so What is sticky intent?
Intent - is a message passing mechanism between components of Android, except for Content Provider. You can use Intent to start any
component.
Sticky Intent - Sticks with Android, for future broadcast listeners. For example if BATTERY_LOW event occurs then that Intent
will stick with Android so that any future requests for
BATTERY_LOW, will return the Intent.
Pending Intent - If you want some one to perform any Intent operation at future point of time on behalf of you, then we will use
Pending Intent.
An intent that is used with sticky broadcast, is called as sticky intent.
This intent will stick with android system for future broadcast receiver requests.
OR
sendStickyBroadcast() performs a sendBroadcast(Intent) known as sticky, i.e. the Intent you are sending stays around after the broadcast is complete, so that others can quickly retrieve that data through the return value of registerReceiver(BroadcastReceiver, IntentFilter). In all other ways, this behaves the same as sendBroadcast(Intent). One example of a sticky broadcast sent via the operating system is ACTION_BATTERY_CHANGED. When you call registerReceiver() for that action -- even with a null BroadcastReceiver -- you get the Intent that was last broadcast for that action. Hence, you can use this to find the state of the battery without necessarily registering for all future state changes in the battery.
Pending Intent: Pending Intent is actually an object which wraps an Intent to do some future work by another app.
It lets us pass a future Intent to another application and allows that application to execute that Intent as if it had the same permissions as our application, whether or not our application is still around when the Intent is eventually invoked.
A PendingIntent is generally used in cases were an AlarmManager needs to be executed or for Notifications. A PendingIntent provides a mean for applications to work, even after their process exits.
PendingIntent uses the following methods to handle the different types of intents:
PendingIntent.getActivity() : Retrieve a PendingIntent to start an Activity
PendingIntent.getBroadcast() : Retrieve a PendingIntent to perform a Broadcast
PendingIntent.getService() : Retrieve a PendingIntent to start a Service
Example :
Intent intent = new Intent(this, SomeActivity.class);
// Creating a pending intent and wrapping our intent
PendingIntent pendingIntent = PendingIntent.getActivity(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
try {
// Perform the operation associated with our pendingIntent
pendingIntent.send();
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
Intent: Intent is basically a message passing mechanism between different components of Android, except for Content Provider. You can use intent to start any component in Android.
Sticky Intent: These are the Intents which sticks with Android for future broadcast listener.
Sticky Intent is also a type of Intent which allows communication between a function and a service sendStickyBroadcast(), performs a sendBroadcast(Intent) known as sticky, the Intent you are sending stays around after the broadcast is complete, so that others can quickly retrieve that data through the return value of registerReceiver(BroadcastReceiver, IntentFilter). In all other ways, this behaves the same as sendBroadcast(Intent).
One example of a sticky broadcast sent via the operating system is ACTION_BATTERY_CHANGED. When you call registerReceiver() for that action — even with a null BroadcastReceiver — you get the Intent that was last Broadcast for that action. Hence, you can use this to find the state of the battery without necessarily registering for all future state changes in the battery.
Intent : Intent is an asynchronous message which is use to communicate between the components in android , except Content Provider.
for example you can start activity by
startActivity(Intent intent);
Sticky Intent : sticky intents are associated with the android system for the future broadcast events.
Pending Intent : Those intent which you want to trigger at some time in future when you application is not alive.
An intent that is used with sticky broadcast, is called as sticky intent. This intent will stick with android system for future broadcast receiver requests.
Sticky Intent allows a communication between function and a service sendStickyBroadcast() performs a sendBroadcast(Intent) know as sticky, the Intent you are sending stays around after the broadcast is complete so that others can quickly retrieve that data through the return value of registerReceiver(BroadcastReceiver, IntentFilter). In all other ways, this works the same as sendBroadcast(Intent).
Related
I am trying to implement some alarm scheduling by using AlarmManager. Since when a alarm is triggered, I want to use a WakefulBroadcastReceiver which starts an IntentService to do some background job.
I have some questions related to security/privacy of the parameters passed for alarm's intents.
When setting a PendingIntent for a alarm I do something like:
Intent myIntent = new Intent(context, MyReceiver.class);
myIntent.putExtra("test", "testValue");
Bundle bundle = new Bundle();
bundle.putParcelable("bundleValue", bundleTestValue2);
myIntent.putExtra("test3", bundle);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
My question is: how private are the values set as Extra for the pendingIntent of the alarm? Is there a chance of them getting read by some other app since is being used by Android Alarm's Manager after it is scheduled?
By having a receiver like
public class MyReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
startWakefulService(context, MyIntentService);
}
And on android manifest
<receiver
android:name=".receivers.MyReceiver"
android:exported="false"/>
<service
android:name=".MyIntentService"
android:exported="false"/>
And the service
public class MyIntentService extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
try {
//logic here
} catch{
} finaly{
MyReceiver.completeWakefulIntent(intent);
}
}
Call from within my Activity
sendBroadcast(new Intent(context, MyReceiver.class).putExtra(...);
Schedule a pending intent from an alarm
Intent myIntent = new Intent(context, MyReceiver.class);
myIntent.putExtra("test", "testValue");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
how exposed is this receiver to other apps? Can it react to other apps except mine? Does this rise any security possible issues?
Thank you.
Later edit:
Since the WakefullBroadcastReceiver seems the only way that guarantees that my service will get a partial wakelock, how can I make sure 100% that no other apps will be aware of my receiver and that my receiver won't get any other calls except ones made from my activity or from my set Alarm?
How would a WakefullBroadcastReceiver pattern works versus CommonsWare's WakefulIntentService ?
Later Edit:
I've finally managed to finish my implementation.
As stated before, both my WakefulBroadcastReceiver and IntentService are declared as exported="false" in my Android Manifest which from what I understand means that only my app can access them. Since the receiver is not exported, does it receive broadcasts from outside the app?
When setting an alarm I use this PendingIntent:
Intent myIntent = new Intent(context, MyReceiver.class);
myIntent.putExtra("databaseId", "1");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 323,
myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
When calling from my Activity I do:
sendBroadcast(new Intent(context, MyReceiver.class).putExtra("databaseId", "1"));
Is this enough?
Privacy considerations related to Intent extras
In general, I would say that it is an insecure practice to put sensitive data in Intent.
In theory, if Intent can only be consumed by specific application (discussed later) then only that application should be able to see its contents. However, given a vast amount of Android devices and OS versions (incl. rooted devices and custom ROMs), I wouldn't count on it.
You did not specify the kind of sensitive data you'd like to pass in Intent extras, therefore I can only give these general recommendations:
Make sure you understand the "confidentiality level" of the data in question: is it secret, or just restricted? Or, maybe, it is public (in which case no protection needed)?
Try to find another approach that doesn't involve passing sensitive data in Intent (I myself never encountered such a need).
If you absolutely must pass sensitive data in Intent extras - consider encrypting it. The encryption model should be adequate to "confidentiality level" of the data, and to potential harm which could be done if that data is being intercepted (it can go all the way up to "server side" encryption).
Privacy/security considerations related to BroadcastReceiver
In general, BroadcastReceiver is a component which receives "system wide" broadcasts. The fact that the broadcasts are "system wide" should speak by itself about the level of privacy associated with them.
That being said, there is one mechanism by which developers can restrict broadcasts' scopes: custom permissions. Usage of custom permissions allows for two "levels of control" over broadcasts:
If broadcast requires specific permission then only if BroadcastReceiver has that permission will it receive the broadcast.
If BroadcastReceiver filters the incoming broadcasts by specific permissions, then only broadcasts carrying that permission will be delivered to that receiver.
While the above points can seem similar on the first sight, these are distinct schemes that can be used separately, or combined. The first scheme associates a broadcast with a permission (and the sender of that broadcast doesn't necessarily have that permission by himself), while the second scheme filters all broadcasts by specific permission (and the receiver must have that permission).
A better approach in your case
EDIT: this COULD BE a better approach if "wakefullness" wouldn't be part of the requirements. But it is. Since there is no guarantee that Service started by AlarmManager will get a chance to acquire a wake lock - this approach is not suitable for OP's case.
Please note that broadcasts and custom permissions were designed in order to introduce "decoupling" at application level - this scheme allows for sender application to be completely agnostic of the receiving application, as long as they agree on one custom permission (well, the same scheme is employed for pre-installed public permissions as well, but you wouldn't want to guard your sensitive data with a public permission).
In your case, however, sender and receiver are the same application. In such setting you don't really need all the trouble associated with broadcasts - just construct PendingIntent that starts the required Service inside your app, and you get it all at once:
PendingIntent and the associated Intent start a specific Service in your application (by name), therefore no other application can intercept it (theoretically, remember the above discussion).
Target Service can be non-exported, therefore no other application can access it in any way.
You welcome :)
I am bit new to android. I would like to know how to communicate with a foreground started service.
So, I got a Foreground service with a notification.
This notification has a (X) button to stop the service.
The service got a Static broadcastreceiver.
public static class NotificationStopButtonHandler extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context,"Close Clicked",Toast.LENGTH_SHORT).show();
Log.i(LOG_TAG, "In Closed");
// imposible to do context.stopForground(true) or
// to call any other private coded by me
}
}
So my question is :
Is BroadcastReceiver is the best way ?
If it is : How I can communicate with the service to call stopForeground in the broadcastReceiver ?
Thanks in advance for your responses.
Same question like mien... But I would like to know which are the other solution than broadcastReceiver. thx
In your notification you will have a PendingIntent for the X button. I presume you have built that PendingIntent with
PendingIntent.getBroadcast(/* ... */);
What you can do instead is to create a PendingIntent for your service
Intent intent = /* intent for starting your service */;
intent.putExtra("STOP_FOREGROUND", true);
PendingIntent.getService(context, requestCode, intent, flags);
and in the intent you pass to the PendingIntent you would add an extra (STOP_FOREGROUND). When this intent is fired, your service will get called in onStartCommand(). Here you check the intent and if it contains your extra, you know you're expected to call stopForeground.
Instead of broadcasts, you can use PendingIntent with an Intent to the Service and tell the Service to shut down. You assign the PendingIntent to the close button action and/or to the notifications onDelete call when you build the notification.
Assuming that you're starting the Service with the notification, you can put commands in the Intent to tell the service to stop itself. Service#onStartCommand will be called on the service with the new Intent. The service checks for the shutdown call and calls stopSelf() when done.
Basically, the reason this works is because there can only be one Service started. Every subsequent attempt to start the service will send the intent to Service#onStartCommand, but it will not restart the Service. Thus, this is a way you can send commands to the service through means outside of binding. Plus it's way cleaner than using broadcasts.
I am developing an android application. This application architecture is divided into 5 modules with 2 modules having multiple features. To develop this app, I am creating 2 process with multiple threads in them as required and 3 other threads. I have a some questions regarding this implementation:
Is this a good model? If not, why not? Right now I am considering only modularity.
I need to send a message from broadcast receiver in process1 to Service thread in process2, what is the best way to do it?
what is the best IPC mechanism in android? I tried to use this link, http://androidapps.org.ua/androidintro_ipc_intent.html which suggests startActivity and startActivityForResult, but these options are not available in broadcast receiver and service does not have startActivityForResult option.
Thank you.
Use Custom BroadcastReceiver
Write this in ActivityA.java
Intent intent = new Intent();
intent.putExtra("message","hi");
intent.setAction("com.android.activity.SEND_DATA");
sendBroadcast(intent);
Write this in ServiceA.java
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
// Extract data included in the Intent
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
Now register Receiver
LocalBroadcastManager.getInstance(mContext).registerReceiver(mMessageReceiver,
new IntentFilter("com.android.activity.SEND_DATA"));
Just create an Intent in the BroadcastReceiver, add your data as extras, can call startService() with the Intent:
Intent intent = new Intent(context, MyService.class);
intent.putExtra("message", "whatever data you need to pass to the service");
context.startService(intent);
The method onStartCommand() will be called in your service with the passed Intent.
To answer your other question "what is the best IPC method", the answer (as always) is "that depends". Using Intents is the easiest method, as it is supported for all components out-of-the-box. If you need more complicated interaction between components you can look at using AIDL which will allow you to do remote method calls in a Service. If that still isn't enough, then just implement your own socket protocol between the 2 components.
First of all, trying to understand your terminologies. By process, I presume you mean activity and "service thread", I presume you mean a service.
If you want to send a message from onReceive() broadcast receiver, running in context of Activity 1, to a service which is already active, you can try one of the below:
1) Create a new intent (service class name as the class) and call startService() with the intent. Add the additional parameters you need as intent extras. It does not matter if your service is already active, the onStartCommand() is still called, you can have special parameters as intent extras to differentiate a onStartCommand() from onReceive.
2) If your scenario allows this, consider registering to same broadcast event in both your activity and service and act appropriately (then no need to pass messages)
3) Write another broadcast receiver in your service and call sendBroadcast() from the Activity's broadcast receiver
I am interested in using pending intents with local broadcasts.
To make myself clear, I am using the following for registering receivers and sending broadcast: android.support.v4.content.LocalBroadcastManager.
I have a local broadcast receiver in a service which works. I am trying to send local broadcasts from a custom notification layout which includes click-able items.
The local broadcast receiver - just receives simple action intents.
I was trying something like this to no avail:
Intent backintent = new Intent("GOTO_START_BROADCAST");
PendingIntent backIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, backintent, 0);
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom_notification);
contentView.setOnClickPendingIntent(R.id.imageView1, backIntent);
I am interested in using pending intents with local broadcasts.
That is not possible.
The point behind a PendingIntent is to allow some other process to perform an action you request, such as sending a broadcast.
The point behind LocalBroadcastManager is to keep broadcast within your process.
Hence, a PendingIntent can issue a regular broadcast, but not one via LocalBroadcastManager.
I'm using this code:
Intent i = getApplicationContext().registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
and as far as I understand i should be null if ACTION_BATTERY_CHANGED didn't occur, but it is never null and always returns me the same data.
It worked fine when I used a broadcast receiver. Do I need to delete the Intent after receiving it?
As soon as you register sticky intents will always deliver you last broadcasted data. So that is the reason you are always recieving data
Sticky=property of adhering
result=which intent adhered with os called sticky intent
Normally you send broadcast a receiver using sendBroadcast(Intent) But When you are calling this method sendStickyBroadcast(Intent) it means that A broadcast Intent can be specified to be sticky in which case it will be retained by the system after it has been sent. But by default Intent.ACTION_BATTERY_CHANGED intent is sticky.
read the full post here http://iphoidtech.com/uncategorized/what-is-stcky-intent/