How to pass data through PendingIntent to Broadcast receiver - android

I'm developing alert app which shows notification and custom message in separate activity when alarm is set off.I'm facing problem in sending identifier to broadcast receiver which is useful in fetching data from database.
I have gone through various blogs, stackoverflow posts but couldn't find the working solution.Please do help me.
My function for scheduling alarm.
void setAlarm(int tag, long time) {
Intent myIntent = new Intent(context, AlarmReceiver.class);
myIntent.putExtra("TEST", "dummy");
myIntent.putExtra("ID",tag);
pendingIntent = PendingIntent.getBroadcast(context, tag, myIntent, Intent.FILL_IN_DATA);
alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, pendingIntent);
}
My Broadcast receiver
#Override
public void onReceive(Context context, Intent intent) {
logHelper.printLog("Alarm Service "+intent.getIntExtra("ID",0)+ intent.getStringExtra("TEST"));
ComponentName comp = new ComponentName(context.getPackageName(),
AlarmService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
Kindly let me know if any further information needed.

Related

How to call onReceive from onReceive of another BroadcastReceiver in Android?

I am developing one android application, In which i need to call onReceive method of Alarmmanager from onReceive of another BroadcastReceiver i.e. Internet connectivity. Is it possible ? Or should i duplicate all my stuff in another BroadcastReceiver?
You can make a new intent from onReceive to trigger another broadcast receiver
#Override
public void onReceive(Context context, Intent intent) {
Intent newIntent = new Intent("com.domain.yourboardcastreceiver");
context.sendBroadcast(newIntent);
}
In OnReceive(..) method of Internet Connectivity broadcast receiver, you can set alarm and thats how alarm manager will get triggered, eg :
#Override
public void onReceive(Context context, Intent intent) {
Intent myIntent = new Intent(getBaseContext(), **AlarmReceiver**.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(getBaseContext(), 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
Don't forget to register alarmmanager's receiver in your manifest file.
Hope it helps !

Pending intent with different intent but same ID

I have two pending Intent to use with Alarm Manager one is:
Intent i = new Intent(context, TriggerAlarm.class);
PendingIntent pi =PendingIntent.getBroadcast(context,0,i,PendingIntent.FLAG_CANCEL_CURRENT);
and the other is:
Intent i = new Intent(context, TriggerNotification.class);
PendingIntent pi = PendingIntent.getBroadcast(context,0, i,PendingIntent.FLAG_CANCEL_CURRENT);
I use these two in different methods in my application
my question is:
Are these pendingIntents differnt from each other?? because the intents are different but the Ids are same
If I set alarm manager for each of these pending intent do both of them trigger or one replace another?
So the easy way is test it directly by yourself.
I have tested it on my computer and here is what i got:
Are these pendingIntents different from each other?? because the intents are different but the Ids are same
-Yes they are different each other although the Ids are same
If I set alarm manager for each of these pending intent do both of them trigger or one replace another?
-Both of them will be triggered
Here are my code for test, you can copy and try it by yourself
Copy this method to your activity, and call it
private void setAlarmManager() {
Log.v("AlarmManager", "Configuring AlarmManager...");
Intent startIntent1 = new Intent(context, AlarmReceiverFirst.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, startIntent1, PendingIntent.FLAG_CANCEL_CURRENT);
Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 20);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Log.v("AlarmManager", "Starting AlarmManager for >= KITKAT version");
alarm.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent1);
alarm.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent2);
} else {
Log.v("AlarmManager", "Starting AlarmManager for < KITKAT version");
alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent1);
alarm.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent2);
}
Log.v("AlarmManager", "AlarmManager has been started");
}
Create your first receiver class
public class AlarmReceiverFirst extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v(this.getClass().getSimpleName(), "first alarm receiver is called");
}
}
Create your second receiver class
public class AlarmReceiverSecond extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.v(this.getClass().getSimpleName(), "second alarm receiver is called");
}
}
Register those receivers to your manifest
<receiver android:name=".AlarmReceiverFirst" />
<receiver android:name=".AlarmReceiverSecond" />
Not to be confused, what you called Id here is called request code. It is used for cancelling the pending intent.
Intents are just the action PendingIntent is bound to execute once it triggers. But this triggering criteria are entirely depending on PendingIntent itself and RequestCode is playing here a pretty good role to uniquely identify, manage and trigger PendingIntent.
Therefore, no matter what the Intent is, if the requestCode is repeated then the latter PendingIntent will trigger. If you need to trigger multiple PendingIntents, the requestCode must be different from each other.
You can have same name of intents but with different ids like following,
Intent i = new Intent(context, TriggerAlarm.class);
PendingIntent pi =PendingIntent.getBroadcast(context,System.currentTimeMillis(),i,PendingIntent.FLAG_CANCEL_CURRENT);
And
Intent i = new Intent(context, TriggerNotification.class);
PendingIntent pi = PendingIntent.getBroadcast(context,System.currentTimeMillis(), i,PendingIntent.FLAG_CANCEL_CURRENT);
This way both the intents would be distinguished differently from each other and will get triggered.You can have any unique id instead of System.currentTimeMillis()

receiving ID of Pending Intent from Broadcast Receiver

