Android Jetpack(四) 行爲

image.png

1、CameraX - 輕鬆地嚮應用中添加相機功能

CameraX 是一個 Jetpack 支持庫,旨在幫助您簡化相機應用的開發工作。它提供一致且易於使用的 API 界面,適用於大多數 Android 設備,並可向後兼容至 Android 5.0(API 級別 21)。
CameraX Extensions 是可選插件,通過該插件,您可以在支持的設備上向自己的應用中添加人像、HDR、夜間模式和美顏等效果。

主要優勢

易用性

CameraX 引入了多個用例,使您可以專注於需要完成的任務,而無需花時間處理不同設備之間的細微差別

確保各設備間的一致性

自動化 CameraX 測試實驗室可確保在多種類型的設備和多個製造商之間實現一致的 API 體驗。

新的相機體驗

CameraX 有一個名爲 Extensions 的可選插件,您只需兩行代碼,便可藉助該插件使用與設備自帶的原生相機應用相同的特性和功能。

首批可用功能包括人像、HDR、夜間模式和美顏。這些功能可在受支持的設備上使用。

Codelab

CameraX 使用入門

代碼示例

官方 CameraX 示例應用

2、下載管理器- 安排和管理大量下載任務

3、媒體和播放- 用於媒體播放和路由(包括 Google Cast)的向後兼容 API

在 Android 中,您可以從零開始構建自己的播放器,也可以從以下選項中進行選擇:

  • MediaPlayer 類提供準系統播放器的基本功能,支持最常見的音頻/視頻格式和數據源。
  • ExoPlayer 是一個提供低層級 Android 音頻 API 的開放源代碼庫。ExoPlayer 支持 DASH 和 HLS 流等高性能功能,這些功能在 MediaPlayer 中未提供。您可以自定義 ExoPlayer 代碼,從而輕鬆添加新組件。ExoPlayer 只能用於 Android 4.1 及更高版本。

media-compat 庫

media-compat 庫包含可幫助您構建音頻和視頻應用的類。這些類與運行 Android 2.3(API 級別 9)及更高版本的設備兼容。它們還可與其他 Android 功能配合使用,以打造舒適親切的 Android 體驗。

媒體會話和媒體控制器的建議實現方式是 MediaSessionCompatMediaControllerCompat 類,它們在 media-compat 支持庫中定義。它們取代了 Android 5.0(API 級別 21)中引入的早期版本的 MediaSessionMediaController 類。compat 類提供相同的功能,但可讓您更輕鬆地開發應用,因爲您只需寫入一個 API。該庫通過將媒體會話方法轉換爲更低版本平臺上的等效方法(可用時)來保證向後兼容性。

如果您已經有使用舊類的實際應用,我們建議更新到 compat 類

衡量性能

在 Android 8.0(API 級別 26)及更高版本中,getMetrics() 方法可用於某些媒體類。它會返回一個包含配置和性能信息的 PersistableBundle 對象(表示爲屬性和值的對應關係)。可以爲這些媒體類定義 getMetrics() 方法:

4、通知 - 提供向後兼容的通知 API,支持 Wear 和 Auto

通知的設計由系統模板決定,您的應用只需定義模板各部分的內容。通知的某些詳細信息僅在展開視圖中顯示。

image

圖 7. 包含基本詳情的通知

圖 7 展示了通知最常見的部分,具體如下所示:

  1. 小圖標:此爲必要圖標,通過 setSmallIcon() 設置。
  2. 應用名稱:此由系統提供。
  3. 時間戳:此由系統提供,不過您可以通過 setWhen() 進行替換,或使用 setShowWhen(false) 將其隱藏。
  4. 大圖標:此爲可選圖標(通常僅用於聯繫人照片;請勿將其用於應用圖標),通過 setLargeIcon() 設置。
  5. 標題:此爲可選內容,通過 setContentTitle() 設置。
  6. 文本:此爲可選內容,通過 setContentText()設置。

版本差異

