I am feeling strange behaviour with service when i close my app or my app is destoyed. Service starts from beggining means onStartCommand() method calls again. If service runs in background it should not be called again please help me why its happening
This is my service code
package gcmtutorial.androidbegin.com.socket;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
/**
* Created by shuser on 21-07-2016.
*/
public class Services extends Service {
public static boolean status;
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
public class Hello implements Runnable{
public void run(){
synchronized (this){
int i=0;
while (i<100){
try {
wait(1000);
Log.e("Status:", "value "+i);
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
stopSelf();
}
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
status = true;
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
Thread thread = new Thread(new Hello());
thread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
status = false;
super.onDestroy();
Log.e("Status:","Service Destroyed");
}
}
This is my MainActivity code
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this, Services.class);
if (Services.status == true) {
Log.e("Check:","Service is Running");
}else {
Log.e("Check:","Service Will run now");
startService(intent);
}
}
}
Please help me why such thing is happening with service. I get Toast as well Service Started and LogCat also shows value from 0
Per START_STICKY:
if this service's process is killed while it is started (after returning from onStartCommand(Intent, int, int)), then leave it in the started state but don't retain this delivered intent. Later the system will try to re-create the service. Because it is in the started state, it will guarantee to call onStartCommand(Intent, int, int) after creating the new service instance;
If you'd like your Service to not automatically restart when your process is destroyed, return START_NOT_STICKY
Related
i have a simple service need to run in background.below is the code for the service.i want to run the code in onStartCommand repeatedly simply for test purpose i displayed toast.but Toast also calling only once
import android.app.IntentService;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;
/**
* An {#link IntentService} subclass for handling asynchronous task requests in
* a service on a separate handler thread.
* <p>
* TODO: Customize class - update intent actions and extra parameters.
*/
public class WiFiCheck extends Service {
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* Handle action Foo in the provided background thread with the provided
* parameters.
*/
private void handleActionFoo(String param1, String param2) {
// TODO: Handle action Foo
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Handle action Baz in the provided background thread with the provided
* parameters.
*/
private void handleActionBaz(String param1, String param2) {
// TODO: Handle action Baz
throw new UnsupportedOperationException("Not yet implemented");
}
}
but onStartCommand is calling only once getting toast only once.
i used
return START_STICKY;
starting service as below
startService(new Intent(this, WiFiCheck.class));
but still no use.any help
Toast will be twice and more called if you start again service
e.g.
startService(new Intent(this, WiFiCheck.class));
startService(new Intent(this, WiFiCheck.class));
new Intent is an intent which is in onStartCommand(Intent intent
Short answer
Call StartService as much times as you want the toast to show up.
About returning START_STICKY(Why doesn't returning START_STICKY show your toast twice?)
Returning START_STICKY at the end of onStartCommand() method lets your service start again(onStartCommand() is called again) when your service is KILLED(by some reasons like system resource depletion). So there is no relevence between return START_STICKY; and your goal.
Solution to reach your goal
Like the Kalyzunyu's answer, just call StartService() twice to show your toast twice. It does not instantiate your Service twice, but calls your onStartService() twice. So be free to call it again.
Refer here.
Or if you want to show the toast every 10 seconds until it is stopped try this.
public class WiFiCheck extends Service
{
private Thread thread;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
startForeground(1, new Notification());
thread=new Thread(new Runnable(){
#Override
public void run()
{
// TODO: Implement this method
while(true)
{
Toast.makeText(WiFiCheck.this, "Service Started", Toast.LENGTH_LONG).show();
try
{
Thread.sleep((long)10000);
}
catch (InterruptedException e)
{}
}
}
});
thread.start();
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
return super.onStartCommand(intent, flags, startId);
}
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
/**
* Handle action Foo in the provided background thread with the provided
* parameters.
*/
private void handleActionFoo(String param1, String param2) {
// TODO: Handle action Foo
throw new UnsupportedOperationException("Not yet implemented");
}
/**
* Handle action Baz in the provided background thread with the provided
* parameters.
*/
private void handleActionBaz(String param1, String param2) {
// TODO: Handle action Baz
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onDestroy()
{
// TODO: Implement this method
thread.stop();
super.onDestroy();
}
}
This code below is equivalant to above.
In Activity
new Thread(new Runnable()
{
#Override
public void run()
{
while(!isInterrupted()){
startService(new Intent(MainActivity.this, WiFiCheck.class));
Thread.sleep(10000L);
}
}
}).start();
Equivalent code #2:
public class WiFiCheck extends IntentService
{
public WiFiCheck() {
super("WiFiCheck");
}
#Override
protected void onHandleIntent(Intent intent)
{
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
startForeground(1, new Notification());
Toast.makeText(this, "Service Started", Toast.LENGTH_LONG).show();
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
}
To add words, starting a service does not mean it is repeatedly called by the system, but rather it can live longer without UI. Actually its context is continued until you manually call stopSelf() or any component calls stopService() on your service.
YES.., You just have to return START_STICKY as KYHSGeekCode suggested. It was down voted, but it is correct answer. So i up voted it back. Thank you
I create a service that start a new thread to do stuff. In Android O, the android document said if the service is not a foreground service, then it will be stopped by the system. But I tested the following code, the service is destroyed but the thread is still running.
My question is how the system can save user's battery if the thread is allowed to be run even if the service is stopped?
MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startService(View view) {
Intent intent = new Intent(this, MyService.class);
startService(intent);
}
public void stopService(View view) {
stopService(new Intent(this, MyService.class));
}
}
MyService
public class MyService extends Service {
#Nullable
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("run in service: ");
}
}
}).start();
return START_NOT_STICKY;
}
#Override
public void onDestroy() {
super.onDestroy();
System.out.println("service onDestroy");
}
}
Did you test this behaviour for longer hours ? I had the same set-up with a service (started via main thread) running a worker thread inside. Upon testing the set-up for longer duration like 2-3 days. You will notice that system shuts down the entire process. So you can not rely on doing the background execution with a worker thread. Better approach is to use periodic or timed Jobs.
Run a service in background continuously. For example, a service has to be kicked off which will display a toast message 20 seconds once even if the app is closed.
public class AppService extends IntentService {
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
public AppService() {
super("AppService");
}
#Override
protected void onHandleIntent(Intent workIntent) {
Toast.makeText(getApplicationContext(), "hai", Toast.LENGTH_SHORT).show();
SystemClock.sleep(20000);
}
}
Below code works for me...
public class AppService extends Service {
#Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, " MyService Created ", Toast.LENGTH_LONG).show();
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, " MyService Started", Toast.LENGTH_LONG).show();
return START_STICKY;
}
}
Accepted answer will not work on from Android 8.0 (API level 26), see the android's background limitations here
Modification in Accepted Answer:
1: You have to invoke the service's startForeground() method within 5 seconds after starting the service. To do this, you can call startForeground() in onCreate() method of service.
public class AppService extends Service {
....
#Override
public void onCreate() {
startForeground(9999, Notification())
}
....
}
2: You must call startForegroundService() instead of startService() by checking API level from where you want to start the service.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
This code work for me..
public class ServiceClass extends Service {
public static final int notify = 300000; //interval between two services(Here Service run every 5 Minute)
private Handler mHandler = new Handler(); //run on another Thread to avoid crash
private Timer mTimer = null; //timer handling
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
if (mTimer != null) // Cancel if already existed
mTimer.cancel();
else
mTimer = new Timer(); //recreate new
mTimer.scheduleAtFixedRate(new TimeDisplay(), 0, notify); //Schedule task
}
#Override
public void onDestroy() {
super.onDestroy();
mTimer.cancel(); //For Cancel Timer
Log.d("service is ","Destroyed");
}
//class TimeDisplay for handling task
class TimeDisplay extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
Log.d("service is ","running");
}
});
}
}
}
In your manifest, where you declare your service, add:
android:process=":processname"
This lets the service run on a separate process and thus it will not be killed with the app.
You can then chose if you want to use foreground. It will show a persistent notification, but reduces the likelihood if the service being killed.
Further, if you want to create a continuously running service, use Service, NOT IntentService. IntentService stops when it is finished doing its action.
I'm a student new to android, and I have an application which use background service.
I want to start/stop the service by clicking on a button, i'm doing it like this:
case R.id.enablepop:
if (!(pop.runningFlag))
startService(new Intent(mainScreen,PopUpService.class));
return true;
case R.id.disablepop:
if (pop.runningFlag)
stopService(new Intent(mainScreen,PopUpService.class));
return true;
In the onStart() function of the service I have runningFlag which I set to "true", then I create a thread that works while runningFlag is true.
I set the runningFlag to false on onDestroy().
The problem is that the service won't stop. Can someone help me plz?
Try to use Handler, like here you can use Handler like Thread.
here is the example
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
public class MyService extends Service{
private Handler handler;
#Override
public IBinder onBind(Intent intent) {
return null;
}
#Override
public void onCreate() {
super.onCreate();
handler = new Handler();
}
#Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
handler.post(updateStatus);
}
#Override
public void onDestroy() {
super.onDestroy();
handler.removeCallbacks(updateStatus);
handler = null;
}
#Override
public boolean onUnbind(Intent intent) {
handler.removeCallbacks(updateStatus);
handler = null;
return super.onUnbind(intent);
}
private Runnable updateStatus = new Runnable() {
#Override
public void run() {
// do something here
handler.postDelayed(updateStatus, 1000);
}
};
}
here the handler can was initialized into the oncreate method now after that when onStart method invoked then the updateStatus object will invoked through the handler.post() which will start the run method of this Runnable object.
Now in this, this will invoked the run() at once and execute the statement at once only so for repeating this task call inside this method on specific delay time like here 1000 milliseconds so after complete all the execution it will again call after 1 sec and repeating this task this will continue until you cannot remove the runnable object from the handler, so basically that was call into the onDestroy()
I want to create a service which will run on a separate thread (not on UI Thread), so I implemented a class which will extend IntentService. But I haven't got any luck. Here is the code.
public class MyService extends IntentService {
public MyService(String name) {
super(name);
// TODO Auto-generated constructor stub
}
#Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}
#Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
Log.e("Service Example", "Service Started.. ");
// pushBackground();
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.e("Service Example", "Service Destroyed.. ");
}
#Override
protected void onHandleIntent(Intent arg0) {
// TODO Auto-generated method stub
for (long i = 0; i <= 1000000; i++) {
Log.e("Service Example", " " + i);
try {
Thread.sleep(700);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Service Consumption in an Activity Button click:
public void onclick(View view) {
Intent svc = new Intent(this, MyService.class);
startService(svc);
}
In your concrete implementation you have to declare a default constructor which calls the public IntentService (String name) super constructor of the abstract IntentService class you extend:
public MyService () {
super("MyServerOrWhatever");
}
You do not need to overwrite onStartCommand if the super implementation fits for you (what I expect).
In your current case you should get an exception (Unable to instantiate service...) - it is always worth to put this in the question.
Not the case here but this might help someone:
Check that your service class is not abstract. I had this problem because I had copied IntentService implementation from SDK and modified it to better suit my needs.
I resolved the "Unable to instantiate the service" issue, by adding the default parameterless constructor.
ServiceDemo.java:
public class ServicesDemo extends Activity implements OnClickListener {
private static final String TAG = "ServicesDemo";
Button buttonStart, buttonStop;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
buttonStart = (Button) findViewById(R.id.buttonStart);
buttonStop = (Button) findViewById(R.id.buttonStop);
buttonStart.setOnClickListener(this);
buttonStop.setOnClickListener(this);
}
public void onClick(View src) {
switch (src.getId()) {
case R.id.buttonStart:
Log.w(TAG, "onClick: starting srvice");
startService(new Intent(this, MyService.class));
startActivity(new Intent(getApplicationContext(),Second.class));
break;
case R.id.buttonStop:
Log.w(TAG, "onClick: stopping srvice");
stopService(new Intent(this, MyService.class));
break;
}
}
}
MyService.java:
package com.example;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private static final String TAG = "MyService";
MediaPlayer player;
#Override
public IBinder onBind(Intent intent) {
Log.w(" ibinder ","");
return null;
}
#Override
public void onCreate() {
Toast.makeText(this, "My Service Created",0).show();
Log.w(TAG, "onCreate");
player = MediaPlayer.create(this,R.raw.frm7v1);
player.setLooping(true); // Set looping
}
#Override
public void onDestroy() {
Toast.makeText(this, "My Service Stopped",0).show();
Log.w(TAG, "onDestroy");
player.stop();
}
#Override
public void onStart(Intent intent, int startid) {
Toast.makeText(this, "My Service Started :"+intent+" start id :"+startid,0).show();
Log.d(TAG, "onStart");
player.start();
}
}
Declare the following attribute in manifest file:
<service android:enabled="true" android:name=".MyService" />
This answer has been updated. Here is the updated, correct answer:
According to the documentation you do not have to override onStartCommand() for IntentServices, instead the documentation says the following about onStartCommand() for IntentServices: You should not override this method for your IntentService. Instead, override onHandleIntent(Intent), which the system calls when the IntentService receives a start request. (Thanks to Ready4Android).
Below is the original incorrect answer (left in so the comments make sense):
According to documentation you should override OnStartCommand() (or deprecated OnStart()) in order to process intent service start-up. Have you tried it? And as K. Claszen wrote - you need to implement default constructor.