Créer une application de prise de notes

La prise de notes est une fonctionnalité essentielle d'Android qui améliore la productivité des utilisateurs sur les appareils à grand écran. Les applications de prise de notes permettent aux utilisateurs d'écrire et de dessiner dans une fenêtre flottante ou en plein écran, de capturer et d'annoter le contenu de l'écran, ainsi que d'enregistrer des notes pour les examiner et les réviser ultérieurement.

Les utilisateurs peuvent accéder aux applications de prise de notes depuis l'écran de verrouillage ou pendant l'exécution d'autres applications.

La compatibilité avec le stylet pour la prise de notes offre une expérience exceptionnelle à l'utilisateur.

Rôle "Notes"

Le rôle RoleManager.ROLE_NOTES identifie les applications de prise de notes et leur accorde l'autorisation LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE.

Pour obtenir le rôle "Notes" pour votre application, procédez comme suit :

  1. Appelez isRoleAvailable() pour vérifier l'état du rôle.
  2. Si le rôle "Notes" est disponible, appelez createRequestRoleIntent() pour obtenir un intent spécifique aux notes.
  3. Appelez startActivityForResult() avec l'intent "Notes" pour inviter l'utilisateur à accorder le rôle "Notes" à votre application.

Une seule application peut disposer du rôle "Notes".

L'application s'ouvre en réponse à une action d'intent ACTION_CREATE_NOTE implicite. Si elle est appelée depuis l'écran de verrouillage de l'appareil, l'application s'ouvre en plein écran. Si elle est appelée lorsque l'écran est déverrouillé, elle s'ouvre dans une fenêtre flottante.

Fichier manifeste d'application

Pour bénéficier du rôle "Notes", votre application doit inclure la déclaration suivante dans son fichier manifeste d'application :

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

La déclaration permet aux utilisateurs d'attribuer le rôle "Notes" à votre application, ce qui en fait l'application de prise de notes par défaut :

  • ACTION_CREATE_NOTE définit l'action d'intent à laquelle votre application répond

  • showWhenLocked rend votre application accessible depuis l'écran de verrouillage de l'appareil

  • turnScreenOn permet à votre application d'allumer l'écran de l'appareil lorsqu'elle s'exécute

Caractéristiques des applications

Une application de prise de notes différenciée sur grand écran offre une gamme complète de fonctionnalités de prise de notes.

Compatible avec les stylets

Lorsque votre application est appelée avec l'intent EXTRA_USE_STYLUS_MODE supplémentaire défini sur true, elle doit ouvrir une note qui accepte la saisie au stylet (ou au doigt).

Si l'intent supplémentaire est défini sur false, votre application doit ouvrir une note acceptant la saisie au clavier.

Accès à l'écran de verrouillage

Votre application doit fournir une activité en plein écran qui s'exécute lorsqu'elle est ouverte depuis l'écran de verrouillage de l'appareil.

Votre application ne doit afficher l'historique des notes que si l'utilisateur a autorisé l'affichage des anciennes notes (lorsque l'appareil est déverrouillé). Sinon, lorsqu'elle est ouverte depuis l'écran de verrouillage, votre application doit toujours créer une nouvelle note.

Vous pouvez vérifier si votre application a été lancée depuis l'écran de verrouillage avec KeyguardManager#isKeyguardLocked(). Pour demander à l'utilisateur de s'authentifier et de déverrouiller l'appareil, appelez 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.
  }
});

Fenêtres flottantes

Pour la prise de notes contextuelle, votre application doit fournir une activité qui s'ouvre dans une fenêtre flottante lorsqu'une autre application est en cours d'exécution.

Votre application doit être compatible avec le mode multi-instance afin que les utilisateurs puissent créer plusieurs notes dans plusieurs fenêtres flottantes, même lorsque votre application de prise de notes est lancée en plein écran ou en mode Écran partagé.

Capture de contenu

La capture de contenu est une fonctionnalité essentielle des applications de prise de notes. Elle permet aux utilisateurs de faire des captures d'écran de l'écran situé derrière la fenêtre flottante de l'application de prise de notes. Les utilisateurs peuvent capturer la totalité ou une partie de l'écran, coller le contenu dans leur note et annoter ou mettre en surbrillance le contenu capturé.

Votre application de prise de notes doit fournir une affordance d'UI qui lance un ActivityResultLauncher créé par registerForActivityResult(). L'action d'intent ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE est fournie au lanceur d'applications directement ou via un ActivityResultContract.

Une activité système capture le contenu, l'enregistre sur l'appareil, puis renvoie l'URI du contenu à votre application dans l'argument de rappel de registerForActivityResult().

L'exemple suivant utilise un contrat StartActivityForResult générique :

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

Votre application doit gérer tous les codes de résultat :

Une fois la capture du contenu effectuée, collez l'image capturée dans la note, par exemple :

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

La fonctionnalité de capture de contenu doit être exposée par le biais d'une affordance d'UI uniquement lorsque votre application de prise de notes est exécutée dans une fenêtre flottante, et non lorsqu'elle est exécutée en plein écran, lancée depuis l'écran de verrouillage de l'appareil. (Les utilisateurs peuvent effectuer des captures d'écran de l'application de prise de notes elle-même grâce aux fonctionnalités de capture d'écran de l'appareil.)

Pour déterminer si votre application se trouve dans une fenêtre flottante (ou info-bulle), appelez les méthodes suivantes :

  • isLaunchedFromBubble() pour vérifier que l'application de prise de notes n'a pas été lancée en plein écran depuis l'écran de verrouillage de l'appareil
  • isRoleHeld(RoleManager.ROLE_NOTES) pour vérifier que votre application est l'application de prise de notes par défaut (votre application peut fonctionner dans une conversation ou un autre type d'info-bulle si l'application n'a pas le rôle "Notes")

Ressources supplémentaires