從 Android 7.0(API 級別 24)開始,您可以添加操作來回復消息,或者直接從通知中輸入其他文本。
從 Android 10(API 級別 29)開始,平臺可以自動生成操作按鈕,此類按鈕包含基於 Intent 的建議操作。

在 Android 8.0 及更高版本上,用戶可以更改每個渠道的重要性
可能的重要性級別如下:
緊急:發出聲音並以浮動通知的形式顯示。
高:發出聲音。
中:不發出聲音。
低:不發出聲音,也不在狀態欄中顯示。

以下是最明顯的 Android 通知行爲變化的摘要。

Android 4.1(API 級別 16)

引入了展開式通知模板(稱爲通知樣式),可以提供較大的通知內容區域來顯示信息。用戶可以使用單指向上/向下滑動的手勢來展開通知。
還支持以按鈕形式向通知添加其他操作。
允許用戶在設置中按應用關閉通知。

Android 4.4(API 級別 19 和 20)

向 API 中添加了通知偵聽器服務
API 級別 20 中添加了對 Android Wear(現稱爲 Wear OS)的支持。

Android 5.0(API 級別 21)

引入了鎖定屏幕和浮動通知。
用戶現在可以將手機設置爲“請勿打擾”模式,並配置當設備處於“僅限優先事項”模式時,哪些通知可以打擾他們。
向 API 集添加了通知是否在鎖定屏幕上顯示的方法 (setVisibility()),以及指定通知文本的“公開”版本的方法。
添加了 setPriority() 方法,告知系統該通知應具有的“干擾性”(例如,將其設置爲“高”,可使該通知以浮動通知的形式顯示)。
Android Wear(現稱爲 Wear OS)設備添加了通知堆棧支持。使用 setGroup() 將通知放入堆棧。請注意,平板電腦和手機尚不支持通知堆棧。通知堆棧以後會稱爲組或 Bundle。

Android 7.0(API 級別 24)

重新設計了通知模板的樣式,以強調主打圖像和頭像。
添加了三個通知模板:一個用於消息應用,另外兩個用於使用可擴展選項和其他系統裝飾來裝飾自定義內容視圖。
向手持設備(手機和平板電腦)添加了對通知組的支持。使用與 Android 5.0(API 級別 21)中引入的 Android Wear(現稱爲 Wear OS)通知堆棧相同的 API。
用戶可以使用內聯回覆直接在通知內回覆(用戶可以輸入文本,然後將其發送給通知的父級應用)。

Android 8.0(API 級別 26)

現在必須將單個通知放入特定渠道中。
用戶現在可以按渠道關閉通知,而不是關閉應用的所有通知。
包含活動通知的應用會在主屏幕/啓動器屏幕上的應用圖標上方顯示通知“標誌”。
現在,用戶可以暫停抽屜式通知欄中的通知。您可以爲通知設置自動超時。
您還可以設置通知的背景顏色。
與通知行爲相關的部分 API 已從 Notification 移至 NotificationChannel。例如,對 Android 8.0 及更高版本使用 NotificationChannel.setImportance(),而不是 NotificationCompat.Builder.setPriority()。

創建通知

dependencies {
        implementation "com.android.support:support-compat:28.0.0"
    }

設置通知內容 ,

//CHANNEL_ID:渠道 ID
   var builder = NotificationCompat.Builder(this, CHANNEL_ID)
//小圖標
            .setSmallIcon(R.drawable.notification_icon)
//標題
            .setContentTitle(textTitle)
//正文
            .setContentText(textContent)
//更長的可展開的通知
//創建包含可展開詳情的通知(https://developer.android.google.cn/training/notify-user/expanded)。

.setStyle(NotificationCompat.BigTextStyle()
                    .bigText("Much longer text that cannot fit one line..."))
//優先級
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)

創建渠道並設置重要性

private fun createNotificationChannel() {
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name = getString(R.string.channel_name)
            val descriptionText = getString(R.string.channel_description)
            val importance = NotificationManager.IMPORTANCE_DEFAULT
            val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
                description = descriptionText
            }
            // Register the channel with the system
            val notificationManager: NotificationManager =
                getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            notificationManager.createNotificationChannel(channel)
        }
    }

