I want to launch a ScheduledExecutorService on boot for checking my database all days.
I should launch this service at boot because if user doesn't launch the app this service couldn't work.
So when I launch my ScheduledExecutorService when app started it's okay but on boot ScheduledExecutorService seems not to work.
The BroadcastReceive on boot is working.
This is my code
public class BootReceiver extends BroadcastReceiver {
#Override
public void onReceive(final Context context, Intent intent) {
Toast.makeText(context, "Ca passe", Toast.LENGTH_LONG).show();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(new Runnable() {
public void run() {
Log.e("sc", "Ca passe");
Toast.makeText(context,"scheduler fonctionne", Toast.LENGTH_LONG).show();;
}
},10, 10, TimeUnit.SECONDS);
}
}
Do you have any idea ?
You need to read the documentation. Especially the documentation on the BroadcastReceiver lifecycle:
A BroadcastReceiver object is only valid for the duration of the call to onReceive(Context, Intent). Once your code returns from this function, the system considers the object to be finished and no longer active.
This has important repercussions to what you can do in an onReceive(Context, Intent) implementation: anything that requires asynchronous operation is not available, because you will need to return from the function to handle the asynchronous operation, but at that point the BroadcastReceiver is no longer active and thus the system is free to kill its process before the asynchronous operation completes.
In particular, you may not show a dialog or bind to a service from within a BroadcastReceiver. For the former, you should instead use the NotificationManager API. For the latter, you can use Context.startService() to send a command to the service.
If you need to use an Executor, host it in an actual Android Service. Otherwise, consider using AlarmManager to wake up your Service.
Related
I've custom JobIntentService witn static method enqueueWork.
public static void enqueueWork(#NonNull Context context, #NonNull Intent intent) {
enqueueWork(context, MyJobIntentService.class, JOB_ID, intent);
}
Also I've custom implementation of the FirebaseMessagingService. When I receive the push notification from FCM, I call the enqueueWork of my JobIntentService.
MyJobIntentService.enqueueWork(context, new Intent());
But method OnHandleWork not called on Android 8.0 and higher.
My manifest.xml.
<service android:name="com.company.MyJobIntentService"
android:permission="android.permission.BIND_JOB_SERVICE" />
Do you have any ideas why it work not correctly? Thank you.
Nothing incorrectly. Unfortunately, JobIntentService will not run immediately on Android 8.0 and higher.
When running as a pre-O service, the act of enqueueing work will generally start the service immediately, regardless of whether the device is dozing or in other conditions. When running as a Job, it will be subject to standard JobScheduler policies for a Job with a setOverrideDeadline(long) of 0: the job will not run while the device is dozing, it may get delayed more than a service if the device is under strong memory pressure with lots of demand to run jobs.
When testing,I new a empty project, it runs immediately when call, but when i use in a real complex project,it runs several minutes later after called.
Currently, I need a bound (Music)Service, because I need to interact with it. But I also want it to not be stopped, even when all components have unbound themselves.
As the Android Developer Guide says
"[...] Multiple components can bind to the service at once, but when all of them unbind, the service is destroyed."
The Guide also says
"[...] your service can work both ways—it can be started (to run indefinitely) and also allow binding."
In my application, the service is started when the application starts.
I want to have this service destroyed only by a user-click on a close-button I am displaying in a custom notification. But currently, when I am destroying my MainActivity the service also stops.
This is where I am now, this is called when I want to create my Service:
public void createServiceConnection(){
musicConnection = new ServiceConnection(){
#Override
public void onServiceConnected(ComponentName name, IBinder service) {
MusicService.MusicBinder binder = (MusicService.MusicBinder)service;
musicSrv = binder.getService();
attachMusicService();
}
};
}
...which calls this:
public void attachMusicService(){
playerFragment.setMusicService(musicSrv);
musicSrv.attach(context); //need this for my listeners, nevermind
bindService(context);
}
...which calls this:
public void bindService(Context act){
if(playIntent==null){
playIntent = new Intent(act, MusicService.class);
act.startService(playIntent);
act.bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
}else{
act.startService(playIntent);
act.bindService(playIntent, musicConnection, Context.BIND_AUTO_CREATE);
}
//finished. I can do stuff with my Service here.
}
Have I misunderstood something?
I feel like the service should keep running, even the activity is destroyed, because I first made a started service and then bound to it.
Bind to your service from custom Application class. I don't think you can keep service alive after activity that's bound to it is destroyed (when onDestroy is called). You can keep service alive if activity pauses (onPause) by calling startForeground from service
Seems like the code was correct.
According to this Question I found out that my problem was the notification I displayed, wich is pretty interesting.
Seems like that a Service that is created for running indefinitely needs to have a Notification wich is displayed by startForeground(NOTIFY_ID, notification);.
I showed my notification with notificationmanager.notify(NOTIFY_ID, notification); before, now I have
`notificationmanager.notify(NOTIFY_ID, notification);
startForeground(NOTIFY_ID, notification);`
and the service won't stop anymore after all my bound Activities are destroyed.
I am writing a Tracking App in Android.
I have got a Service implements LocationListener, which does all the stuff with location and writing to database, and Activity.
I would like to run Service in new thread to optimize my app. I want also to send both sides messsages from Service to Activity, which will show info about location.
I bind service, like it is mentioned in Bind to Service section and implement using a Messenger. Next I tried to do:
Thread t = new Thread(){
public void run(){
bindService(new Intent(this, GPSLogger.class), mConnection, Context.BIND_AUTO_CREATE);
}
};
t.start();
App is working, but all the GPSLogger stuff is doing in main thread.
Is it any way to repair this?
Regular services run in main thread.
You can use IntentService instead. It is a job queue with a single bg thread.
If you insist on using the base Service class then you'll have to spawn your own threads.
I've been struggling with this question for weeks now. I'm fairly new to Android, hopefully you can give me a hand.
I have this service which runs on a separate thread than the app's. Essentially, the user instructs it to start, and it should stay alive either until the user tells it to stop or until it has served its purpose - it schedules its own destruction (stop) when needed. The service needs to stay alive as it holds important priority-related information, so I can't simply turn to the alarm manager to revive it when needed - though I do use alarm manager for other purposes. I'm having two problems:
First of all, when the user closes the application (by holding the middle button and close the app) the service is destroyed, which means, I lose my data (I'm assuming it gets destroyed as it reboots automatically).
Secondly, it restarts itself, thus causing the data to be re-loaded hence, I lose the data.
As for the activity, its binding to the server through:
private void startService() {
startService(new Intent(this, CES.class));
bindService(new Intent(this, CES.class), mConnection, 0);
}
Finally, the relevant (or at least the ones I find relevant) methods in the Service:
private final IBinder mBinder = new ICESInterface.Stub() { ..... }
#Override
public void onCreate() {
//keeps being called thus I lose my data }
#Override
public IBinder onBind(Intent intent) {
return mBinder;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent,flags,startId);
//return START_STICKY;
}
Let me know if there is more data/information you need.
By returing a binder in onBind you are creating a bound service, which means it is "bound" to your app. This means that it get's destroyed when you app does, that explains the home button destroy. You should be returning null for a background service.
#Override
public void onCreate() {
//keeps being called thus I lose my data
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
You should start your service with START_STICKY flag, so that if the OS destroys your service when running low on resources, it will later recreate it.
Prior to destroying your service, Android will call public void onLowMemory(), there save any data you need so that when it restarts your service, you will be able to do your task again.
EDIT: As per your comment, you would like a service that is running in the background and also allows binding. You can do that if you call the startService() method before any bindService() calls are made... this will effectively make your service a started service instead of bound. In that case you are able to return a IBInder and bind to it.
There is a really, really good article HERE
In my PollFragment.java that able to call new PollTask((MainActivity)getActivity()).execute((Void)null);
And in my PollTask.java
public PollTask(MainActivity activity){
super(activity);
TerminalCfg terminalCfg = Global.getTerminalCfg();
terminalId = terminalCfg.getTerminalId();
retailerAcc = terminalCfg.getRetailerAcc();
internalId = APIUtil.getInternalId(activity);
username = APIUtil.getUsername(activity);
}
And now I want to call the new PollTask((MainActivity)getActivity()).execute((Void)null);
in MyBackgroundService with extends Service like below :
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
new PollTask((MainActivity)getActivity()).execute((Void)null);
// For each start request, send a message to start a job and deliver the
// start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
// If we get killed, after returning from here, restart
return START_STICKY;
}
Is there any other way to replace the getActivity() to call the method?
A Service is a separate component from an Activity and thus you cannot get a reference to it using getActivity(). Services are designed for doing work not visible to the user, including (but not limited to) background work on a separate thread from the UI thread. Services are more robust and offer more control over what work is being performed that is not visible to the user. They do not require an Activity to run.
An AsyncTask is a simple way of doing work from inside an Activity on a separate Thread from the UI thread.
Basically, you dont want or need an AsyncTask in a Service.
Instead, in your Service you should either spawn a Thread, or use IntentService which will handle creating a worker Thread for you. Then when you are finished, send an intent back to the Activity either by starting it or using a LocalBroadcast
Alternatively, you can tie a Service to an Activity and provide methods that the Service and Activity can call directly on each other through an IBinder interface. These are called bound services and will only be alive as long as the Activity is alive.
Try an IntentService
I think your best bet is to try learning how to use an IntentService
http://developer.android.com/reference/android/app/IntentService.html