GVKun编程网logo

[Chromium 文档转载,第 001 章] Mojo Migration Guide(mono morphemic words)

18

这篇文章主要围绕[Chromium文档转载,第001章]MojoMigrationGuide和monomorphemicwords展开,旨在为您提供一份详细的参考资料。我们将全面介绍[Chromium

这篇文章主要围绕[Chromium 文档转载,第 001 章] Mojo Migration Guidemono morphemic words展开,旨在为您提供一份详细的参考资料。我们将全面介绍[Chromium 文档转载,第 001 章] Mojo Migration Guide的优缺点,解答mono morphemic words的相关问题,同时也会为您带来android – IllegalArgumentException:org.chromium.components.minidump_uploader.CrashFileManager、App Programming Guide for iOS --Background Execution 1、App Programming Guide for iOS --Background Execution 2、Brave 浏览器更换 Chromium 内核,支持 Chrome 扩展的实用方法。

本文目录一览:

[Chromium 文档转载,第 001 章] Mojo Migration Guide(mono morphemic words)

[Chromium 文档转载,第 001 章] Mojo Migration Guide(mono morphemic words)

 

 

 
For Developers‎ > ‎ Design Documents‎ > ‎ Mojo‎ > ‎

Mojo Migration Guide

目录

  1. Summary
  2. How do I migrate my IPC to Mojo?
    1. 2.1 Don’t panic
    2. 2.2 Read the Mojo documentation
    3. 2.3 Claim your message(s)
    4. 2.4 Convert your Chrome IPCs to Mojo
      1. 2.4.1 Convert the message definition
      2. 2.4.2 Whitelist the IPC
      3. 2.4.3 Fix build files and includes
      4. 2.4.4 Register the interface implementation
      5. 2.4.5 Call the interface
      6. 2.4.6 Two approaches to migrating your IPC
    5. 2.5 Common scenarios
      1. 2.5.1 Converting BrowserMessageFilters
      2. 2.5.2 Converting WebContentsObservers
      3. 2.5.3 Lifetime issues
      4. 2.5.4 Handling "late" messages
      5. 2.5.5 Mocking in tests
      6. 2.5.6 Replacing request/response messages pairs
      7. 2.5.7 Replacing routing IDs
      8. 2.5.8 Dealing with message ordering
      9. 2.5.9 Dealing with circular build dependencies
    6. 2.6 Example CLs

Summary

We’re migrating Chrome’s IPCs to Mojo, our new IPC system. See the  chromium-dev post for the motivation behind this project.

How do I migrate my IPC to Mojo?

Don’t panic

If you get stuck reach out to chromium-mojo@ and we’ll help. :)

Read the Mojo documentation

The Mojo documentation and a getting started guide can be found on the Mojo  documentation page. There’s also a  Chrome IPC To Mojo IPC Cheat Sheet which is particularly useful for this conversion.
A simplified guide is available at  https://chromium.googlesource.com/chromium/src/+/master/docs/mojo_guide.md 

Claim your message(s)

We track the messages that still need to be converted in two spreadsheets:
  • Chrome IPC to Mojo migration - for non-web platform messages
  • Mojoifying Platform Features - for web platform messages
Please put your username next to the one(s) you’re converting to prevent duplication of effort. If you’re not very familiar with the messages you plan to convert, it might be worth asking the owner first.

Convert your Chrome IPCs to Mojo

Converting from Chrome IPC to Mojo is mostly straightforward, but still requires some thought. Here we outline the basic approach. See the  Chrome IPC To Mojo IPC Cheat Sheet for more details. See the "Common scenarios" section below for commonly occurring scenarios.
 
The below examples snippets were taken from  https://codereview.chromium.org/2024363002, where you can find a complete example. The code below removes some details from that CL for clearer presentation.

Convert the message definition

The old Chrome IPC system uses macros to generate IPC “stubs”. In Mojo we use an  IDL. For example, if you previously had this old-style IPC message defined in  mime_registry_messages.h:
 
 
IPC_SYNC_MESSAGE_CONTROL1_1(MimeRegistryMsg_GetMimeTypeFromExtension,   
                            base::FilePath::StringType /* extension */, 
                            std::string /* mime_type */)
 
You need to replace that with this .mojom file:
 
 
module blink.mojom;
 
 
interface MimeRegistry {
  [Sync]
  GetMimeTypeFromExtension(string extension) => (string mime_type);
};
 

Note that Mojo can group several messages together into an interface, which helps bring some structure to Chrome’s many IPCs.

Whitelist the IPC

We don''t want every process to be able to talk to every other process so we maintain a whitelist of which interfaces each process exports. You will need to add your interface to the right whitelist. If you don''t you''ll find that e.g. browser tests fail with an error saying that the connection to the interface was disallowed.
 
There are several of these files e.g.  chrome/browser/chrome_content_utility_manifest_overlay.json lists the interfaces exported by the utility process to the browser process. You will have to find the corresponding JSON file your process.

Fix build files and includes

Add a build target for your new .mojom file:
 
 
import("//mojo/public/tools/bindings/mojom.gni")
mojom("mime_registry_mojom") {
  sources = [
    "platform/mime_registry.mojom",
  ]
}
 
If your new .mojom file imports any other .mojom files, add their targets as  public_deps above.
 
Include the generated Mojo header in your C++ file instead of the old IPC header:
 
#include "third_party/WebKit/public/platform/mime_registry.mojom.h"

Register the interface implementation

Interface implementations (the "server" side of the interface) need to be registered before they can be called by a client. The registration happens in interface registries. Such registries can be accessed in the various processes (e.g. one is passed to  RenderProcessHostImpl::RegisterMojoInterfaces, in which you can register your service).
 
Here’s now you get the  InterfaceRegistry to register the interface implementation on, depending on where the message is sent from and if the old Chrome IPC message was routed or not:
 
   Renderer-initiated  Browser-initiated
 Routed  RenderFrameHost::GetInterfaceRegistry()  RenderFrame::GetInterfaceRegistry()
 Control  RenderProcessHostImpl::RegisterMojoInterfaces()  RenderThreadImpl::Init()
