记事功能是 Android 的一项核心功能,可提高用户在大屏幕设备上的工作效率。记事应用允许用户在浮动窗口或全屏模式下书写和素描,截取和批注屏幕内容,以及保存笔记供日后查阅和修改。
用户可以从锁定屏幕或运行其他应用时访问记事应用。
记事功能对触控笔的支持提供了卓越的用户体验。
Notes 角色
RoleManager.ROLE_NOTES 角色用于标识记事应用,并授予其 LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE 权限。
如需为您的应用获取 notes 角色,请按以下步骤操作:
- 调用
isRoleAvailable()检查角色的状态。 - 如果 notes 角色可用,则调用
createRequestRoleIntent()获取针对 notes 的 intent。 - 使用 notes intent 调用
startActivityForResult(),提示用户向您的应用授予 notes 角色。
只有一个应用可以拥有 notes 角色。
应用会响应隐式的 ACTION_CREATE_NOTE intent 操作而打开。如果从设备锁定屏幕调用,应用会全屏打开;如果在屏幕解锁时调用,则会以浮动窗口的形式打开。
应用清单
为了符合 notes 角色的条件,您的应用必须在应用清单中包含以下声明:
<activity
android:name="YourActivityName"
android:exported="true"
android:showWhenLocked="true"
android:turnScreenOn="true">
<intent-filter>
<action android:name="android.intent.action.CREATE_NOTE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
该声明使用户能够将 notes 角色分配给您的应用,从而将其设为默认记事应用。
ACTION_CREATE_NOTE设置您的应用响应的 intent 操作。showWhenLocked使您的应用可以从设备锁定屏幕访问。turnScreenOn使您的应用在运行时可以点亮设备屏幕。
应用功能
针对大屏幕设备的差异化记事应用提供全套记事功能。
触控笔支持
当您的应用使用 EXTRA_USE_STYLUS_MODE intent extra 并将其设置为 true 调用时,应用应打开一个接受触控笔(或手指触摸)输入的笔记。
如果 intent extra 设置为 false,您的应用应打开一个接受键盘输入的笔记。
锁定屏幕访问
您的应用必须提供一个全屏 Activity,当应用从设备锁定屏幕打开时运行。
如果用户已同意(在设备解锁状态下)显示过去的笔记,您的应用应仅显示历史笔记。否则,从锁定屏幕打开时,您的应用应始终创建新笔记。
您可以使用 KeyguardManager#isKeyguardLocked() 检查您的应用是否从锁定屏幕启动。要要求用户验证和解锁设备,请调用 KeyguardManager#requestDismissKeyguard()
Kotlin
val keyguardManager =
getSystemService(KEYGUARD_SERVICE) as KeyguardManager
keyguardManager.requestDismissKeyguard( this, object :
KeyguardDismissCallback() { override fun onDismissError() { // Unlock failed.
Dismissing keyguard is not feasible. } override fun onDismissSucceeded() { //
Unlock succeeded. Device is now unlocked. } override fun onDismissCancelled()
{ // Unlock failed. User cancelled operation or request otherwise cancelled. }
} )Java
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); boolean isLocked = keyguardManager.isKeyguardLocked(); keyguardManager.requestDismissKeyguard( this, new KeyguardManager.KeyguardDismissCallback() { @Override public void onDismissError() { // Unlock failed. Dismissing keyguard is not feasible. } @Override public void onDismissSucceeded() { // Unlock succeeded. Device is now unlocked. } @Override public void onDismissCancelled() { // Unlock failed. User cancelled operation or request otherwise cancelled. } });
浮动窗口
对于上下文记事功能,您的应用必须提供一个 Activity,当另一个应用运行时,该 Activity 会在浮动窗口中打开。
您的应用应支持 multi-instance 模式,以便用户即使在您的记事应用全屏或分屏模式下启动时,也可以在多个浮动窗口中创建多个笔记。
内容捕获
内容捕获是记事应用的一项关键功能。通过内容捕获,用户可以截取记事应用浮动窗口后面的屏幕显示。用户可以截取显示屏的全部或部分内容,将其粘贴到笔记中,并对捕获的内容进行批注或高亮显示。
您的记事应用应提供一个 UI 辅助功能,用于启动由 registerForActivityResult() 创建的 ActivityResultLauncher。ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE intent 操作会直接或通过 ActivityResultContract 提供给 launcher。
系统 Activity 会捕获内容,将其保存在设备上,并在 registerForActivityResult() 的回调参数中将内容 URI 返回给您的应用。
以下示例使用泛型 StartActivityForResult contract:
Kotlin
private val startForResult =
registerForActivityResult( ActivityResultContracts.StartActivityForResult()) {
result: ActivityResult -> if (result.resultCode ==
Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS) { val uri = result.data?.data // Use
the URI to paste the captured content into the note. } } override fun
onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState)
setContent { NotesTheme { Surface(color =
MaterialTheme.colorScheme.background) { CaptureButton( onClick = {
Log.i("ContentCapture", "Launching intent...")
startForResult.launch(Intent(ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE))
}) } } } } @Composable fun CaptureButton(onClick: () -> Unit) {
Button(onClick = onClick)
{Text("Capture Content")} }Java
private final ActivityResultLauncher<Intent> startForResult = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS) { Uri uri = result.getData() != null ? result.getData().getData() : null; // Use the URI to paste the captured content into the note. } }); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button captureButton = findViewById(R.id.capture_button); captureButton.setOnClickListener( view -> { Log.i("ContentCapture", "Launching intent..."); startForResult.launch(new Intent(ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE)); }); }
您的应用应处理所有结果代码:
CAPTURE_CONTENT_FOR_NOTE_SUCCESSCAPTURE_CONTENT_FOR_NOTE_FAILEDCAPTURE_CONTENT_FOR_NOTE_USER_CANCELEDCAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTEDCAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN
内容捕获成功后,将捕获的图像粘贴到笔记中,例如:
Kotlin
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
result: ActivityResult -> if (result.resultCode ==
Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS) { val uri = result.data?data // Use
the URI to paste the captured content into the note. } }Java
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Intent.CAPTURE_CONTENT_FOR_NOTE_SUCCESS) { Uri uri = result.getData() != null ? result.getData().getData() : null; // Use the URI to paste the captured content into the note. } });
内容捕获功能应仅在您的记事应用在浮动窗口中运行时通过 UI 辅助功能公开,而不是在全屏运行或从设备锁定屏幕启动时公开。(用户可以使用设备截图功能截取记事应用本身的截图。)
要确定您的应用是否在浮动窗口(或气泡)中,请调用以下方法:
isLaunchedFromBubble()检查您的记事应用不是从设备锁定屏幕全屏启动的。isRoleHeld(RoleManager.ROLE_NOTES)验证您的应用是否是默认记事应用(如果您的应用没有 notes 角色,则可以在对话气泡或其他类型的气泡中运行)。