Android 12 已來,你的 App 崩潰了嗎?

2022-01-04 ByteCode

hi 大家好,我是 DHL。專注分享最新技術原創文章,涉及 Kotlin、Jetpack、算法動畫、數據結構 、系統源碼、 LeetCode / 劍指 Offer / 多線程 / 國內外大廠算法題 等等。


Android 12 已來,你的 App 崩潰了嗎?我們已經開始做 Android 12 的適配了,在 Android 12 中包含了很多的功能和一些行為的變更,接下來我們一起來分析這些行為的變更對我們的應用產生了那些影響。

通過這篇文章你將學習到以下內容:

為什麼在 Android 12 上需要顯示聲明 android:exported 屬性?為什麼在 Android 12 上需要顯示指定 PendingIntent 的可變性?為什麼在 Android 12 上限制 adb 備份的默認行為?android:exported 屬性

在 Android 12 中包含 <intent-filter> 的 activity 、 service 或 receiver 必須為這些應用組件顯示聲明 android:exported 屬性,如下所示。

<activity
    android:name=".TestActivity"
    android:exported="false">
    <intent-filter>
        .
    </intent-filter>
</activity>

如果在包含 <intent-filter> 的 activity 、 service 或 receiver 組件中,沒有顯示聲明 android:exported 的值,你的應用將無法安裝,錯誤日誌如下所示。

Installation did not succeed.
The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
List of apks:
[0] '.../build/outputs/apk/debug/app-debug.apk'
Installation failed due to: 'null'

如果您的應用在需要聲明 android:exported 的值時未進行此聲明,錯誤日誌如下所示。

Targeting S+ (version 10000 and above) requires that an explicit value for \
android:exported be defined when intent filters are present

如果對上面的異常產生的條件,不是很理解,可以點擊下方連結查看,目前已經有很多開源項目都已經開始適配這個行為的變更了,例如 leakcanary 等等,詳情前往查看下列地址:

https://github.com/square/leakcanary/pull/2074https://github.com/microsoft/appcenter-sdk-android/pull/1520

這個行為的變更無論是對庫開發者 和 還是應用開發者影響都非常大。

為什麼在 Android 12 上需要顯示聲明 android:exported 屬性

android:exported 屬性的默認值取決於是否包含 <intent-filter>,如果包含 <intent-filter> 那麼默認值為 true,否則 false。

當 android:exported="true" 時,如果不做任何處理,可以接受來自其他 App 的訪問當 android:exported="false" 時,限制為只接受來自同一個 App 或一個具有相同 user ID 的 App 的訪問

正因為 android:exported 的屬性的默認值的問題,Twicca App 發生過一次安全性問題,因為另一個沒有訪問 SD 卡或網絡權限的 App,可以通過 Twicca App 將存儲在 SD 卡上的圖片或電影上傳到 Twicca 用戶的 Twitter 帳戶上的社交網絡上。

產生問題的代碼如下所示:

<activity android:configChanges="keyboard|keyboardHidden|orientation" android:name=".media.yfrog.YfrogUploadDialog" android:theme="@style/Vulnerable.Dialog" android:windowSoftInputMode="stateAlwaysHidden">           
    <intent-filter android:icon="@drawable/yfrog_icon" android:label="@string/YFROG">
        <action android:name="jp.co.vulnerable.ACTION_UPLOAD" />                
        <category android:name="android.intent.category.DEFAULT" />                
        <data android:mimeType="image/*" />                
        <data android:mimeType="video/*" />            
    </intent-filter>        
</activity>

因為添加了 intent-filter 所以 android:exported 的屬性的默認值為 true,因此可以接受來自其他 App 的訪問,進而造成了上述問題(通過 Twicca App 將存儲在 SD 卡上的圖片或電影上傳到 Twicca 用戶的 Twitter 帳戶上的社交網絡上),而解決方案有兩個:

方案一:添加 android:exported="false" 屬性
<activity android:exported="false" android:configChanges="keyboard|keyboardHidden|orientation" android:name=".media.yfrog.YfrogUploadDialog" android:theme="@style/ VulnerableTheme.Dialog" android:windowSoftInputMode="stateAlwaysHidden" >    
</activity>