Example:
 
 
GetInterfaceRegistry()->AddInterface(
    base::Bind(&MimeRegistryImpl::Create),
    BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
 
(In the above example we want messages to be handled on a particular thread, so we pass an optional argument to indicate that.)
 
As you can see above, the interface implementation is created lazily when a connection is created through the call to  MimeRegistryImpl::Create. This is done to not unnecessarily create instances that might not be used. The ownership of the created instances is often tied to the lifetime of the connection, using a  StrongBinding:
 
 
 
// static
void MimeRegistryImpl::Create(blink::mojom::MimeRegistryRequest request) {
  mojo::MakeStrongBinding(
      base::MakeUnique< MimeRegistryImpl >(),
      std::move(request));
}
 
(MakeStrongBinding was introduced after the CL this example is based on, as a simplification.)
 
See  https://codereview.chromium.org/2024363002 for details.

Call the interface

Calling the interface requires creating a connection (which can be reused for multiple calls) and an interface proxy to use to call the implementation (the server):
 
 
// Only once:
blink::mojom::MimeRegistryPtr mime_registry;
RenderThread::Get()->GetRemoteInterfaces()->GetInterface(
    mojo::GetProxy(&mime_registry));
 
// Every time:
std::string mime_type;
if (!mime_registry->GetMimeTypeFromExtension(
    base::UTF16ToUTF8(base::string16(file_extension)), &mime_type)) {
  return string();  // Error handling.
}
 
Here’s how you get the  InterfaceProvider to lookup the interface implementation from, depending on where the message is sent from and if the old Chrome IPC message was routed or not:
 
   Browser-initiated  Renderer-initiated
 Routed  RenderFrameHost::GetRemoteInterfaces()  RenderFrame::GetRemoteInterfaces()
 Control  RenderProcessHost::GetRemoteInterfaces()  RenderThread::GetRemoteInterfaces()

Two approaches to migrating your IPC

Longer term we''d like Chrome to consist of more loosely connected services. This means that we''d like to avoid unnecessary ordering constraints between Mojo interfaces. This is why Mojo messages aren''t ordered between interfaces (unless you use associated interfaces) by default.
 
Because today there are many such ordering dependencies, you have two options when converting IPC to Mojo:
  • For things that could be easily made a standalone service (e.g. a JSON parser) use the above means of registering your interface.
  • For things that can''t be easily converted into standalone services, use the helpers described in "Converting BrowserMessageFilters" and "Converting WebContentsObservers" below. These provide stronger (i.e. the same as before) ordering guarantees for messages and lifetime guarantees for the service implementations.

Common scenarios

Converting BrowserMessageFilters

Example CL: https://codereview.chromium.org/2167513003 

Browser message filters are quite straightforward to convert:

  1. Have your message filter inherit from BrowserAssociatedInterface. You typically can just keep the old implementation with some minor tweaks e.g. you need to remove the On prefix from the message handler method names.
  2. Optionally override methods such as OnDestruct if you e.g. need your implementation to be deleted on a certain thread.

Converting WebContentsObservers

Example CL:  https://codereview.chromium.org/2310583002/
 
Use the  GetAssociatedInterfaceRegistry and  GetRemoteAssociatedInterfaces helpers to register your service and connect your client. Your messages will be ordered w.r.t. all old Chrome IPCs,  WebContentsObservermethods, and other interfaces using these helpers.

Lifetime issues

In the typical case we use StrongBinding for the server side. StrongBinding takes ownership of the interface implementation and will delete it when the connection to the client is closed. This means that the implementation will be deleted quite "late" i.e. some time before the message loop is. This in turn means that some care must be taken when referring to other objects in the implementation''s destructor, as they might have been deleted.

These issues can typically be avoided using the helpers described above.

Handling "late" messages

Messages can in principle arrive at any time before the connection is closed. In particular messages could arrive e.g. after the render process host has been deleted. This means that any state referred to in the interface method implementations must be either

  • owned
  • referred to through some form of weak pointer (so we can detect if it still exists), or
  • or looked up on each use e.g. using the process ID (which is not unlike using a weak pointer).

These issues can typically be avoided using the helpers described above.

Mocking in tests

Unlike Chrome IPC, Mojo IPCs can currently only be mocked on the server side, meaning that the test will actually send a message and your mock will make sure that it arrived. This introduces a few extra steps in your test.

First you need a mock of the interface. Your mock is probably be similar to your old Chome IPC test. Example:

class MockPageLoadMetrics : public mojom::PageLoadMetrics {
 public:
  MOCK_METHOD2(TimingUpdated,
               void(const PageLoadTiming&, const PageLoadMetadata&));
};
 
Second, to put it all together, you create a client connection connected to your mock:
 
 
class PageTimingMetricsSenderTest : public testing::Test {
 public:
  PageTimingMetricsSenderTest() : binding_(&mock_page_load_metrics_) {}
 
 protected:
  void SetUp() override {
    binding_.Bind(mojo::GetProxy(&page_load_metrics_));
  }
 
  base::MessageLoop loop_;  // 1
  mojom::PageLoadMetricsPtr page_load_metrics_;  // 2
  MockPageLoadMetrics mock_page_load_metrics_;  // 3
  mojo::Binding<mojom::PageLoadMetrics> binding_;
};
  1. You will not actually use the loop_ variable, but one need to exist and this declaration causes a global message loop to be created.
  2. This is the client side, which you will pass to the class under of test (which will need to e.g. have a test-only constructor that allows it to be injected).
  3. This is your mock (aka the server side).
Third, after a method that causes a message to be sent is called, we need to manually step the message loop to actually deliver the message (i.e. to your server-side mock):
 
 
TEST_F(PageTimingMetricsSenderTest, MyTest) {
  MyClient client(std::move(page_load_metrics_));
  client.SomeMethod();  // Calls TimingUpdated internally.  
  base::RunLoop().RunUntilIdle();  // Actually deliver message(s).
  EXPECT_CALL(mock_page_load_metrics_, TimingUpdated(_, _));
}

Replacing request/response messages pairs

A set of request/response messages
 
 
IPC_MESSAGE_ROUTED0(FooHostMsg_Frobinate)
IPC_MESSAGE_ROUTED0(FooMsg_DidFrobinate)
IPC_MESSAGE_ROUTED1(FooMsg_FrobinateError, std::string /* error */)
 
should be replaced by a method with a return value (with an optional error)
 
 
Interface Foo {
  Frobinate() => (bool success, string? error);
};
 
This doesn’t work if the reply isn’t always sent (in which case you need two interfaces, similar to the current Chrome IPC situation).

Replacing routing IDs

Chrome IPC uses routing IDs to dispatch messages specific to a particular RenderFrame(Host). When converting to Mojo, a whole connection may be specific to a particular frame. It is the responsibility of interface implementation to retain this knowledge. Example:
 
GetInterfaceRegistry->AddInterface(
    base::Bind(&CreateUsbDeviceManager, render_frame_host));
 
When sending messages, instead of passing the routing ID in the message, use the  InterfaceProvider on the  RenderFrame(Host) corresponding to the routing ID.

Dealing with message ordering

Mojo doesn’t provide a FIFO guarantee between messages sent on different message pipes. If you need cross-interface message ordering either
  • use the associated interface feature or
  • use the GetAssociatedInterfaceRegistry and GetRemoteAssociatedInterfaces helpers mentioned earlier.

Dealing with circular build dependencies

With Mojo’s typemap feature, which lets you have Mojo automatically communicate in terms of your own existing C++ types, there are situations where you might end up with a circular build dependency. Here’s an example:
 
 
Here we have a mojom target and the content component involved in a cycle. The mojom typemaps some type defined in  your_type.h and thus depends on content. Content contains code using the mojom and thus depends on it, hence the cycle.
 
The answer here is to pick one component that will link the mojom symbols and then re-export the symbols, for use in another component. Example ( CL):
 
mojom("mojo_bindings") {
  # ...
 
  # The chromium variant must be linked with content and use the same export
  # settings in component build because of the WebBluetoothDeviceId typemap
  # inside content.
  export_class_attribute = "CONTENT_EXPORT"
  export_define = "CONTENT_IMPLEMENTATION=1"
  export_header = "content/common/content_export.h"
  # Similarly, the blink variant must be linked with the platform component
  # since it uses types from it in its typemaps.
  export_class_attribute_blink = "BLINK_PLATFORM_EXPORT"
  export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1"
  export_header_blink = "third_party/WebKit/public/platform/WebCommon.h"
}

Example CLs

  • https://codereview.chromium.org/2024363002 - Convert MimeRegistry to a separate Mojo service.
  • https://codereview.chromium.org/1948303002 - Convert JSON parser to a separate Mojo service.
  • https://codereview.chromium.org/1844103004 - Convert the utility process image decoder into a Mojo service.
Some additional example CLs are listed in  this document.
 
 
 

android – IllegalArgumentException:org.chromium.components.minidump_uploader.CrashFileManager

android – IllegalArgumentException:org.chromium.components.minidump_uploader.CrashFileManager

在我的开发者控制台中,我偶尔会看到以下崩溃中的峰值:

java.lang.IllegalArgumentException
org.chromium.components.minidump_uploader.CrashFileManager.<init>

java.lang.RuntimeException: 
  at android.os.AsyncTask$3.done (AsyncTask.java:309)
  at java.util.concurrent.FutureTask.finishCompletion (FutureTask.java:354)
  at java.util.concurrent.FutureTask.setException (FutureTask.java:223)
  at java.util.concurrent.FutureTask.run (FutureTask.java:242)
  at android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:234)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1113)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:588)
  at java.lang.Thread.run (Thread.java:818)
Caused by: java.lang.IllegalArgumentException: 
  at org.chromium.components.minidump_uploader.CrashFileManager.<init> (CrashFileManager.java:43)
  at org.chromium.android_webview.AwbrowserProcess$1.doInBackground (AwbrowserProcess.java:7)
  at android.os.AsyncTask$2.call (AsyncTask.java:295)
  at java.util.concurrent.FutureTask.run (FutureTask.java:237)
  at android.os.AsyncTask$SerialExecutor$1.run (AsyncTask.java:234)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1113)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:588)
  at java.lang.Thread.run (Thread.java:818)

这超出了我的控制范围吗?上述崩溃报告中没有一个直接与我项目中的任何方法或类有关,所以我不知道在哪里查看.此外,我几周都没有看到这些错误,然后突然出现几个小时的峰值,然后又回到了无关:

enter image description here

尖峰与我认识的任何尖峰都不一致,例如新版本发布.这告诉我,我无能为力,尽管它很烦人,因为它似乎确实反映了Android Vitals的统计数据.此外,崩溃来自各种Android版本和设备.

编辑,自从我几天前提交此文件以来,此类别中没有进一步的崩溃报告:

enter image description here

EDIT2 …现在我看到更多这个错误的实例…我没有在这个时间框架内发布我的应用程序的任何更新,所以它没有什么我打破(它真的影响我的Android Vitals统计数据) :

enter image description here

EDIT3 …… aaargh!现在看一下(现在几个月没有发布应用程序的新版本……所以我没有做过):

enter image description here

解决方法:

我找到了解决这个问题的方法:
检查你的代码,可能是你在网络请求之前或之后擦除catch目录或文件并执行任何文件过程,如make a zip,提取zip或压缩,解压缩,这意味着你正在使用任何文件进程,这是临时捕获内存所以,那个时候你调用任何擦除捕获内存然后这个类型的问题创建.

在我的申请中.我使用下面的代码擦除捕获,所以,我得到这种类型的问题.

 private   void deleteCache(Context context) {
    try {
        File dir = context.getCacheDir();
        deleteDir(dir);
    } catch (Exception ignore) {
    }
}

private   boolean deleteDir(File dir) {
    if (dir != null && dir.isDirectory()) {
        String[] children = dir.list();
        for (String aChildren : children) {
            boolean success = deleteDir(new File(dir, aChildren));
            if (!success) {
                return false;
            }
        }
        return dir.delete();
    } else
        return dir != null && dir.isFile() && dir.delete();
}

App Programming Guide for iOS --Background Execution 1

App Programming Guide for iOS --Background Execution 1

Background Execution 1

When the user is not actively using your app,the system moves it to the background state. For many apps,the background state is just a brief stop on the way to the app being suspended. Suspending apps is a way of improving battery life it also allows the system to deVote important system resources to the new foreground app that has drawn the user’s attention.
当用户不使用您的应用程序时,系统会将其移动到后台状态。对于许多应用程序来说,后台状态只是在被暂停的应用程序的途中的一个短暂的停留。挂起应用程序是提高电池续航时间的一种方式,它还允许系统将重要的系统资源投入到引起用户注意的新的前台应用程序上。

