Stwórz aplikację do robienia notatek

Robienie notatek to jedna z podstawowych funkcji Androida, która zwiększa produktywność użytkowników korzystających z urządzeń z dużymi ekranami. Aplikacje do notatek umożliwiają pisanie i szkicowanie w pływającym oknie lub na pełnym ekranie, przechwytywanie zawartości ekranu i dodawanie do niej adnotacji, a także zapisywanie notatek do późniejszego przejrzenia i poprawienia.

Użytkownicy mogą uzyskiwać dostęp do aplikacji do robienia notatek na ekranie blokady lub podczas uruchamiania innych aplikacji.

Obsługa rysika do robienia notatek zapewnia użytkownikom wyjątkowe wrażenia.

Rola w notatkach

Rola RoleManager.ROLE_NOTES identyfikuje aplikacje do notatek i przyzna im uprawnienie LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE.

Aby uzyskać rolę związaną z notatkami w aplikacji:

  1. Wywołaj isRoleAvailable(), aby sprawdzić stan roli.
  2. Jeśli rola notatek jest dostępna, wywołaj createRequestRoleIntent(), aby uzyskać intencję związaną z notatkami.
  3. Wywołaj metodę startActivityForResult() z intencją związaną z notatkami, aby zachęcić użytkownika do przypisania roli notatek do aplikacji.

Rolę notatek może mieć tylko jedna aplikacja.

Aplikacja otwiera się w odpowiedzi na niejawne działanie intencji ACTION_CREATE_NOTE. Jeśli zostanie wywołana z ekranu blokady urządzenia, aplikacja otwiera się na pełnym ekranie, a jeśli zostanie wywołana po odblokowaniu ekranu – w pływającym oknie.

Plik manifestu aplikacji

Aby kwalifikować się do roli notatek, aplikacja musi zawierać w manifeście tę deklarację:

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

Deklaracja umożliwia użytkownikom przypisanie do aplikacji roli do notatek, dzięki czemu jest to domyślna aplikacja do robienia notatek:

  • ACTION_CREATE_NOTE ustawia działanie intencji, na które odpowiada aplikacja

  • showWhenLocked umożliwia dostęp do aplikacji na ekranie blokady urządzenia

  • turnScreenOn umożliwia aplikacji włączanie ekranu urządzenia podczas działania aplikacji

Funkcje aplikacji

Zróżnicowana aplikacja do robienia notatek na dużym ekranie oferuje wszystkie funkcje.

Obsługa rysika

Po wywołaniu aplikacji z dodatkową intencją EXTRA_USE_STYLUS_MODE ustawioną na true aplikacja powinna otworzyć notatkę, która akceptuje wprowadzanie rysikiem (lub dotykiem).

Jeśli dodatek intencji ma wartość false, aplikacja powinna otwierać notatkę, która akceptuje wprowadzanie z klawiatury.

Dostęp do ekranu blokady

Aplikacja musi udostępniać aktywność na pełnym ekranie, gdy jest otwierana z ekranu blokady urządzenia.

Aplikacja powinna wyświetlać notatki historyczne tylko wtedy, gdy użytkownik wyraził zgodę (na odblokowanym urządzeniu) na pokazywanie wcześniejszych notatek. W przeciwnym razie po otwarciu na ekranie blokady aplikacja powinna zawsze tworzyć nową notatkę.

Aby sprawdzić, czy aplikacja została uruchomiona na ekranie blokady, użyj aplikacji KeyguardManager#isKeyguardLocked(). Aby poprosić użytkownika o uwierzytelnienie i odblokowanie urządzenia, wywołaj metodę 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.
  }
});

Pływające okna

Aby możliwe było kontekstowe robienie notatek, aplikacja musi udostępniać aktywność, która otwiera się w pływającym oknie, gdy uruchomiona jest inna aplikacja.

Twoja aplikacja powinna obsługiwać tryb multi-instance, aby użytkownicy mogli tworzyć wiele notatek w wielu pływających oknach nawet wtedy, gdy aplikacja do robienia notatek jest uruchomiona na pełnym ekranie lub w trybie podzielonego ekranu.

Rejestrowanie treści

Przechwytywanie treści to kluczowa funkcja aplikacji do notatek. Przechwytywanie treści pozwala użytkownikom robić zrzuty ekranu ekranu za pływającym oknem aplikacji do robienia notatek. Użytkownicy mogą przechwycić cały ekran lub jego część, wkleić treść do notatki i dodać adnotacje lub zaznaczyć treść.

Aplikacja do notatek powinna udostępniać interfejs użytkownika, który uruchamia ActivityResultLauncher utworzony przez registerForActivityResult(). Działanie intencji ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE jest przekazywane do programu uruchamiającego bezpośrednio lub przez ActivityResultContract.

Aktywność systemu przechwytuje treść, zapisuje ją na urządzeniu i zwraca identyfikator URI treści do aplikacji w argumentie wywołania zwrotnego registerForActivityResult().

W tym przykładzie użyto ogólnej umowy 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));
        });
}

Aplikacja powinna obsługiwać wszystkie kody wyników:

Jeśli uda się przechwycić treść, wklej do notatki przechwycony obraz, na przykład:

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

Funkcja przechwytywania treści powinna być widoczna w interfejsie tylko wtedy, gdy aplikacja do robienia notatek działa w pływającym oknie, a nie w trybie pełnoekranowym, ale uruchamiana z poziomu ekranu blokady urządzenia. (Użytkownicy mogą robić zrzuty ekranu aplikacji do notatek za pomocą funkcji tworzenia zrzutów ekranu na urządzeniu).

Aby określić, czy aplikacja jest w pływającym oknie (lub dymku), wywołaj te metody:

  • isLaunchedFromBubble(), aby sprawdzić, czy aplikacja do robienia notatek nie została uruchomiona na pełnym ekranie z poziomu ekranu blokady urządzenia;
  • isRoleHeld(RoleManager.ROLE_NOTES), aby sprawdzić, czy aplikacja jest domyślną aplikacją do robienia notatek (aplikacja może działać w rozmowie lub w dymku innego typu, jeśli nie ma przypisanej roli notatek).

Dodatkowe materiały