方案二:Twicca App 沒有使用方式一,而是檢查調用者的包名是否與自身的包名相同
public void onCreate(Bundle arg5) {
    super.onCreate(arg5);
    ...
    ComponentName v0 = this.getCallingActivity();
    if(v0 == null) {
        this.finish();
    } else if(!jp.r246.twicca.equals(v0.getPackageName())) {
        this.finish();
        } else {
            this.a = this.getIntent().getData();
            if(this.a == null) {
                this.finish();
            }
            ...
        }
    }
}

這種方案也是可行的,因為在一臺設備上,不可能會出現兩個包名相同的應用,更多詳細的信息可以前往查看 Restrict access to sensitive activities。
https://wiki.sei.cmu.edu/confluence/display/android/DRD09.+Restrict+access+to+sensitive+activities

這僅僅是關於 activity 的安全漏洞的其中一個,在不同的場景下利用這些漏洞做的事情也可能不一樣。當然還有 service 和 receiver 組件也都是一樣,存在安全性問題。

指定 PendingIntent 的可變性

在 Android 12 中創建 PendingIntent 的時候,需要顯示的聲明是否可變,請分別使用 PendingIntent.FLAG_MUTABLE 或 PendingIntent.FLAG_IMMUTABLE 標誌,如果您的應用試圖在不設置任何可變標誌的情況下創建 PendingIntent 對象,系統會拋出 IllegalArgumentException 異常,錯誤日誌如下所示。

PACKAGE_NAME: Targeting S+ (version 10000 and above) requires that one of \
FLAG_IMMUTABLE or FLAG_MUTABLE be specified when creating a PendingIntent.

Strongly consider using FLAG_IMMUTABLE, only use FLAG_MUTABLE if \
some functionality depends on the PendingIntent being mutable, e.g. if \
it needs to be used with inline replies or bubbles.

為什麼在 Android 12 上需要顯示的指定 PendingIntent 的可變性

在 Adnroid 12 之前,默認創建一個 PendingIntent 它是可變的,因此其他惡意應用程式可能會攔截,重定向或修改此 Intent。(但是是有條件限制的)

一個 PendingIntent 是一個可以給另一個應用程式使用的 Intent,PendingIntent 接收待處理意圖的應用程式可以使用與產生待處理意圖的應用程式相同的權限和身份執行待處理意圖中指定的操作。

因此,創建待處理意圖時必須小心,為了安全性 Google 在 Android 12 中需要開發者自己來指定 PendingIntent 的可變性。

更多關於 PendingIntent 安全性介紹,可以前往查看 Always pass explicit intents to a PendingIntent。
https://wiki.sei.cmu.edu/confluence/display/android/DRD21-J.+Always+pass+explicit+intents+to+a+PendingIntent

adb 備份限制

Android 開發者都應該知道這個命令 adb backup , 它可以備份應用的數據,在 Android 12 中,為了保護私有應用數據,用戶運行 adb backup 命令時,從設備導出的任何其他系統數據都不包含應用數據。

如果你在測試和開發過程中需要使用 adb backup 來備份應用數據,你可以在 AndroidManifest 中將 android:debuggable 設置為 true 來導出應用數據。

<application
    android:name=".App"
    android:debuggable="true"
    ./>

注意:在發布應用前將 android:debuggable 設置為 false。

為什麼在 Android 12 上限制了 adb backup 命令的默認行為

因為這個存在嚴重的安全問題,當初 Google 為了提供 App 數據備份和恢復功能,可以在 AndroidManifest 中添加 android:allowBackup 屬性,默認值為 true, 當你創建一個應用的時候,會默認添加這個屬性,如下所示。

<application
    android:name=".App"
    android:allowBackup="true"
    ./>

當 android:allowBackup="true" 時,用戶可以通過 adb backup 和 adb restore 命令對應用數據進行備份和恢復,也就是說可以在其他的 Android 手機上安裝同一個應用,通過如上命令恢復用戶的數據。

