8

新しいアプリケーションでサービスを開始しました。サービスは、通知を使用してフォアグラウンドで表示されます。これを AVD 2.1 API レベル 7 で実行すると、すべて正常に動作します。しかし、Gingerbread を実行している Samsung Galaxy Tab で実行すると、サービスは開始されますが (通知領域の上部にアイコンとアプリ名が表示されます)、数秒後にサービスが消えます。表示できるログの最後のエントリは、アプリに関連付けられています。これは、Log.d("Taglines","Returning with " + START_STICKY) の結果であり、"return START_STICKY ;" の直前にあります。次のように、私のサービスの onStartCommand オーバーライドで:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    int rc ;
    Log.d("Taglines","onStartCommand()");
    Toast.makeText(this, "Starting service TagsManager", Toast.LENGTH_SHORT).show();
    Log.d("Taglines","Calling super.onStartCommand()");
    rc = super.onStartCommand(intent,flags,startId);
    Log.d("Taglines","super.onStartCommand return code was " + rc);
    createNotification(INITIAL_NOTIFICATION_TEXT);
    Log.d("Taglines","Returning with " + START_STICKY);
    return START_STICKY ;
}

通知は次のように設定されます。

void createNotification(String text) {

    Log.d("Taglines","createNotification called");
    if (mNotificationManager == null) {
        // Get a reference to the Notification Manager
        String ns = Context.NOTIFICATION_SERVICE;
        mNotificationManager = (NotificationManager) getSystemService(ns);
        Log.d("Taglines","Obtained reference to Notification Manager");
    }

    // Instantiate the Notification
    int icon = R.drawable.ic_notification;
    CharSequence tickerText = "Taglines";
    long when = System.currentTimeMillis();

    notification = new Notification(icon, tickerText, when);

    // Define Notification's expanded message and intent
    Log.d("Taglines","createNotificacion() .. getApplicationContext");
    context = getApplicationContext();
    contentText = text;
    // notificationIntent = new Intent(this, TagsOverview.class);
    notificationIntent = new Intent(this, TagsServiceMenu.class);
    contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);

    // Pass the Notification to the NotificationManager: 
    Log.d("Taglines","createNotificacion() ... passing notification");
    mNotificationManager.notify(NOTIFICATION_ID, notification);
    Log.d("Taglines","Starting foreground");
    startForeground(NOTIFICATION_ID, notification);
    Log.d("Taglines","Started");
}

これは、サービスが開始されたときの「adb logcat」の結果です。

D/Taglines(21863): Starting service
D/Taglines(21863): TagsManager(nullary) completed
D/Taglines(21863): onStartCommand()
D/Taglines(21863): Calling super.onStartCommand()
D/Taglines(21863): super.onStartCommand eturn code was 2
D/Taglines(21863): createNotification called
D/Taglines(21863): Obtained reference to Notification Manager
D/Taglines(21863): createNotificacion() .. getApplicationContext
D/Taglines(21863): createNotificacion() ... passing notification
D/Taglines(21863): Starting foreground
D/Taglines(21863): Started
D/Taglines(21863): Returning with 1

その後、特別なことは何もありません (PID 21863 からは何もありません)。ほんの一握り:

D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
W/InputManagerService(  302): Window already focused, ignoring focus gain of:         com.android.internal.view.IInputMethodClient$Stub$Proxy@40bc06e8
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false
D/KeyguardViewMediator(  302): setHidden false

この場合は必要ないと思いますが、AndroidManifest.xml の関連部分を次に示します。

    <service android:name=".TagsManager"
             android:exported="false">
    </service>

どこで間違ったのでしょうか?他にどのような情報を提供できますか?

4

2 に答える 2

11

いくつかのこと:

  1. を取り除きmNotificationManager.notify(NOTIFICATION_ID, notification);ます。startForeground()通知アイコンが表示されます。

  2. foregroundServiceはまだ殺される可能性がありますが、そうなる可能性は低くなります。

  3. 2.3 にはバグがあり (まだ修正されているかどうかはわかりません)、 aServiceを強制終了して再起動すると、onStartCommand()再度呼び出されません。代わりに、で設定を行う必要がありますonCreate()

于 2011-07-29T19:19:49.210 に答える
1

両方のコードは、電話機がメモリ不足になり、Service実行が完了する前に を強制終了した場合にのみ関連します。十分なメモリが確保された後にサービスを再作成し、null インテントで再度START_STICKY呼び出すよう OS に指示します。わざわざサービスを再作成しないように OS に指示します。OS に同じ目的で AND 再配信を再作成するように指示する 3 番目のコードもあります。onStartCommand()START_NOT_STICKYSTART_REDELIVER_INTENTServiceonStartCommand()

Dianne Hackborn によるこの記事は、この背景を公式ドキュメントよりもはるかによく説明しています。

ここでの重要な部分は、関数によって返される新しい結果コードであり、実行中にプロセスが強制終了された場合にサービスに対して何をすべきかをシステムに伝えます。

START_STICKY は基本的に以前の動作と同じで、サービスが「開始」されたままになり、後でシステムによって再起動されます。プラットフォームの以前のバージョンとの唯一の違いは、プロセスが強制終了されたために再起動された場合、サービスの次のインスタンスで onStartCommand() がまったく呼び出されないのではなく、null インテントで呼び出されることです。このモードを使用するサービスは、常にこのケースをチェックし、適切に処理する必要があります。

START_NOT_STICKY は、onStartCreated() から戻った後、配信する開始コマンドが残っていない状態でプロセスが強制終了された場合、サービスが再起動される代わりに停止されることを示しています。これは、送信されたコマンドを実行している間だけ実行することを意図したサービスにとって、より理にかなっています。たとえば、アラームから 15 分ごとにサービスを開始して、ネットワークの状態をポーリングすることができます。その作業中に殺されたら、それを停止させて、次にアラームが鳴ったときに開始するのが最善です.

START_REDELIVER_INTENT は START_NOT_STICKY と似ていますが、特定のインテントに対して stopSelf() を呼び出す前にサービスのプロセスが強制終了された場合、そのインテントは完了するまで再配信されます (さらに何回か試行しても完了できない場合を除き、その時点でシステムはあきらめます)。これは、実行する作業のコマンドを受信し、送信された各コマンドの作業を最終的に完了することを確認したいサービスに役立ちます。

于 2013-11-12T16:12:08.373 に答える