Most apps can move to the suspended state easily enough but there are also legitimate reasons for apps to continue running in the background. A hiking app might want to track the user’s position over time so that it can display that course overlaid on top of a hiking map. An audio app might need to continue playing music over the lock screen. Other apps might want to download content in the background so that it can minimize the delay in presenting that content to the user. When you find it necessary to keep your app running in the background,iOS helps you do so efficiently and without draining system resources or the user’s battery. The techniques offered by iOS fall into three categories:
大多数应用程序都可以很容易地进入暂停(挂起)状态,但也有正当的理由让应用程序在后台继续运行。一个徒步旅行应用程序可能想要随时间的推移跟踪用户的位置,以便它可以显示该路线覆盖在徒步旅行地图之上。音频应用程序可能需要继续已经锁定的屏幕上播放音乐。其他应用程序可能希望在后台下载内容,这样就可以最大限度地减少向用户展示内容的延迟。当你发现有必要让你的应用程序在后台运行时,iOS可以帮助你高效地运行,而且不需要消耗系统资源或用户的电池。iOS提供的技术可分为三类:

  • Apps that start a short task in the foreground can ask for time to finish that task when the app moves to the background.
    在前台启动一个短任务的应用程序可以在应用程序移动到后台时请求时间来完成该任务。(在后台请求短暂时间来完成任务)
  • Apps that initiate downloads in the foreground can hand off management of those downloads to the system,thereby allowing the app to be suspended or terminated while the download continues.
    在前台启动下载的应用程序可以将这些下载的管理交给系统,从而允许应用程序在下载过程中被暂停或终止。
  • Apps that need to run in the background to support specific types of tasks can declare their support for one or more background execution modes.
    需要在后台运行以支持特定类型任务的应用程序可以声明它们对一个或多个“后台执行模式”的支持。

Always try to avoid doing any background work unless doing so improves the overall user experience. An app might move to the background because the user launched a different app or because the user locked the device and is not using it right Now. In both situations,the user is signaling that your app does not need to be doing any meaningful work right Now. Continuing to run in such conditions will only drain the device’s battery and might lead the user to force quit your app altogether. So be mindful about the work you do in the background and avoid it when you can.
除非这样做可以改善用户的整体体验,否则一定要尽量避免做任何后台任务。一个应用程序可能会移动到后台,因为用户启动了另一个应用程序,或者因为用户锁定了设备,并且现在没有使用它。在这两种情况下,用户都表示您的应用程序现在不需要做任何有意义的工作。继续在这种情况下运行只会耗尽设备的电池,并可能导致用户强制退出应用程序。所以,要注意你在后台做的工作,并在可能的情况下避免它。

Executing Finite-Length Tasks 执行有限时长的任务

Apps moving to the background are expected to put themselves into a quiescent state as quickly as possible so that they can be suspended by the system. If your app is in the middle of a task and needs a little extra time to complete that task,it can call the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method of the UIApplication object to request some additional execution time. Calling either of these methods delays the suspension of your app temporarily,giving it a little extra time to finish its work. Upon completion of that work,your app must call the endBackgroundTask: method to let the system kNow that it is finished and can be suspended.
被移动到后台的应用程序将尽快进入quiescent状态,以便系统可以把它们挂起,如果你的应用程序正在完成任务的途中(middle of a task) 并且需要额外的时间来完成整个任务,你可以调用 beginBackgroundTaskWithName:expirationHandler: 或者是beginBackgroundTaskWithExpirationHandler: 这两个方法向UIApplication申请更多的运行时间, 调用这两种方法都会暂时推迟挂起应用程序,从而给它额外的时间来完成它的工作。完成这项工作后,应用程序必须调用endBacklandTask:方法,让系统知道它已经完成并可以挂起。

Each call to the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method generates a unique token to associate with the corresponding task. When your app completes a task,it must call the endBackgroundTask: method with the corresponding token to let the system kNow that the task is complete. Failure to call the endBackgroundTask: method for a background task will result in the termination of your app. If you provided an expiration handler when starting the task,the system calls that handler and gives you one last chance to end the task and avoid termination.
对beginBackgroundTaskWithName:expirationHandler: 或者是beginBackgroundTaskWithExpirationHandler: 这两个方法的调用都会产生与当前任务相一致的一个唯一token,当应用程序完成任务时,它必须使用相对应的token来调用endBacklandTask:方法,让系统知道任务已经完成。如果执行后台任务调用endBacklandTask:方法失败,将导致应用程序的终止。如果在启动任务时提供了过期处理程序,则系统将调用该处理程序,并给您最后一次结束任务和避免终止的机会。

You do not need to wait until your app moves to the background to designate background tasks. A more useful design is to call the beginBackgroundTaskWithName:expirationHandler: or beginBackgroundTaskWithExpirationHandler: method before starting a task and call the endBackgroundTask: method as soon as you finish. You can even follow this pattern while your app is executing in the foreground.
您不需要等到你的应用程序移动到后台指定background任务,在任务开始前调用beginBackgroundTaskWithName:expirationHandler: 或者是beginBackgroundTaskWithExpirationHandler:方法,在任务完成后调用endBackgroundTask方法是一个有用的设计; 你甚至可以在应用程序在前台执行时遵循此模式。

Listing 3-1 shows how to start a long-running task when your app transitions to the background. In this example,the request to start a background task includes an expiration handler just in case the task takes too long. The task itself is then submitted to a dispatch queue for asynchronous execution so that the applicationDidEnterBackground: method can return normally. The use of blocks simplifies the code needed to maintain references to any important variables,such as the background task identifier. The bgTask variable is a member variable of the class that stores a pointer to the current background task identifier and is initialized prior to its use in this method.
清单3-1展示了如何在应用程序切换到后台时启动一个长期运行的任务。在本例中,启动后台任务的请求包括一个过期处理程序,以防任务花费太长时间。然后,将任务异步提交到调度队列中,以便applicationDidEnterBackplace:方法能够正常返回。块的使用简化了对任何重要变量(例如后台任务标识符)的引用所需的代码的维护。bgTask变量是类的成员变量,它存储指向当前后台任务标识符的指针,并在使用它之前进行初始化。

Listing 3-1 Strarting a background task at quit time

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    bgTask = [application beginBackgroundTaskWithName:@"MyTask" expirationHandler:^{
        // Clean up any unfinished task business by marking where you
        // stopped or ending the task outright.
        [application endBackgroundTask:bgTask];
        bgTask = uibackgroundtaskInvalid;
    }];
// Start the long-running task and return immediately.
<a href="https://www.jb51.cc/tag/dis/" target="_blank">dis</a>patch_async(<a href="https://www.jb51.cc/tag/dis/" target="_blank">dis</a>patch_get_global_queue(<a href="https://www.jb51.cc/tag/dis/" target="_blank">dis</a>PATCH_QUEUE_PRIORITY_DEFAULT,0),^{

    // Do the work associated with the task,preferably in chunks.

    [application endBackgroundTask:bgTask];
    bgTask = <a href="https://www.jb51.cc/tag/uibackgroundtask/" target="_blank">uibackgroundtask</a>Invalid;
});

}

Note: Always provide an expiration handler when starting a task,but if you want to kNow how much time your app has left to run,get the value of the backgroundTimeRemaining property of UIApplication.
注意:在启动任务时,总是提供一个过期处理程序,但是如果您想知道您的应用程序还有多长时间可以运行,请获取UIApplication的backgroundTimeRemaining属性值。

In your own expiration handlers,you can include additional code needed to close out your task. However,any code you include must not take too long to execute because,by the time your expiration handler is called,your app is already very close to its time limit. For this reason,perform only minimal cleanup of your state information and end the task.
在您自己的过期处理程序中,可以包含关闭长任务所需的其他代码。但是,您包含的任何代码都不能花费太长的时间来执行,因为在调用过期处理程序时,您的应用程序已经非常接近其时间限制。因此,只执行少量清除状态信息的代码并结束任务。

Downloading Content in the Background 后台下载

When downloading files,apps should use an NSURLSession object to start the downloads so that the system can take control of the download process in case the app is suspended or terminated. When you configure an NSURLSession object for background transfers,the system manages those transfers in a separate process and reports status back to your app in the usual way. If your app is terminated while transfers are ongoing,the system continues the transfers in the background and launches your app (as appropriate) when the transfers finish or when one or more tasks need your app’s attention.
在下载文件时,应用程序应该使用NSURLSession对象启动下载,以便系统能够控制下载过程,以防应用程序被暂停或终止。当您为后台传输( background transfers)配置NSURLSession对象时,系统将以单独的进程管理这些传输,并以通常的方式向应用程序报告状态。如果您的应用程序在传输过程中被终止,系统将继续在后台进行传输,并在传输完成时或当一个或多个任务需要应用程序处理时启动应用程序(as appropriate)。

To support background transfers,you must configure your NSURLSession object appropriately. To configure the session,you must first create a NSURLSessionConfiguration object and set several properties to appropriate values. You then pass that configuration object to the appropriate initialization method of NSURLSession when creating your session.
要支持后台传输,必须适当地配置NSURLSession对象。要配置session(会话),您必须首先创建一个NSURLSessionConfiguration对象,并将几个属性设置为适当的值。然后,在创建session(会话)时,将该配置对象传递给NSURLSession的适当初始化方法。

The process for creating a configuration object that supports background downloads is as follows:
创建支持后台下载的配置对象的过程如下:

  1. Create the configuration object using the backgroundSessionConfigurationWithIdentifier: method of NSURLSessionConfiguration.
    利用 NSURLSessionConfiguration 对象的 backgroundSessionConfigurationWithIdentifier: method 方法创建sestion configuration
  2. Set the value of the configuration object’s sessionSendsLaunchEvents property to YES.
    将Configuration对象的sessionSendsLaunchEvents属性的值设置为yes。
  3. if your app starts transfers while it is in the foreground,it is recommend that you also set the discretionary property of the configuration object to YES.
    如果应用程序在前台启动传输,建议您也将配置对象的discretionary属性设置为YES。
  4. Configure any other properties of the configuration object as appropriate.
    酌情配置配置对象的任何其他属性。
  5. Use the configuration object to create your NSURLSession object.
    使用Configuration对象创建NSURLSession对象。