設置通知的點按操作

 // Create an explicit intent for an Activity in your app
    val intent = Intent(this, AlertDetails::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, 0)

    val builder = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle("My notification")
            .setContentText("Hello World!")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            // Set the intent that will fire when the user taps the notification
            .setContentIntent(pendingIntent)
            .setAutoCancel(true)

請注意,該代碼會調用 setAutoCancel(),它會在用戶點按通知後自動移除通知

顯示通知

要顯示通知,請調用 NotificationManagerCompat.notify(),並將通知的唯一 ID 和 NotificationCompat.Builder.build()的結果傳遞給它。例如:

    with(NotificationManagerCompat.from(this)) {
        // notificationId is a unique int for each notification that you must define
        notify(notificationId, builder.build())
    }
    

添加操作按鈕

要添加操作按鈕,請將 PendingIntent 傳遞給 addAction() 方法。這就像是設置通知的默認點按操作,不同的是不會啓動 Activity,而是可以完成各種其他任務
例如啓動在後臺執行作業的 BroadcastReceiver,這樣該操作就不會干擾已經打開的應用。

 val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
        action = ACTION_SNOOZE
        putExtra(EXTRA_NOTIFICATION_ID, 0)
    }
    val snoozePendingIntent: PendingIntent =
        PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
    val builder = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle("My notification")
            .setContentText("Hello World!")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setContentIntent(pendingIntent)
            .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                    snoozePendingIntent)

添加直接回復操作

Android 7.0(API 級別 24)中引入的直接回復操作允許用戶直接在通知中輸入文本,然後會直接提交給應用
1、創建 RemoteInput.Builder 的實例以便您添加到通知操作

   // Key for the string that's delivered in the action's intent.
    private val KEY_TEXT_REPLY = "key_text_reply"
    var replyLabel: String = resources.getString(R.string.reply_label)
    var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
        setLabel(replyLabel)
        build()
    }

2、爲回覆操作創建 PendingIntent

 // Build a PendingIntent for the reply action to trigger.
    var replyPendingIntent: PendingIntent =
        PendingIntent.getBroadcast(applicationContext,
            conversation.getConversationId(),
            getMessageReplyIntent(conversation.getConversationId()),
            PendingIntent.FLAG_UPDATE_CURRENT)

3、使用 addRemoteInput() 將 RemoteInput 對象附加到操作。

 // Create the reply action and add the remote input.
    var action: NotificationCompat.Action =
        NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
            getString(R.string.label), replyPendingIntent)
            .addRemoteInput(remoteInput)
            .build()
    

4、對通知應用操作併發出通知。

    // Build the notification and add the action.
    val newMessageNotification = Notification.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_message)
            .setContentTitle(getString(R.string.title))
            .setContentText(getString(R.string.content))
            .addAction(action)
            .build()

    // Issue the notification.
    with(NotificationManagerCompat.from(this)) {
        notificationManager.notify(notificationId, newMessageNotification)
    }

要從通知回覆界面接收用戶輸入,請調用 RemoteInput.getResultsFromIntent() 並將 BroadcastReceiver 收到的 Intent 傳遞給它:

 private fun getMessageText(intent: Intent): CharSequence? {
        return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
    }

處理完文本後,必須使用相同的 ID 和標記(如果使用)調用 NotificationManagerCompat.notify() 來更新通知。若要隱藏直接回復界面並向用戶確認他們的回覆已收到並得到正確處理,則必須完成該操作。

   // Build a new notification, which informs the user that the system
    // handled their interaction with the previous notification.
    val repliedNotification = Notification.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_message)
            .setContentText(getString(R.string.replied))
            .build()

    // Issue the new notification.
    NotificationManagerCompat.from(this).apply {
        notificationManager.notify(notificationId, repliedNotification)
    }

在處理這個新通知時,請使用傳遞給接收者的 onReceive() 方法的上下文。