為了安全起見,我們在發布出去的 Apk 中一定要將 android:allowBackup 屬性設置為 false 來關閉應用程式的備份和恢復功能,以免造成信息洩露。國民級應用 XX 信, 在曾今發出的版本中 allowBackup 的屬性值是 true,被其他逆向開發者利用之後,現在的版本中這個值已經修改為 false了,有興趣的小夥們可以反編譯看看。

如何檢查 App 的安全漏洞

在這裡推薦一個開源項目 linkedin/qark  這是由 LinkedIn 開源的項目,這個工具被設計用來尋找與安全相關的 Android 應用程式漏洞,無論是原始碼還是打包的 APK,具體的用法文檔上寫的非常的清楚了,這裡不做詳細的介紹了。
https://github.com/linkedin/qark

這個開源項目的檢查結果,作為參考即可。當然也有很多公司花了重金去購買第三方的服務來檢查 App 的安全漏洞。

在 Android 12 上這幾個行為的變更它們都有一個共性:安全性,可見 Google 這幾年在安全上做了很多的努力,當然還有其他的一些行為的變更,可以前往查看 行為變更:以 Android 12 為目標平臺的應用。
https://developer.android.com/about/versions/12/behavior-changes-12


參考文章

https://developer.android.com/about/versions/12/behavior-changes-12https://github.com/square/leakcanary/pull/2074https://github.com/microsoft/appcenter-sdk-android/pull/1520https://wiki.sei.cmu.edu/confluence

