Android 应用在后台时监听器停止 运行

Android Listener stop running when app in background

我正在开发一个应用程序,该应用程序将检测蓝牙信号(Sensoro Smart Beacon 设备)并打开 activity。但我希望应用程序即使在后台运行甚至被杀死时仍然能够检测到信号。我使用了前台服务,当我打开应用程序并在活动之间移动时它会检测到信号,但是当将应用程序发送到后台并打开其他应用程序时,尽管服务仍在运行,但侦听器停止了。我正在打印日志。 System.out.println("Sensoro 2" ); 即使我终止应用程序或打开另一个应用程序,也会继续打印。但是 BeaconManagerListener 中的打印日志不起作用。我尝试使用后台服务,但它也不起作用。 您能否告知当应用程序在后台或被杀死时是否有办法让侦听器在服务中工作? 这是服务代码:

public class MyService extends Service {
    public static final String CHANNEL_ID = "ForegroundServiceChannel";
    int service_timer=0;
    Timer timer = new Timer();
    SensoroManager sensoroManager;
    @Override
    public void onCreate() {
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        sensoroManager = SensoroManager.getInstance(MyService.this);
        String input = intent.getStringExtra("inputExtra");
        System.out.println("Sensoro 2" );
        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);
        //do heavy work on a background thread
        //stopSelf();
                if (sensoroManager.isBluetoothEnabled()) {
                    sensoroManager.setCloudServiceEnable(true);
                    /**
                     * Enable SDK service
                     **/
                    try {
                        sensoroManager.startService();

                    } catch (Exception e) {
                        e.printStackTrace(); // Fetch abnormal info
                    }
                }
                else
                {
                    Toast.makeText(MyService.this,"Bluetooth off",Toast.LENGTH_LONG).show();
                }
        new Timer().scheduleAtFixedRate(new TimerTask() {
            @Override
           public void run() {
                //your method
                System.out.println("Sensoro 2" );


                BeaconManagerListener beaconManagerListener = new BeaconManagerListener() {

                    @Override
                    public void onUpdateBeacon(ArrayList<Beacon> beacons) {
                        // Refresh sensor info
                        for (Beacon beacon : beacons
                        ) {
                            System.out.println("Sensoro 3" );
                           // System.out.println("Sensoro" +beacon.getAccuracy());
                        }
                    }

                    @Override
                    public void onNewBeacon(Beacon beacon) {

                        if (beacon.getSerialNumber().equals("0117C59B243C")){
                            System.out.println("Sensoro 3" );
                            System.out.println("Sensoro acc" +beacon.getAccuracy());
                }
            }

                    @Override
                    public void onGoneBeacon(Beacon beacon) {

                        if (beacon.getSerialNumber().equals("0117C59B243C")){
                            System.out.println("Sensoro acc gone");
                            System.out.println("Sensoro acc Timer" +service_timer);
                        }
                    }
                };
                sensoroManager.setBeaconManagerListener(beaconManagerListener);
            }
        }, 0, 2000);



        return START_NOT_STICKY;
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
       // timer.cancel();
    }
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    private void createNotificationChannel() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel serviceChannel = new NotificationChannel(
                    CHANNEL_ID,
                    "Foreground Service Channel",
                    NotificationManager.IMPORTANCE_DEFAULT
            );
            NotificationManager manager = getSystemService(NotificationManager.class);
            manager.createNotificationChannel(serviceChannel);
        }
    }


}

我在这里称呼它:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        startService();
        }


    public void startService() {
        Intent serviceIntent = new Intent(this, MyService.class);
        serviceIntent.putExtra("inputExtra", "Foreground Service Example in Android");
        System.out.println("Sensoro 1 ");
        ContextCompat.startForegroundService(this, serviceIntent);
    }
    public void stopService() {
        Intent serviceIntent = new Intent(this, MyService2.class);
        stopService(serviceIntent);
    }


    public void movingg(View view) {
        Intent intent=new Intent(this,Usermain.class);
       startActivity(intent);    }
}

我查看了 Android 规章制度页面

根据 Google 文件,从 Android 8 开始,所有没有 Google 批准签名的应用程序将在几分钟后从后台删除。

但解决方案:

  1. 第一个解决方案是运行调试模式下的应用程序
  2. 第二种解决方案是为应用程序分配签名并将其发送到Google以供批准

推荐:

  1. 第三种解决方案是从模拟器中删除google播放服务应用程序或androidphone

我不知道这是否对你有帮助,但这是我的答案:

public void startService() {
      Intent serviceIntent = new Intent(this, MyService.class);
      serviceIntent.putExtra("inputExtra", "Foreground Service Example in Android");
      System.out.println("Sensoro 1 ");
      startService(serviceIntent);
  }

您可以使用 BroadcastReceiver。 如果您的应用程序被杀死或在后台,广播接收器将捕获 bluetoth

事件

这与您搜索的内容并非 100% 匹配,但接近您想要的内容。

您可以使用甚至在后台运行的应用程序 WorkManager。有两种类型的 WorkManager。 1) OneTimeWorkRequest 2) PeriodicWorkRequest.

所以你可以 PeriodicWorkRequest 每 15 分钟(最小间隔)调用一次,你可以在 WorkManager 中添加代码来检测蓝牙信号。所以你可以每隔15分钟检测一次蓝牙信号。

希望本文能帮助您解决问题。

我发现您的方法存在两个问题。

首先,您应该检查特定的信标序列号是否会导致问题。

其次,您正在使用一个每 2 秒关闭一次的计时器,每次它都会添加一个新的 BeaconManagerListener,这不应该是您应该将侦听器提取到外部的情况,也许可以将其设为 class 成员,并且然后每次都使用相同的侦听器,而不是不断创建新的侦听器,然后替换旧的侦听器。

还有为什么我认为应该在调用 sensoroManager.startService()

之前添加 2 秒后添加侦听器

最后,如果任务不需要每隔几秒重复一次并且可以间隔 >= 15 分钟完成,那么请考虑改用 Periodic Work Manager。