Checked the log for it.. onDestroy() method gets called instead of onHandleIntent()
i am using two intent services, and have written similar code for both... but one runs all the time but for the second intentService(code attached)...sometimes it runs and sometimes it doesn't without changing anything in the whole project.
can anyone please help?
public class GetDataService extends IntentService {
private static final String TAG="GetDataService";
public GetDataService(){
super("GetDataService");
}
#Override
protected void onHandleIntent(Intent intent) {
GetDataTask task= new GetDataTask();
Log.d(TAG,intent.getStringExtra(GetDataTask.INSTA_TOKEN_URL));
task.execute(this,intent);
ApplicaitonsData.GetDataServiceRunning=true;
Log.d(TAG,"data service running status = "+ ApplicaitonsData.GetDataServiceRunning);
}
#Override
public void onDestroy() {
super.onDestroy();
ApplicaitonsData.GetDataServiceRunning=false;
Log.d(TAG,"data service running status = "+ApplicaitonsData.GetDataServiceRunning);
}
}
the task.execute() method in code had a if loop in it and the condition was false. so there wasn't anything for the IntentService to do..therefore it was destroying itself.
Related
I am currently resuming a project I had been working on, and starting from scratch to recreate it.
However, upon creating a Service class, I noticed something - in my old project, a method inside the Service called onStartCommand contains all of the code that needs to be fired, whereas in my new project when I create a Service class, this method is nowhere to be found.
- Do I need to manually ADD this "onStartCommand" method to contain my service code?
- If not, where exactly would my code go? It seems in my "old" project's code, I completely comment-block public TimerService, and pass null into IBinder, and create onStartCommand etc instead.. and I can't quite figure out why.
- While i'm here, can someone please double-check my CountdownTimer code below? and if it's correct, should I be putting it inside of a Thread?
When I create a new Service Class, it looks like this:
public class TimerService extends Service {
public TimerService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
However in my old Project, my Service class looks like this:
public class TimerService extends Service {
/*
public TimerService() {
}
*/
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public int onStartCommand(final Intent intent, int flags, int startId) {
intent.getStringExtra("TIMER_VALUE");
String string_timerValue;
string_timerValue = intent.getStringExtra("TIMER_VALUE");
long long_timerValue;
long_timerValue = Long.parseLong(String.valueOf(string_timerValue));
// I DO NOT WANT ANY TICK VALUE, SO GIVE IT FULL TIMER VALUE
long long_tickValue;
long_tickValue = Long.parseLong(String.valueOf(string_timerValue));
new CountDownTimer(long_timerValue, long_tickValue) {
public void onTick(long millisUntilFinished) {
// DO NOTHING
}
public void onFinish() {
Toast.makeText(TimerService.this, "TIMES UP", Toast.LENGTH_LONG).show();
stopService(intent);
}
}.start();
return START_STICKY;
// END OF onStartCommand
}
#Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "Service Destroyed", Toast.LENGTH_LONG).show();
}
// END OF ENTIRE SERVICE CLASS
}
THANK YOU!!
Do I need to manually ADD this "onStartCommand" method to contain my service code?
Yes.
can someone please double-check my CountdownTimer code below?
Only create a service when one is absolutely necessary. It is unclear why this service is necessary.
Beyond that:
Use stopSelf(), not stopService(), to stop a service from inside that service.
Examining Intent extras and using START_STICKY is not a good combination. START_STICKY says "if you terminate my process to free up system RAM, please restart my service when possible, but pass null for the Intent". That will cause your service to crash with a NullPointerException.
I have a DialogFragment that can be launched from anywhere, let’s call it UploadDialogFragment. This fragment allows the user to accomplish two related tasks:
Upload an image (can take up to 1min)
Upload a JSON object with some text and a reference to the saved image
This two tasks need to be accomplished in sequence - you can’t do 2. without having completed 1.. So what really happens is:
I start uploading the image (1.)
Meanwhile, the user writes the text and adds other info
When all is ready, dismiss the dialog and start the second task (2.).
I used to do this with background tasks, but now I’d like to switch to a Service: the whole operation should be completed even if, after dismissing, I force quit the app.
Current design
In my experience I have always used IntentService, so I am a complete newbie. The current flawed design I am moving forward is something like:
public class UploadService extends Service {
private final Binder binder = new Binder();
public class Binder extends android.os.Binder {
UploadService getService() {
return UploadService.this;
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
#Override
public IBinder onBind(Intent intent) {
return binder;
}
public void completeFirstTask() {
...
}
public void completeSecondTask() {
// wait for first task to complete if necessary...
...
stopSelf();
}
}
And here’s my UploadDialogFragment:
public class UploadDialogFragment extends AppCompatDialogFragment implements
ServiceConnection {
private UploadService uploadService;
private boolean boundService;
#Override
public void onServiceDisconnected(ComponentName name) {
uploadService = null;
boundService = false;
}
private void bindService() {
Intent i = new Intent(getActivity().getApplicationContext(), UploadService.class);
getActivity().getApplicationContext().bindService(i, this, Context.BIND_AUTO_CREATE);
boundService = true;
}
private void unbindService() {
if (boundService) {
getActivity().unbindService(this);
boundService = false;
}
}
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
uploadService = ((UploadService.Binder) service).getService();
uploadService.completeFirstTask();
}
// THEN, LATER:
// OnClick of a button, I call uploadService.completeSecondTask();
// and this.dismiss();
}
This is deeply flawed right now.
I need to reliably unbind() when the dialog fragment is closed/dismissed/recreating itself, otherwise I am going to leak it because of the ServiceConnection (right?). I don’t know when to do it?. onDismiss, onDestroyView, onSaveInstanceState ... I have tried many options but I often end up with a IllegalArgumentException saying that the service connection is not registered.
The service might never reach the completeSecondTask() part, and so no one is going to stop it, leaking it for no reason. I should probably call stopService() somewhere, but where? These are different scenarios:
I force-quit the app / recreate the fragment after a completeSecondTask() call: the Service should keep going until it ends.
I recreate the fragment without having called completeSecondTask() : the Service should keep going until it ends. (There’s proper logic inside my fragment to handle this)
I force-quit the app without having called completeSecondTask() : the Service should stop.
Questions
Now, you might see this as two questions: how to handle unbind(), and how to handle stopService().
However, because I am finding so hard to set up this little task, I am thinking that this is deeply flawed and I should use a totally different approach. I hope you can shed some light on this for me.
I want to stop my thread when my app closes. Does any one know how can I do this?
public class ControlApplication extends Application
{
private static final String TAG=ControlApplication.class.getName();
private Waiter waiter; //Thread which controls idle time
private MySharedPrefrences prefs;
// only lazy initializations here!
#Override
public void onCreate()
{
super.onCreate();
Log.d(TAG, "Starting application" + this.toString());
Context ctx=getApplicationContext();
waiter=new Waiter(1*60*1000,ctx);//(1*60*1000); //1 mins
prefs=new MySharedPrefrences(this);
// start();
}
#Override
public void onTerminate() {
super.onTerminate();
Log.d(TAG,"App terminated");
prefs.SetLastVisitedActivity("");
waiter.stopThread();
waiter.loginUpdate(false);
}
}
I want to call some methods when app terminates but I can't seem to get it working. Any suggestion please?
Try calling super.onTerminate(); after stopping the thread, i.e.,
#Override
public void onTerminate() {
Log.d(TAG,"App terminated");
prefs.SetLastVisitedActivity("");
waiter.stopThread();
waiter.loginUpdate(false);
super.onTerminate();
}
Update: onTerminate will never work on a device. http://developer.android.com/reference/android/app/Application.html#onTerminate%28%29
This method is for use in emulated process environments. It will never be called on a >production Android device, where processes are removed by simply killing them; no user code >(including this callback) is executed when doing so.
So your best bet is to create a base activity and let all other activities extend it. You can use onPause() of an Activity but if the app is terminated then there is no guarantee unless you call finish().
Update: As Nasir said in one of the comments, using onPause is not a good idea.
If your application has only one entry point then in your home/first activity override onDestroy() method, and from that method stop the thread.
At the moment I have got a singleton class that extends service like this:
public class ServiceSingleton extends Service {
private static ServiceSingleton instance;
private static boolean serviceSt;
private static PrefValues preferences;
private static Context context;
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
public static ServiceSingleton getInstance(Context cont) {
if (instance == null) {
context = cont;
// Some code
}
return instance;
}
So basically I run some methods in this class about every 30 minutes by using something like this:
private static void oneTasks() {
//task itself
}
private static void oneService() {
if (!serviceSt) {
serviceRunning = false;
return;
}
serviceRunning = true;
oneTasks();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
oneService();
}
}, (INTERVAL));
}
I also heard AlarmManager can do the same thing.
Anyway, my question is, If I am running periodical methods, which way to invoke methods is the best way(especially with the consideration of battery usage)?
At the moment I have got a singleton class that extends service like this
Yuck. Do not make a service be held indefinitely in a static data member.
So basically I run some methods in this class about every 30 minutes
You have not stated how you are doing that.
Anyway, my question is, If I am running periodical methods, which way to invoke methods is the best way(especially with the consideration of battery usage)?
If your objective is to only do this work when your process happens to be running for other reasons, you are welcome to use pretty much anything you want. I'd use ScheduledExecutorService.
If your objective is to do this work, even if your app is not running, AlarmManager covers that scenario. Team it with an IntentService, so that your process only needs to be in system RAM when it is actually doing work.
If your objective is to do this work, even if your app is not running, and even if the device falls asleep, you will need to use AlarmManager with a _WAKEUP alarm, coupled with either WakefulBroadcastReceiver, my WakefulIntentService, or the equivalent.
By using the Alarm Manager you can register a repeated alarm that will fire automatically every specific time, even if your application is closed. so it's a very efficient in term of battery usage.
Then inside the alarm's broadcast receiver you have to implement what you need. and you should consider creating a new thread or using IntentService class if your method will take more than a few seconds.
I know it's surely not the most elegant and best solution, but you could simply have a Thread with an infinite loop that had a SystemClock.sleep(1800000) at the end, so basically something like this:
final Thread buf_liberator = new Thread(
new Runnable() {
public void run() {
while (true) {
/* Your stuff */
SystemClock.sleep(1800000);
}
}
}
);
buf_liberator.setPriority(7);
buf_liberator.start();
Also you would need to have a stop condition inside the Thread as you can't stop it with the stop() method anymore.
You can also do it by CountDownTimer
CountDownTimer countDownTimer;
public void usingCountDownTimer() {
countDownTimer = new CountDownTimer(Long.MAX_VALUE, 10000) {
// This is called after every 10 sec interval.
public void onTick(long millisUntilFinished) {
setUi("Using count down timer");
}
public void onFinish() {
start();
}
}.start();
}
and onPause() method add
#Override
protected void onPause() {
super.onPause();
try {
countDownTimer.cancel();
} catch (Exception e) {
e.printStackTrace();
}
}
I have a Service like this (this is not the actual Service, it's just for describing my problem).
public class UploadService {
private BlockingQueue<UploadData> queue = null;
private UploadInfoReceiver receiver = null;
public void onStart(...) {
queue = new LinkedBlockingQueue<UploadData>();
(new Processor()).start();
// creating and reigtering receiver
}
public void onDestroy() {
queue.add(new ServiceDestroyedData());
// unregistering the receiver
}
private class Processor extends Thread() {
public void run() {
while (true) {
UploadData data = queue.take();
if (data instanceof ServiceDestroyedData) {
return;
}
// processing data
}
}
}
private class UploadInfoReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
queue.add(new UploadData(/* getting data from intent */));
}
}
}
And my problem is that if I do something like this in my App:
if (!isUploadServiceRunning()) {
// start the Service
}
Then it starts the Service, but when I move my App to the background and open task manager (android 4.2.2), and kill the app, Android restart my Service, and I can see that it creates a whole new instance of it, and I can see that onDestroy never gets called for the previous Service instance. And I also can see that the instance of the previous Processor Thread is no longer running. How can this be? If onDestroy never gets called how does Android know that it should stop my Thread?
Thanks for your answers.
Android will kill off anything that it finds that is attached to your apps classloader when you select force stop from the menu. Think kill -9 on Linux. There will be no nice callbacks to any onDestroy methods, the system will just end everything.
Now for your service:
while(true) should really NEVER be used. It will instantly kill the battery and will not do any work 99% of the time anyway.
You area already using a receiver, you can just put your while logic into there and once the upload is done call the next upload and so on. There is absolutely no need for the loop.