web-dev-qa-db-ja.com

Android:バックグラウンドサービスを維持する(プロセスの停止を防ぐ)

次のように定義されているサービスがあります。

public class SleepAccelerometerService extends Service implements SensorEventListener

基本的に、ユーザーがベッドで携帯電話/デバイスを使用して寝ている間に、さまざまな理由で加速度計のアクティビティを監視するアプリを作成しています。これは長時間実行されるサービスであり、夜間に停止することはできません。夜間に発生するバックグラウンドアプリと定期的なプロセスの数に応じて、Androidがプロセスを強制終了し、サービスが終了することがあります。例:

10-04 03:27:41.673: INFO/ActivityManager(1269): Process com.androsz.electricsleep (pid 16223) has died.
10-04 03:27:41.681: INFO/WindowManager(1269): WIN DEATH: Window{45509f98 com.androsz.electricsleep/com.androsz.electricsleep.ui.SleepActivity paused=false}

ユーザーに「SleepActivity」やその他のアクティビティをフォアグラウンドとしてアプリに強制させることは望みません。 onSensorChangedを常にインターセプトしているため、サービスを定期的に実行することはできません。

任意のヒント?ソースコードはこちら: http://code.google.com/p/electricsleep/

51
Jon Willis

Android 2.0以降では、 startForeground() method を使用して、サービスをフォアグラウンドで開始できます。

ドキュメントには次のように書かれています

開始されたサービスはstartForeground(int, Notification) AP​​Iを使用してサービスをフォアグラウンド状態にすることができます。システムは、ユーザーが積極的に認識しているため、メモリ不足時に強制終了の候補ではないと見なします。 (現在のフォアグラウンドアプリケーションからの極端なメモリプレッシャーのもとで、サービスが強制終了される可能性はありますが、実際には心配する必要はありません。)

これは主に、サービスを強制終了するとユーザーを混乱させる場合を対象としています。音楽プレーヤーサービスを停止すると、音楽の再生が停止します。

Ongoingセクションの通知バーに表示されるメソッドにNotificationを提供する必要があります。

72
Dave Webb

BIND_AUTO_CREATEを使用してサービスをアクティビティにバインドすると、アクティビティが破棄およびバインド解除された直後にサービスが強制終了されます。 Services unBindメソッドをどのように実装したかに依存せず、まだ強制終了されます。

もう1つの方法は、アクティビティからstartServiceメソッドを使用してサービスを開始することです。これにより、アクティビティが破棄されても、サービスは破棄されず、一時停止することもありませんが、必要に応じてstopSelf/stopServiceを使用して自分で一時停止/破棄する必要があります。

16
Witold Graca

Daveは既に指摘されています のように、Serviceをフォアグラウンド優先度で実行できます。ただし、この方法は、絶対に必要な場合、つまり、サービスがAndroidによって強制終了された場合にユーザーエクスペリエンスが低下する場合にのみ使用してください。これが「フォアグラウンド」の本当の意味です。あなたのアプリはどういうわけかフォアグラウンドにあり、ユーザーはそれが殺されるとすぐにそれに気づくでしょう(例えば、歌やビデオを再生したため)。

ほとんどの場合、サービスのフォアグラウンド優先度を要求することは逆効果です!

何故ですか? AndroidがServiceを削除することを決定した場合、リソース(通常はRAM)が不足しているため削除します。さまざまな優先度クラスに基づいて、Androidは、リソースを解放するために終了する実行中のプロセスとこれに含まれるサービスを決定します。これは、ユーザーがスムーズに操作できるようにするための健全なプロセスです。正当な理由なく、サービスが強制終了されないようにするためにフォアグラウンドの優先順位を要求すると、ユーザーエクスペリエンスが低下する可能性が高くなります。または、サービスが最小限のリソース消費内に留まり、メモリリークがないことを保証できますか?1

Androidは、スティッキーサービスを提供して、一定の猶予期間が経過した後に再起動する必要があるサービスをマークします。通常、この再起動は数秒以内に行われます。

Android用のXMPPクライアントを作成する画像。 XMPP接続を含むServiceのフォアグラウンド優先度を要求する必要がありますか?間違いなく、そうする理由はまったくありません。ただし、START_STICKYをサービスのonStartCommandメソッドの戻りフラグとして使用する必要があります。リソースが圧迫されるとサービスが停止し、状況が正常に戻るとサービスが再開されるようにします。

