メモ作成アプリを作成する

メモは、大画面デバイスでのユーザーの生産性を向上させる Android の中核機能です。メモ作成アプリを使用すると、フローティング ウィンドウまたは全画面で文書やスケッチをしたり、画面コンテンツをキャプチャして注釈を付けたり、メモを保存して後で確認、修正したりできます。

ロック画面から、または他のアプリの実行中でも、メモ作成アプリにアクセスできます。

メモを取るためのタッチペン対応により、優れたユーザー エクスペリエンスが実現します。

メモのロール

RoleManager.ROLE_NOTES ロールは、メモ作成アプリを特定し、LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE 権限を付与します。

アプリのメモロールを取得する手順は次のとおりです。

  1. isRoleAvailable() を呼び出してロールのステータスを確認します。
  2. メモのロールが使用可能な場合は、createRequestRoleIntent() を呼び出してメモ固有のインテントを取得します。
  3. メモ インテントを使用して startActivityForResult() を呼び出し、アプリにメモロールを付与するようにユーザーに求めます。

メモのロールを持つことができるアプリは 1 つだけです。

暗黙的な 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>

この宣言により、ユーザーがアプリにメモのロールを割り当て、デフォルトのメモ作成アプリを指定できるようになります。

  • ACTION_CREATE_NOTE は、アプリが応答するインテントのアクションを設定します。

  • showWhenLocked を使用すると、デバイスのロック画面からアプリにアクセスできるようになります

  • turnScreenOn を使用すると、アプリの実行時にデバイスの画面をオンにできます

アプリの機能

大画面によって差別化されたメモ作成アプリは、メモ作成機能を補完します。

タッチペンのサポート

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 モードをサポートする必要があります。

コンテンツ キャプチャ

コンテンツ キャプチャは、メモ作成アプリの重要な機能です。コンテンツ キャプチャを使用すると、メモ作成アプリのフローティング ウィンドウの背後にあるディスプレイのスクリーンショットを撮ることができます。ディスプレイの全部または一部をキャプチャし、コンテンツをメモに貼り付けて、キャプチャしたコンテンツに注釈またはハイライトを付けることができます。

メモ作成アプリは、registerForActivityResult() によって作成された ActivityResultLauncher を起動する UI アフォーダンスを提供する必要があります。ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE インテントのアクションは、直接または ActivityResultContract を介してランチャーに提供されます。

システム アクティビティは、コンテンツをキャプチャしてデバイスに保存し、registerForActivityResult() のコールバック引数でコンテンツ URI をアプリに返します。

次の例では、汎用の 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): アプリがデフォルトのメモ作成アプリであることを確認します(アプリがメモのロールを持っていない場合、会話や他の種類のバブル内で実行可能です)

参考情報