您還應通過調用 setRemoteInputHistory() 將回復附加到通知底部。但如果要構建消息應用,應創建消息式通知,並在會話中附加新消息。

有關來自消息應用的通知的更多建議,請參閱消息應用的最佳做法

添加進度條

image.png
通過調用 setProgress(max, progress, false) 使用指示器。
第一個參數是“完成”值(如 100);第二個參數是當前完成的進度,最後一個參數表明這是一個確定性進度條。

 val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
        setContentTitle("Picture Download")
        setContentText("Download in progress")
        setSmallIcon(R.drawable.ic_notification)
        setPriority(NotificationCompat.PRIORITY_LOW
    }
    val PROGRESS_MAX = 100
    val PROGRESS_CURRENT = 0
    NotificationManagerCompat.from(this).apply {
        // Issue the initial notification with zero progress
        builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
        notify(notificationId, builder.build())

        // Do the job here that tracks the progress.
        // Usually, this should be in a
        // worker thread
        // To show progress, update PROGRESS_CURRENT and update the notification with:
        // builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
        // notificationManager.notify(notificationId, builder.build());

        // When done, update the notification one more time to remove the progress bar
        builder.setContentText("Download complete")
                .setProgress(0, 0, false)
        notify(notificationId, builder.build())
    }

操作結束時,progress 應等於 max。您可以在操作完成後仍保留顯示進度條,也可以將其移除。要移除進度條,請調用 setProgress(0, 0, false)

要顯示不確定性進度條(不指示完成百分比的進度條),請調用 setProgress(0, 0, true)
結果會產生一個與上述進度條樣式相同的指示器,區別是這個進度條是一個持續動畫,不指示完成情況。
在您調用 setProgress(0, 0, false) 之前,進度動畫會一直運行,調用後系統會更新通知以移除 Activity 指示器。

設置系統範圍的類別

如果您的通知屬於 NotificationCompat 中定義的預定義通知類別之一
(例如 CATEGORY_ALARM、CATEGORY_REMINDER、CATEGORY_EVENT 或 CATEGORY_CALL),
您應通過將相應類別傳遞到 setCategory() 來進行聲明。

  var builder = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle("My notification")
            .setContentText("Hello World!")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setCategory(NotificationCompat.CATEGORY_MESSAGE)

顯示緊急消息

注意:如果應用的目標平臺是 Android 10(API 級別 29)或更高版本,必須在應用清單文件中請求 USE_FULL_SCREEN_INTENT 權限,以便系統啓動與時效性通知關聯的全屏 Activity。
以下代碼段展示瞭如何將通知與全屏 Intent 關聯:

    val fullScreenIntent = Intent(this, ImportantActivity::class.java)
    val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
        fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

    var builder = NotificationCompat.Builder(this, CHANNEL_ID)
            .setSmallIcon(R.drawable.notification_icon)
            .setContentTitle("My notification")
            .setContentText("Hello World!")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT)
            .setFullScreenIntent(fullScreenPendingIntent, true)

設置鎖定屏幕公開範圍

要控制鎖定屏幕中通知的可見詳情級別,請調用 setVisibility() 並指定以下值之一:

更新通知

要在發出此通知後對其進行更新,請再次調用 NotificationManagerCompat.notify(),並將之前使用的具有同一 ID 的通知傳遞給該方法。如果之前的通知已被關閉,則系統會創建一個新通知。

您可以選擇性調用 setOnlyAlertOnce(),這樣通知只會在通知首次出現時打斷用戶(通過聲音、振動或視覺提示),而之後更新則不會再打斷用戶。

有關消息應用的最佳做法

從 Android 7.0(API 級別 24)起,Android 提供了專用於消息內容的通知樣式模板。使用 NotificationCompat.MessagingStyle 類,您可以更改在通知中顯示的多個標籤,包括會話標題、其他消息和通知的內容視圖。
以下代碼段展示瞭如何使用 MessagingStyle 類自定義通知的樣式。

    var notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setStyle(NotificationCompat.MessagingStyle("Me")
                    .setConversationTitle("Team lunch")
                    .addMessage("Hi", timestamp1, null) // Pass in null for user.
                    .addMessage("What's up?", timestamp2, "Coworker")
                    .addMessage("Not much", timestamp3, null)
                    .addMessage("How about lunch?", timestamp4, "Coworker"))
            .build()

