首页 文章

Job Scheduler与后台服务

提问于
浏览
24

我有一个应用程序,其功能A应该每分钟在后台运行 . 功能A是应用程序应该连接到数据库,读取一些数据然后获取设备的当前位置并根据它们检查条件,如果条件为真,它应该向用户发送状态栏通知,以便用户点击通知,将显示应用程序的UI并发生一些事情 .
这个后台任务应该每分钟都运行一次,无论应用程序是否被使用,关闭,终止(例如facebook或Whatsapp向我们显示通知,无论它们是否在应用程序堆栈中) .
现在我已经搜索并发现Android提供 Job SchedulerBackground ServiceAlarmManagerHandlers .
但是我越了解他们,这些陈述对我来说就越矛盾 .

  • 关于处理程序我已经读过,它们不存在长时间延迟,并将在系统重启后终止 . 所以他们不适合我的任务 .

  • 但是AlarmManager似乎是这个问题的一个很好的候选者,因为当它被允许时,即使在系统重启后它们也存在并且可以重新运行应用程序 . 但是在_613521中,警报管理器旨在用于必须在特定时间运行的任务(如闹钟) . 但我的任务必须每分钟运行一次 .

  • 然后有后台服务 . 这更像是我在阅读后在后台下载的任务,而不是用于我已经解释过的事情 .

  • JobScheduler似乎不适用于必须永久完成的任务,但是对于满足特定约束条件的任务,例如空闲或无网络......那么您建议使用以下哪些(或其他如果存在的话)用于我在第一部分中解释的任务

6 回答

  • 22

    我有一个应用程序,其功能A应该每分钟都在后台运行 .

    由于打盹模式(以及可能的应用程序待机状态,取决于应用程序的其余部分),数以亿计的Android设备(运行Android 6.0及更高版本的设备)不会发生这种情况 .

    但是AlarmManager似乎是这个问题的一个很好的选择,因为在允许的情况下它们甚至在系统重启后也存在

    不,他们没有 . 重启后,您需要重新安排使用 AlarmManager 安排的所有警报 .

    Alarm Manager旨在用于必须在特定时间运行的任务

    AlarmManager 支持重复选项 .

    这更像是我在阅读后在后台下载的任务,而不是用于做我已经解释过的事情 .

    无论你使用什么解决方案, Service 都是必不可少的 .

    JobScheduler似乎不是为了必须永久完成的任务,而是针对满足特定约束(如空闲或无网络)的任务

    JobScheduler ,与 AlarmManager 一样,支持重复作业 .

    因此,您建议将哪一个(或其他如果存在的话)用于我在第一部分中解释的任务

    不使用它们,因为一旦设备进入打盹模式,您将无法在Android 6.0上每分钟运行一次,这将在屏幕关闭后一小时内完成 . 相反,重新设计应用程序只需要每天几次背景工作,或者不打扰编写应用程序 .

  • 12

    如果您的minSdkVersion = 21,您可以使用Android 5.0中引入的现代 JobScheduler API .

    还有https://github.com/firebase/firebase-jobdispatcher-android需要安装Google Play minSdkVersion = 9

    但我建议使用这个库https://github.com/evernote/android-job,根据Android版本,将使用 JobSchedulerGcmNetworkManagerAlarmManager .

    使用这些API,您可以安排作业并运行描述任务的服务 .

    UPDATE 现在最好使用新的 WorkManagerdocs) . android-job 即将弃用

  • 1

    首先,JobService是一种服务 . 后台服务不明确,让我猜你的意思是在后台线程中运行的服务 . 作业服务在ui线程上运行,但您可以在其中创建异步任务对象以使其在后台运行 .

    从您的问题来看,JobService不是要走的路 . 我建议的是:

    • 您可以在该类的onDestroy方法中创建一个扩展IntentService(在后台线程上运行)的类,发送广播并使广播重新启动该服务 .
    @onDestroy(){
     Intent broadcastIntent = new 
     Intent("com.example.myapp.serviceRestarted");
     sendBroadcast(broadcastIntent);}
    
    • 创建一个扩展广播接收器的类
    public class RestartServiceReceiver extends BroadcastReceiver {
     @Override
     public void onReceive(Context context, Intent intent) {
     context.startService(new Intent(context, 
     MyService.class));
    } 
    }
    
    • 在您的清单中,注册您的服务和接收人

    <接收器
    机器人:名字= “RestartServiceReceiver”
    机器人:启用=“真”
    机器人:导出=“真”>
    <意图滤波器>
    <action android:name =“com.example.myapp.serviceRestarted”/>
    <action android:name =“android.intent.action.BOOT_COMPLETED”/>
    </意图滤波器>
    </接收机>

    引导权限是为了使接收器能够在系统完成引导时被调用,并且一旦调用接收器,将再次调用该服务 .

  • 0

    根据this和下面评论1中的其他链接

    您应该使用AlarmManager完成任务 .

    如果你需要设置在Doze中发出的警报,使用:

    setAndAllowWhileIdle() or setExactAndAllowWhileIdle().
    

    有关在后台执行操作的不同方法的完整易懂理解,请阅读:https://www.bignerdranch.com/blog/choosing-the-right-background-scheduler-in-android/

    祝好运!

  • 6

    在以前的Android版本中,人们使用Handler或后台服务来实现此目的 . 过了一会儿,他们宣布了警报管理员课程,用于永久性的预定作品 .

    Whatsapp,脸书或一些社交媒体应用程序大多使用谷歌 Cloud 消息传递通知目的,这对你没用 .

    我建议你使用报警管理器 . 在KitKat版本(4.2)之后,操作系统会阻止后台处理程序以更好地使用电池 .

    后台服务主要用于图像上传或一些具有结束时间的繁重过程 . 当您在Whatsapp上向朋友发送视频时,后台进程启动并将视频上传到后端服务器 .

    我不确定JobScheduler api是否支持旧版本的支持,但它与Alarm Manager一样好 .

  • 2

    您可以通过服务,以回报start_sticky在“START_STICKY告诉操作系统重新创建服务它有足够的内存后,用空的意图再次调用onStartCommand()做到这一点 . START_NOT_STICKY告诉OS不要再打扰重建服务 . 有也是第三个代码START_REDELIVER_INTENT,它告诉操作系统重新创建服务并将相同的意图重新发送到onStartCommand()“

    并设置一个周期为1分钟的TIMER并执行您的代码 .

    如果你想在用户强制停止服务时重启服务,你可以“像以前的答案一样”

    • 您可以在该类的onDestroy方法中创建一个扩展IntentService(在后台线程上运行)的类,发送广播并使广播重新启动该服务 .
    @onDestroy(){
        Intent broadcastIntent = new Intent("com.example.myapp.serviceRestarted");
        sendBroadcast(broadcastIntent);
    }
    
    • 创建一个扩展广播接收器的类
    public class RestartServiceReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            context.startService(new Intent(context, MyService.class));
        } 
    }
    
    • 在您的清单中,注册您的服务和接收者
    <receiver
       android:name=".RestartServiceReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="com.example.myapp.serviceRestarted" />
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    

    此外,您可以使用AlarmManager,如果需要设置在Doze中触发的警报,请使用:

    setAndAllowWhileIdle()或setExactAndAllowWhileIdle() .

    设置“当前时间在第二个60秒”,这样你就可以在下一分钟设置它 .

    然后执行你的代码,最后在下一分钟重置AlarmManager .

    此外,您可以在重新启动设备后启动服务或AlarmManager,只需在“RECEIVE_BOOT_COMPLETED”时使用brodcastReciever

    并把这个权限:

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    

相关问题