相關焦點

  • Android兼容性優化-Android 8.0設置Activity透明主題崩潰
    崩潰日誌:1 java.lang.RuntimeException:Unable to start
  • 歡迎體驗 | Android 12 開發者預覽版 3
    /window/SplashScreen.OnExitAnimationListener所有應用都已默認啟用了這個新特性,您無需做任何事情即可獲益。/doze-standbyhttps://developer.android.google.cn/reference/android/app/AlarmManager#setExact(int,%20long,%20android.app.PendingIntent)針對 Android 12 的應用如果想要使用精確鬧鐘,現在需要申請一個新的權限: SCHEDULE_EXACT_ALARM。
  • Android 12 適配你準備好了嗎?
    閃屏動畫UI 大大們會滿足於默認的的閃屏頁嗎?顯然不會!://developer.android.com/about/versions/12/features/splash-screen《Jetpack新成員SplashScreen:打造全新的App啟動畫面》https://juejin.cn/post/6997217571208445965❞在 Android
  • 【Android 】你了解嗎?
    在它的底部是 Linux 內核,它已被修改來在移動環境中獲得更好的性能。 Linux 內核還必須與所有硬體組件交互,因此也包含大多數硬體驅動程序。此外,它負責 Android 中存在的大多數安全功能。 由於 Android 基於 Linux 平臺,它還使開發人員易於將 Android 移植到其他平臺和架構。
  • 打破你的認知,數字除以 0 一定會崩潰嗎?
    二、代碼1System.out.println("1/0=" + 1/0);大叔的靈魂拷問:上面的代碼會崩潰嗎?如果不會,會輸出什麼呢?上面的代碼會崩潰嗎?如果不會,會輸出什麼呢?上面的代碼會崩潰嗎?如果不會,會輸出什麼呢?
  • Android 12:全新的App啟動動畫!
    早期的Android上App的啟動速度常為人詬病,如今的啟動表現已不遜iOS。Google針對系統的不斷優化絕對功不可沒,從8.0獨立出來的SplashWindow,到12上推出的全新SplashScreen。在App的主要內容展示之前,按照需求的不同,或多或少會先展示這樣幾個畫面。
  • Android 12 適配工作來了,實踐Jetpack SplashScreen API
    3、小甲同學:我想看Android12 SplashScreen源碼,可以嗎?進入正題,我們先介紹:SplashScreen如何使用,以及目前會遇到的問題,如何無縫過渡?會出現什麼問題,怎麼解決?首先我們需要把compileSdk和targetSdk(可選)升級到31。
  • 一篇文章帶你領略Android混淆的魅力
    這時,資源壓縮器會採取防禦性行為,將所有具有匹配名稱格式的資源標記為可能已使用,無法移除。 {   void set*(***);   *** get*();}-keepclassmembers class * extends android.app.Activity {   public void *(android.view.View);}-keepclassmembers enum * {
  • 來了,Android 12 適配簡介!
    如果大家需要遷移到 Android 12, 設置 TargetSdkVersion 成 31, 可以根據自身產品使用的東西並參考 官方文檔 來進行遷移。通配性問題 通配性問題,咱的定義是,無論你使用哪個版本的 TargetSdkVersion, 只要跑在 Android 12 上,你都需要關注。這裡個人節選了幾個比較重要的,一起來看看吧.
  • 打破你的認知,數字除以 0 一定會崩潰嗎?源碼藏著彩蛋
    二、代碼1System.out.println("1/0=" + 1/0);大叔的靈魂拷問:上面的代碼會崩潰嗎?如果不會,會輸出什麼呢?上面的代碼會崩潰嗎?如果不會,會輸出什麼呢?上面的代碼會崩潰嗎?如果不會,會輸出什麼呢?
  • 打破你的認知,Java除以0一定會崩潰嗎?
    不要看不起這些零零碎碎的基礎知識,這些基礎日積月累,慢慢的會讓你跟同事拉開差距。接下來,我們直奔主題。開始我們的基本功。System.out.println("1/0=" + 1/0);大叔的靈魂拷問:運行直接崩潰。
  • 幾行代碼,讓你的 APP 變得花俏—Android Design Support Library 代碼實驗
    其深度是自動設置的最佳實踐之一:6dp 在空閒狀態,12dp 是按下狀態。反正你可以通過定義重寫這些值,app:elevation 為空閒狀態下的陰影深度,andapp:pressedTranslationZ 為按下狀態的。關於按鈕的顏色,FAB 基本上使用強調色,但是你可以重寫 app:backgroundTint 屬性來修改。
  • 能否讓APP永不崩潰—小光和我的對決
    「這位老哥,你可以把異常上傳到自己的伺服器處理啊,你能拿到你的崩潰原因,用戶也不會因為異常導致APP崩潰,這不挺好?」將崩潰的一些信息——比如線程,進程,進程id,崩潰原因等等通過Log列印出來了。來張崩潰日誌圖給大家對對看:
  • Android測試那點事兒_這樣的BUG你遭不住兒~
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2445)at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2505)at android.app.ActivityThread.access
  • Android 12 預覽版來了!
    原文連結:https://android-developers.googleblog.com/2021/02/android-12-dp1.htmlFirst preview of Android 1218 February 2021Posted by Dave Burke, VP of Engineering
  • Android 優化 APP 構建速度的 17 條建議
    有許多配置是你在準備 app 的 release 版本的時候需要,但是當你開發 app 的時候是不需要的,開啟不必要的構建進程會使你的增量構建或者 clean 構建變得很慢,因此需要構建一個只保留開發時需要配置的變體,如下例子創建了一個 dev 和 prod 變體(prod 為release 版本的配置)。android {    ...
  • 是時候讓 Android Tools 屬性拯救你了
    如果存在像 TextView 或者 ImageView 這種基礎控制項,你是不是還在通過諸如 android:text="xxx" 和 android:src="@drawable/xxx" 的方式來測試和預覽UI效果?
  • Android 優化 APP 構建速度的17條建議
    3、配置debug 構建的Crushlytics為不可用狀態在debug 構建狀態下,如果你不需要運行崩潰上報,你可以將這個插件設置為不可用狀態來提升你的構建速度,如下:android {    ...
  • 我感覺我學了一個假的Android...
    上個周末是雙休,我決定來顛覆一下大家的認知。<init>(Handler.java:207)    at android.os.Handler.<init>(Handler.java:119)    at android.app.Dialog.<init>(Dialog.java:133)    at android.app.Dialog.
  • 還在用Android正經布局來寫頁面嗎?
    ="parent"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toBottomOf="parent"下面來實現一個這樣的功能,讓一個控制項在距離左邊和距離右邊的比例是1:3,來看看正經寫法: