I stop a service from various places. How can I check when the sender of the command "stopService(Intent intent)" was my NetworkReceivar class (extends BroadcastReceiver)??
This is my code for do this more clear:
public class NetworkReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
boolean isNetworkDown = intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (isNetworkDown) {
context.stopService(new Intent(context, MyService.class));
}
My service class:
public void onDestroy() {
Log.i(TAG, "OnDestroy");
// if came from NetworkReceiver do something.
this.updater.interrupt();
this.updater = null;
super.onDestroy();
}
How can I check when the sender of the command "stopService(Intent intent)" was my NetworkReceivar class (extends BroadcastReceiver)??
AFAIK, you can't.
However, instead of stopService(), you could call startService(), sending over a command that your service interprets as "time to shut down". Something on that Intent that is your command could be used to indicate the sender, so that you can distinguish one sender from another. And, the service can call stopSelf() to shut itself down.
Related
In my activity, I start my service in onStart() of my activity & bind to service in onResume() :
public class MyActivity extends Activity{
private boolean isBound;
ServiceConnection myConnection = new ServiceConnection(){...};
#Override
public void onStart(){
super.onStart();
startService(new Intent(this, MyService.class));
}
#Override
public void onResume(){
super.onResume();
Intent service = new Intent(this, MyService.class);
isBound = bindService(service, myConnection, Context.BIND_AUTO_CREATE);
}
}
I have a BroadcastReceiver class , in its onReceive() callback, I want to re-start my service. I mean destroy it completely & creat it by calling startService() again:
public class MyBroadcastReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent) {
//I want to re-start MyService from scratch, i.e. destroy it & start it (create it) again
Intent service = new Intent(context, MyService.class);
stopService(service);
startService(service);
}
}
But as Android document says, my above code doesn't guarantee the previous started service will be destroyed since I have also bind to it.
My question is what is the most efficient way to unbind MyService in MyBroadcastReceiver to restart MyService from scratch? As you see, the bound myConnection instance is in MyActivity...
From the Service documentation:
Multiple clients can connect to the service at once. However, the
system calls your service's onBind() method to retrieve the IBinder
only when the first client binds. The system then delivers the same
IBinder to any additional clients that bind, without calling onBind()
again.
When the last client unbinds from the service, the system destroys the
service (unless the service was also started by startService()).
So, when using your service, don't start your service using startService(intent), but rather by called bindService(service, conn, flags). This way, if your Activity is the only activity bound to the service, when you call unbindService(ServiceConnection conn) the system will kill your service, then you can rebind afterwards.
In my Android project, I have a normal Service:
public class MyService extends Service{
#Override
public int onStartCommand(...){...}
...
#Override
public void onDestroy() {
super.onDestroy();
Log.d("MyApp","MyService onDestroy() is called!");
}
}
In my BroadcastReceiver class, I stop MyService & do another task :
public static class MyReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
context.stopService(new Intent(context, MyService.class));
doAnotherTask();
}
}
According to my log, onDestroy() of MyService is executed after doAnotherTask() is done.
How can I guarantee that onDestory() of MyService is executed before doAnotherTask() get called?
P.S.: I thought I could do something like:
boolean isStopped = context.stopService(new Intent(context, MyService.class));
if(isStopped){
doAnotherTask();
}
But it could be possible that there is no service has been started, which means stopService(...) does nothing. So, I can't rely on my above code.
call startActivityForResult() .... and after you got the onActivityResult,.... call your method doAnotherTask()
i think that will do the job
How about sending a special intent to your broadcast receiver from the onDestroy() function? When your receiver gets it, then call doAnotherTask(). (I am assuming that you can't simply call doAnotherTask() from onDestroy() directly.)
send a broadcast in the service's onDestroy function and in it's observer do your after things
The call to stopService() is asynchronous. You are basically telling Android that you want it to stop the Service. You have no control over when this actually occurs.
If you need to trigger something AFTER the Service is destroyed, then you send a broadcast Intent in MyService.onDestroy() and use that to trigger whatever you want to happen when the Service is destroyed.
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?
on a broadcast I want to call a non static method from Service XYZ. The Service is start by the receiver on boot.
Has someone a idea to run methods from this running service?
One solution in this forum is to make the method static and use a singleton pattern to execute. But is there another method? Maybe with a binder?
//EDIT for example i have the following clases:
public class MyService extends Service{
.....
public void method(){
//TODO
}
}
public class MyBroadcastReceiver extends BroadcastReceiver{
.....
public void onReceive(Context context, Intent intent) {
String intentAction=intent.getAction();
if(intentAction.equals(Intent.ACTION_BOOT_COMPLETED)){
//start service
Intent serviceIntent = new Intent(context, MyService.class);
context.startService(serviceIntent);
}
else{
//TODO call method() in MyService
}
}
how can i call the method method()? I know that i can cast with context.getSystemService() system services. But how can i get my own service object?
greetings
You can add an action string to your intent using setAction in the intent that launches the Service. In your service's onStartcommand you can extract the intent's action, and based off that you can execute the method in your service.
You will always send commands to your service using startService this will not launch your service twice. It will either get started once, or the new intent is sent to the service.
So, in your on boot completed section you should set the intent action to whatever you want, and start the service - you can remove the else block completely.
In your Service implement the onStartCommand, extract the intent's action, and based off that action you can just execute your method.
Rarely I have an issue where a phone will get in a state (known as "funny state") where my Intent Services won't get a startService command from a Broadcast Receiver. (yes, the manifest has the receivers and services defined).
In this example I am listening for push notifications then calling a CheckinService.
Receiver:
public class PushReceiver extends BroadcastReceiver {
private static final String LOG_TAG = "push_receiver";
#Override
public void onReceive(Context context, Intent intent) {
logger.putExtra("debug", "Received Push");
Intent serviceIntent = new Intent(context, CheckinService.class);
context.startService(serviceIntent);
logger.putExtra("debug", "Sent to Service");
}
Service:
public class CheckinService extends IntentService {
private static final String LOG_TAG = "checkin_service";
public static final int SERVICE_ID = 3;
public CheckinService() {
super(LOG_TAG);
Log.i(LOG_TAG, "Service says: Checkin service started no constructor");
}
public CheckinService(String name) {
super(LOG_TAG);
Log.i(LOG_TAG, "Service says: Checkin service started with constructor");
}
#Override
protected void onHandleIntent(Intent intent) {
Log.i(LOG_TAG, "Auto Checkin started");
.....tons of genius logic.....
}
}
So when the phone gets in the funny state the "received push" gets logged and the "sent to service" gets logged but the constructors and onHandleIntent methods of the service never get called.
I also have this happen not only on pushes but on receivers for inexactRepeatingAlarm and perhaps others but these two have been confirmed for sure.
Again this is very, very, rare and seems to happen after the phone has been left unused for a period of time; and perhaps goes into a power saving mode.
Also, terminating the application's process clears this up.
I realized what was happening here.
The IntentService is single threaded. So if something in my " .....tons of genius logic....." was blocking (like a http request with no timeout) the next intent that came into the service would not be processed.
Nice and humbling.