Basically I want to broadcast and receive every 5 seconds using this code:
private final BroadcastReceiver checkWifiStateChanged = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
checkWifiStateHasChanged();
}
};
How could I do this?
As the comments have stated, this is basically an unnecessary way to approach this. The Android platform automatically sends out Intents for certain changes, and Wifi status is one of them. You need only have a BroadcastReceiver registered that filters on that Intent to be able to respond to it.
Related
I have registered BroadcastReceiver for Calendar Provider. Code works fine but when I just change one calendar event - I get several broadcasted intents. This would not be too much annoying but each intent in my app causes download all calendar events for specific time period. There could be lots of events in several days and each includes String texts and other data. Extra broadcasted intents force exchange too many extra data. And this all happens on mobile device connected to cellular or Wi-Fi network. This wastes traffic and battery.
I do not know - is there a way to separate really creative intent from others. Code is simple:
class RegisterReceiver implements Runnable
{
private Activity a;
private CalendarReceiver receiver;
public RegisterReceiver(Activity _a){
a = _a;
}
public void run(){
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_PROVIDER_CHANGED);
filter.addDataScheme("content");
filter.addDataAuthority("com.android.calendar", null);
a.registerReceiver(receiver = new CalendarReceiver(), filter);
}
public CalendarReceiver getreceiver()
{
return receiver;
}
}
class CalendarReceiver extends BroadcastReceiver
{
public void onReceive(Context context, Intent intent)
{
MainControl.DebugMessage( intent.getAction() );
MainControl.calendarChanged();
}
}
The MainControl.calendarChanged(); forces further processing. The intent.getAction() just contains info this is a "provider changed" intent. On each calendar action it appears several times with long delays. It is the same when I add calendar events, delete ot change them. Is there a way how to define which one intent is "my"? Is there any description of how to separate new, deleted, changed event intents?
I need to have a two way communication between my activity and a running IntentService.
The scenario is like this: the app can schedule alarms which on run, start an IntentService which fetches some data from web and process it. There are three possible situations when IntentService finishes:
The app is in focus, which means that when the IntentService will finish, the app needs to refresh its views with the new data.
The app is closed and when opened after IntentService has finished the work, so the app will have access to processed data
The app is opened while the IntentService is running, in which case I need to have a way from the activity to ask the IntentService if its doing something in the background.
For 1. I have already implemented a BroadcastReceiver in my activity which gets registered with the LocalBroadcastManager. When IntentService finishes the work, sends a broadcast and the activity reacts. This works fine
For 2. There is nothing needed to be done
For 3. I don't know what to do. So far I've tried this:
In Activity:
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_SEND_TO_SERVICE));
In IntentService
private LocalBroadcastManager localBroadcastManager;
private BroadcastReceiver broadcastReceiverService = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BROADCAST_SEND_TO_SERVICE)) {
//does not reach this place
//Send back a broadcast to activity telling that it is working
}
}
};
#Override
protected void onHandleIntent(Intent intent) {
localBroadcastManager = LocalBroadcastManager.getInstance(context);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BROADCAST_SEND_TO_SERVICE);
localBroadcastManager.registerReceiver(broadcastReceiverService, intentFilter);
.... //do things
}
The problem with my implementation is that n the IntentService the BroadcastReceiver does not fire onReceive. Any suggestions or maybe a simpler way for the Activity to ask the IntentService what it is doing?
LE:
Trying to get atomicboolean.
In Service:
public static AtomicBoolean isRunning = new AtomicBoolean(false);
#Override
protected void onHandleIntent(Intent intent) {
isRunning.set(true);
// do work
// Thread.sleep(30000)
isRunning.set(false);
}
In Activity, restarting the app while service is running:
Log(MyIntentService.isRunning.get());
//this returns always false, even if the intent service is running
On AndroidManifest
<service
android:name=".services.MyIntentService"
android:exported="false" />
This is for a GPS. I have a parent class with an embedded receiver class, and a separate LocationTrackingService class that handles the GPS stuff. I need to Broadcast the mileage traveled to update the UI, but the broadcast is never received. This is the only BroadcastReceiver in the project. I guess I could set a timer to have my ServiceConnection check every couple of seconds and grab the new mileage, but that's bad coding.
Nothing is in the Manifest because I'm registering and unregistering dynamically.
public class Parent
{
GPSReceiver gpsreceiver;
public class EmbeddedReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context arg0, Intent intent)
{
Bundle extras = intent.getExtras();
if (extras != null) {
distance = extras.getDouble(LocationTrackingService.UPDATE_MILEAGE_MESSAGE);
}
}
}
#Override
public void onCreate(Bundle savedInstanceState)
{
gpsReceiver = new EmbeddedReceiver();
}
private void gpsStart()
{
if (gpsReceiver != null) {
intentFilter = new IntentFilter();
intentFilter.addAction("don't know what goes here");
LocalBroadcastManager.getInstance(this).registerReceiver(gpsReceiver, intentFilter);
}
}
private void gpsStop()
{
if (gpsReceiver != null) {
LocalBroadcastManager.getInstance(this).unregisterReceiver(gpsReceiver);
}
}
}
public class LocationTrackingService extends Service
{
private LocalBroadcastManager broadcaster;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
super.onStartCommand(intent, flags, startId);
broadcaster = LocalBroadcastManager.getInstance(this);
return START_STICKY;
}
.... code
private void sendResult(String message)
{
Intent i = new Intent("ParentActivity");
i.setAction("ParentActivity");
if (message != null) {
i.putExtra(message, mileageRunningTotal);
}
broadcaster.sendBroadcast(i);
}
}
When I follow the code into LocalBroadcastManager, on line 215 it does mActions.get(intent.getAction() to get an ArrayList<ReceiverRecord>, and it's null, but I don't know why.
I appreciate any help you can give.
Broadcasts work in such a way that the action acts as a trigger for the receiver. In other words, there are tons of broadcasts being sent around throughout your phone at any given time, the goal of the receiver is to catch the broadcast with the corresponding action when it flies by. It will let all other broadcasts continue through without interruption. Once it finds the one it is looking for, it will receive it and perform the onReceive() functionality.
Though an action can be any string key you care for it to be, it is advised to add in your package name. This gives specificity to your broadcast and allows your broadcast to be more easily managed in the barrage of broadcasts that your phone is sending. This is important as broadcasts can be sent between applications. It makes it so you avoid the following scenario
Application A sends out a system broadcast with action "SOME_ACTION" which we have no interest in. Application B will also be sending out a local broadcast with action "SOME_ACTION" which we are awnt to receive. We will setup Receiver 1 to look for and receive the action "SOME_ACTION" from Application B. However, because of conflicting actions, when Application A sends out a broadcast of "SOME_ACTION", we will inappropriately receive it in Receiver 1 and perform our onReceive() functionality as though we had just received a local broadcast from Application B.
Following recommended convention, you avoid the above situation by doing the following
Instead of setting your action as "SOME_ACTION", it would be set to "com.app_b.package.SOME_ACTION". That way when the broadcast action "com.app_a.package.SOME_ACTION" passes by, it won't be confused for our action and will be allowed to pass.
There may be other reasons for using package name, and this may not be the best of them, but to the best of my knowledge this is the reasoning behind the convention.
I cant see the declaration for the broadcaster object.
broadcaster.sendBroadcast(i);
Is it a Local Broadcast Manager instance?
If not it won't work.
I'm trying to use a local broadcast receiver.
In order to do so I"ve done the next steps -
1) At an Activity, where Iwould like something to happen, I've created a class -
private class NewGroupReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
Log.d("The group ", "GOT IN THE RECIVING");
Toast.makeText(this, "Working",Toast.LENGTH_SHORT).show();
}
}
2) At the same activity I've used the next code in order to create a receiver -
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NewGroupReceiver receiver = new NewGroupReceiver();
//the intent filter will be action = "com.example.demo_service.action.SERVICE_FINISHED"
IntentFilter filter= new IntentFilter("com.example.apps.action.NEW_GROUP");
// register the receiver:
registerReceiver(receiver, filter);
}
3) At the a service class I've used the next code to know when something has happened-
Intent resultsIntent=new Intent("com.example.apps.action.NEW_GROUP");
LocalBroadcastManager localBroadcastManager =LocalBroadcastManager.getInstance(this);
localBroadcastManager.sendBroadcast(resultsIntent);
Now the problem is that when the thing I WOuld like to know has happen - I see the it's get into the code that I've used at step 3, but it doesen't seem to get into the BroadcastReceiver - the step 1 code.
Any idea what am I doing wrong here?
Thanks for any kind of help.
You are using the LocalBroadcastManager to send the request, but you register the receiver on the "global" Intent. You should either use LocalBroadcastManager to register the receiver or send the broadcast on the
application context:
Step 2
LocalBroadcastManager.getInstance(this).registerReceiver (receiver, filter);
I'm wanting to implement what CommonsWare describes on this blog post: http://commonsware.com/blog/2010/08/11/activity-notification-ordered-broadcast.html. The post makes sense, and I was able to browse the example source here: https://github.com/commonsguy/cw-advandroid/tree/master/Broadcast.
What I'm curious about is if calling LocalBroadcastManager.getInstance(UnzipService.this).sendBroadcast(broadcast); inside of a service will still be picked up by a broadcast receiver of the type you define in your manifest.
In case what I'm asking isn't clear, what I'm trying to do is use the LocalBroadcastManager because the broadcasts from my service don't necessarily need to be seen system wide and I'd rather keep them private if possible, but I also want to display notifications if the user closes my app and the service is still running. Is there a way to combine both of those capabilities without sending a broadcast twice inside of the service?
(What I don't want to have to do) like:
LocalBroadcastManager.getInstance(UnzipService.this).sendBroadcast(broadcast);
sendOrderedBroadcast(broadcast);
What I'm curious about is if calling LocalBroadcastManager.getInstance(UnzipService.this).sendBroadcast(broadcast); inside of a service will still be picked up by a broadcast receiver of the type you define in your manifest.
No. LocalBroadcastManager only works with receivers registered with the LocalBroadcastManager singleton itself. Moreover, LocalBroadcastManager does not support ordered broadcasts, last I checked.
what I'm trying to do is use the LocalBroadcastManager because the broadcasts from my service don't necessarily need to be seen system wide and I'd rather keep them private if possible
So long as you are not using an <intent-filter> on your BroadcastReceiver in the manifest, and therefore are using an explicit Intent as the broadcast itself, your broadcast will only be seen by yourself and the bit of the OS that manages broadcasts. Other apps will not be able to spy upon it.
If you only have 2 objects that might handle your broadcast (in your case an Activity and a notifications controller), you can achieve the behavior of a ordered broadcast using only the LocalBroadcastManager.
The general idea is:
Set up your Service so that it broadcasts an Intent to your Activity with a particular action when you want to display your result
In your Activity create a BroadcastReceiver that handles your Service result Intent, and register it on the LocalBroadcastManager with an IntentFilter using the action from step 1
In your Service, when the results are available, try to send the result Intent using LocalBroadcastManager.getInstance(Context).sendBroadcast(Intent) this method returns a boolean that indicates if the broadcast has been sent to at least one receiver. If this boolean is false, it means that your Activity didn't handle your broadcast and you should show a notification instead.
In your service:
public UnzipService extends IntentService {
public static final String ACTION_SHOWRESULT = UnzipService.class.getCanonicalName() + ".ACTION_SHOWRESULT";
#Override
protected void onHandleIntent(Intent intent) {
Thread.sleep(500); // Do the hard work
// Then try to notify the Activity about the results
Intent activityIntent = new Intent(this, YourActivity.class);
activityIntent.setAction(ACTION_SHOWRESULT);
activityIntent.putExtra(SOME_KEY, SOME_RESULTVALUE); // Put the result into extras
boolean broadcastEnqueued = LocalBroadcastManager.getInstance(this).sendBroadcast(activityIntent);
if (!broadcastEnqueued) { // Fallback to notification!
PendingIntent pendingIntent = PendingIntent.getActivity(this, (int) System.currentTimeMillis(), activityIntent, PendingIntent.FLAG_UPDATE_CURRENT);
((NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE))
.notify(SOME_ID, new NotificationCompat.Builder(this)
.setContentIntent(pendingIntent)
.setTicker("results available")
.setContentText("results")
.build());
}
}
}
In your Activity:
public YourActivity extends Activity {
private BroadcastReceiver resultReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
processResult(intent); // Results Intent received through local broadcast
}
}
private IntentFilter resultFilter = new IntentFilter(UnzipService.ACTION_SHOWRESULT);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate();
Intent intent = getIntent();
if (UnzipService.ACTION_SHOWRESULT.equals(intent.getAction())) {
// The Activity has been launched with a tap on the notification
processResult(intent); // Results Intent contained in the notification PendingIntent
}
}
#Override
protected void onResume() {
super.onResume();
LocalBroadcastManager.getInstance(this)
.registerReceiver(resultReceiver, resultFilter);
}
#Override
protected void onPause() {
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(resultReceiver);
super.onPause();
}
private void processResult(Intent intent) {
// Show the results from Intent extras
}
}
This should be a complete working example.
I hope this helps who is trying to implement ordered broadcasts with LocalBroadcastManager from support library!
I understand you want to achieve the following:
"I have an event that occurs in the background. I want to update my activity, if the activity is on the screen. Otherwise, I want to raise a Notification." (#TheCommonsBlog)
You can achieve this behaviour by implementing a ResultReceiver.
Examples Restful API service and
http://itekblog.com/background-processing-with-intentservice-class/
What you basically do is instance a ResultReceiver in your Activity and pass it to the Service like a Parcelable parameter through an intent. Then, each time your service whats to update the UI, the service verifies the ResultReceiver object for NULL. If not NULL, you update the Ui via the onReceiveResult interface. Else, you raise a notification. When your activity dismisses, make sure you set the ResultReceiver on the Service to NULL.
Hope it helps.
PS: IMO, broadcasts are too much work and hard to control.
Use LocalBroadcastManager and broadcasts become easy to use.
I am not in favor of updating an Activity if an event occurs in the background. The user might already be doing something else in the Activity. Seems to me that a Notification is sufficient; it's always visible and remains until the user dismisses it. Gmail and Gcal work like this; Gmail doesn't update the current screen if a new mail comes in. If you want to know how to handle the task flow for handling a notification when the user is already in the app, see the Notifications API guide and also the [Notifying The User2 training class.