從 Android 8.0(API 級別 26)起,使用 NotificationCompat.MessagingStyle 類的通知會在採用摺疊形式時顯示更多內容

5、權限 - 用於檢查和請求應用權限的兼容性 API

6、偏好設置 - 創建交互式設置屏幕

**注意:**本指南介紹如何使用 AndroidX Preference Library。自 Android 10 開始,系統已棄用 android.preference 庫平臺。

創建層次結構

<PreferenceScreen
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <SwitchPreferenceCompat
        app:key="notifications"
        app:title="Enable message notifications"/>

    <Preference
        app:key="feedback"
        app:title="Send feedback"
        app:summary="Report technical issues or suggest new features"/>

</PreferenceScreen>

擴充層次結構

class MySettingsFragment : PreferenceFragmentCompat() {
    override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
        setPreferencesFromResource(R.xml.preferences, rootKey)
    }
}

然後,與您對其他 Fragment 進行的操作一樣,您可以將此 Fragment 添加到您的 Activity:

class MySettingsActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        supportFragmentManager
                .beginTransaction()
                .replace(R.id.settings_container, MySettingsFragment())
                .commit()
    }
}

7、共享 - 提供適合應用操作欄的共享操作

Android 應用的一大優點是它們能夠互相通信和集成。如果某一功能並非應用的核心,而且已存在於另一個應用中,爲何要重新開發它?

本節說明如何藉助 Intent對象使用 Android Sharesheet 和 Intent Resolver 在不同應用之間發送和接收簡單數據(如文本、圖像和文件)的一些常用方法。

1、將簡單的數據發送給其他應用

Android 爲用戶提供了兩種在應用之間分享數據的方式:

  • Android Sharesheet 主要用於將內容發送到應用外部和/或直接發送給其他用戶。例如,將網址分享給朋友。
  • Android intent 解析器最適合將數據傳遞到明確定義的任務的下一個階段。例如,從應用中打開 PDF,並讓用戶挑選他們首選的查看器。

發送文本內容

    val sendIntent: Intent = Intent().apply {
        action = Intent.ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }

    val shareIntent = Intent.createChooser(sendIntent, null)
    startActivity(shareIntent)

發送二進制內容

 val shareIntent: Intent = Intent().apply {
        action = Intent.ACTION_SEND
        putExtra(Intent.EXTRA_STREAM, uriToImage)
        type = "image/jpeg"
    }
    startActivity(Intent.createChooser(shareIntent, resources.getText(R.string.send_to)))

使用正確的 MIME 類型

