A criação de anotações é um recurso importante do Android, que melhora 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 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:
- Chame
isRoleAvailable()
para verificar o status do papel. - Se o papel de anotações estiver disponível, chame
createRequestRoleIntent()
para receber uma intent específica. - Chame
startActivityForResult()
com a intent de anotações para solicitar que o usuário conceda esse papel ao seu 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
inteira. 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, o 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 notas padrão:
ACTION_CREATE_NOTE
define a ação da intent a que o 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 do dedo).
Se o extra da intent estiver definido como false
, seu app precisará abrir uma anotação que aceite
entrada do teclado.
Acesso pela tela de bloqueio
O app precisa oferecer 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, o app sempre precisará criar uma nova anotação.
É possível conferir se o app foi iniciado na tela de bloqueio com
KeyguardManager#isKeyguardLocked()
.
Para pedir que o usuário autentique e desbloqueie o dispositivo, chame
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. } });
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.
O app precisa oferecer suporte ao modo
multi-instance
para que os usuários possam criar várias notas em diversas 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 nas anotações 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 à tela de início diretamente ou por 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:
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)); }); }
Seu app precisa processar todos os códigos de resultado:
CAPTURE_CONTENT_FOR_NOTE_SUCCESS
CAPTURE_CONTENT_FOR_NOTE_FAILED
CAPTURE_CONTENT_FOR_NOTE_USER_CANCELED
CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPPORTED
CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN
Quando a captura de conteúdo for bem-sucedida, cole a imagem capturada na nota, por exemplo:
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. } });
O recurso de captura de conteúdo precisará ser exposto em uma funcionalidade de interface somente quando o app de anotações estiver em execução em uma janela flutuante, e não quando estiver 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 usando os recursos de captura de tela do dispositivo.
Para determinar se o app está em uma janela flutuante (ou um balão), chame estes métodos:
isLaunchedFromBubble()
para verificar se o app de anotações não foi iniciado em tela cheia pela tela de bloqueio do dispositivo.isRoleHeld(RoleManager.ROLE_NOTES)
para verificar se o app é o padrão para anotações. O app pode ser executado em uma conversa ou outro tipo de balão caso não tenha o papel de anotações.