Once configured,your NSURLSession object seamlessly hands off upload and download tasks to the system at appropriate times. If tasks finish while your app is still running (either in the foreground or the background),the session object notifies its delegate in the usual way. If tasks have not yet finished and the system terminates your app,the system automatically continues managing the tasks in the background. If the user terminates your app,the system cancels any pending tasks.
配置完后,NSURLSession对象将在适当的时候无缝地将上传和下载任务传递到系统。如果任务在应用程序仍在运行时完成(无论是在前台还是在后台),session对象会按照通常的方式通知其代理。如果任务尚未完成并且系统终止您的应用程序,系统将自动继续管理后台的任务。如果用户终止您的应用程序,系统将取消任何挂起的任务。

When all of the tasks associated with a background session are complete,the system relaunches a terminated app (assuming that the sessionSendsLaunchEvents property was set to YES and that the user did not force quit the app) and calls the app delegate’s application:handleEventsForBackgroundURLSession:completionHandler: method. (The system may also relaunch the app to handle authentication challenges or other task-related events that require your app’s attention.) In your implementation of that delegate method,use the provided identifier to create a new NSURLSessionConfiguration and NSURLSession object with the same configuration as before. The system reconnects your new session object to the prevIoUs tasks and reports their status to the session object’s delegate.
当与后台会话(background session)相关的所有任务都完成后,系统将重新启动终止的应用程序(假设sessionSendsLaunchEvents 属性值为YES 并且用户没有强制退出你的app)并且调用AppDelegate的application:handleEventsForBackgroundURLSession:completionHandler:方法。(系统还可能重新启动应用程序,以处理身份验证(authentication challenges)或其他需要应用程序关注的和任务相关事件) 在该委托方法的实现中,使用提供的标识符创建一个新的NSURLSessionConfiguration和NSURLSession对象,其配置与前面相同。系统将新会话对象重新连接到以前的任务,并将其状态报告给会话对象的委托。

Implementing Long-Running Tasks 实现长时间运行的任务

For tasks that require more execution time to implement,you must request specific permissions to run them in the background without their being suspended. In iOS,only specific app types are allowed to run in the background:
对于需要更多执行时间来实现的任务,您必须请求特定的权限才能在后台运行它们,而不会挂起它们。在IOS中,只允许特定的应用程序类型在后台运行:

  • Apps that play audible content to the user while in the background,such as a music player app
    在后台播放可听内容的应用程序,如音乐播放器应用程序。
  • Apps that record audio content while in the background
    在后台录制音频内容的应用程序。
  • Apps that keep users informed of their location at all times,such as a navigation app
    让用户随时知道自己所在位置的应用程序,如导航应用程序。
  • Apps that support Voice over Internet Protocol (VoIP)
    支持互联网语音协议(VoIP)的应用程序。
  • Apps that need to download and process new content regularly
    需要定期下载和处理新内容的应用程序。
  • Apps that receive regular updates from external accessories(外部配件:也许和硬件相关 比如蓝牙)
    从外部附件(可以理解为其他硬件)接收定期更新的应用程序。

Apps that implement these services must declare the services they support and use system frameworks to implement the relevant aspects of those services. Declaring the services lets the system kNow which services you use,but in some cases it is the system frameworks that actually prevent your application from being suspended.
实现这些服务的应用程序必须声明它们支持的服务,这些服务使用系统框架来实现相关方面的功能。声明服务可以让系统知道您使用的是哪些服务,但在某些情况下,实际上是系统框架阻止应用程序被挂起。

Declaring Your App’s Supported Background Tasks 声明App支持的后台任务

Support for some types of background execution must be declared in advance by the app that uses them. In Xcode 5 and later,you declare the background modes your app supports from the Capabilities tab of your project settings. Enabling the Background Modes option adds the uibackgroundmodes key to your app’s Info.plist file. Selecting one or more checkBoxes adds the corresponding background mode values to that key. Table 3-1 lists the background modes you can specify and the values that Xcode assigns to the uibackgroundmodes key in your app’s Info.plist file.
对某些支持后台运行的App必须在使用它们之前提前声明。在Xcode 5和更高版本中,您可以在项目设置的Capability选项卡中声明应用程序支持的后台模式。启用后台模式选项会将uibackgroundmodes key添加到应用程序的Info.plist文件中。选择一个或多个复选框将相应的背景模式值添加到该键(uibackgroundmodes key)。表3-1列出了可以指定的uibackgroundmodes,以及Xcode在应用程序的Info.plist文件中分配给uibackgroundmodes键的值(Xcode 中设置Capability 选项卡 并选中相应的后台模式 ,这些设置也会在info.plist 文件中 )。

Table 3-1 Background modes for apps

Aaron Swartz

Each of the preceding modes lets the system kNow that your app should be woken up or launched at appropriate times to respond to relevant events. For example,an app that begins playing music and then moves to the background still needs execution time to fill the audio output buffers. Enabling the Audio mode tells the system frameworks that they should continue to make the necessary callbacks to the app at appropriate intervals. If the app does not select this mode,any audio being played or recorded by the app stops when the app moves to the background.
上述每一种模式都让系统知道,您的应用程序应该在适当的时候被唤醒或启动,以响应相关事件。例如,一个开始播放音乐然后移动到后台的应用程序仍然需要执行的时间来填充音频输出缓冲区。启用音频模式会告诉系统框架,它们应该继续在适当的时间间隔内对应用程序进行必要的回调。如果应用程序不选择此模式,则当应用程序移动到后台时,应用程序播放或录制的任何音频都会停止。

Tracking the User’s Location 跟随用户位置

There are several ways to track the user’s location in the background,most of which do not actually require your app to run continuously in the background:
有几种方法可以在后台跟踪用户的位置,其中大多数实际上不需要您的应用程序在后台连续运行:

  • The significant-change location service (Recommended)
    显著变化的位置服务(推荐)。
  • Foreground-only location services
    前台定位服务。
  • Background location services
    后台定位服务。

The significant-change location service is highly recommended for apps that do not need high-precision location data. With this service,location updates are generated only when the user’s location changes significantly; thus,it is ideal for social apps or apps that provide the user with noncritical,location-relevant information. If the app is suspended when an update occurs,the system wakes it up in the background to handle the update. If the app starts this service and is then terminated,the system relaunches the app automatically when a new location becomes available. This service is available in iOS 4 and later,and it is available only on devices that contain a cellular radio.
对于不需要高精度定位数据的应用程序,强烈建议使用significant-change位置服务。有了这项服务,只有当用户的位置发生显著变化时,才会产生位置更新;因此,它非常适合于为用户提供非关键的位置相关信息的应用程序或者社交应用程序。如果应用程序在更新时被挂起,系统会在后台唤醒它来处理更新。如果应用程序启动此服务,然后被终止(、、、、被终止、、、),系统将在新位置可用时自动重新启动该应用程序。此服务在IOS 4及更高版本中可用,并且仅在包含蜂窝无线电的设备上可用。

The foreground-only and background location services both use the standard location Core Location service to retrieve location data. The only difference is that the foreground-only location services stop delivering updates if the app is ever suspended,which is likely to happen if the app does not support other background services or tasks. Foreground-only location services are intended for apps that only need location data while they are in the foreground.
前台定位服务和后台定位服务都使用标准的LocationCore定位服务来检索位置数据。唯一不同的是,只有前台位置服务停止提供更新,如果应用程序被暂停,这很可能会发生,如果应用程序不支持其他后台服务或任务。前台定位服务的目的是仅为在前台运行的应用程序提供位置数据。

You enable location support from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the location value in your app’s Info.plist file.) Enabling this mode does not prevent the system from suspending the app,but it does tell the system that it should wake up the app whenever there is new location data to deliver. Thus,this key effectively lets the app run in the background to process location updates whenever they occur.
您可以从Xcode项目的Capability选项卡的后台模式部分启用位置支持。(还可以通过在应用程序的Info.plist文件中包含带有Location值的uibackgroundmodes key来启用此支持)。启用此模式并不能阻止系统挂起应用程序,但它确实告诉系统,只要有新的位置数据要传递,系统就应该唤醒应用程序。因此,这个键有效地让应用程序在后台运行,以便在发生位置更新时处理它们。

Important: You are encouraged to use the standard services sparingly(少量的) or use the significant location change service instead. Location services require the active use of an iOS device’s onboard radio hardware. Running this hardware continuously can consume a significant amount of power. If your app does not need to provide precise and continuous location information to the user,it is best to minimize the use of location services.

For information about how to use each of the different location services in your app,see Location and Maps Programming Guide.
重要提示:建议您尽量少使用标准服务,或者使用significant location服务。定位服务需要激活IOS设备板载无线硬件。连续运行此硬件会消耗大量的电能。如果您的应用程序不需要向用户提供精确和连续的位置信息,则最好尽量减少位置服务的使用。
有关如何使用应用程序中的不同位置服务的信息,请参阅位 Location and Maps Programming Guide.

Playing and Recording Background Audio 后台播放和录制音频

An app that plays or records audio continuously (even while the app is running in the background) can register to perform those tasks in the background. You enable audio support from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the audio value in your app’s Info.plist file.) Apps that play audio content in the background must play audible content and not silence.
一个连续播放或记录音频的应用程序(即使在后台运行)可以在后台注册以执行这些任务。您可以从Xcode项目中的“Capabilities”选项卡的后台模式部分启用音频支持 (还可以通过在应用程序的Info.plist文件中包含带有音频值的UIBackoundModes键来启用这种支持)在后台播放音频内容的应用程序必须播放可听得到的声音,而不是没有声音的。

