web-dev-qa-db-ja.com

アプリケーションを閉じた後もブロードキャストレシーバーを実行し続ける

アプリを起動した後も、放送受信機を常時稼働させておく必要があります。

このレシーバーをアプリケーションに登録するコードは次のとおりです

    IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
    filter.addAction(Intent.ACTION_SCREEN_OFF);
    BroadcastReceiver mReceiver = new ScreenEventsReceiver();
    registerReceiver(mReceiver, filter);

そして、受信機のコード

public class ScreenEventsReceiver extends BroadcastReceiver {
     public static boolean wasScreenOn = true;

     @Override
     public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
            wasScreenOn = false;
            Log.d("ScreenEventReceiver", "ON");
        } else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
            wasScreenOn = true;
            Log.d("ScreenEventReceiver", "ON");
        }
     }
}
28
Sergey Pekar

サービスを利用できます

メインアプリでサービスを開始/停止します

Intent service = new Intent(context, MyService.class);
context.startService(service);
...
Intent service = new Intent(context, MyService.class);
context.stopService(service);

サービス

public class MyService extends Service
{
 private static BroadcastReceiver m_ScreenOffReceiver;

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

 @Override
 public void onCreate()
 {
  registerScreenOffReceiver();
 }

 @Override
 public void onDestroy()
 {
  unregisterReceiver(m_ScreenOffReceiver);
  m_ScreenOffReceiver = null;
 }

 private void registerScreenOffReceiver()
 {
  m_ScreenOffReceiver = new BroadcastReceiver()
  {
   @Override
   public void onReceive(Context context, Intent intent)
   {
     Log.d(TAG, "ACTION_SCREEN_OFF");
     // do something, e.g. send Intent to main app
   }
  };
  IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
  registerReceiver(m_ScreenOffReceiver, filter);
 }
}
27
j.holetzeck

受け入れられた答えは私が思う実際の答えではありません。何が問題なのかを説明します。 Huawie、Oppo、Vivo、Xiomi、asus .......またはいくつかのデバイスでアプリをテストしていると思います。そのデバイスでは、アプリケーションを閉じると、ブロードキャストレシーバーも閉じます。それが問題です(ピクセルネクサスエミュレーターを使用することを確認するには)。これを解決する方法を説明します。」

  • アプリを保護されたアプリのリストに追加します。OSは、ブロードキャストレシーバーのアクティビティを続行することのみを許可します。(この配列宣言をコードにコピーします)

    _private static final Intent[] POWERMANAGER_INTENTS = {
        new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
        new Intent().setComponent(new ComponentName("com.letv.Android.letvsafe", "com.letv.Android.letvsafe.AutobootManageActivity")),
        new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
        new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),
        new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
        new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
        new Intent().setComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
        new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
        new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
        new Intent().setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
        new Intent().setComponent(new ComponentName("com.samsung.Android.lool", "com.samsung.Android.sm.ui.battery.BatteryActivity")),
        new Intent().setComponent(new ComponentName("com.htc.pitroad", "com.htc.pitroad.landingpage.activity.LandingPageActivity")),
        new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.MainActivity"))};
    _
  • これらのコードをonCreateメソッドに追加します。ここでは、共有設定を使用して、アプリを初めて開いたときにのみ確認します。

final SharedPreferences.Editor pref = getSharedPreferences("allow_notify", MODE_PRIVATE).edit(); pref.apply(); final SharedPreferences sp = getSharedPreferences("allow_notify", MODE_PRIVATE);

_if(!sp.getBoolean("protected",false)) {
    for (final Intent intent : POWERMANAGER_INTENTS)
        if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {

        AlertDialog.Builder builder  = new AlertDialog.Builder(this);
        builder.setTitle("Alert Title").setMessage("Alert Body")
                .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        startActivity(intent);
                        sp.edit().putBoolean("protected",true).apply();

                    }
                })
                .setCancelable(false)
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                    }
                })
                .create().show();
        break;
_
8
Tharuka Lakshan

マニフェストでBroadcastReceiverを宣言すると、アプリケーションが閉じられたり停止されたりしても、常にアクティブになり呼び出されます。

4
Abraham

マニフェストで宣言されたコンポーネントを介して一部のブロードキャストイベントを受信できません。

これらのイベントは

  • ACTION_BATTERY_CHANGED
  • ACTION_CONFIGURATION_CHANGED
  • ACTION_SCREEN_OFF(このイベントで遊んでいます)
  • ACTION_SCREEN_ON(このイベントで遊んでいます)
  • ACTION_TIME_TICK

リファレンス https://developer.Android.com/reference/Android/content/Intent.html#ACTION_SCREEN_ON

したがって、特定のイベントでは、サービスを作成する必要があり、Context.registerReceiverでサービスonCreate()に明示的にイベントを登録する必要があります()。

他のイベントの場合、マニフェストのエントリで十分です。

2
Vivek A Naik

Android 4.4.xを使用している場合は注意してください。アプリを閉じるときにバックグラウンドサービスを強制終了するバグがあるため、Android 4.4でアプリをテストしていました.2と私は同じ問題を抱えていました。ここに詳細な説明があります:

http://www.androidpolice.com/2014/03/07/bug-watch-stopping-apps-on-Android-4-4-2-can-silently-kill-related-background-services- a-fix-is-on-the-way /

フォアグラウンドで実行されているサービスを開始できます。これが、アプリが確実にイベントを受け取るようにする(ほとんどの場合)唯一の方法です。フォアグラウンドサービスは、OSからの異常なメモリプレッシャーの際に強制終了される可能性があります(そのため、絶対確実ではありません)。ただし、フォアグラウンドでサービスを開始すると、ユーザーには、サービスが常に実行されていることを通知する永続的な通知が表示されます。

つまり、この話の教訓は、常に画面のオフ/オンイベントを常に監視する必要があるのでしょうか。彼らがあなたにマニフェストにない受信機を登録することを強制する理由は、人々が常にこれらのイベントを監視してデバイスを遅くすることを望まないからです。あなたは何を成し遂げようとしているのですか?

1
natez0r