Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/192.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在应用程序关闭后保持广播接收器运行_Java_Android_Broadcastreceiver - Fatal编程技术网

Java 在应用程序关闭后保持广播接收器运行

Java 在应用程序关闭后保持广播接收器运行,java,android,broadcastreceiver,Java,Android,Broadcastreceiver,我需要保持广播接收器一直运行后,应用程序已经启动 以下是在应用程序中注册此接收器的代码 IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); BroadcastReceiver mReceiver = new ScreenEventsReceiver(); registerReceiver(mRecei

我需要保持广播接收器一直运行后,应用程序已经启动

以下是在应用程序中注册此接收器的代码

    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");
        }
     }
}
你可以使用服务

在主应用程序中启动/停止服务

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);
 }
}

您可以启动正在前台运行的服务。这是确保(大部分情况下)你的应用程序获得事件的唯一方法。你的前台服务仍然有可能在操作系统疯狂的内存压力下被杀死(所以它不是万无一失的)。但是,如果您在前台启动服务,用户将看到一个持久通知,知道它始终在运行


因此,这个故事的寓意是,你真的需要随时监控屏幕关闭/打开的事件吗?他们强迫您注册一个不在清单中的接收者的原因是他们不希望人们总是监视这些事件并减慢设备的速度。你想实现什么?

如果你在清单中声明了
BroadcastReceiver
,它将始终处于活动状态,即使应用程序关闭/停止,它也会被调用如果你使用的是安卓4.4.x,请小心,因为在关闭应用程序时有一个bug会杀死后台服务。我在安卓4.4.2上测试我的应用程序,我也遇到了同样的问题。这里有一个详细的解释:


您无法通过清单中声明的组件接收某些广播事件

这些事件是

  • 动作\u电池\u更换
  • 操作\u配置\u已更改
  • 动作\屏幕\关闭(您正在玩此事件)
  • 动作屏幕打开(您正在玩此事件)
  • 行动时间滴答声
参考文献

所以在您的具体活动中, 您必须创建一个服务&您必须使用Context.registerReceiver()在Service onCreate()中显式注册事件

对于其他事件
清单中的条目就足够了。

我认为接受的答案不是实际答案。我会解释问题所在。我认为您正在华威、Oppo、维梧、Xiomi、华硕……或一些设备上测试您的应用程序。有了这些设备,如果我们关闭应用程序,它们也会关闭我们的广播接收器。所以这就是问题所在。(要检查这一点,请使用像素nexus仿真器)。我将解释如何解决这个问题``

  • 我们会将我们的应用程序添加到受保护的应用程序列表中。操作系统只允许他们继续广播接收器活动。(将此数组声明复制到代码中)

  • 将这些代码放到onCreate方法中。在这里,我使用共享首选项,仅在应用程序打开后第一次检查它。

`


我找到的最好的方法是
前台服务
。我仅在
onStartCommand()
下从我的服务注册了广播接收器,因为我希望我的服务需要始终运行,所以我返回了
START\u STICKY

这样,即使在从堆栈终止应用程序后,我的广播接收器仍能存活

在我的服务中使用以下代码

    @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i("rht", "Received start id " + startId + ": " + intent);
    
            String input = intent.getStringExtra("inputExtra");
            createNotificationChannel();
            Intent notificationIntent = new Intent(this, MainActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(this,
                    0, notificationIntent, 0);
            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle("Foreground Service")
                    .setContentText(input)
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setContentIntent(pendingIntent)
                    .build();
            startForeground(1, notification);
}
Intent serviceIntent = new Intent(this, SpeechServiceForeground.class);
ContextCompat.startForegroundService(this, serviceIntent);
我就是这样开始我的服务的

    @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            Log.i("rht", "Received start id " + startId + ": " + intent);
    
            String input = intent.getStringExtra("inputExtra");
            createNotificationChannel();
            Intent notificationIntent = new Intent(this, MainActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(this,
                    0, notificationIntent, 0);
            Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
                    .setContentTitle("Foreground Service")
                    .setContentText(input)
                    .setSmallIcon(R.drawable.ic_launcher_background)
                    .setContentIntent(pendingIntent)
                    .build();
            startForeground(1, notification);
}
Intent serviceIntent = new Intent(this, SpeechServiceForeground.class);
ContextCompat.startForegroundService(this, serviceIntent);

您可能想创建一个屏幕,但是接收事件呢?您真的需要监视屏幕开/关事件吗?他们强迫您注册不在清单中的接收者的原因是他们不希望人们总是监视这些事件并减慢设备的速度。不能在清单文件中声明SCREEN_ON和SCREEN_OFF。@alfoks:为什么不能在AndroidManifest中声明SCREEN_ON和SCREEN_OFF?你能explain@Kushal这只是他们选择如何实施它。我不记得这背后的理由。@Kushal,因为它在:)我在清单中声明它,但如果我不动态创建接收者,这将不起作用。我正在尝试接收连接了ACTION\u POWER\u,断开了ACTION\u POWER\u的连接。因此,当应用程序强制关闭时,服务仍在运行?我不这么认为。我认为这与Android“O”不兼容。是否可以从前台服务注册广播接收器,即使在应用程序关闭后也会运行?当应用程序从最近的应用程序中删除时,这不起作用screen@Bhavesh,你的意思是当应用程序关闭时广播接收器将不工作吗?实际上,当应用程序的服务正在运行时,它被视为正在运行。而这个特定的接收者操作屏幕在应用程序不运行时无法接收事件,即使它在清单中声明,并且必须在永久运行的服务中创建。所以你的答案是公认答案的补充,但不是一个完整的答案。在小米红米6A中尝试过。应用程序被选中为“autostart”,但当我关闭应用程序时,服务会一直停止。我的服务在“普通”设备上运行得很好,但在小米设备上无法运行。此时,他们改变了机制。我会根据您的需要更新我的答案。您能解释一下您提供的代码/解决方案吗?真的很难理解为什么会显示这个对话框,以及它是如何工作的。