Typical examples of background audio apps include:
后台音频应用程序的典型示例包括:

  • Music player apps
    音乐播放器应用程序
  • Audio recording apps
    录音应用程序
  • Apps that support audio or video playback over AirPlay
    支持在AirPlay上播放音频或视频的应用程序
  • VoIP apps
    VoIP应用程序

When the uibackgroundmodes key contains the audio value,the system’s media frameworks automatically prevent the corresponding app from being suspended when it moves to the background. As long as it is playing audio or video content or recording audio content,the app continues to run in the background. However,if recording or playback stops,the system suspends the app.
当uibackgroundmodes键包含音频值时,系统的媒体框架会自动防止相应的应用程序在移动到后台时被挂起。只要播放音频或视频内容或录制音频内容,应用程序就会继续在后台运行。但是,如果停止录制或播放,系统将暂停应用程序。

You can use any of the system audio frameworks to work with background audio content,and the process for using those frameworks is unchanged. (For video playback over AirPlay,you can use the Media Player or AV Foundation framework to present your video.) Because your app is not suspended while playing media files,callbacks operate normally while your app is in the background. In your callbacks,though,you should do only the work necessary to provide data for playback. For example,a streaming audio app would need to download the music stream data from its server and push the current audio samples out for playback. Apps should not perform any extraneous tasks that are unrelated to playback.
您可以使用任何系统音频框架来处理后台音频内容,并且这些框架的使用过程没有改变(导入框架的流程没有改变)。(对于AirPlay上的视频播放,您可以使用Media Player或AV Foundation框架来显示视频)因为你的应用程序在播放媒体文件时不会被挂起,所以当你的应用程序处于后台时,回调就会正常运行。但是,在回调中,您应该只做为播放提供所需数据的工作。例如,流音频应用程序需要从其服务器下载音乐流数据,并将当前的音频采样数据推送出去播放。应用程序不应该执行与播放无关的任何任务。

Because more than one app may support audio,the system determines which app is allowed to play or record audio at any given time. The foreground app always has priority for audio operations. It is possible for more than one background app to be allowed to play audio and such determinations are based on the configuration of each app’s audio session objects. You should always configure your app’s audio session object appropriately and work carefully with the system frameworks to handle interruptions and other types of audio-related notifications. For information on how to configure audio session objects for background execution,see Audio Session Programming Guide.
因为不止一个应用程序可以支持音频播放,所以系统决定哪个应用程序可以在任何给定时间播放或录制音频。前台应用程序始终具有音频操作的优先级。允许多个后台应用程序播放音频是可能的,并且这样的决定是基于每个应用程序的音频会话对象的配置。您应该始终适当地配置应用程序的音频会话对象,并与系统框架一起小心处理中断和其他类型的音频相关通知。有关如何配置后台执行音频会话对象的信息,请参阅Audio Session Programming Guide。

Implementing a VoIP App 实现VoIP应用程序

A Voice over Internet Protocol (VoIP) app allows the user to make phone calls using an Internet connection instead of the device’s cellular service. Such an app needs to maintain a persistent network connection to its associated service so that it can receive incoming calls and other relevant data. Rather than keep VoIP apps awake all the time,the system allows them to be suspended and provides facilities for monitoring their sockets for them. When incoming traffic is detected,the system wakes up the VoIP app and returns control of its sockets to it.
互联网语音协议(VoiceoverInternetProtocol,VoIP)应用程序允许用户使用Internet连接而不是设备(手机)的蜂窝服务拨打电话。这样的应用程序需要与其相关服务的保持持久网络连接,以便能够接收来电和其他相关数据。与其让VoIP应用程序始终保持awake,不如让它们suspended,并为它们提供监视套接字的设施。当检测到传入流量时,系统会唤醒VoIP应用程序并将其套接字的控制权返回给它。

To configure a VoIP app,you must do the following:
要配置VoIP应用程序,必须执行以下操作:

  1. Enable support for Voice over IP from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the voip value in your app’s Info.plist file.)
    从Xcode项目中的Capability选项卡的背景模式部分启用对IP语音的支持。(还可以通过在应用程序的Info.plist文件中包含带有VoIP值的UIBackoundModes键来启用这种支持)。
  2. Configure one of the app’s sockets for VoIP usage.
    为VoIP的使用配置应用程序的一个套接字。
  3. Before moving to the background,call the setKeepAliveTimeout:handler: method to install a handler to be executed periodically. Your app can use this handler to maintain its service connection.
    在移到后台之前,调用setKeepAliveTimeout:Handler:方法来安装要定期执行的处理程序。您的应用程序可以使用此处理程序来维护与其服务连接。
  4. Configure your audio session to handle transitions to and from active use.
    配置您的音频会话以处理活动与非活动状态之间的转换(翻译貌似有问题)

Including the voip value in the uibackgroundmodes key lets the system kNow that it should allow the app to run in the background as needed to manage its network sockets. An app with this key is also relaunched in the background immediately after system boot to ensure that the VoIP services are always available.
将VoIP值包含在uibackgroundmodes键中让系统知道,它应该允许应用程序在后台运行,以管理其网络套接字。在系统启动后,还会立即在后台重新启动具有此键的应用程序,以确保VoIP服务始终可用。

Most VoIP apps also need to be configured as background audio apps to deliver audio while in the background. Therefore,you should include both the audio and voip values to the uibackgroundmodes key. If you do not do this,your app cannot play or record audio while it is in the background. For more information about the uibackgroundmodes key,see information Property List Key Reference.
大多数VoIP应用程序也需要配置为后台音频应用程序,以便在后台提供音频。因此,您应该将音频和VoIP值都包含到uibackgroundmodes键中。如果你不这样做,你的应用程序不能在后台播放或录制音频。有关UIBackoundModes键的更多信息,请参见属性列表。

For specific information about the steps you must take to implement a VoIP app,see Tips for Developing a VoIP App.
有关实现VoIP应用程序必须采取的步骤的具体信息,请参阅开发VoIP应用程序的提示。

Fetching Small Amounts of Content Opportunistically (适时获取少量的内容)

Apps that need to check for new content periodically can ask the system to wake them up so that they can initiate a fetch operation for that content. To support this mode,enable the Background fetch option from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the fetch value in your app’s Info.plist file.) Enabling this mode is not a guarantee that the system will give your app any time to perform background fetches. The system must balance your app’s need to fetch content with the needs of other apps and the system itself. After assessing(评估) that information,the system gives time to apps when there are good opportunities to do so.
需要定期检查新内容的应用程序可以要求系统唤醒它们,以便它们能够为该内容启动一个获取操作。若要支持此模式,请从Xcode项目中“Capabilities”选项卡的后台模式部分启用Background fetch选项。(还可以通过在应用程序的Info.plist文件中包含带有FETCH值的UIBackoundModes键来启用这种支持)启用此模式并不能保证系统会给您的应用程序任何时间执行后台获取任务。系统必须平衡您的应用程序获取内容的需求与其他应用程序和系统本身的需求。在评估了这些信息之后,当有很好的机会时,系统会给应用程序时间去执行获取任务。

When a good opportunity arises,the system wakes or launches your app into the background and calls the app delegate’s application:performFetchWithCompletionHandler: method. Use that method to check for new content and initiate a download operation if content is available. As soon as you finish downloading the new content,you must execute the provided completion handler block,passing a result that indicates whether content was available. Executing this block tells the system that it can move your app back to the suspended state and evaluate its power usage. Apps that download small amounts of content quickly,and accurately reflect when they had content available to download,are more likely to receive execution time in the future than apps that take a long time to download their content or that claim(声称) content was available but then do not download anything.
当机会到达时,系统会唤醒或者launch你的应用进入到后台并调用application:performFetchWithCompletionHandler:方法,使用这个方法检查新的内容并且初始化一个下载操作在内容可获得的情况下;当你完成新的下载内容,你必须执行之前提供的handler block。 a result 指示内容是否可获得.执行这个块会告诉系统,它可以将你的应用程序移回到挂起的状态,并评估它的电源使用情况。如果应用程序能快速下载少量内容,并准确地反映出它们何时有内容可供下载,那么相比于那些需要很长时间下载内容或声称可以下载内容但随后什么都不下载的应用程序,它们在未来更有可能获得执行时间。

When downloading any content,it is recommended that you use the NSURLSession class to initiate and manage your downloads. For information about how to use this class to manage upload and download tasks,see URL Session Programming Guide.
在下载任何内容时,建议您使用NSURLSession类来启动和管理您的下载。有关如何使用该类管理上传和下载任务的信息,请参阅URL Session Programming Guide。

Using Push Notifications to Initiate a Download 使用推送通知启动下载

If your server sends push notifications to a user’s device when new content is available for your app,you can ask the system to run your app in the background so that it can begin downloading the new content right away. The intent of this background mode is to minimize the amount of time that elapses between when a user sees a push notification and when your app is able to able to display the associated content. Apps are typically woken up at roughly the same time that the user sees the notification but that still gives you more time than you might have otherwise.
如果您的服务器将推送通知发送给用户的设备,当您的应用程序有可用的新内容时,您可以要求系统在后台运行您的应用程序,以便它能够立即开始下载新内容。这种后台模式的意图是最小化用户看到推送通知时以及应用程序能够显示相关内容时之间所花时间是最小的。应用程序通常会在用户看到通知的同时被唤醒,但仍然会给您更多的时间。

