0

ローカルではないサービスを開始するアクティビティがあります。アクションを実行するために生きているかどうかを確認することがあります。

現時点での私の試みは、静的ブール変数を使用することでした。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
    }
}
...

}

4

1 に答える 1

0

これをあまり頻繁に行っていない場合は、「実行中のサービスを繰り返す」方法を使用することをお勧めします。Android が保持する内部データ構造にアクセスするだけで、携帯電話で実行されているサービスがそれほど多くないはずです。うまくいくはずです。

于 2012-10-17T08:33:58.600 に答える