Criar um app de anotações

A criação de anotações é um recurso importante do Android, que aumenta a produtividade do usuário em dispositivos de tela grande. Os apps de anotações permitem que os usuários escrevam e desenhem em uma janela flutuante ou em tela cheia, capturem e façam anotações no conteúdo da tela e salvem anotações para revisão e revisão posterior.

Os usuários podem acessar os apps de anotação na tela de bloqueio ou enquanto executam outros apps.

O suporte da stylus à criação de anotações proporciona uma experiência excepcional aos usuários.

Papel de anotações

O papel RoleManager.ROLE_NOTES identifica apps de anotações e concede a eles a permissão LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE.

Para adquirir o papel de anotações do seu app, faça o seguinte:

  1. Chame isRoleAvailable() para verificar o status do papel.
  2. Se o papel de anotações estiver disponível, chame createRequestRoleIntent() para receber uma intent específica.
  3. Chame startActivityForResult() com a intent de notas para solicitar que o usuário conceda esse papel ao app.

Apenas um app pode ter esse papel.

O app é aberto em resposta a uma ação da intent implícita ACTION_CREATE_NOTE. Se invocado pela tela de bloqueio do dispositivo, o app é aberto em tela cheia. Se invocado enquanto a tela está desbloqueada, ele é aberto em uma janela flutuante.

Manifesto do app

Para se qualificar para o papel de anotações, seu app precisa incluir a seguinte declaração no manifesto:

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

A declaração permite que os usuários atribuam o papel de anotações ao app, tornando-o o aplicativo de anotações padrão:

  • ACTION_CREATE_NOTE define a ação da intent à qual seu app responde.

  • showWhenLocked torna o app acessível na tela de bloqueio do dispositivo.

  • turnScreenOn permite que o app ative a tela do dispositivo quando for executado.

Características do app

Um app de anotações diferenciado para telas grandes oferece um conjunto completo de recursos de anotação.

Suporte à stylus

Quando o app é invocado com o extra da intent EXTRA_USE_STYLUS_MODE definido como true, ele abre uma anotação que aceita entrada da stylus (ou toque de toque).

Se o extra da intent estiver definido como false, seu app precisará abrir uma anotação que aceite a entrada pelo teclado.

Acesso pela tela de bloqueio

Seu app precisa fornecer uma atividade em tela cheia que é executada quando ele é aberto na tela de bloqueio do dispositivo.

O app só vai mostrar notas históricas se o usuário tiver permitido (no estado do dispositivo desbloqueado) a exibição de notas anteriores. Caso contrário, quando aberto na tela de bloqueio, ele sempre precisará criar uma nova anotação.

É possível verificar se o app foi iniciado na tela de bloqueio com KeyguardManager#isKeyguardLocked(). Para pedir ao usuário para autenticar e desbloquear o dispositivo, chame KeyguardManager#requestDismissKeyguard():

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

Janelas flutuantes

Para anotações contextuais, seu app precisa fornecer uma atividade que seja aberta em uma janela flutuante quando outro aplicativo estiver em execução.

Seu app precisa oferecer suporte ao modo multi-instance para que os usuários possam criar várias notas em várias janelas flutuantes, mesmo quando o app de anotações for iniciado em tela cheia ou no modo de tela dividida.

Captura de conteúdo

A captura de conteúdo é um recurso importante dos apps de anotação. Com a captura de conteúdo, os usuários podem fazer capturas da tela por trás da janela flutuante do app de anotações. Os usuários podem capturar toda a tela ou parte dela, colar o conteúdo na nota e anotar ou destacar o conteúdo capturado.

Seu app de anotações precisa fornecer uma funcionalidade de interface que inicie uma ActivityResultLauncher criada por registerForActivityResult(). A ação da intent ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE é fornecida diretamente à tela de início ou usando um ActivityResultContract.

Uma atividade do sistema captura o conteúdo, salva no dispositivo e retorna o URI de conteúdo para o app no argumento de callback de registerForActivityResult().

O exemplo a seguir usa um contrato StartActivityForResult genérico:

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

Seu app precisa processar todos os códigos de resultado:

Quando a captura de conteúdo for concluída, cole a imagem capturada na nota. Por exemplo:

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

O recurso de captura de conteúdo precisa ser exposto em uma funcionalidade de interface somente quando o app de anotações está sendo executado em uma janela flutuante, e não quando executado em tela cheia, iniciado pela tela de bloqueio do dispositivo. Os usuários podem fazer capturas de tela do próprio app de anotações com recursos de captura de tela do dispositivo.

Para determinar se o app está em uma janela flutuante (ou um balão), chame os seguintes métodos:

  • isLaunchedFromBubble(), para verificar se o app de anotações não foi iniciado em tela cheia na tela de bloqueio do dispositivo.
  • isRoleHeld(RoleManager.ROLE_NOTES) para verificar se o app é o padrão para anotações. Ele poderá ser executado em uma conversa ou outro tipo de balão caso não tenha o papel de anotações.

Outros recursos