To support this background mode,enable the Remote notifications option from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the remote-notification value in your app’s Info.plist file.)
为了支持此后台模式,请从你项目中的“Capabilities”选项卡的后台模式部分启用(Remote notifications)远程通知选项。(您还可以通过在应用程序的Info.plist文件中包含具有远程通知值remote-notification value与uibackgroundmodes key 以此来启用此支持)

For a push notification to trigger a download operation,the notification’s payload must include the content-available key with its value set to 1. When that key is present,the system wakes the app in the background (or launches it into the background) and calls the app delegate’s application:didReceiveRemoteNotification:fetchCompletionHandler: method. Your implementation of that method should download the relevant content and integrate it into your app.
为了远程通知触发下载操作,通知的有效负载必须包括可获得的key,其值设置为1。当这个key出现的时候,系统在后台唤醒app(或者lanuch it into background) 并且 调用app delegate 的idReceiveRemoteNotification:fetchCompletionHandler:的方法,此方法的实现应该下载相关内容并将其集成到您的应用程序中。

When downloading any content,see URL Session Programming Guide.
在下载任何内容时,建议您使用NSURLSession类来启动和管理您的下载。有关如何使用该类管理上传和下载任务的信息,请参阅URL Session Programming Guide。

Downloading Newsstand Content in the Background 后台下载报摊内容

A Newsstand app that downloads new magazine or newspaper issues can register to perform those downloads in the background. You enable support for newsstand downloads from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the newsstand-content value in your app’s Info.plist file.) When this key is present,the system launches your app,if it is not already running,so that it can initiate the downloading of the new issue.
下载新杂志或发行的报纸应用程序可以注册,以便在后台执行这些下载。你可以在Xcode项目中的“Capabilities”选项卡的Background modes部分开启对newsstand downloads的支持。(还可以通过在应用程序的Info.plist文件中包含带有newsstand-content value的UIBackoundModes键来启用这种支持)当该key出现时,如果app尚未运行,系统启动您的应用程序以便它可以开始下载新的发布内容。

When you use the Newsstand Kit framework to initiate a download,the system handles the download process for your app. The system continues to download the file even if your app is suspended or terminated. When the download operation is complete,the system transfers the file to your app sandBox and notifies your app. If the app is not running,this notification wakes it up and gives it a chance to process the newly downloaded file. If there are errors during the download process,your app is similarly woken up to handle them.
当您使用Newsstand Kit框架启动下载时,系统将处理应用程序的下载过程。系统继续下载文件,即使您的应用程序被挂起或终止。下载操作完成后,系统将文件传输到应用程序沙箱并通知应用程序。如果应用程序没有运行,这个通知会唤醒它并给它一个处理新的下载的文件的机会。如果在下载过程中出现错误,您的应用程序也会被唤醒来处理这些错误。

For information about how to download content using the Newsstand Kit framework,see Newsstand Kit Framework Reference.
有关如何使用“Newsstand Kit”框架下载内容的信息,请参阅newsstand Kit Framework Reference。

Communicating with an External Accessory 与外部配件通信

Apps that work with external accessories can ask to be woken up if the accessory delivers an update when the app is suspended. This support is important for some types of accessories that deliver data at regular intervals,such as heart-rate monitors. You enable support for external accessory communication from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the external-accessory value in your app’s Info.plist file.) When you enable this mode,the external accessory framework does not close active sessions with accessories. (In iOS 4 and earlier,these sessions are closed automatically when the app is suspended.) When new data arrives from the accessory,the framework wakes your app so that it can process that data. The system also wakes the app to process accessory connection and disconnection notifications.
当app挂起的时候,如果与app协同工作的外部配件传递更新信息过来,那么app可以要求被唤醒,这种支持对于某些定期提供数据的配件非常重要,例如心率监视器。您可以从Xcode项目中的“Capabilities”选项卡的Background modes部分启用对external accessory communication的支持。(还可以通过在应用程序的Info.plist文件中包含带有external-accessory value的UIBackoundModes键来启用这种支持) 启用此模式时,外部配件框架不会关闭与配件的活动会话。(在iOS 4和更早版本中,当应用程序被暂停时,这些会话会自动关闭)当新数据从配件到达时,框架会唤醒应用程序,以便它能够处理这些数据。系统还会唤醒应用程序来处理配件连接和断开时的通知。

Any app that supports the background processing of accessory updates must follow a few basic guidelines:
任何支持后台处理配件更新的应用程序都必须遵循以下几个基本准则:

  • Apps must provide an interface that allows the user to start and stop the delivery of accessory update events. That interface should then open or close the accessory session as appropriate.
    应用程序必须提供一个接口,允许用户启动和停止交付配件更新事件。然后,该接口应酌情打开或关闭配件会话。
  • Upon being woken up,the app has around 10 seconds to process the data. Ideally,it should process the data as fast as possible and allow itself to be suspended again. However,if more time is needed,the app can use the beginBackgroundTaskWithExpirationHandler: method to request additional time; it should do so only when absolutely necessary,though.
    一旦app被唤醒,应用程序就有大约10秒的时间来处理数据。理想情况下,它应该尽可能快地处理数据,并允许自己(app)再次被挂起。但是,如果需要更多的时间,应用程序可以使用 beginBackgroundTaskWithExpirationHandler:方法来请求额外的时间;不过,只有在绝对必要的时候才能这样做。

Communicating with a Bluetooth Accessory 与蓝牙配件会话

Apps that work with Bluetooth peripherals can ask to be woken up if the peripheral delivers an update when the app is suspended. This support is important for Bluetooth-LE accessories that deliver data at regular intervals,such as a Bluetooth heart rate belt. You enable support for using bluetooth accessories from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the bluetooth-central value in your app’s Info.plist file.) When you enable this mode,the Core Bluetooth framework keeps open any active sessions for the corresponding peripheral. In addition,new data arriving from the peripheral causes the system to wake up the app so that it can process the data. The system also wakes up the app to process accessory connection and disconnection notifications.
当应用程序挂起时,如果与app协同工作的外围设备提供更新,则使应用程序可以要求被唤醒。这种支持对于定期传输数据的蓝牙配件非常重要,例如蓝牙心率带。您可以在Xcode的“Capabilities”选项卡中开启bluetooth accessories 后台模式(还可以通过在应用程序的Info.plist文件中包含带有bluetooth-central value的UIBackoundModes键来启用这种支持)启用此模式时,Core Bluetooth框架将与相应外围设备的任何活动会话保持打开的状态。此外,新的数据从外设到达时,使系统唤醒应用程序,以便它可以处理数据。系统还唤醒应用程序处理配件连接和断开时的通知。

In iOS 6,an app can also operate in peripheral mode with Bluetooth accessories. To act as a Bluetooth accessory,you must enable support for that mode from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the uibackgroundmodes key with the bluetooth-peripheral value in your app’s Info.plist file.) Enabling this mode lets the Core Bluetooth framework wake the app up briefly in the background so that it can handle accessory-related requests. Apps woken up for these events should process them and return as quickly as possible so that the app can be suspended again.
在iOS 6中,应用程序也可以以蓝牙配件的身份在外部模式下运行。要充当蓝牙配件,必须从Xcode项目中的Capability选项卡的uibackgroundmodes部分启用对该模式的支持(还可以通过在应用程序的Info.plist文件中包含带有bluetooth-peripheral value的UIBackoundModes键来启用这种支持) 启用这种模式可以让Bluetooth framework框架在后台简单地唤醒应用程序,以便它能够处理与配件相关的请求。应用程序因这些事件被唤醒,这些事件应该被及时处理,并尽快返回,以便应用程序可以再次暂停。

Any app that supports the background processing of Bluetooth data must be session-based and follow a few basic guidelines:
任何支持蓝牙数据后台处理的应用程序都必须基于会话,并遵循以下几个基本准则:

  • Apps must provide an interface that allows the user to start and stop the delivery of Bluetooth events. That interface should then open or close the session as appropriate.
    应用程序必须提供一个接口,允许用户启动和停止交付配件更新事件。然后,该接口应酌情打开或关闭配件会话。
  • Upon being woken up,though.
    一旦app被唤醒,应用程序就有大约10秒的时间来处理数据。理想情况下,它应该尽可能快地处理数据,并允许自己(app)再次被挂起。但是,如果需要更多的时间,应用程序可以使用beginBackgroundTaskWithExpirationHandler:方法来请求额外的时间;不过,只有在绝对必要的时候才能这样做。

Getting the User’s Attention While in the Background 在后台应该引起用户的注意

Notifications are a way for an app that is suspended,is in the background,or is not running to get the user’s attention. Apps can use local notifications to display alerts,play sounds,badge the app’s icon,or a combination of the three. For example,an alarm clock app might use local notifications to play an alarm sound and display an alert to disable the alarm. When a notification is delivered to the user,the user must decide if the information warrants bringing the app back to the foreground. (If the app is already running in the foreground,local notifications are delivered quietly to the app and not to the user.)
通知是一种引起用户的注意方式,对于被挂起,或者是处于后台,或者没有运行的app来说。应用程序可以使用本地通知来显示alerts、播放声音、标记应用程序的图标或三者的组合。例如,闹钟应用程序可能使用本地通知来播放闹钟的声音,并显示用来关闭闹钟的alert。当通知传递给用户时,用户必须决定这些信息是否值得将应用程序带回前台。(如果应用程序已经在前台运行,本地通知将悄悄地传递给应用程序,而不是用户)