1:多くのAndroidアプリにメモリリークがあると確信しています。カジュアルな(デスクトップ)プログラマーはそれほど気にしません。

11
Flow

同様の問題がありました。しばらくすると一部のデバイスでAndroidが私のサービスを強制終了し、さらに startForeground() でも役に立たない。顧客はこの問題を好まない。私の解決策は- AlarmManager クラスは、必要なときにサービスが実行されていることを確認します。 AlarmManager を使用して、一種のウォッチドッグタイマーを作成します。また、 SharedPreferences を使用して、サービスを実行するかどうかのフラグを保持します。

ウォッチドッグタイマーの作成/非表示:

void setServiceWatchdogTimer(boolean set, int timeout)
{
    Intent intent;
    PendingIntent alarmIntent;
    intent = new Intent(); // forms and creates appropriate Intent and pass it to AlarmManager
    intent.setAction(ACTION_WATCHDOG_OF_SERVICE);
    intent.setClass(this, WatchDogServiceReceiver.class);
    alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    AlarmManager am=(AlarmManager)getSystemService(Context.ALARM_SERVICE);
    if(set)
        am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, alarmIntent);
    else
        am.cancel(alarmIntent);
}

ウォッチドッグタイマーからのインテントの受信と処理:

/** this class processes the intent and
 *  checks whether the service should be running
 */
public static class WatchDogServiceReceiver extends BroadcastReceiver
{
    @Override
    public void onReceive(Context context, Intent intent)
    {

        if(intent.getAction().equals(ACTION_WATCHDOG_OF_SERVICE))
        {
            // check your flag and 
            // restart your service if it's necessary
            setServiceWatchdogTimer(true, 60000*5); // restart the watchdogtimer
        }
    }
}

実際、 BroadcastReceiver の代わりに WakefulBroadcastReceiver を使用します。コードを単純化するためにBroadcastReceiverでコードを提供しました。

5
ivan

http://developer.Android.com/reference/Android/content/Context.html#BIND_ABOVE_CLIENT

public static final intBIND_ABOVE_CLIENT-APIレベル14に追加

bindService(Intent, ServiceConnection, int)のフラグ:このサービスにバインドしているクライアントアプリケーションは、アプリ自体よりもサービスが重要であると見なすことを示します。設定すると、プラットフォームはバインドされているサービスを強制終了する前にメモリ不足のキラーにアプリを強制終了させようとしますが、これは保証されません。

同じグループの他のフラグは、BIND_ADJUST_WITH_ACTIVITY、BI​​ND_AUTO_CREATE、BIND_IMPORTANT、BIND_NOT_FOREGROUND、BIND_WAIVE_PRIORITYです。

ICSでBIND_AUTO_CREATEの意味が変更されていることに注意してください。指定しない古いアプリケーションBIND_AUTO_CREATEは自動的にフラグを持ちますBIND_WAIVE_PRIORITYandBIND_ADJUST_WITH_ACTIVITYそれらに設定。

私はアプリに取り組んでおり、アプリを殺すことでサービスを殺すという問題に直面しています。私はグーグルで調査し、フォアグラウンドにする必要があることがわかりました。コードは次のとおりです。

public class UpdateLocationAndPrayerTimes extends Service {

 Context context;
@Override
public void onCreate() {
    super.onCreate();
    context = this;
}

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

    StartForground();
    return START_STICKY;
}

@Override
public void onDestroy() {


    super.onDestroy();
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}


private void StartForground() {
    LocationChangeDetector locationChangeDetector = new LocationChangeDetector(context);
    locationChangeDetector.getLatAndLong();
    Notification notification = new NotificationCompat.Builder(this)
            .setOngoing(false)
            .setSmallIcon(Android.R.color.transparent)

            //.setSmallIcon(R.drawable.picture)
            .build();
    startForeground(101,  notification);

    }
}

それが役立つかもしれないことを願っています!!!!

2
Irfan Ul Haq

サービスのフットプリントを小さくしておくと、Androidアプリケーションを閉じる確率が低くなります。アプリケーションが強制終了されるのを防ぐことはできません。

2
BeRecursive