2

START_STICKY onStartCommand でサービスを開始する mainActivity があります。そのサービスでは、startForeground と alarmManager リピーターも使用します。アプリをスワイプしてメイン アクティビティを閉じると、サービスはまだ実行されており、startForeground からの通知アイコンは残りますが、alarmManager からのアラームがサービス内で発生すると、サービスがクラッシュし、5000 ミリ秒以内に再起動します。アラームを設定するとすぐにサービスがクラッシュするのはなぜですか?

MainActivity.java:

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Messenger;
import android.util.Log;
public class MainActivity extends Activity {
    Messenger mService = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CheckIfServiceIsRunning();
    }
    private void CheckIfServiceIsRunning() {
        if (MyService.isRunning()) {
        } else {
            startService(new Intent(MainActivity.this, MyService.class));
        }
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        //stopService(new Intent(MainActivity.this, MyService.class)); //disabled line so that killing UI-app doesn't kill service aswell
    }
}

MyService.java:

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.util.Log;
public class MyService extends Service {
    public AlarmManager alarmManager;
    public PendingIntent pendingIntent;
    private Timer timer = new Timer();
    private int counter = 0, incrementby = 1;
    private static boolean isRunning = false;
    final public static int NOTIFICATION_FOREGROUND = 34444;
    ArrayList<Messenger> mClients = new ArrayList<Messenger>();
    final Messenger mMessenger = new Messenger(new IncomingHandler());
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }
    @SuppressLint("HandlerLeak")
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    }
    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("MyService", "---- Service Started. ----");
        timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 0, 1000L);
        isRunning = true;
        StartForegroundNotification();
        alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
        Intent broadcast_intent = new Intent(this, MyAlarmReceiver.class); 
        pendingIntent = PendingIntent.getBroadcast(this, 0,  broadcast_intent, 0);
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 10*1000, pendingIntent);
    }
    @SuppressWarnings("deprecation")
    public void StartForegroundNotification(){
        String title = "Service Title";
        String message = "Service Message";
        Notification notify = new Notification(R.drawable.ic_launcher, null, 0);            
        Intent notifIntent = new Intent(this, MainActivity.class);          
        PendingIntent i = PendingIntent.getActivity(this, 0, notifIntent, 0);
        notify.setLatestEventInfo(this, title, message, i);
        notify.flags |= Notification.FLAG_NO_CLEAR;
        startForeground(NOTIFICATION_FOREGROUND, notify);
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyService", "Received start id " + startId + ": " + intent);
        return START_STICKY;
    }
    public static boolean isRunning()
    {
        return isRunning;
    }
    private void onTimerTick() {
        Log.i("TimerTick", "Timer doing work." + counter);
        try {
            counter += incrementby;
        } catch (Throwable t) {
            Log.e("TimerTick", "Timer Tick Failed.", t);            
        }
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        alarmManager.cancel(pendingIntent);
        if (timer != null) {timer.cancel();}
        stopForeground(true);
        counter=0;
        Log.i("MyService", "---- Service Stopped. ----");
        isRunning = false;
    }
}

MyAlarmReceiver.java:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MyAlarmReceiver extends BroadcastReceiver { 
    @Override
    public void onReceive(Context context, Intent intent) {
        Log.i("alarmer", "I got it");
    }
}

そしてマニフェストで私が使用した:

<service android:name=".MyService" />
<receiver android:name=".MyAlarmReceiver" />

およびlogcat(アラーム時間に達するとすぐに-この場合はタイマーティック3の後-アプリを閉じるとクラッシュしましたが、再起動した後は再びクラッシュしません。別のコンテキストから開始されているためだと思います、MainActivity.this からではなく、onStartCommand で「null」インテントを取得します):

12-16 19:08:50.614: I/TimerTick(27069): Timer doing work.1
12-16 19:08:53.614: I/TimerTick(27069): Timer doing work.2
12-16 19:08:56.614: I/TimerTick(27069): Timer doing work.3
12-16 19:08:57.622: I/ActivityManager(395): Killing 27069:com.example.serviceexample/u0a10097: remove task
12-16 19:08:57.629: W/ActivityManager(395): Scheduling restart of crashed service com.example.serviceexample/.MyService in 5000ms
12-16 19:09:02.661: I/ActivityManager(395): Start proc com.example.serviceexample for service com.example.serviceexample/.MyService: pid=27100 uid=10097 gids={50097, 1028}
12-16 19:09:02.715: I/MyService(27100): ---- Service Started. ----
12-16 19:09:02.715: I/TimerTick(27100): Timer doing work.0
12-16 19:09:02.723: I/MyService(27100): Received start id 3: null
4

0 に答える 0