创建笔记应用

笔记功能是 Android 的核心功能,它增强了用户在大屏幕设备上的生产力。笔记应用使用户能够在浮动窗口或全屏中书写和素描,捕获和注释屏幕内容,并保存笔记以供日后查看和修改。

用户可以从锁定屏幕或运行其他应用时访问笔记应用。

对笔记的支持提供了非凡的用户体验。

笔记角色

The RoleManager.ROLE_NOTES 角色标识笔记应用并授予它们 LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE 权限。

要为您的应用获取笔记角色,请执行以下操作

  1. 调用 isRoleAvailable() 检查角色的状态。
  2. 如果笔记角色可用,请调用 createRequestRoleIntent() 获取特定于笔记的意图。
  3. 调用 startActivityForResult() 并使用笔记意图提示用户向您的应用授予笔记角色。

只有一个应用可以拥有笔记角色。

该应用响应隐式 ACTION_CREATE_NOTE 意图操作打开。如果从设备锁定屏幕调用,该应用会全屏打开;如果在屏幕解锁时调用,则会在浮动窗口中打开。

应用清单

要获得笔记角色的资格,您的应用必须在应用清单中包含以下声明

<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>

该声明使用户能够将笔记角色分配给您的应用,使其成为默认笔记应用

应用功能

大屏幕差异化笔记应用提供了全面的笔记功能。

触控笔支持

当您的应用使用 EXTRA_USE_STYLUS_MODE 意图附加项(设置为 true)调用时,该应用应打开接受触控笔(或手指触控)输入的笔记。

如果意图附加项设置为 false,您的应用应打开接受键盘输入的笔记。

锁定屏幕访问

您的应用必须提供一个全屏活动,在从设备锁定屏幕打开应用时运行。

如果用户同意(在解锁的设备状态下)显示过去的笔记,您的应用应仅显示历史笔记。否则,从锁定屏幕打开时,您的应用应始终创建一个新笔记。

您可以使用 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.
  }
});

浮动窗口

对于上下文笔记,您的应用必须提供一个活动,该活动在其他应用运行时在浮动窗口中打开。

您的应用应支持 multi-instance 模式,以便用户即使在全屏启动笔记应用或在分屏模式下运行笔记应用时,也能在多个浮动窗口中创建多个笔记。

内容捕获

内容捕获是笔记应用的一项关键功能。通过内容捕获,用户可以截取笔记应用浮动窗口后面的显示屏的屏幕截图。用户可以捕获全部或部分显示屏,将内容粘贴到他们的笔记中,并对捕获的内容进行注释或突出显示。

您的笔记应用应提供一个 UI 功能,该功能会启动一个 ActivityResultLauncher,该功能由 registerForActivityResult() 创建。The ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE 意图操作直接或通过 ActivityResultContract 提供给启动器。

系统活动捕获内容,将其保存在设备上,并将内容 URI 返回到您的应用中的 registerForActivityResult() 回调参数中。

以下示例使用一个泛型 StartActivityForResult 合同

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));
        });
}

您的应用应处理所有结果代码

当内容捕获成功时,将捕获的图像粘贴到笔记中,例如

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) 确认您的应用是否是默认笔记应用(如果应用不拥有笔记角色,则您的应用可以在对话或其他类型的“气泡”中运行)

其他资源