page.title=直接启动 page.keywords=Preview、SDK、直接启动 page.tags=androidn page.image=images/cards/card-nyc_2x.jpg @jd:body <div id="qv-wrapper"> <div id="qv"> <h2>本文内容</h2> <ol> <li><a href="#run">请求在直接启动时运行</a></li> <li><a href="#access">访问设备加密存储</a></li> <li><a href="#notification">接收用户解锁通知</a></li> <li><a href="#migrating">迁移现有数据</a></li> <li><a href="#testing">测试您的加密感知应用</a></li> </ol> </div> </div> <p>当设备已开机但用户尚未解锁设备时,Android N 将在安全的“直接启动”模式下运行。<i></i> 为支持此操作,系统为数据提供两个存储位置:</p> <ul> <li><i>凭据加密存储</i>,这是默认存储位置,仅在用户解锁设备后可用。 </li> <li><i>设备加密存储</i>,该存储位置在“直接启动”模式下和用户解锁设备后均可使用。 </li> </ul> <p>默认情况下,应用不会在“直接启动”模式下运行。如果您的应用需要在“直接启动”模式下进行操作,您可以注册在此模式期间应运行的应用组件。 对于需要在“直接启动”模式下运行的应用,常见的一些用例包括: </p> <ul> <li>已安排通知的应用,如闹钟应用。 </li> <li>提供重要用户通知的应用,如短信应用。</li> <li>提供无障碍服务的应用,如 Talkback。</li> </ul> <p>如果您的应用在“直接启动”模式下运行时需要访问数据,则使用设备加密存储。 设备加密存储包含使用密钥加密的数据,仅在设备已成功执行验证启动后密钥才可用。 </p> <p>对于应使用与用户凭据(如 PIN 或密码)关联的密钥加密的数据,请使用凭据加密存储。凭据加密存储仅在用户已成功解锁设备后可用,直到用户再次重启设备。 如果用户在解锁设备后启用锁定屏幕,则不会锁定凭据加密存储。 </p> <h2 id="run">请求在直接启动时运行</h2> <p>应用必须先向系统注册其组件,然后才能在“直接启动”模式下运行或访问设备加密存储。 应用通过将组件标记为“加密感知”来注册系统。 <i></i>若要将您的组件标记为加密感知,请在清单中将 <code>android:directBootAware</code> 属性设为 true。 <p> <p>当设备重启后,加密感知组件可以注册接收来自系统的 <code>LOCKED_BOOT_COMPLETED</code> 广播消息。 此时设备加密存储可用,您的组件可以在“直接启动”模式下执行需要运行的任务,例如触发已设定的闹铃。 </p> <p>以下代码段展示如何将 {@link android.content.BroadcastReceiver} 注册为加密感知并在应用清单中为 <code>LOCKED_BOOT_COMPLETED</code> 添加 Intent 过滤器: </p> <pre> <receiver android:directBootAware="true" > ... <intent-filter> <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" /> </intent-filter> </receiver> </pre> <p>在用户解锁设备后,所有组件均可访问设备加密存储以及凭据加密存储。 </p> <h2 id="access">访问设备加密存储</h2> <p>要访问设备加密存储,请通过调用 <code>Context.createDeviceProtectedStorageContext()</code> 创建另一个 {@link android.content.Context} 实例。使用此上下文执行的所有存储 API 调用均访问设备加密存储。 以下示例访问设备加密存储并打开现有应用数据文件: </p> <pre> Context directBootContext = appContext.createDeviceProtectedStorageContext(); // Access appDataFilename that lives in device encrypted storage FileInputStream inStream = directBootContext.openFileInput(appDataFilename); // Use inStream to read content... </pre> <p>仅针对在“直接启动”模式下必须可访问的信息使用设备加密存储。请勿将设备加密存储用作通用加密存储。对于专有用户信息,或在“直接启动”模式下不需要的加密数据,请使用凭据加密存储。 </p> <h2 id="notification">接收用户解锁通知</h2> <p>重启后一旦用户解锁了设备,您的应用即可切换至访问凭据加密存储,并使用依赖用户凭据的常规系统服务。 </p> <p>为了在重启后用户解锁设备时收到通知,请从一个正在运行的组件注册 {@link android.content.BroadcastReceiver} 以侦听 <code>ACTION_USER_UNLOCKED</code> 消息。 或者,您可以接收现有 {@link android.content.Intent#ACTION_BOOT_COMPLETED ACTION_BOOT_COMPLETED} 消息,该消息现在表明设备已启动,且用户已解锁设备。 </p> <p>您可以通过调用 <code>UserManager.isUserUnlocked()</code> 直接查询用户是否已解锁设备。 </p> <h2 id="migrating">迁移现有数据</h2> <p>如果用户将其设备更新为使用“直接启动”模式,您可能需要将现有数据迁移到设备加密存储。 使用 <code>Context.moveSharedPreferencesFrom()</code> 和 <code>Context.moveDatabaseFrom()</code> 在凭据加密存储和设备加密存储之间迁移首选项和数据库数据。 </p> <p>请运用您的最佳判断来决定从凭据加密存储向设备加密存储迁移哪些数据。 您不应将专有用户信息(如密码或权限令牌)迁移到设备加密存储。 。在某些情况下,您可能需要在这两个加密存储中管理单独的数据集。 </p> <h2 id="testing">测试您的加密感知应用</h2> <p>使用新的“直接启动”模式测试您的加密感知应用。有两种方式可以启用直接启动模式: </p> <p class="caution"><strong>注意:</strong>启用“直接启动”将擦除设备上的所有用户数据。 </p> <p>在已安装 Android N 的受支持的设备上,通过执行以下操作之一启用“直接启动”: </p> <ul> <li>在设备上,如果您尚未启用 <b>Developer options</b>,则可通过转到 <b>Settings > About phone</b> 并点击 <b>Build number</b> 七次启用它。 当开发者选项屏幕可用后,转到 <b>Settings > Developer options</b> 并选择 <b>Convert to file encryption</b>。 </li> <li>使用以下 adb shell 命令启用“直接启动”模式: <pre class="no-pretty-print"> $ adb reboot-bootloader $ fastboot --wipe-and-use-fbe </pre> </li> </ul> <p>另外,还提供模拟直接启动模式,以防您需要在测试设备上切换模式。 模拟模式应仅在开发期间使用,否则可能导致数据丢失。 若要启用模拟直接启动模式,请在设备上设置锁定模式,如果在设置锁定模式时系统提示安全启动屏幕,则选择“No thanks”,然后使用以下 adb shell 命令: </p> <pre class="no-pretty-print"> $ adb shell sm set-emulate-fbe true </pre> <p>若要关闭模拟直接启动模式,请使用以下命令:</p> <pre class="no-pretty-print"> $ adb shell sm set-emulate-fbe false </pre> <p>使用这些命令会导致设备重启。</p>