To schedule the delivery of a local notification,create an instance of the UIlocalnotification class,configure the notification parameters,and schedule it using the methods of the UIApplication class. The local notification object contains information about the type of notification to deliver (sound,alert,or badge) and the time (when applicable) at which to deliver it. The methods of the UIApplication class provide options for delivering notifications immediately or at the scheduled time.
若要规划本地通知的传递,请创建UIlocalnotification类的实例,配置通知参数,并使用UIApplication类的方法对其进行调度。本地通知对象包含要传递通知的类型(sound,or badge章)以及传递通知的时间(如果适用)。UIApplication类的方法提供了立即或在预定时间传递通知的选项。

Listing 3-2 shows an example that schedules a single alarm using a date and time that is set by the user. This example configures only one alarm at a time and cancels the prevIoUs alarm before scheduling a new one. (Your own apps can have no more than 128 local notifications active at any given time,any of which can be configured to repeat at a specified interval.) The alarm itself consists of an alert Box and a sound file that is played if the app is not running or is in the background when the alarm fires. If the app is active and therefore running in the foreground,the app delegate’s application:didReceivelocalnotification: method is called instead.
清单3-2显示了一个使用用户设置的日期和时间规划的一个闹钟的示例。此示例一次只配置一个闹钟,并在规划新闹钟之前取消先前的闹钟(您自己的应用程序在任何给定时间都不能有超过128个本地通知活动,其中任何一个都可以配置为在指定的时间间隔内重复执行) 闹钟本身包括一个alter框和一个声音文件,如果应用程序没有运行,或者当闹钟启动时处于后台,则播放该声音文件。如果应用程序处于活动状态并且在前台运行,则将调用app delegate的 didReceivelocalnotification: method 方法

Listing 3-2 Scheduling an alarm notification

- (void)scheduleAlarmForDate:(NSDate*)theDate
{
    UIApplication* app = [UIApplication sharedApplication];
    NSArray*    oldNotifications = [app scheduledlocalnotifications];
// Clear out the old notification before scheduling a new one.
if ([oldNotifications count] > 0)
    [app cancelAll<a href="https://www.jb51.cc/tag/localnotification/" target="_blank">localnotification</a>s];

// Create a new notification.
UI<a href="https://www.jb51.cc/tag/localnotification/" target="_blank">localnotification</a>* alarm = [[UI<a href="https://www.jb51.cc/tag/localnotification/" target="_blank">localnotification</a> alloc] init];
if (alarm)
{
    alarm.fireDate = theDate;
    alarm.timeZone = [NSTimeZone defaultTimeZone];
    alarm.repeatInterval = 0;
    alarm<a href="https://www.jb51.cc/tag/so/" target="_blank">.so</a>undName = @"alarmsound.caf";
    alarm.alertBody = @"Time to wake up!";

    [app schedule<a href="https://www.jb51.cc/tag/localnotification/" target="_blank">localnotification</a>:alarm];
}

}

Sound files used with local notifications have the same requirements as those used for push notifications. Custom sound files must be located inside your app’s main bundle and support one of the following formats: Linear PCM,MA4,µ-Law,or a-Law. You can also specify the UIlocalnotificationDefaultSoundName constant to play the default alert sound for the device. When the notification is sent and the sound is played,the system also triggers a vibration on devices that support it.
与本地通知一起使用的声音文件的要求与推送通知的要求相同。自定义声音文件必须位于应用程序的主包中(main bundle),并支持以下格式之一:线性PCM、MA4、µ-Law或a-Law。还可以指定UIlocalnotificationDefaultSoundName常量来播放设备的默认警报声音。当发出通知和播放声音时,系统还会在支持它的设备上触发振动。

You can cancel scheduled notifications or get a list of notifications using the methods of the UIApplication class. For more information about these methods,see UIApplication Class Reference. For additional information about configuring local notifications,see Local and Remote Notification Programming Guide.
可以使用UIApplication类的方法取消预定通知或获取通知列表。有关这些方法的详细信息,请参阅UIApplication类引用。有关配置本地通知的其他信息,请参阅Local and Remote Notification Programming Guide

Understanding When Your App Gets Launched into the Background

Apps that support background execution may be relaunched by the system to handle incoming events. If an app is terminated for any reason other than the user force quitting it,the system launches the app when one of the following events happens:
支持后台执行的应用程序可以通过系统重新启动来处理传入事件。如果应用程序因除了用户强制退出它以外的任何原因终止,则系统在下列事件之一发生时启动应用程序:

  • For location apps:
    对使用位置的app而言:

    • The system receives a location update that meets the app’s configured criteria for delivery.
      该系统接收到一个满足应用程序配置的交付标准的位置更新。
    • The device entered or exited a registered region. (Regions can be geographic regions or iBeacon regions.)
      该设备进入或退出注册区域。(区域可以是地理区域或iBeacon regions)。
  • For audio apps,the audio framework needs the app to process some data. (Audio apps include those that play audio or use the microphone.)
    对于音频app而言,audio framework需要app处理数据(音频app包括使用麦克风与播放音频)
  • For Bluetooth apps:
    对于蓝牙应用程序:

    • An app acting in the central role receives data from a connected peripheral.
      一个扮演中心角色的应用程序接收来自连接外围的数据。
    • An app acting in the peripheral role receives commands from a connected central.
      一个扮演外围角色的应用程序接收来自连接中心的命令。

  • For background download apps:
    对于执行后台下载的app而言:

    • A push notification arrives for an app and the payload of the notification contains the content-available key with a value of 1.
      一个应用程序的推送通知到达应用程序,通知的有效负载(payload)包含一个可用键,值为1。
    • The system wakes the app at opportunistic moments to begin downloading new content.
      该系统在合适的时刻唤醒应用程序,开始下载新内容。
    • For apps downloading content in the background using the NSURLSession class,all tasks associated with that session object either completed successfully or received an error.
      对于使用NSURLSession类在后台执行下载任务的应用程序,所有与该会话对象关联的任务都成功地完成或收到错误。
    • A download initiated by a Newsstand app finishes.
      由Newsstand应用程序启动的下载任务完成。

In most cases,the system does not relaunch apps after they are force quit by the user. One exception is location apps,which in iOS 8 and later are relaunched after being force quit by the user. In other cases,the user must launch the app explicitly or reboot the device before the app can be launched automatically into the background by the system. When password protection is enabled on the device,the system does not launch an app in the background before the user first unlocks the device.
在大多数情况下,系统在用户强制退出app之后不会重新启动应用程序。其中一个例外是位置应用程序,ios 8和以后的版本中都是用户强制退出后重新启动的。但是,在其他情况下,用户在该应用程序可以自动地启动到后台执行之前必须显式启动应用程序或者重启设备,当设备上启用密码保护时,系统在用户解锁设备之前不会在后台启动应用程序。

App Programming Guide for iOS --Background Execution 2

App Programming Guide for iOS --Background Execution 2

Background Execution 2

Being a Responsible Background App 成为一个负责的后台执行的app

