ios - 代号一中的 BackgroundFetch
问题描述
我正在为 iOS 开发一个 Codename One 应用程序,并且我正在尝试使用 BackgroundFetch 界面。
我复制了用 Javadoc ( https://www.codenameone.com/javadoc/com/codename1/background/BackgroundFetch.html )编写的示例代码,并添加了ios.background_modes=fetch构建提示。
在模拟器上启动应用,后台操作正确执行。
在真实设备(iPhone 7s、iOs 12.1.4)上启动它,行为是不可预测的。尽管如此setPreferredBackgroundFetchInterval(10)
,我注意到几乎每次启动应用程序时,后台操作都没有执行。很少执行后台操作,但应用程序必须在几分钟前处于后台才能恢复,而不是通过 setPreferredBackgroundFetchInterval(10) 方法设置的 10 秒。
该Display.isBackgroundFetchSupported()
方法返回真。
如果负担得起且可预测,我不明白如何制作。
编辑
我修改了示例代码,仅在 performBackgroundFetch() 实现中(Display.setPreferredBackgroundFetchInterval(10)
未更改)。我只是在标签中放了一些文字:
@Override
public void performBackgroundFetch(long deadline, Callback<Boolean> onComplete) {
supported.setText("deadline: " + deadline + "; timeMillis: " + System.currentTimeMillis());
onComplete.onSucess(Boolean.TRUE);
}
我观察到模拟器和真实设备的两种不同行为。在模拟器中,该方法在进入暂停状态后正好 10 秒执行。在真实设备中,该方法在进入暂停状态后 10 秒不执行:某些情况下,它会在 20 分钟后执行(在其他情况下,它根本不执行)。但是,在这两种情况下,我都可以计算出最后期限和方法执行时间之间的差异:它总是 25 分钟。
例如,您可以看到以下应用程序的屏幕截图(在 iPhone 上运行):
截止日期 = 1560246881647 时间戳 = 1560245381647
截止日期 - 时间戳 = 1500000 毫秒 = 1500 秒 = 25 分钟。
据我了解,在 iOS 上,执行后台获取的时间限制为 30 秒,否则操作系统将终止应用程序。此外,Display.setPreferredBackgroundFetchInterval()
用于设置后台提取之间的首选时间间隔,但不能保证,因为 iOS 保持对后台提取执行的控制。
使用后台获取的正确方法是什么?
这是完整的代码:
public class MyApplication implements BackgroundFetch{
private Form current;
private Resources theme;
List<Map> records;
Label supported;
// Container to hold the list of records.
Container recordsContainer;
public void init(Object context) {
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature, uncomment if you have a pro subscription
// Log.bindCrashProtection(true);
}
public void start() {
if(current != null){
// Make sure we update the records as we are coming in from the
// background.
updateRecords();
current.show();
return;
}
Display d = Display.getInstance();
// This call is necessary to initialize background fetch
d.setPreferredBackgroundFetchInterval(10);
Form hi = new Form("Background Fetch Demo");
hi.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
supported = new Label();
if (d.isBackgroundFetchSupported()){
supported.setText("Background Fetch IS Supported");
} else {
supported.setText("Background Fetch is NOT Supported");
}
hi.addComponent(new Label("Records:"));
recordsContainer = new Container(new BoxLayout(BoxLayout.Y_AXIS));
//recordsContainer.setScrollableY(true);
hi.addComponent(recordsContainer);
hi.addComponent(supported);
updateRecords();
hi.show();
}
/**
* Update the UI with the records that are currently loaded.
*/
private void updateRecords() {
recordsContainer.removeAll();
if (records != null) {
for (Map m : records) {
recordsContainer.addComponent(new SpanLabel((String)m.get("title")));
}
} else {
recordsContainer.addComponent(new SpanLabel("Put the app in the background, wait 10 seconds, then open it again. The app should background fetch some data from the Slashdot RSS feed and show it here."));
}
if (Display.getInstance().getCurrent() != null) {
Display.getInstance().getCurrent().revalidate();
}
}
public void stop() {
current = Display.getInstance().getCurrent();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = Display.getInstance().getCurrent();
}
}
public void destroy() {
}
/**
* This method will be called in the background by the platform. It will
* load the RSS feed. Note: This only runs when the app is in the background.
* @param deadline
* @param onComplete
*/
@Override
public void performBackgroundFetch(long deadline, Callback<Boolean> onComplete) {
supported.setText("deadline: " + deadline + "; timeMillis: " + System.currentTimeMillis());
onComplete.onSucess(Boolean.TRUE);
}
}
解决方案
setPreferredBackgroundFetchInterval
javadoc 指出:
设置后台提取之间的首选时间间隔。这只是一个首选间隔,不能保证。某些平台,例如 iOS,对何时以及是否允许后台获取保持主权控制。此数字仅用作指导。
推荐阅读
- javascript - 映射时,如何访问循环内的对象键?角
- ms-access - Access 组合具有相似值的不同列
- javascript - JqueryUI 拖放助手占位符位置
- javascript - 使用一个输入从 HTML 页面创建 JSON 文件
- javascript - 从数组中获取唯一的类别属性值
- vb.net - 从 BarCode Vb.Net 下方删除文本
- android - 在 Java Android 中将 Parcelable 和 JSON 字符串放入 Intent
- google-cloud-platform - 谷歌云 Kubernetes - 套接字服务器
- regex - Powershell正则表达式匹配括号之间的字符串
- mysql - django __date 在 MySQL 中返回 None 而在 Sqlite3 中返回日期对象