I need to access the ID of the Pending Intent from the Broadcast Receiver class.
Here is the code of my Main Activity from which I set the Alarm using PendingIntent.
private void setAlarm(Calendar targetCal)
{
Intent alarmintent = new Intent(AddAlarm.this, AlarmReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(AddAlarm.this, pen, alarmintent, PendingIntent.FLAG_ONE_SHOT); //where pen is the ID
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(), sender);
}
And here is the code of my Broadcast Receiver:
public class AlarmReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
int vibrator = intent.getIntExtra("vibrator", 1);
//PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
//intent to call the activity which shows on ringing
Intent myIntent = new Intent(context, Time_Date.class);
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(myIntent);
//display that alarm is ringing
Toast.makeText(context, "Alarm Ringing...!!!", Toast.LENGTH_LONG).show();
ComponentName comp = new ComponentName(context.getPackageName(),
AlarmService.class.getName());
startWakefulService(context, (intent.setComponent(comp)));
setResultCode(Activity.RESULT_OK);
}
}
Can I use Intent.putExtra() to receive the same or any other easy way to get the unique ID to the Broadcast Receiver? Any help will be appreciated.
I don't think the second argument to PendingIntent.getBroadcast() is meant to be used by the component that eventually receives the intent (at least I have found no way to access it). If you want to pass some data along that is specific to your app, just use an extra.

Call web service in interval on background

Application need synchronize data from server in interval (for example every 30min) or manually on background. Result is saved to local database. After sync is done I want remind activity/fragment ... and force update list (if needed). There are many activities, so I want move it outside of activity and make it more consistent.
For now I created AsyncTask which get result from server and save to DB.
What shoud I use? BroadcastReciever, Service, AlarmManager?
UPDATE
Based on answers I start alarm in Application
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
manager.setInexactRepeating(AlarmManager.RTC, 0, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
Created Receiver
public class AlarmReceiver extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent syncIntent = new Intent();
syncIntent.setClass(context, DataSyncer.class);
startWakefulService(context, syncIntent);
}
}
Created IntentService
public class DataSyncer extends IntentService {
#Override
protected void onHandleIntent(Intent intent) {
// get data from server
// save to DB
AlarmReceiver.completeWakefulIntent(intent);
}
}
And registered Receiver and Service in AndroidManifest
<service
android:name="com.cloudit.tsystems.app.DataSyncer"
android:enabled="true">
</service>
<receiver
android:name="com.cloudit.tsystems.app.AlarmReceiver"
android:enabled="true">
</receiver>
Where and how I notify that sync is done in Activity/Fragment?
I would use the AlarmManager and register a BroadcastReceiver. Once the receiver is fired, I will launch an IntentService to download the data in the background.
Configure your alarm:
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, MyBroadcast.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
manager.setInexactRepeating(AlarmManager.RTC, 0, AlarmManager.INTERVAL_HALF_HOUR, pendingIntent);
Create a BroadcastReceiver that will get notified when the alarm goes off. Note that I'm using a WakefulBroadcastReceiver so that the device doesn't go to sleep when you're syncing.
class MyBroadcast extends WakefulBroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent syncIntent = new Intent();
syncIntent.setClass(context, DataSyncer.class);
startWakefulService(context, syncIntent);
}
}
Next, an IntentService that will download data in the background:
class DataSyncer extends IntentService{
...
#Override
protected void onHandleIntent(Intent intent) {
//sync data
MyBroadcast.completeWakefulIntent(intent);
}
}
Update:
So now that you have your data synced, there are several options to notify Activities and Fragments. You can use a LocalBroadcastManager to broadcast. Take a look at this link for more details.
Use an AlarmManager to trigger a PendingIntent on a 30 minute interval that starts an IntentService to do your download.
Intent intent = new Intent(context, PollingService.class);
PendingIntent pendingIntent = PendingIntent.getService(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(
AlarmManager.RTC,
System.currentTimeMillis(),
AlarmManager.INTERVAL_HALF_HOUR,
pendingIntent
);
When the IntentService is done updating your data, it can send a Broadcast that your Activity/Fragment has registered to listen for to notify it of new data and refresh it's view.
sendBroadcast(new Intent("DATA_UPDATED"));
In your Fragment
getActivity().registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
//update UI
}
}, new IntentFilter("DATA_UPDATED"));

android : all of alarm were cleared how to get them back

first of all , i would like to apologize for my English its bad
all of alarm that i create by this class
Intent intent = new Intent(SETALARM.this, ALARMRECEIVER.class);
intent.putExtra("pk", pk);
sender = PendingIntent.getBroadcast(this, pk, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),60000, sender);
were cleared when device is shut off
what should i do to restore all of alarm back
thank you very much for your help
edit
here is receiver class
#Override
public void onReceive(Context context, Intent intent) {
WakeLocker.acquire(context);
pk = Integer.parseInt(intent.getExtras().get("pk").toString());
Intent intent2 = new Intent(context,ALERT.class);
intent2.putExtra("pk", pk);
intent2.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent2);
WakeLocker.release();
}}
If you mean that you lose the alarms when the device is turned off then this issue has been addressed well here
https://stackoverflow.com/a/5439320/374866

Categories

Resources