Android R對ACTION_IMAGE_CAPTURE的限制

說到ACTION_IMAGE_CAPTURE,大家肯定不陌生,如果我們只想簡簡單單拍個照片,然后在應(yīng)用中使用,那它肯定是最快的方式。只需:

  1. 調(diào)起第三方相機應(yīng)用,
  2. 讓用戶選擇自己喜歡的相機拍照,
  3. 把結(jié)果返回給我們的應(yīng)用即可。
    三步即可使用第三方提供給我們的豐富功能。

當(dāng)然ACTION_IMAGE_CAPTURE也是有不少坑的:

  • 有些相機會以豎屏的形式保存圖片,有些相機會以橫屏方式保存圖片,設(shè)置一個EXIF標(biāo)志說“嘿,圖片查看器,展示的時候請給我旋轉(zhuǎn)一下”。但是BitmapFactory會忽略此標(biāo)志,因此Android應(yīng)用程序經(jīng)常直接忽略掉這個標(biāo)志將這些圖片作為橫向圖片加載。而且,這些行為居然都是合法的,因為 ACTION_IMAGE_CAPTURE沒有明確指定用哪種方式保存。

  • 有些相機會直接使用前置相機拍攝的圖片,有些會反轉(zhuǎn)一下圖片,使圖片看起來跟在相機預(yù)覽中看到的圖片保持一致。這些也都是合法的,因為 ACTION_IMAGE_CAPTURE也沒有明確指定該怎么做。

  • 文檔說默認(rèn)情況下,相機應(yīng)該返回“a small sized image”,但符合什么標(biāo)準(zhǔn)才是“a small sized image”它沒說。我們知道由于IPC的限制,它必須小于1MB,但是相機應(yīng)用可以決定它是120x80的縮略圖還是512x512的圖片。

  • 文檔說我們可以用EXTRA_OUTPUT來指定圖片保存的位置,但是什么樣的EXTRA_OUTPUT是有效的,文檔沒說。是只能用file:// Uri呢,還是content:// Uri也有效呢?

谷歌一直對ACTION_IMAGE_CAPTURE也沒怎么管,好在一般我們用這個方式拍攝的圖片要么會進行裁切旋轉(zhuǎn)處理,要么不處理直接上傳,似乎也沒出過什么大的問題。

而最近我在看R的行為變更時碰巧看到了它的身影。

從 Android 11 開始,只有預(yù)裝的系統(tǒng)相機應(yīng)用可以響應(yīng)以下 intent 操作:

目前看來如果用戶禁用預(yù)裝的相機應(yīng)用,即使用戶安裝了其它的相機應(yīng)用,都會拋出ActivityNotFoundException。谷歌對此回應(yīng)稱是" working as intended ",為了用戶的安全和隱私故意為之。引來了不少開發(fā)者的吐槽:

  • 能否詳細(xì)說說用第三方相機怎么不安全了?
  • 我想知道安卓什么時候會為了用戶安全考慮禁止選擇默認(rèn)瀏覽器。
  • 我不太認(rèn)同安卓實現(xiàn)這次改變的方式,能不能增加一個開發(fā)者選項讓原來的選項回來,然后大部分享受這個改變帶來的"好處",其他人還按需選擇。到目前為止我看到Android 11上都是一些負(fù)面更新,這個在相機上的決定無濟于事。

我覺得谷歌可能是覺得第三方相機可能會惡意收集數(shù)據(jù),所以在這方面比較激進。這項改變不受限于targetSdkVersion,哪怕targetSdkVersion設(shè)置成29,在Android 11的手機上,應(yīng)用也會收到ActivityNotFoundException異常 。而且即使清單文件中包含<queries>元素,我們也不能通過queryIntentActivities()用來查找所有支持我們Intent 操作的Activity。

然后文檔給了一種不算解決方法的解決方法:

如果您希望自己的應(yīng)用使用特定的第三方相機應(yīng)用來代表其捕獲圖片或視頻,可以通過為 intent 設(shè)置軟件包名稱或組件來使這些 intent 變得明確。

這也適用于EXTRA_INITIAL_INTENTS

private val CAMERA_CANDIDATES = listOf(
  "com.xxx.xxxcamera"
)

fun enhanceCameraIntent(context: Context, baseIntent: Intent, title: String): Intent {
  val pm = context.packageManager

  val cameraIntents =
    CAMERA_CANDIDATES.map { Intent(baseIntent).setPackage(it) }
      .filter { pm.queryIntentActivities(it, 0).isNotEmpty() }
      .toTypedArray()

  return Intent.createChooser(baseIntent, title)
    .putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents)
}

在這里,如果同時有2個以上的相機應(yīng)用可用,enhanceCameraIntent()將返回一個展示選擇器的Intent,展示預(yù)裝的相機跟你想要的相機。如果只有你想要的相機可用,或者只有預(yù)裝的相機可用,那么會跳過選擇直接打開。理論上,我們可以把市面上所有的相機應(yīng)用都添加到 CAMERA_CANDIDATES中去,算是一個白名單吧。最后以防萬一我們還要try/ catch一下ActivityNotFoundException,避免出現(xiàn)用戶沒有可用相機應(yīng)用的情況。不過這樣也僅僅是在糟糕的情況上稍微改變了一點點,變成了我們開發(fā)者去指定用戶可以使用的相機,不管從開發(fā)體驗上還是從用戶體驗上,都是比較糟的,我們開發(fā)者可能還會被用戶罵,為什么不讓我用美圖......

整體上我是不太明白為什么谷歌現(xiàn)在要加這個限制,這下肯定有不少應(yīng)用要被用戶給差評了。如果有朋友現(xiàn)在的項目里有用到ACTION_IMAGE_CAPTURE這種方式去拍照,可以開始著手考慮是自己用CameraX或者CameraKit之類的庫實現(xiàn)一下相關(guān)功能,還是通過上面說到的白名單的方式去列舉所有可能的相機應(yīng)用了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容