您應該爲要發送的數據提供最具體的 MIME 類型。例如,分享純文本時,應使用 text/plain。以下是在 Android 中發送簡單數據時一些常用的 MIME 類型。

  • text/plain、text/rtf、text/html 和 text/json,接收方應註冊 text/*
  • image/jpg、image/png 和 image/gif,接收方應註冊 image/*
  • video/mp4 和 video/3gp,接收方應註冊 video/*
  • application/pdf,接收方應註冊支持的文件擴展名
  • 您可以使用 MIME 類型 /,但強烈建議您不要這樣做,因爲它僅與能夠處理通用數據流的 Activity 匹配。
    Android Sharesheet 可能會根據提供的 MIME 類型顯示內容預覽。某些預覽功能僅適用於特定類型。

分享多份內容

要分享多份內容,請將 ACTION_SEND_MULTIPLE 操作與指向該內容的一系列 URI 一起使用

    val imageUris: ArrayList<Uri> = arrayListOf(
            // Add your image URIs here
            imageUri1,
            imageUri2
    )

    val shareIntent = Intent().apply {
        action = Intent.ACTION_SEND_MULTIPLE
        putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris)
        type = "image/*"
    }
    startActivity(Intent.createChooser(shareIntent, "Share images to.."))

向文本預覽添加豐富的內容

從 Android 10(API 級別 29)開始,Android Sharesheet 可以顯示分享的文本的預覽。
如果要預覽文本,您可以設置標題和/或縮略圖。在調用 Intent.createChooser() 之前,先添加 Intent.EXTRA_TITLE 的說明。通過 ClipData 添加相關的縮略圖。

     val share = Intent.createChooser(Intent().apply {
          action = Intent.ACTION_SEND
          putExtra(Intent.EXTRA_TEXT, "https://developer.android.com/training/sharing/")

          // (Optional) Here we're setting the title of the content
          putExtra(Intent.EXTRA_TITLE, "Introducing content previews")

          // (Optional) Here we're passing a content URI to an image to be displayed
          setClipData(contentUri);
          setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
      }, null)
      startActivity(share)

添加自定義目標

在調用 Intent.createChooser() 之後,向您的分享 intent 添加 Intent.EXTRA_CHOOSER_TARGETSIntent.EXTRA_INITIAL_INTENTS

val share = Intent.createChooser(myShareIntent, null).apply {
        putExtra(Intent.EXTRA_CHOOSER_TARGETS, myChooserTargetArray)
        putExtra(Intent.EXTRA_INITIAL_INTENTS, myInitialIntentArray)
    }

按組件排除特定目標

在調用 Intent.createChooser() 之後,向您的 intent 添加 Intent.EXTRA_EXCLUDE_COMPONENTS

  val share = Intent.createChooser(myShareIntent, null).apply {
      // Only use components you have control over
      share.putExtra(Intent.EXTRA_EXCLUDE_COMPONENTS, myComponentArray)
    }

獲取有關分享的信息

   var share = new Intent(Intent.ACTION_SEND);
    ...
    val pi = PendingIntent.getBroadcast(myContext, requestCode, Intent(myContext, MyBroadcastReceiver.class),
    Intent.FLAG_UPDATE_CURRENT)
    share = Intent.createChooser(share, null, pi.intentSender);

然後,在 MyBroadcastReceiver 中接收回調,並查看 Intent.EXTRA_CHOSEN_COMPONENT

    override fun onReceive(context: Context, intent: Intent) {
      ...
      val clickedComponent : ComponentName = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
    }
    

使用 Android intent 解析器

    val sendIntent: Intent = Intent().apply {
        action = Intent.ACTION_SEND
        putExtra(Intent.EXTRA_TEXT, "This is my text to send.")
        type = "text/plain"
    }
    startActivity(sendIntent)

2、從其他應用接收簡單的數據

您的應用可以通過三種方式接收其他應用發送的數據:

  • 在清單中有匹配的 intent-filter 標記的 Activity
  • 由您的 ChooserTargetService 返回的一個或多個 ChooserTarget 對象
  • 您的應用發佈的共享快捷方式。它們將取代 ChooserTarget 對象。只有當您的應用在 Android 10(API 級別 29)平臺上運行時,纔可以使用共享快捷方式。

支持 MIME 類型

您的應用應支持接收儘可能廣泛的 MIME 類型。例如,用於發送文本、圖像和視頻的短信應用應支持接收 text/、image/ 和 video/*。以下是在 Android 中發送簡單數據時常見的一些 MIME 類型。

text/,發送方通常會發送 text/plain、text/rtf、text/html、text/json
image/
,發送方通常會發送 image/jpg、image/png、image/gif
video/*,發送方通常會發送 video/mp4、video/3gp
接收方應註冊受支持的文件擴展名,發送方通常會發送 application/pdf

通過 Activity 接收數據

  <activity android:name=".ui.MyActivity" >
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="image/*" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.SEND_MULTIPLE" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="image/*" />
        </intent-filter>
    </activity>

處理傳入的內容

要處理 Intent 傳送的內容,請調用 getIntent() 以獲取 Intent 對象

override fun onCreate(savedInstanceState: Bundle?) {
        ...
        when {
            intent?.action == Intent.ACTION_SEND -> {
                if ("text/plain" == intent.type) {
                    handleSendText(intent) // Handle text being sent
                } else if (intent.type?.startsWith("image/") == true) {
                    handleSendImage(intent) // Handle single image being sent
                }
            }
            intent?.action == Intent.ACTION_SEND_MULTIPLE
                    && intent.type?.startsWith("image/") == true -> {
                    handleSendMultipleImages(intent) // Handle multiple images being sent
            }
            else -> {
                // Handle other intents, such as being started from the home screen
            }
        }
        ...
    }

    private fun handleSendText(intent: Intent) {
        intent.getStringExtra(Intent.EXTRA_TEXT)?.let {
            // Update UI to reflect text being shared
        }
    }

    private fun handleSendImage(intent: Intent) {
        (intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri)?.let {
            // Update UI to reflect image being shared
        }
    }

    private fun handleSendMultipleImages(intent: Intent) {
        intent.getParcelableArrayListExtra<Parcelable>(Intent.EXTRA_STREAM)?.let {
            // Update UI to reflect multiple images being shared
        }
    }
    

確保用戶能夠識別您的應用

從 Android 10(API 級別 29)開始,Android Sharesheet 將僅使用清單中的 application 標籤上設置的圖標。在 intent-filter 和 activity 標籤上設置的圖標將被忽略。

提供直接共享目標

直接共享於 Android 6.0(API 級別 23)中引入,支持應用通過 ChooserTargetService 提供 ChooserTarget 對象。在此機制下,系統會根據需要被動檢索結果,從而造成目標加載緩慢。
在 Android 10(API 級別 29)中,新的 Sharing Shortcuts API 取代了 ChooserTargetService Direct Share API。
要查看發佈共享快捷方式的示例,請參閱共享快捷方式代碼示例

獲得最佳排名

 val person = Person.Builder()
      ...
      .setName(fullName)
      .setKey(staticPersonIdentifier)
      .setUri("tel:$phoneNumber") // alternatively "mailto:$email" or CONTENT_LOOKUP_URI
      .build()

    val shortcutInfo = ShortcutInfoCompat.Builder(myContext, staticPersonIdentifier)
      ...
      .setShortLabel(firstName)
      .setLongLabel(fullName)
      .setPerson(person)
//通過調用 setLongLived(true)確保快捷方式長期存在。

      .setLongLived(true)
      .setRank(personRank)
      .build()
    
  val notif = NotificationCompat.Builder(myContext, channelId)
      ...
//確保所有 shortcutId 獨一無二,且不在不同的目標上重複使用。
      .setShortcutId(staticPersonIdentifier)
      .build()

提供快捷方式圖像

要製作共享快捷方式,您需要通過 setIcon() 添加圖像。

聲明共享目標

    <shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
      <share-target android:targetClass="com.example.android.sharingshortcuts.SendMessageActivity">
        <data android:mimeType="text/plain" />
        <category android:name="com.example.android.sharingshortcuts.category.TEXT_SHARE_TARGET" />
      </share-target>
    </shortcuts>

使用 AndroidX 提供共享快捷方式和 ChooserTarget

    <activity
        android:name=".SendMessageActivity"
        android:label="@string/app_name"
        android:theme="@style/SharingShortcutsDialogTheme">
        <!-- This activity can respond to Intents of type SEND -->
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
        </intent-filter>
        <!-- Only needed if you import the sharetarget AndroidX library that
             provides backwards compatibility with the old DirectShare API.
             The activity that receives the Sharing Shortcut intent needs to be
             taken into account with this chooser target provider. -->
        <meta-data
            android:name="android.service.chooser.chooser_target_service"
            android:value="androidx.sharetarget.ChooserTargetServiceCompat" />
    </activity>

8、切片 - 創建可在應用外部顯示應用數據的靈活界面元素

Android Jetpack 內置了對切片的支持,並且可以向後一直擴展到 Android 4.4,覆蓋約 95% 的 Android 用戶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章