The foreground app always has precedence over background apps when it comes to the use of system resources and hardware. Apps running in the background need to be prepared for this discrepancy and adjust their behavior when running in the background. Specifically,apps moving to the background should follow these guidelines:
当涉及到系统资源和硬件的使用时,在前台的应用总是优先于后台应用程序。在后台运行的应用程序需要为这种差异做好准备,并在后台运行时调整它们的行为。具体来说,移动到后台的应用程序应该遵循以下指导原则:

  • Do not make any OpenGL ES calls from your code. You must not create an EAGLContext object or issue any OpenGL ES drawing commands of any kind while running in the background. Using these calls causes your app to be killed immediately. Apps must also ensure that any prevIoUsly submitted commands have completed before moving to the background. For information about how to handle OpenGL ES when moving to and from the background,see Implementing a Multitasking-aware OpenGL ES Application in OpenGL ES Programming Guide.
    不要从代码中调用OpenGL ES。您不能在后台运行时创建EAGLContext对象或执行任何OpenGL ES绘图命令。使用这些调用会使您的应用程序立即被杀死。应用程序还必须确保在进入后台之前任何之前提交的命令都已经完成。有关在前后台切换时如何处理OpenGL ES的信息,请参阅在OpenGL ES编程指南中的实现 Multitasking-aware OpenGL ES应用程序。
  • Cancel any Bonjour-related services before being suspended. When your app moves to the background,and before it is suspended,it should unregister from Bonjour and close listening sockets associated with any network services. A suspended app cannot respond to incoming service requests anyway. Closing out those services prevents them from appearing to be available when they actually are not. If you do not close out Bonjour services yourself,the system closes out those services automatically when your app is suspended.
    当您的应用程序移到后台时,在挂起之前,取消任何与Bonjour相关的服务。它应该从Bonjour中取消注册,并关闭与任何网络服务相关的侦听套接字。挂起的应用程序无论如何都不能响应传入的服务请求。关闭这些服务会防止它们在实际不能使用时出现可用的情况发生。如果您不亲自关闭Bonjour服务,则当应用程序暂停时,系统会自动关闭这些服务。
  • Be prepared to handle connection failures in your network-based sockets. The system may tear down socket connections while your app is suspended for any number of reasons. As long as your socket-based code is prepared for other types of network failures,such as a lost signal or network transition,this should not lead to any unusual problems. When your app resumes,if it encounters a failure upon using a socket,simply reestablish the connection.
    准备好处理基于网络的套接字连接失败的故障。当应用程序因为各种原因被挂起时系统可能会拆除套接字连接。只要你的基于套接字的代码为其他类型的网络故障做好准备,例如丢失信号或网络过渡(4G->3G),这就不会导致任何不寻常的问题。当应用程序恢复时,如果它在使用套接字时遇到故障,只需重新建立连接即可。
  • Save your app state before moving to the background. During low-memory conditions,background apps may be purged from memory to free up space. Suspended apps are purged first,and no notice is given to the app before it is purged. As a result,apps should take advantage of the state preservation mechanism in iOS 6 and later to save their interface state to disk. For information about how to support this feature,see Preserving Your App’s Visual Appearance Across Launches.
    在移到后台之前保存您的应用程序状态。在内存不足的情况下,后台应用程序可能会从内存中清除,以腾出空间。被挂起的应用程序首先被清除,在清除应用程序之前,App不会得到通知。因此,应用程序应该利用iOS 6和更高版本中的状态保存机制将它们的interface(界面以及变量)状态保存到磁盘上。有关如何支持此功能的信息,请参阅保留应用程序的可视化外观。
  • Remove strong references to unneeded objects when moving to the background. If your app maintains a large in-memory cache of objects (especially images),remove all strong references to those caches when moving to the background. For more information,see Reduce Your Memory Footprint.
    移到后台时,删除对不需要的对象的强引用。如果您的应用程序维护了大量的对象内存缓存(特别是图像),那么在移动到后台时,删除对这些缓存的所有强引用。有关更多信息,请参见减少内存占用。
  • Stop using shared system resources before being suspended. Apps that interact with shared system resources such as the Address Book or calendar databases should stop using those resources before being suspended. Priority for such resources always goes to the foreground app. When your app is suspended,if it is found to be using a shared resource,the app is killed.
    在挂起之前停止使用共享系统资源。与共享系统资源(如通讯簿或日历数据库)交互的应用程序应该在挂起之前停止使用这些资源。对这些资源的优先级总是放在前台应用程序上。当您的应用程序被挂起时,如果发现它正在使用共享资源,则该应用程序将被杀死。
  • Avoid updating your windows and views. Because your app’s windows and views are not visible when your app is in the background,you should avoid updating them. The exception is in cases where you need to update the contents of a window prior to having a snapshot of your app taken.
    避免更新windows和views。因为当应用程序处于后台时,应用程序的windows和views是不可见的,所以您应该避免更新它们。例外情况是,您需要更新窗口的内容,然后才能获得应用程序的快照(例外是创建新的快照时必须先更新界面内容)。
  • Respond to connect and disconnect notifications for external accessories. For apps that communicate with external accessories,the system automatically sends a disconnection notification when the app moves to the background. The app must register for this notification and use it to close out the current accessory session. When the app moves back to the foreground,a matching connection notification is sent,giving the app a chance to reconnect. For more information on handling accessory connection and disconnection notifications,see External Accessory Programming Topics.
    响应与外部配件连接和断开时的通知。对于与外部配件通信的应用程序,当应用程序移动到后台时,系统会自动发送断开连接通知。应用程序必须注册此通知,并使用它关闭当前与配件会话。当应用程序移回前台时,将发送一个与之相匹配的连接通知,给应用程序重新连接的机会。有关处理配件连接和断开连接通知的详细信息,请参阅外部配件编程主题。
  • Clean up resources for active alerts when moving to the background. In order to preserve context when switching between apps,the system does not automatically dismiss action sheets (UIActionSheet) or alert views (UIAlertView) when your app moves to the background. It is up to you to provide the appropriate cleanup behavior prior to moving to the background. For example,you might want to cancel the action sheet or alert view programmatically or save enough contextual information to restore the view later (in cases where your app is terminated).
    移动到后台时,清除活的alerts资源。为了在应用程序之间切换时保留上下文,当应用程序移动到后台时,系统不会自动关闭操作表(UIActionSheet)或alter视图(UIAlertView)。在移到后台之前,应该由您提供适当的清理行为。例如,您可能希望以编程方式取消action sheet或alert view,或者保存足够的上下文信息,以便稍后恢复视图(在应用程序终止的情况下)。
  • Remove sensitive information from views before moving to the background. When an app transitions to the background,the system takes a snapshot of the app’s main window,which it then presents briefly when transitioning your app back to the foreground. Before returning from your applicationDidEnterBackground: method,you should hide or obscure passwords and other sensitive personal information that might be captured as part of the snapshot.
    移到后台前,从视图中删除敏感信息。当应用程序转换到后台时,系统会对应用程序的主窗口截取快照,然后在将应用程序转换回前台时简要地显示该快照。在 applicationDidEnterBackground: 方法返回之前,应该隐藏或掩盖可能作为快照一部分被捕获的密码和其他敏感个人信息。
  • Do minimal work while running in the background. The execution time given to background apps is more constrained than the amount of time given to the foreground app. Apps that spend too much time executing in the background can be throttled back by the system or terminated.
    在后台运行时,要做最少的工作。给后台应用程序的执行时间比给前台应用程序的时间更受限制。在后台执行时间过长的应用程序可能会被系统节流或终止。

If you are implementing a background audio app,or any other type of app that is allowed to run in the background,your app responds to incoming messages in the usual way. In other words,the system may notify your app of low-memory warnings when they occur. And in situations where the system needs to terminate apps to free even more memory,the app calls its delegate’s applicationWillTerminate: method to perform any final tasks before exiting.
如果您正在实现在后台播放音频应用程序,或允许在后台运行的任何其他类型的应用程序,则您的应用程序将以通常的方式响应传入的消息。换句话说,系统可能会在出现低内存警告时通知应用程序。在系统需要终止应用程序以释放更多内存的情况下,在退出之前调用 app delegate 的applicationWillTerminate: 方法以执行任何最后工作。

Opting Out of Background Execution 选择退出后台执行

If you do not want your app to run in the background at all,you can explicitly opt out of background by adding the UIApplicationExitsOnSuspend key (with the value YES) to your app’s Info.plist file. When an app opts out,it cycles between the not-running,inactive,and active states and never enters the background or suspended states. When the user presses the Home button to quit the app,the applicationWillTerminate: method of the app delegate is called and the app has approximately 5 seconds to clean up and exit before it is terminated and moved back to the not-running state.
如果您根本不希望应用程序在后台运行,可以通过将UIApplicationExitsOnSuspend键(值为YES)添加到应用程序的Info.plist文件中,从而显式地选择退出后台。当应用程序选择退出时,它会在不运行、不活动和活动状态之间循环,并且永远不会进入后台或挂起状态。当用户按Home键退出应用程序时,会调用app delegate applicationWillTerminate:方法,并且应用程序在终止并移回未运行状态之前有大约5秒的时间清理和退出

Opting out of background execution is strongly discouraged but may be the preferred option under certain conditions. Specifically,if coding for background execution adds significant complexity to your app,terminating the app might be a simpler solution. Also,if your app consumes a large amount of memory and cannot easily release any of it,the system might kill your app quickly anyway to make room for other apps. Thus,opting to terminate,instead of switching to the background,might yield the same results and save you development time and effort.
选择退出后台执行是非常不鼓励的,但在某些条件下可能是首选方案。具体来说,如果为后台执行编写代码会给应用程序增加很大的复杂性,那么终止应用程序可能是一个更简单的解决方案。另外,如果你的应用程序消耗了大量的内存,并且不能轻易地释放其中的任何一个,系统可能很快就会杀死你的应用程序,以便为其他应用程序腾出空间。因此,选择终止,而不是切换到后台,可能会产生相同的结果,并节省您的开发时间和精力。

For more information about the keys you can include in your app’s Info.plist file,see information Property List Key Reference.
有关您可以在应用程序的Info.plist文件中包含的键的更多信息,请参见信息属性列表键引用。

Brave 浏览器更换 Chromium 内核,支持 Chrome 扩展

Brave 浏览器更换 Chromium 内核,支持 Chrome 扩展

以保护个人隐私为中心的 Brave 浏览器目前已经完成了最后一个阶段的工作,将用户使用的浏览器迁移到 Chromium 内核,与 Chrome、Vivaldi、Opera 和 Edge 相同。

在更换完成后,Brave 浏览器的运行速度将提升 22%。

用户在更新 Brave 0.57 版本后,就可以直接在 Google 网上商店上下载 Google Chrome 的相关扩展程序,扩展程序和 Brave 完全兼容。

Brave 浏览器之前并没有完全使用 Chromium 内核,自 2016 年以来,Brave 仅使用了 Chromium 中的页面渲染引擎,其他部分均是团队开发的自定义组件。这个组件被称为 Muon。Muon 被团队内部称为是更安全的 Electron 分支。他允许使用自定义的 HTML、CSS、JavaScript 来定义用户界面。

但缺点也显而易见:由于团队规模和资金的限制,Muon 的开发是相当耗时的,Muon 并没有达到团队的预期效果。

早在 2018 年 3 月,Brave 团队就宣布放弃使用 Muon,选择使用 Chromium 项目提供的技术标准作为 Brave 浏览器的标准。

上周五发布的 Brave 0.57 版本完成了 Muon 接口向 Chromium 接口的过渡。

在替换为 Chromium 之后,Brave 浏览器可以更好的支持 WebExtensions API,现在所有的可扩展 API 以及在 Muon 上从未实现过的 API。

虽然使用了 Chromium 作为 Brave 浏览器的内核,但并不会向浏览器中添加任何 Google 的功能。Brave 团队目前已经禁用了 Google 账户同步功能,并且删除了 Google 用于搜索建议相关的代码和信息上报代码。以此来保证 Brave 浏览器是一款 "以保护个人隐私为中心" 的浏览器。

关于[Chromium 文档转载,第 001 章] Mojo Migration Guidemono morphemic words的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于android – IllegalArgumentException:org.chromium.components.minidump_uploader.CrashFileManager、App Programming Guide for iOS --Background Execution 1、App Programming Guide for iOS --Background Execution 2、Brave 浏览器更换 Chromium 内核,支持 Chrome 扩展的相关信息,请在本站寻找。

本文标签: