为什么当设备进入睡眠模式时前台服务停止工作

Mar*_*zak 5 java android foreground-service

我想创建一个不断检查位置变化并将当前位置放入 firebase 的应用程序(例如跑步者的应用程序)。

\n\n

不幸的是,每次设备进入睡眠模式时,前台服务都会停止或暂停。

\n\n

对于初学者,我想创建一个前台服务,每秒不断地将信息写入基础(这将是一个时间戳或一个简单的字符串)。\n一段时间后,它只是停止写入 firebase 而不调用 stopself()。

\n\n

该服务在模拟器上运行良好(即使处于睡眠状态),但在真实设备 \xe2\x80\x93 上测试时停止(在我的情况下为华为,Android 8.1.0)。\n我应该做什么来强制服务运行在设备的每个状态下?

\n\n
My MainActivity: \n\npublic class MainActivity extends AppCompatActivity {\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n             Intent intent = new Intent(this, MyService.class);\n            intent.putExtra("action", "start");\n            startForegroundService(intent);\n        }\n        else {\n             Intent intent = new Intent(this, MyService.class);\n            intent.putExtra("action", "start");\n            startService(intent);\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {\n            Intent intent = new Intent(this, MyService.class);\n            intent.putExtra("action", "stop");\n            startForegroundService(intent);\n        }\n        else {\n            Intent intent = new Intent(this, MyService.class);\n            intent.putExtra("action", "stop");\n            startService(intent);\n        }\n    }\n\n}\nMyService:  \n\npublic class MyService extends Service {\n\n    int i =0;\n    private String CHANNEL_ID = "2345";\n    @Override\n    public void onCreate() {\n        super.onCreate();\n    }\n\n    public MyService() {\n    }\n\n    @Override\n    public int onStartCommand(Intent intent, int flags, int startId) {\n        startForeground(1000, createNotification());\n        String action = intent.getExtras().getString("action"); \n        switch (action){\n            case "start":\n                final Handler handler = new Handler();\n             Runnable runnable = new Runnable() {\n             @Override\n             public void run() {\n                        myfunction();\n                 handler.postDelayed(this, 1000);\n            }\n        };\n\n            break;\n            case "stop":\n                stopfunction();\n                break;\n        }\n        handler.postDelayed(runnable, 1000);\n        return START_NOT_STICKY;\n    }\n\n    private void stopfunction() {\n        stopSelf();\n}\n\n    private void myfunction() {\n        FirebaseDatabase database = FirebaseDatabase.getInstance();\n        DatabaseReference myRef = database.getReference("locations");\n        myRef.child("location").setValue(i);\n        i++;\n    }\n\n    @Override\n    public IBinder onBind(Intent intent) {\n        // TODO: Return the communication channel to the service.\n        return null;\n    }\n\n    @RequiresApi(Build.VERSION_CODES.O)\n    private void createChannel(){\n        NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);\n        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, getString(R.string.infoTxt),\n                NotificationManager.IMPORTANCE_HIGH);\n        channel.setShowBadge(false);\n        channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);\n        notificationManager.createNotificationChannel(channel);\n    }\n\n    private Notification createNotification(){\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){\n            createChannel();\n        }\n\n        Intent notificationItent = new Intent(this, MainActivity.class);\n        notificationItent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);\n        PendingIntent intent = PendingIntent.getActivity(this, 0, notificationItent, 0);\n\n        return new NotificationCompat.Builder(this, CHANNEL_ID)\n                .setColor(ContextCompat.getColor(this, android.R.color.background_dark))\n                .setContentIntent(intent)\n                .setSmallIcon(R.drawable.ic_launcher_background)\n                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)\n                .setOnlyAlertOnce(true)\n                .setContentTitle("GPS Location")\n                .build();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Mar*_*zak 4

我已经尝试了一切:服务、前台服务、广播接收器、jobSheduler、WorkerManager \xe2\x80\x93 没有任何帮助。然后我发现\xe2\x80\x99是华为的一个新功能,名为\xe2\x80\x9c耗电应用监控\xe2\x80\x9c。除非用户授予特殊权限,否则它会杀死长时间在后台运行的每个应用程序。\n执行此操作的路径:\n设置 -> 安全和隐私 -> 位置服务 -> 最近的位置请求:您的应用程序名称 -> 电池 -> 取消选中耗电提示,应用程序启动:手动管理:选中所有三个位置:自动-启动、二次启动、后台运行。

\n\n

我不知道有没有办法以编程方式执行此操作。我认为最好的方法是创建一种帮助活动,并向用户解释如果应用程序无法运行\xe2\x80\x99t 该怎么做。

\n