I can't stop my service.
I have two services. Service1 starts Service2 with startService(intent).
I stop service1 with stopSelf();
Then I'm doing something in Service2 and start Service1 again and stop Service2.
So they are always starting each other again.
The behavior of the services are different after the first start.
I write some log messages and I can see that the information are multiply times in log cat.
I also tried to stop the activities in the onStartCommand of the other activty with stopService. (In onStartCommand of Service1 I call stopService service2)
Here is a Part of my Code:
Service1:
public class Service1 extends Service{
private int startId;
#Override
public void onCreate(){
super.onCreate();
}
private void doSomething(){
...
...
Intent intent = new Intent(getApplicationContext(), Service2.class);
startService(intent);
this.stopSelf(startId);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.startId=startId;
Intent beaconIntent = new Intent(getApplicationContext(), Service2.class);
stopService(beaconIntent);
doSomething();
return START_STICKY;
}
}
Service2:
public class Service2 extends Service implements BeaconConsumer, RangeNotifier{
private BeaconManager mBeaconManager;
private int startId;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Intent service1 = new Intent(getApplicationContext(), Service1.class);
stopService(service1);
mBeaconManager = BeaconManager.getInstanceForApplication(this);
mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("s:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19"));
mBeaconManager.bind(this);
this.startId = startId;
return START_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
mBeaconManager.unbind(this);
}
#Override
public void onBeaconServiceConnect() {
region = new Region("all-beacons-region", null, null, null);
try {
mBeaconManager.startRangingBeaconsInRegion(region);
} catch (RemoteException e) {
e.printStackTrace();
}
mBeaconManager.addRangeNotifier(this);
}
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
if(!beacons.isEmpty()){
doSomething...
...
...
Intent intent = new Intent(getApplicationContext(), Service1.class);
startService(intent);
this.stopSelf();
}
}
}
What am I doing wrong?
Edit: I didn't mention, that I'm working with altbeacon library. I thought that doesn't make any impact.
But when I'm looking at the services which are running when I start the app and after I stop the Service2 there are always two altbeacon services running(BeaconIntentProcessor and BeaconService).
Maybe they calling my service mutlipy times.
I got what I did wrong.
The problem was not the service it self, it was the altbeacon library. More concrete the BeaconManager which was still searching in the background for a beacon, even when the service was destroyed.
In the logs it looked like the service is running multiple times.
The solution was to not only unbind, also to stop Ranging and remove the range notifier.
mBeaconManager.stopRangingBeaconsInRegion(region);
mBeaconManager.removeAllRangeNotifiers();
mBeaconManager.unbind(this);
Related
I successfully used a service to do a certain task in the foreground. Now, to do it in the background, I'd remove the handler.removeCallbacks method in onDestroy().
But this would also prevents me from stopping the service using stopService(intent).
I saw on the official docs that I should maybe use JobScheduler (as I target API 28).
Here is a more precise indication of my code :
public class MainActivity {
private Intent intent;
onCreate() {
if (intent == null) {
intent = new Intent(this, MyService.class);
}
}
startService(intent);
... // Then is some code to stop the service if needed with stopService(intent)
}
--------------------------------------------------------------
public class myService {
private Handler handler = null;
private static Runnable runnable = null;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
handler = new Handler();
runnable = new Runnable() {
#Override
public void run() {
System.out.println("Running service times " + i);
i++;
handler.postDelayed(runnable, 1000);
}
};
handler.post(runnable);
}
#Override
public void onDestroy() {
handler.removeCallbacks(runnable);
super.onDestroy();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
I would like it to run in the background (even if the device is locked) but still being able to disable the service (or JobScheduler?).
What are your suggestions?
you can use work manager
or job dispatcher
and there is a lot of options like
SyncAdapter, Bound services, Intent Service
you can use one of these options according to your need
So I have code that I want called when my application is closed. Not just when it is sent to the background or the surface is destroyed. How do I do this? Is there a method that I can override in a SurfaceView or Activity class?
New Edit - current BackgroundService class:
public class BackgroundService extends Service {
private String savedString;
public void onCreate() {
System.out.println("Service created");
super.onCreate();
}
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("start command: ");
savedString = intent.getStringExtra("myString);
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent intent) {
return null;
}
public void onTaskRemoved(Intent rootIntent) {
System.out.println("the saved string was: " + savedString);
super.onTaskRemoved(rootIntent);
}
public void onDestroy() {
System.out.println("destroyed service");
super.onDestroy();
}
}
Where I then have this in my other class:
Intent serviceIntent = new Intent(activity.getApplicationContext(), BackgroundService.class);
serviceIntent.putExtra("myString", "this is my saved string");
activity.startService(serviceIntent);
you need to add a background service
public class BackgroundServices extends Service
{
#Override
public void onCreate() {
Toast.makeText(this, "start", Toast.LENGTH_SHORT).show();
super.onCreate();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onDestroy() {
super.onDestroy();
}
}
then in your activity. where you want to trigger this service
use
startService(new Intent(getBaseContext(), BackgroundServices.class));
in your case it will be call on onDestory function of that activity
Yes when the process is terminated
That is not possible in general. Nothing in your app is called when the process is terminated.
For example when you open the running apps screen, and swipe away the app to stop it from running
That is a task removal. It may result in your process being terminated, and there are many ways in which your process can be terminated that has nothing to do with task removal.
To detect task removal, override onTaskRemoved() in a Service.
I know that is a well known subject, but I have tried lot of things. I have an simple application, dedicated to a specific user, application has an mainActivity which is displaying some status on screen and it's starting two services, one is making request from a server (at every 5 minutes) and one which is sending sms and replay to server (at every ten minutes).
The application is running on a Samsung pocket 2 with Android 4.4.2, this device is used only for this application. While the device is connected to ADB the services are working just fine, but if I disconnect the phone and let it running normally, the services are killed repeatable and restarted after a while. The messaged are send with very much delay. I would be thankful for any suggestions.
Here is my code:
Main activity:
public class MainActivity extends Activity {
private TextView _internet;
private TextView _signal;
private TextView _server;
private BroadcastReceiver receiver;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
IntentFilter intentFilter = new IntentFilter(Constants.SS);
receiverWorker();
registerReceiver(receiver, intentFilter);
startService(new Intent(this, RefreshDBService.class));
startService(new Intent(this, SmsService.class));
}
private void receiverWorker() {
receiver = new BroadcastReceiver() {
public void onReceive(Context arg0, Intent arg1) {
checkState();
}};
}
public void refreshButonClicked(View v) {
checkState();
}`
Here is my first service:
public class RefreshDBService extends Service {
private Thread _backgroundWork;
private ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(1);
private DataBaseOperations _dataSource;
#Override
public void onCreate() {
super.onCreate();
_dataSource = new DataBaseOperations(this);
_backgroundWork = new Thread(new Runnable() {
#Override
public void run() {
if(Checks.checkInternetConnection(getApplicationContext())){
if(ServerOperations.isServerAvailable(getApplicationContext())){
String inputData = ServerOperations.makeRequest(Constants.GET_DATA_ROUTE, ServerOperations.getMessagesFromServer(getApplicationContext()));
ArrayList<DataSmsObj> dataFromServer=null;
if(inputData!=null && !inputData.isEmpty()){
dataFromServer = ServerOperations.fromJsonToObjects(inputData);
if(dataFromServer.size()>0){
_dataSource.open();
_dataSource.insertDataFromServer(dataFromServer);
_dataSource.close();
}
}
System.out.println("check server for messages in pending status, received -> "+ dataFromServer.size());
}else{
System.out.println("no server");
sentErrorToUI(Constants.NO_SERVER);
}
}else{
System.out.println("no internet");
sentErrorToUI(Constants.NO_INTERNET);
}
}
});
}
public int onStartCommand(Intent intent, int flags, int startId) {
scheduleTaskExecutor.scheduleWithFixedDelay(_backgroundWork, 0, Constants.NEXT_CYCLE/2, TimeUnit.MINUTES);
return START_REDELIVER_INTENT;
}
#Override
public void onDestroy() {
super.onDestroy();
scheduleTaskExecutor.shutdownNow();
}
public IBinder onBind(Intent intent) {
return null;
}
private void sentErrorToUI(String message){
Intent intent = new Intent(Constants.SS);
intent.putExtra(Constants.SS, message);
System.out.println("trimit" +message);
sendBroadcast(intent);
}
}
And this is the second one:
public class SmsService extends Service {
private Thread _backgroundWork;
private ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(1);
private DataBaseOperations _dataSource;
#Override
public void onCreate() {
super.onCreate();
_dataSource = new DataBaseOperations(this);
_backgroundWork = new Thread(new Runnable() {
#Override
public void run() {
sendFeedbackToServer();
List<DataSmsObj> dataToSent = new ArrayList<DataSmsObj>();
_dataSource.open();
dataToSent = _dataSource.getDataToSent();
_dataSource.close();
System.out.println("messages to sent: "+ dataToSent.size());
for (int i = 0; i < dataToSent.size(); i++) {
//here the messages are send, the code is to long to put it here, but if is need i can do it afterwards
}
}
});
}
public int onStartCommand(Intent intent, int flags, int startId) {
scheduleTaskExecutor.scheduleWithFixedDelay(_backgroundWork, 0, Constants.NEXT_CYCLE, TimeUnit.MINUTES);
return START_REDELIVER_INTENT;
}
#Override
public void onDestroy() {
super.onDestroy();
scheduleTaskExecutor.shutdownNow();
public IBinder onBind(Intent intent) {
return null;
}
If you are using a background Service with a scheduled task, it could be killed by the system. The only way to prevent the killing is a foreground Service. Quoting the documentation:
A foreground service is a service that the user is actively aware of and is not a candidate for the system to kill when low on memory.
You have to call the method startForeground() inside your Service using a Notification to show it. For further information you can check: https://developer.android.com/guide/components/services.html#Foreground
By the way, I recommend you to use the new JobScheduler api above api 21.
https://developer.android.com/reference/android/app/job/JobScheduler.html
Android kills service based on priority stack.
Android: keeping a background service alive (preventing process death)
What is START_STICKY,START_NOT_STICKY and START_REDELIVER_INTENT Service
Above links might help you.
Your devices will sleeps if it is unplugged from computer . So, the solutions :
Use startForeground method to prevent service to be killed and/or use AlarmManager in order to charge event.
It is possible to use start_stiky flag but it just restarts the process if it killed by system.
I create Service and call it from MainActivity.class with put string extra to intent but when I call getStringExtra in onStartCommand, it returns NullPointerException
Here is my code:
MainService.class :
public class MainService extends Service {
private WindowManager wm;
private WindowManager.LayoutParams params;
#Override
public IBinder onBind(Intent i) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
if (mView != null) {
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
wm.removeView(mView);
}
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
final String quote = intent.getStringExtra("quote");
Log.d("datastring",quote);
return super.onStartCommand(intent, flags, startId);
}
}
In MainActivity.class I called :
Intent i=new Intent(MainActivity.this, MainService.class);
i.putExtra("quote", "dataquote");
stopService(i);
How I can get string from MainActivity in MainService?
If you want to provide more data to your Service you need to use something like:
Intent intent = new Intent(MainActivity.this, MainService.class);
intent.putExtra("quote", "dataquote");
startService(intent);
This will start the service and you should be able to get the data intent in the onStartCommand(). If the Service is already running, onStartCommand() will still be called with the new intent. This is because Service components are inherently singleton, so only one instance of a particular service run at a time.
In your case, you are providing the data via stopService(intent). Not only its not possible to get this intent, your Service will also stop after this statement so, you cannot really do much with the data even if you could have read it.
If you still need to stop your Service and pass data at the same time, you should check this post.
I hava a simple service with data - ArrayList < MyObject > , when I close the app - service is restarted, called onCreate method and data is losing. This is my onStartCommand method:
public int onStartCommand(Intent intent, int flags, int startId) {
.....
return START_STICKY;
}
Service start in Application class
Intent serviceIntent = new Intent(this, ChatNotificationService.class);
startService(serviceIntent);
I not called stopService method.
I need after closing the application, the service continued to work and the data saved in it.
How I can do it?
In activity:
#Override
protected void onCreate() {
super.onCreate();
bindService(serviceIntent, sConn, 0);
}
#Override
public void onDestroy(){
super.onDestroy();
chatNotificationService.closeConnections();
unbindService(sConn);
}