Проверка состояния службы не работает, потому что загрузчик классов
У меня есть активность, которая запускает службу, которая не является локальной. Иногда я проверяю, жив ли для выполнения действий.
Моя попытка на данный момент заключалась в использовании статической логической переменной. Читая некоторые посты на SO, я обнаружил, что это не работает, потому что у каждого процесса есть свой загрузчик классов.
Перебор всех запущенных сервисов обходится дорого для выполнения такой простой задачи, как эта.
Другие решения указывают на использование AIDL. В ближайшем будущем в моем сервисе я сохраню WeakReference для текущего выполняемого действия, чтобы выполнить его снова в случае сбоя. Предположим, сейчас я просто хочу проверить состояние сервиса, это тоже дорогое решение?
PS: я знаю, что это уродливое решение - неправильно обрабатывать исключения. Это просто попытка.
РЕДАКТИРОВАТЬ: Чтобы уточнить, что я делаю, я опубликовать код. Это Сервис Класс:
public class CrashRecover extends Service {
private volatile boolean stop = false;
private Thread backgroundThread;
private Messenger serviceMessenger = null;
private static boolean running = false;
...
@Override
public int onStartCommand(Intent intent, int flags, int startID){
serviceMessenger = new Messenger(new ServiceHandler(serviceLooper));
return START_STICKY;
}
@Override
public void onCreate(){
super.onCreate();
HandlerThread handlerThread = new HandlerThread("CrashRecoverThread", Process.THREAD_PRIORITY_BACKGROUND);
handlerThread.start();
serviceLooper = handlerThread.getLooper();
backgroundThread = new Thread(){
@Override
public void run(){
synchronized(this){
try {
while(!stop){
sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
running = true;
}
@Override
public void onDestroy(){
super.onDestroy();
try {
Message destroyMessage = Message.obtain();
destroyMessage.arg1 = CrashRecover.DESTROY_SERVICE;
serviceMessenger.send(destroyMessage);
} catch (RemoteException e) {
e.printStackTrace();
}
running = false;
}
@Override
public IBinder onBind(Intent arg0) {
return serviceMessenger.getBinder();
}
public static boolean isRunning(){
return CrashRecover.running;
}
...
private class ServiceHandler extends Handler{
public ServiceHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message message){
switch(message.what){
case REGISTER_CLIENT:
//addActivityToRespawn(null);
//respawnActivity();
Log.i("INFO", "Service is registered");
break;
case UNREGISTER_CLIENT:
activityParams = message.getData();
//respawnActivity();
if(backgroundThread.isAlive()){
stop = true;
}
Log.i("INFO", "Service is unregistered");
break;
case DESTROY_SERVICE:
Log.i("INFO", "Service is destroyed");
break;
default:
super.handleMessage(message);
}
}
}
}
И это мой класс, когда я проверяю, работает ли служба:
public class Main extends Activity {
private Button serviceButton, crashButton;
private Intent serviceIntent;
private ClientMessageHandler clientHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
...
clientHandler = new ClientMessageHandler();
serviceIntent = new Intent(Main.this, CrashRecover.class);
startService(serviceIntent);
}
...
@Override
public void onBackPressed(){
if(CrashRecover.isRunning()){
Log.i("INFO", "Service is running");
//Execute some actions
}
}
...
}
1 ответ
Если вы делаете это не очень часто, то я бы предложил использовать метод "итерации по запущенным службам". Не должно быть так много сервисов, работающих на вашем телефоне и перебирающих их, просто доступ к некоторым внутренним структурам данных, которые хранит Android. Должно работать просто отлично.