public class MainActivity extends Activity {
public TextView batteryTxt;
private BroadcastReceiver receiver;
BroadcastReceiver mybroadcast = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
int batterylevel = intent.getIntExtra("level", 0);
batteryTxt.setText("Battery Level: " + Integer.toString(batterylevel) + "%");
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
batteryTxt = (TextView) findViewById(R.id.textView1);
IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(mybroadcast, filter);
}
}
Eventhough i have not used intent.putExtra() in above program, how intent.getIntExtra("level", 0) is working?
It's an IntentFilter, which sends an Intent to the BatteryManager to check ACTION_BATTERY_CHANGED. The BatteryManager then calls intent.putIntExtra to put the int that you're reciving in the Intent.
The intent is what your BroadcastReceiver receives from the system, when the action "ACTION_BATTERY_CHANGED" is performed. It's the information about battery level in this case, and "0" is the default value (in case there isn't extra named "level"). The intent is not created by any activity in this app.
You need to read the documentation on BroadcastReceivers and Intents.
http://developer.android.com/reference/android/content/BroadcastReceiver.html
http://developer.android.com/reference/android/content/Intent.html
Essentially these two mechanisms act as Android's preferred method of transferring state between applications and processes.
In short:
Broadcast Receivers are registered for Intents, and whenever an intent is "Fired" or "Launched" which corresponds to the "Mime-Type" for which your intent is registered, that Broadcast Receiver will be activated. At this time your Broadcast Receiver will be given the opportunity to handle state passed to it via the intent which was sent.
In your case:
You have created a Broadcast Receiver which is registered (presumably) for the Battery Service intents. That means every time the battery service sends out an Intent to all interested parties you'll receive an a message. The Battery Service includes in it's intent certain data which is useful to an application,service or process which is interested in the state of the Battery. In this case it is the "level".
Related
I've look at many solutions to other questions with similar issues but I can't figure out what's wrong with my code. I understand that LocalBroadcast is a popular way to do this and I've spent time trying to implement it. At the moment, the receiver isn't declared in my manifest but from what I understand, that's what the register lines are for.
In my activity:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d("MyActivity", "onReceive");
String action = intent.getAction();
int current = intent.getIntExtra("test", 0);
Toast.makeText(MyActivity.this, current.toString(), Toast.LENGTH_LONG).show();
}
};
#Override
public void onResume() {
super.onResume();
Log.d("MyActivity", "onResume()");
LocalBroadcastManager.getInstance(MyActivity.this).registerReceiver(
mMessageReceiver, new IntentFilter("currentUpdate"));
}
#Override
protected void onPause() {
Log.d("MyActivity", "onPause()");
LocalBroadcastManager.getInstance(MyActivity.this).unregisterReceiver(mMessageReceiver);
super.onPause();
}
In the service I have a method defined:
private void sendNewBroadcast(Intent intent, int current){
intent.putExtra("test", current);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
Log.d("MyService", "new Broadcast sent from service");
}
and I use it like this elsewhere in the service:
Intent intent = new Intent("currentUpdate");
sendNewBroadcast(intent, 5);
I've debugged and everything seems to be working except for the 'receiving' part. Am I missing something? The service is started in a different activity and is ongoing.
Firstly, the action String on the broadcast Intent needs to match the action set on the IntentFilter you're registering the Receiver with. Originally, they were different, but it was possibly just a typo.
Secondly, LocalBroadcastManager does not work across processes. The Activity and the Service must be running in the same process to be able to use LocalBroadcastManager. If the Service needs to be in a separate process, you'll have to use some other mechanism; e.g., Intents, broadcasts sent and received on a Context, some event bus implementation that supports IPC, etc.
I am trying to build a notification while a music playback service is running and use the notification to interact with the service (play, pause, stop) using the Broadcast mechanism.
(I know there is also the possibility to use PendingIntent.getService() as an action button in the notification, but I don't like this idea, because this would trigger the onStartCommand() of the service and I need to parse and analyze the Intent object to take action, which seems not as clean as the BroadcastReceiver approach, described below).
Let's illustrate what we have so far with some (truncated) code.
We are creating a Notification object inside the service lifecycle, add an action button, and showing the notification using startForeground().
...
Intent i = new Intent(getBaseContext(), PlayerService.class);
PendingIntent piStop = PendingIntent.getBroadcast(getBaseContext(), 1, i, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Action actionStopPlayback = new NotificationCompat.Action(R.drawable.ic_stop_white_36dp, "Stop playback", piStop);
notification.addAction(actionStopPlayback);
...
Then we are registering a BroadcastReceiver inside the onCreate() of the service (and unregistering it in onDestroy of course; this is a more simplified example).
IntentFilter intentFilter = new IntentFilter();
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(getClass().toString(), "Broadcast received");
}
}, intentFilter);
And the final result is that the onReceive() of the receiver is never called. The service is a continuous one and is active when the Notification action sends the broadcast. Since I have no way of debugging broadcasts due to their nature, I'm kind of blocked here.
You're creating this explicit Intent for the PendingIntent:
Intent i = new Intent(getBaseContext(), PlayerService.class);
This won't work for a couple of reasons. Explicit Intents - those created for a specific target class - do not work with dynamically registered Receiver instances. Also, this is targeting the wrong class. A broadcast Intent with a Service class target will just fail outright. A getBroadcast() PendingIntent would need a BroadcastReceiver class as the target.
With your current setup - the dynamically registered Receiver instance - you'll need to use an implicit Intent; i.e., an Intent with an action String, rather than a target class. For example:
Intent i = new Intent("com.hasmobi.action.STOP_PLAYBACK");
You would then use that action String for the IntentFilter you're using to register the Receiver.
IntentFilter intentFilter = new IntentFilter("com.hasmobi.action.STOP_PLAYBACK");
Do note that an IntentFilter can have multiple actions, so you can register a single Receiver to handle several different actions.
Alternatively, you could stick with using an explicit Intent, and statically register a BroadcastReceiver class in the manifest. For example:
public class NotificationReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
...
}
}
In the manifest:
<receiver android:name=".NotificationReceiver" />
Then your Intent would be similar to:
Intent i = new Intent(PlayerService.this, NotificationReceiver.class);
However, this would require an additional step, as you would then need to somehow pass the broadcast info from NotificationReceiver to the Service; e.g., with an event bus, LocalBroadcastManager, etc.
For instance some example here, a phone running 2 or more apps, calling onReceive().
Has android some kind of task order to run all thouse #Overrides by ordered sequence? Probably yes, then in which order, app importance?
App1 & App2:
App1:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
Log.d("receiver", "Got message: " + message);
}
};
App2:
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
deleteMessageFromInbox(message); // or just something that can conflict other Instance
}
};
You can define the order that intents are handled using the android:priority attribute of BroadcastReceivers. When an intent can be handled by multiple receivers, Android generates an ordered list (based on the priority of each receiver) and delivers the intent sequentially.
So in your case, when you register the receivers (via registerReceiver(BroadcastReceiver receiver, IntentFilter filter), all you have to do is assign a higher priority (via a call to setPriority(int priority)) to the intent filter in App1 than to the filter in App2 to make sure that App1 receives the intent before App2.
There is also an old article in the Android developers blog that gives you examples about how to implement this mechanism efficiently.
i am new to Android and trying to understand the communication between apps.
I am trying to write 3 little apps which can communicate with each other. If you want to sent a message to everybody you just use an implicit broadcast.
implicit Intent intent.setAction("com.example.myChatMessage")
if you want to adress only 1 specifc receiver i did it with
explicite Intentintent.setComponent("com.example.test.android.broadcastreceiver.b",
"com.example.test.android.broadcastreceiver.b.myBroadcastReceiver")
this works, when the broadcast receiver is a seperate class and defined in the AndroidManifest.xml.
My Question: Is it possible to explicit adress a dynamicall registered broadcast receiver?
package com.example.test.android.broadcastreceiver.b;
public class MainActivity extends Activity {
private final IntentFilter intentfilter = new IntentFilter("com.example.myChatMessage");
private myBroadcastReceiver broadcastreceiver;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
broadcastreceiver = new myBroadcastReceiver();
registerReceiver(broadcastreceiver, intentfilter);
}
public static class myBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
String message = intent.getStringExtra("message");
Log.d("message", "B received: "+message);
}
}
}
It receives all implicit broadcasts but no explicit one - i don't know hot to adress it. Can you help me?
It does not appear possible to send an explicit intent to a dynamically registered broadcast receiver. Registering the receiver in AndroidManifest.xml is the only way.
If you dynamically register a BroadcastReceiver – by calling Context.registerReceiver() – you supply a BroadcastReceiver instance ... If you try to send an Intent to the receiver by naming the class of the BroadcastReceiver, it will never get delivered .. The Android system will not match the Intent you declared to the class of the BroadcastReceiver instance you registered.
Source: http://onemikro2nd.blogspot.com/2013/09/darker-corners-of-android.html
i have a android service running in the background which receives the coordinates from the server every few seconds. i am not sure how do i display the coordinates on a map every time the service receives a response from the server. kindly help or give an idea.
thanks
I don't know any tutorials on this, but here's a version of mine:
To send a broadcast, you use the 'sendBroadcast(Intent i)' method of the Context class. The Service class extends Context, so you can access it from your implementation.
So in your Service goes:
public static final String BROADCAST_ACTION="com.yourservice.update";
public void onStart( Intent intent, int startId ) {
...
Intent broadcastIntent = new Intent(BROADCAST_ACTION);
sendBroadcast(broadcastIntent);
...
}
You have to register a receiver for this broadcast in you Activity (possibly before you start boradcasting them), like this:
private BroadcastReceiver receiver=new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
//Here goes handling the stuff you got from the service
Bundle extras = intent.getExtras();
if(extras != null)processUIUpdate(extras);
}
};
public void onResume() {
...
//Register for the update broadcasts from the torrent service
registerReceiver(receiver, new IntentFilter(YourService.BROADCAST_ACTION));
...
}
Don't forget to deregister when the Activity goes background:
public void onPause() {
...
//Deregister for the update broadcast from the torrent service
unregisterReceiver(receiver);
...
}
This should work.
Your service could broadcast intents whenever it wants to update the displayed location on the map. The Activity displaying the map should register a receiver for that boradcast, and the boradcast's intent can hold the values for lat. and long.