(免责声明:本译文未参考任何其他文章,如有与其他译版雷同部分,纯属巧合)
(声明:中文版权归作者zbc所有,转载请注明出处)
翻译原文地址(来自 Github)
当你的 app 在后台时安排你的 JavaScript 代码进行工作,或者够胆量的话你也可以尝试当 app 正在前台运行时进行此操作。
即使是该 app 已经被关闭了,此项进程依旧在运行。默认情况下,该进程在重启程序后也会保持存在。
本类库依赖于 React-Native 中目前只支持 Android 平台的 HeadlessJS
原生端代码它使用的是 Firebase JobDispatcher
或者 AlarmManager
.
-
Firebase JobDispatcher (默认):工作不能被确切地安排并且取决于 Android api 不同时期的版本。 FirebaseJobDispatcher 是安排后台任务最省电且向后兼容的方式。
-
AlarmManager 通过把“exact”设置为“true”:简单的属性实现,仅测试用。只在意
按时处理任务,其他参数均被忽略。重启程序后任务也不复存在。
要求:
- React-Native 0.36+
- Android api 16+
已经支持的平台
- Android
想要IOS版本?到官网去投票使其开发IOS版:产品之痛
起步
$ yarn add react-native-background-job
或者
$ npm install react-native-background-job --save
大多数的自动安装
$ react-native link react-native-background-job
手动安装
-
Android
1.打开文件,位置: android/app/src/main/java/[...]/MainApplication.java
- 添加引用层代码
import com.pilloxa.backgroundjob.BackgroundJobPackage;
- 添加新的初始化对象
new BackgroundJobPackage()
到getPackages()
方法里。
2.将以下代码添加到 android/settings.gradle
文件:
include ':react-native-background-job'
project(':react-native-background-job').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-job/android')
3.添加以下代码至依赖模块文件 android/app/build.gradle
并确保 minSdkVersion 是 21。
compile project(':react-native-background-job')
用法
进程必须在 React-Native 每次启动时注册,可以通过 register
方法。因为 HeadlessJS 没有安装任何 components,所以 register
方法必须在定义任意类之外运行。(参见 example/index.android.js,此网址位于github)
注册一个 job 并不意味着此 job 已经被安排,而只是告诉 React-Native 此 job 已经与这个 jobKey 绑定。此 job 接下来将要被安排使用你安排的方法。默认情况下,当你的app正在前台运行时,此 job 不会被激活。这是因为此 job 运行于 JavaScript 线程,并且如果你在 app 正运行于前台时启用此 job 将可能会冻结你的 app 动作。通过设置 allowExecutionInForeground
为“true”可以允许你这么做。我们推荐你不要这样使用,但如果是快速作业的话也许可以如此。
一个完整的例子 example/index.android.js
API
目录列表
【register】
注册一个 job 以启动想要运行的函数。
这个函数必须在每次 React-Native 初始化时运行,并且必须运行在全局环境而不是在任何组件内部的生命周期函数。见示例项目。只注册 job 不会使之运行。它必须被安排后续执行。
参数
<object>
Examples
import BackgroundJob from 'react-native-background-job';
const backgroundJob = {
jobKey: "myJob",
job: () => console.log("Running in background")
};
BackgroundJob.register(backgroundJob);
【schedule】
安排一个新 job。
因为在每次 React-Native 初始化时,register 都被运行了一次,因此 schedule 应该仅运行一次。
参数
<object>
-
obj.jobKey
string 那个在注册 job 时使用的 key,并且将在接下来退出时使用。 -
obj.timeout
number 不管任务是否完成,都应终止响应的时间量(ms)(可配置,默认:2000
) -
obj.period
number 运行此 job 的频率(ms),其具体数字是不确定的,Android 可能会为了节省电量而修改这个设置。注意:对于 Android 平台,此值将大于等于 900,0000(15min)(可配置项,默认:900,0000
) -
obj.persist
boolean 重启应用时此 job 是否应继续保持。(可配置项,默认:true
) -
obj.override
boolean 当前 job 是否应被已存在的相同 key 的其他 job 替换。(可配置项,默认:true
) -
obj.networkType
number 只针对特殊网络需要(可配置项,默认:NETWORK_TYPE_NONE
) -
obj.requiresCharging
boolean 仅在设备充电时运行, (不支持 pre Android N 设备) 文档(可配置项, 默认false
) -
obj.requiresDeviceIdle
boolean 仅在设备空闲时使用, (不支持 pre Android N 设备) 文档(可配置项, 默认false
) -
obj.exact
boolean 计划在定义的时间段内精准触发 job。注意:这项操作没有任何省电做法 (可配置项, 默认false
) -
obj.allowWhileIdle
boolean 允许 job 在睡眠时处理任务. (可配置项, 默认false
) -
obj.allowExecutionInForeground
boolean 即便是 app 正在前台运行时依然允许 job 执行任务,请仅在小进程时使用 (配置, 默认false
) -
obj.notificationText
string 对于 Android SDK 版本大于 26, 通知文本应该是什么 (可配置项, 默认"Running in background..."
) -
obj.notificationTitle
string 对于 Android SDK 版本大于 26, 通知标题应该是什么 (可配置项, 默认"Background job"
)
Examples
import BackgroundJob from 'react-native-background-job';
const backgroundJob = {
jobKey: "myJob",
job: () => console.log("Running in background")
};
BackgroundJob.register(backgroundJob);
var backgroundSchedule = {
jobKey: "myJob",
}
BackgroundJob.schedule(backgroundSchedule);
【cancel】
退出特定 job。
参数
<object>
-
obj.jobKey
string job 唯一标识。
Examples
import BackgroundJob from 'react-native-background-job';
BackgroundJob.cancel({jobKey: 'myJob'});
【cancelAll】
退出所有 job。
Examples
import BackgroundJob from 'react-native-background-job';
BackgroundJob.cancelAll();
【setGlobalWarnings】
设置全局警报等级。
参数
-
warn
**[boolean]
Examples
import BackgroundJob from 'react-native-background-job';
BackgroundJob.setGlobalWarnings(false);
【isAppIgnoringBatteryOptimization】
检测 app 是否针对电池进行优化,在睡眠时使用,返回 boolean 值。
参数
-
callback
Callback 在从 Android 模块收到结果后,携带参数被调用。
Examples
import BackgroundJob from 'react-native-background-job';
BackgroundJob.isAppIgnoringBatteryOptimization((error,ignoringOptimization)=>{});
问题聚焦
1.No task registered for key myJob(对于 key myJob 不存在注册的任务)
确保你是在全局环境调用的register
函数(也就是说不是在任何组件的生命周期函数内部使用,如 render()
,componentDidMount()
等). 由于在 Headless 模式下不会被渲染,如果你在那些位置使用的话,它将不会在后台环境运行,因此导致库中找不到该执行哪一个函数任务。
查看示例项目
2.当我在后台运行 Headless 任务时 AppState.currentState 是 "active" 。
这是一个 React Native 本身的问题,你可以选择直接调用NativeModules.AppState.getCurrentAppState
代替之。
3.即便是是我指定了 requiresCharging
, requiresDeviceIdle
或者 networkType
,我的 job 也总是在后台运行。
这是一个 Android 的问题,看来对 Android N 设备而言,当你对其有周期间隔限制的同时不能再对这些配置做限制。
其他详细信息
包含了检查 app 是否为“耗电型 app” 的方法。#62
Android SDK 在高于23版本之后,Doze 默认是被使用的,目的是为了当手机被闲置几个小时的情况下,可以暂时关闭后台任务以节省电量。
但是,一些 app 可能会要求后台任务始终执行,忽略 doze 并且不考虑省电优化方案(这意味着每当使用此 app 时都要以更大的电池消耗以换取性能和表现)。那些要求在较短周期内持续与服务器同步数据的 app 就是此类 app 的典型例子。
所以对于开发人员来讲,检测 app 是否为 “省电型 App ”是很好的举动。因为如此做法,可以通知用户此 app 不是每次使用时都能如所预期的那样工作,除非用户手动将此 app 手动地移出“省电列表”(省电列表可以在 “设置”==>“电池”=>“选项(右上角)”=>“省电方案”并选择“所有 app”)。就为了某一个 app 而修改此项设定。
为了实现上述的检测功能,做了明确改进,包含进了一个用于检测(是否省电)的方法(isAppIgnoringBatteryOptimization
)它可以检测 app 是否为耗电型 app ,如果是“耗电型”,返回 true,是“省电型”则返回 false。
安排一个耗电型任务的逻辑也已经被添加,这取决于用户是否手动将其“省电列表”
赞助商
------------------- 结束线 -----------------------
本文翻译结合笔者开发经验,如有错误,欢迎留言指正、探讨。
网友评论