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