Service is stopped when running on BOOT_COMPLETED

Asked

Viewed 731 times

0

People were making an example for a service an application to be started on boot, it seems to start but it breaks off in a few seconds and I can’t understand why, I’m following an example of a book, and I found the same thing in many almost equal examples. Some hint because I can not understand why the service is interrupted.

public class NotificacaoTask extends TimerTask {

    private static int i = 0;

    @Override
    public void run() {
        Log.i("servico" ,"Incremento: "+ i++);

    }
 }
public class Servico extends Service {

 public static final String CATEGORIA = "servico";
 public Timer timer;

@Override

 public int onStartCommand(Intent intent, int flags, int startId) {
    Log.i("servico","O servico foi iniciado!!!!");
    timer = new Timer();
    long delayInicial = 1 * 1000; //segundos
    long periodo = (long) 1 * 1000;

    timer.scheduleAtFixedRate(new NotificacaoTask() ,  delayInicial, periodo );
    return START_STICKY;
 }


public void onDestroy(){
    Log.i("servico" , "servico destruido");
    timer.cancel();
    super.onDestroy();
}


@Override
public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
}

}
public class BootReciever extends BroadcastReceiver {

public static Intent service;

@Override
public void onReceive(Context context, Intent intent) {
    service = new Intent("INICIAR_SERVICO");

    context.startService( service );

    Log.i("servico","iniciou serviço boot");

}
}

<uses-sdk
    android:minSdkVersion="8"
    android:targetSdkVersion="18" />


<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>


<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.serviceboot.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>


    <service android:name="Servico">
     <intent-filter>
     <action android:name="INICIAR_SERVICO" />
     <category android:name="android.intent.category.DEFAULT" />
     </intent-filter>
    </service>

    <receiver android:name="BootReciever">
        <intent-filter >
            <action android:name="android.intent.action.BOOT_COMPLETED"/>
        </intent-filter>
    </receiver>

</application>

logcat output

04-08 18:37:47.036: I/servico(704): iniciou serviço boot
04-08 18:37:47.057: I/servico(704): O servico foi iniciado!!!!
04-08 18:37:48.077: I/servico(704): Incremento: 0
04-08 18:37:49.186: I/servico(704): Incremento: 1
04-08 18:37:50.166: I/servico(704): Incremento: 2
04-08 18:37:51.077: I/servico(704): Incremento: 3
04-08 18:37:52.077: I/servico(704): Incremento: 4
04-08 18:37:53.077: I/servico(704): Incremento: 5
04-08 18:37:54.085: I/servico(704): Incremento: 6

1 answer

0


What seems to me to be happening is the following: your service creates an instance (object) of Timer calling for timer, but this instance will only last as long as the Service is running, after that there will be no one else referencing that instance and it will be deleted by Garbage Collector. And indeed, your Service is executed after the boot and then ends (there is no reason why you should not finish executing, because there is no loop on it or any other longer execution command - don’t think that timer.scheduleAtFixedRate() stands still waiting for tasks to execute) and, when the service is finished, the instance of Timer is Garbage-collected shortly after.

(Note that even if this does not happen, the line timer.cancel(); in the method onDestroy() will do the timer be canceled and the tasks stop running the same way).

The solution in this case would be to keep the reference to Timer in a variable of longer duration, such as a static variable.

But the surest way to do it, if you want to program your device to perform a task from time to time, is to not use TimerTask and do the method onReceive() of your broadcast receiver schedule the periodic execution of a service through Alarmmanager (you use this class to program the execution of a service in a similar way as you programmed the execution of TimerTask. But I’m not being precise: what actually happens is that the AlarmManager will call another broadcast receiver, that this yes will call the service you want to run). Reading like this looks complicated, but it’s simple - there’s a link below with an example. Doing so, which is the "Android" way to do, after the boot the device will perform the desired service from time to time.

Tip: By programming the execution of the service in this way, you will probably want to define your service as a subclass of Intentservice and overwrite your method onHandleIntent(), performing tasks in a thread secondary. That’s because the basic class Service performs in the thread main (also called thread of UI), that should not be overloaded with time-consuming tasks because it is responsible for updating the screen.

Useful links:

  • Thanks using Alertmanager worked beauty, but got a little doubt, in my Service when it finishes normally it does not call onDestroy() ? or onDestroy() is only called by stopService()

  • @user4438 If I am not mistaken, the call to onDestroy() is not guaranteed to be executed. It is better not to rely on it in all situations.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.