My Application class creates an alarm and receives the system broadcast once per day. In the onReceive() it sends an application broadcast that is received by my MainActivity class.
The problem is that the onReceive() in the MainActivity class is continually called whenever an orientation change occurs. I understand why onResume() is called across orientation changes, but I don't understand why onReceive() is also getting called.
I assumed that because the Application class only sends out the local broadcast once, my
MainActivity would only receive the broadcast once.
Does anyone know why onReceive() in my MainActivity class is continually called?
Here is the onCreate() in my Application class:
#Override
public void onCreate()
{
super.onCreate();
// register a receiver in the Application class to receive a broadcast
// at the start of each day
IntentFilter intentFilter = new IntentFilter(START_OF_DAY_ACTION);
startOfDayReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(TaskReminderApp.this,
"Application: startofday broadcast received",
Toast.LENGTH_LONG).show();
// send a broadcast to MainActivity
Intent i = new Intent();
i.setAction(TEST_ACTION);
context.sendBroadcast(i);
}
};
this.registerReceiver(startOfDayReceiver, intentFilter);
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 19); // for testing purposes
calendar.set(Calendar.MINUTE, 51); // for testing purposes
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
Intent intent = new Intent(START_OF_DAY_ACTION);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
am.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
}
Here is onResume() and onPause() in MainActivity:
#Override
protected void onResume()
{
super.onResume();
IntentFilter intentFilter = new IntentFilter(TEST_ACTION);
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
// This is getting called on every orientation change
// and every time the activity resumes.
Toast.makeText(MainActivity.this,
"MainActivity: broadcast received",
Toast.LENGTH_LONG).show();
}
};
this.registerReceiver(receiver, intentFilter);
}
#Override
protected void onPause()
{
super.onPause();
// I thought this might be the problem, but it makes no
// difference if I comment it out.
this.unregisterReceiver(receiver);
}
Because you need to create the Receiver in your onCreate(). Else it will be created again and again and again..
The registering is just fine, same as the unregistering.
I solved this by sending a local application broadcast instead of a system broadcast.
In my class that extends Application, I send a local broadcast like this:
Intent i = new Intent(TEST_ACTION);
LocalBroadcastManager.getInstance(context).sendBroadcast(i);
Then in my MainActivity class, I define a BroadcastReceiver like this:
private BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent)
{
Toast.makeText(MainActivity.this,
"MainActivity: broadcast received",
Toast.LENGTH_LONG).show();
}
};
I register the receiver in MainActivity's onCreate():
LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
new IntentFilter(TEST_ACTION));
Then I unregister the receiver in MainActivity's onDestroy():
LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver);
It works well now and I only receive a single broadcast.
Related
At point A in my application I start my service and expect the service get closed from point B. However, there might be few scenarios that point B doesn't ask service to get closed. In this case I want the service close itself after fixed amount of time.
I have written following code into my Service class and expect the service gets closed after 10 seconds from launch time (It will be 45min in the future but I don't want to stay that long for test).
public class ChatService extends Service implements ITCPConnection
{
private static final int SERVICE_LIFE_TIME = 10 * 1000; // In millis
private AlarmReceiver mAlarmReceiver;
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
#Override
public void onCreate()
{
super.onCreate();
//
mAlarmReceiver = new AlarmReceiver();
registerReceiver(mAlarmReceiver, new IntentFilter());
//
Intent intent = new Intent(this, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + SERVICE_LIFE_TIME, alarmIntent);
}
#Override
public void onDestroy()
{
super.onDestroy();
Log.e(TAG, "onDestroy()");
// Unregister receiver
if (mAlarmReceiver != null)
{
unregisterReceiver(mAlarmReceiver);
}
disconnect();
}
public void disconnect()
{
// If the alarm has been set, cancel it.
if (alarmMgr!= null)
{
alarmMgr.cancel(alarmIntent);
}
...
Log.e(TAG, "disconnect()");
}
/*****************
* Alarm Receiver
*****************/
private static class AlarmReceiver extends BroadcastReceiver
{
#Override
public void onReceive(Context context, Intent intent)
{
Log.e(TAG, "Stop service from AlarmReceiver");
context.stopService(intent);
}
}
}
My problem is AlarmReceiver.onReceive() never gets called and therefore my service will be alive indefinitely.
What you are trying to do is to targeting a broadcast receiver explicitly.
According to this, it cannot be done over a dinamically created (i.e. not declared into the manifest) broadcast receiver, because the os would not know how to resolve it.
To check if this is the root of the problem, you can go with the implicit way and set an action inside the intent and by filtering it in the IntentFilter.
Anyway, using the post delayed can be seen as a valid alternative, since you expect the service to be shut down naturally or still be around to intercept the delayed event.
Another (unrelated) thing is that you are calling
context.stopService(intent);
by using the broadcast intent and not the intent that started the service. You could simply call stopSelf().
I'm working on app in which I want to schedule service in a interval of 6 hours. I'm calling this method from main activity. When this activity open then it call this method and hits the service. I don't want to execute it whenever this method executes. After first exceution of this service it should execute after 6 hours or so not app open. Is there any flag or something I need to do set to do that.
public static void scheduleHeartBeat(Context mContext) {
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
Intent myIntent = new Intent(mContext, HearBeatService.class);
PendingIntent pendingIntent = PendingIntent.getService(mContext, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() , 6*60*60*1000, pendingIntent);
}
public class HearBeatService extends IntentService {
public HearBeatService() {
super("HearBeatService");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.d("HeartBeat", "Hey Testing!!!");
}
}
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
.....
scheduleHeartBeat(this);
...
}
Thanks in advance.
User broadcastreceiver.
Create class that extends Intent service class
Create class that broadcastreceiver class and call the Intent service (from step1)
Create pending intent for the broadcastreciever(from step2)
Register the pending intent with alarm manager of 6 hours delay
Dont Forget to register your service and receiver in the android manifest.
When I have the AlarmReceiver class below in it's own file, the log statement gets logged and the onReceive method gets called. I need to make my BroadcastReceiver an inner class so I can call getFragmentManager() from my Activity. However, when I make it an inner class to my main Activity class, it does not get called. Why is that?
public class MainActivity extends Activity {
public class AlarmReceiver extends BroadcastReceiver { //this needs to be an inner class to access the activity
#Override
public void onReceive(Context arg0, Intent arg1) {
Log.d("BROADCAST","RECEIVED");
//start a new activity, an alarm has gone off
AlarmFragment alarmFragment=new AlarmFragment();
// getFragmentManager().beginTransaction().replace(R.id.container, alarmFragment).commit();
}
}
public void setAlarm(){
Intent intentAlarm = new Intent(this, AlarmReceiver.class);
//Get the Alarm Service
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Long currentTime = new GregorianCalendar().getTimeInMillis();
//DEBUG TIME
alarmManager.set(AlarmManager.RTC_WAKEUP,currentTime+7500,PendingIntent.getBroadcast(this,1, intentAlarm, PendingIntent.FLAG_UPDATE_CURRENT));
}
}
Kindly change your Activity Class to FragmentActivity and also Access with context Object,like below code.
arg0.getFragmentManager().beginTransaction().replace(R.id.container, alarmFragment).commit();
Its is a Try. Kindly let me know your feedback.
Why is that?
you are got major fundamental mistake about how to send and receive broadcast mechanism works:
you are providing to alarm manager a PendingIntent to start broadcast, but in practice - you providing it intent without any Action specified.
sending broadcast without an action is meaningless!!!
you should add to the intentAlarm object an custom action string that identify your broadcast, and register your AlarmReceiver receiver programatically with an IntentFilter that handles this custom action:
Intent intentAlarm = new Intent(CUSTOM_ACTION_STRING);
....
....
(you should hold reference to an instance of your AlarmReceiver class. that's the mAlarmReceiver ...)
add to the Activity onResume() callback registration to the broadcast:
#Override
public void onResume() {
super.onResume();
registerReceiver(mAlarmReceiver , new IntentFilter(CUSTOM_ACTION_STRING));
}
don't forget also to unregister the receiver:
#Override
public void onPause() {
unregisterReceiver(mAlaramReceiver);
super.onPause();
}
I have an application that needs to start and stop activities.
So far we are OK with starting the Activity.
The problem comes when I try to stop the Activity.
This is the AlarmManager that broadcasts the intent to close the activity:
Intent ftue = new Intent(ctxt, VideoActivty.class);
ftue.putExtra("finish", true);
PendingIntent pftue = PendingIntent.getBroadcast(ctxt, 0, ftue, 0);
Calendar calSet4 = Calendar.getInstance();
calSet4.set(Calendar.MONTH, c.get(Calendar.MONTH));
calSet4.set(Calendar.YEAR, c.get(Calendar.YEAR));
calSet4.set(Calendar.DAY_OF_WEEK, 3);
calSet4.set(Calendar.HOUR_OF_DAY, hftue);
calSet4.set(Calendar.MINUTE, mftue);
calSet4.set(Calendar.SECOND, 0);
calSet4.set(Calendar.MILLISECOND, 0);
//calSet.setTimeZone(TimeZone.getTimeZone("UTC"));
mgr.setRepeating(AlarmManager.RTC_WAKEUP, calSet4.getTimeInMillis(),
7 * 24 * 60 * 60 * 1000, pftue);
And in my Activty I have implemented a BroadcastReceiver that should shut down the Activty.
#Override
public void onResume() {
super.onResume();
IntentFilter f=new IntentFilter();
registerReceiver(receiver, f);
}
#Override
public void onPause() {
unregisterReceiver(receiver);
super.onPause();
}
BroadcastReceiver receiver=new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
Log.e("","intento ricevuto");
if(intent.getBooleanExtra("finish",false))finish();
}
};
My application does not receive the broadcasted intents, and I understand that is because the intent filter is empty.
Please how should I implement the intent filter to receive the broadcasts?
Thanks!
Why your intent filter is blank? You can write intent action as any string (BUT that should not exists in SDK Actions)
// like
IntentFilter f = new IntentFilter("com.android.INTENT_ACTION_TO_CLOSE_ACTIVITY");
And use
Intent mIntent = new Intent("com.android.INTENT_ACTION_TO_CLOSE_ACTIVITY");
sendBroadcast(mIntent);
at the condition, when you want to close the Activity.
I want to make a service in android which run in background always and start as soon as I boot my phone and send message at a regular interval.I have writen my code as below
MainActivity.class
package test.sai;
public class MainActivity extends Activity {
Timer t;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
alrm();
Log.e("msg", "in main");
}
public void alrm() {
Intent myAlarm = new Intent(getApplicationContext(), AlarmReceiver.class);
Log.e("msg", "in alrm");
//myAlarm.putExtra("project_id", project_id); //Put Extra if needed
PendingIntent recurringAlarm = v PendingIntent.getBroadcast(getApplicationContext(), 0, myAlarm, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarms = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
Calendar updateTime = Calendar.getInstance();
Log.e("msg", "in alrm1");
//updateTime.setWhatever(0);
alarms.setInexactRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, recurringAlarm); //you can modify the interval of course
}
}
This class is calling AlarmReceiver.class
package test.sai;
public class AlarmReceiver extends BroadcastReceiver
{
GPSTracker gps;
#Override
public void onReceive(Context context, Intent intent)
{
gps = new GPSTracker(context);
if ("android.intent.action.BOOT_COMPLETED".equals(intent.getAction())) {
Intent pushIntent = new Intent(context,MainActivity.class);
pushIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(pushIntent);
Log.e("pro", "alrmmanager");
}
Intent myService = new Intent(context, FirstService.class);
myService.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(myService);
Log.e("msg", "in alrmmanager1");
}
}
and finally AlarmReceiver is calling the service class
package test.sai;
public class FirstService extends Service{
Timer t;
int time = 0;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onStart(Intent intent, int startId) {
Log.e("time", time++ +"");
Toast.makeText(this, time+1+"", 500).show();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
}
Now I want to on GPS as soon as service starts and then I want to use GPS to track location of mobile and send a message to another mobile.I also have code for GPS and sms sending but I am not getting how to call and where to call those methodss,so that my service keep on running and sending messages at some perticular interval.please help.
You can use alarmManager for this... Because if you create your own timerTask, it is very much susceptible to get destroyed by the processor.
To answer your two part question:
First you need to learn how to handle onBoot within Android Framework. Refer to this Q/A Trying to start a service on boot on Android
Lastly you need to understand the SMSManager class. Refer to the documentation http://developer.android.com/reference/android/telephony/SmsManager.html
I don't think anyone should provide complete code for your request as your main problem/question is "How can I help myself and stop looking for others to fix all my problems".
Try registering a BroadcastReceiver with AlarmManager to receive an intent at your regular interval. You'll probably want two, one that listens for a BOOT_COMPLETED action, and another that the AlarmManager will start on interval. You can have the second receiver start a service if whatever you want to do will take a while to execute.
Here's a question on how to make the receiver run on boot so you can register the other receiver with AlarmManager:
Android BroadcastReceiver on startup
Here's another that wants pretty much the same thing you want, minus the SMS:
How to Autostart an AlarmManager to start a Scheduled Activity?