建立筆記應用程式

記事應用程式是 Android 的核心功能,可以提高使用者在大螢幕裝置上的工作效率。記事應用程式可讓使用者在浮動視窗或全螢幕畫面撰寫和素描,擷取螢幕畫面內容並加上註解,以及儲存記事供日後查看和修改。

記事應用程式可以從螢幕鎖定畫面存取,也可以在執行其他應用程式時使用。

支援使用觸控筆做記事,帶來卓越的使用者體驗。

「記事」角色

RoleManager.ROLE_NOTES 角色可識別記事應用程式,並授予其 LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE 權限。

如要取得應用程式的記事角色,請按照下列步驟操作:

  1. 如要查看角色狀態,請呼叫 isRoleAvailable()
  2. 如果可以使用記事角色,請呼叫 createRequestRoleIntent() 來取得記事專屬的意圖。
  3. 使用記事意圖呼叫 startActivityForResult(),提示使用者為應用程式授予記事角色。

只有一個應用程式可擁有記事角色。

應用程式會為了回應隱含的 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>

這項宣告可讓使用者將記事角色指派給應用程式,使其成為預設的記事應用程式:

應用程式功能

一款與眾不同的應用程式,提供完善的記事功能。

觸控筆支援

透過設為 trueEXTRA_USE_STYLUS_MODE 意圖額外項目叫用應用程式時,應用程式應開啟一則記事,接受以觸控筆 (或手指觸控) 輸入的內容。

如果意圖 Extra 設為 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 模式,這樣即使筆記應用程式以全螢幕模式或分割畫面模式啟動,使用者也能在多個浮動視窗中建立多則記事。

內容擷取

內容擷取是記事應用程式的重要功能,透過內容擷取功能,使用者可以擷取記事應用程式浮動視窗背後的螢幕截圖。使用者可以擷取全部或部分內容、將內容貼到自己的記事中,並加上註解或醒目顯示擷取的內容。

記事應用程式應提供 UI 預設用途,啟動 registerForActivityResult() 建立的 ActivityResultLauncher。系統會直接或透過 ActivityResultContract,將 ACTION_LAUNCH_CAPTURE_CONTENT_ACTIVITY_FOR_NOTE 意圖動作提供給啟動器。

系統活動會擷取內容並將其儲存在裝置上,然後在 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) 可驗證應用程式是否為預設的記事應用程式 (如果應用程式不具備記事角色,應用程式可在對話或其他類型的對話框中執行)

其他資源