Android14原生PackageInstaller安裝某些apk報錯問題
最近遇到Android14安裝客戶一個大型app的時候,執(zhí)行到開始安裝的時候就直接閃退了,查看log發(fā)現(xiàn)下面報錯:
03-25 18:01:29.531 3085 3085 E AndroidRuntime: java.lang.RuntimeException: Could not copy bitmap to parcel blob. 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.graphics.Bitmap.nativeWriteToParcel(Native Method) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.graphics.Bitmap.writeToParcel(Bitmap.java:2271) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Parcel.writeParcelable(Parcel.java:2606) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.packageinstaller.PackageUtil$AppSnippet.writeToParcel(PackageUtil.java:151) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Parcel.writeParcelable(Parcel.java:2606) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Parcel.writeValue(Parcel.java:2507) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Parcel.writeValue(Parcel.java:2384) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Parcel.writeArrayMapInternal(Parcel.java:1320) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1843) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Bundle.writeToParcel(Bundle.java:1389) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Parcel.writeBundle(Parcel.java:1389) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.content.Intent.writeToParcel(Intent.java:11826) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Parcel.writeTypedObject(Parcel.java:2225) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.app.IActivityTaskManager$Stub$Proxy.startActivity(IActivityTaskManager.java:2077) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.app.Instrumentation.execStartActivity(Instrumentation.java:1873) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:5634) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.app.Activity.startActivityForResult(Activity.java:5592) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.app.Activity.startActivity(Activity.java:6090) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.app.Activity.startActivity(Activity.java:6057) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.packageinstaller.PackageInstallerActivity.startInstall(PackageInstallerActivity.java:70 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.packageinstaller.PackageInstallerActivity.lambda$bindUi$0(PackageInstallerActivity.java 79) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.packageinstaller.PackageInstallerActivity.$r8$lambda$RCIm8wl1VPqdfQgkgmrBIDbuvOQ(Packag nstallerActivity.java:0) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.packageinstaller.PackageInstallerActivity$$ExternalSyntheticLambda0.onClick(R8$$Synthet Class:0) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.packageinstaller.AlertController$ButtonHandler.handleMessage(AlertController.java:144) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:106) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:205) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.os.Looper.loop(Looper.java:294) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:8248) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552) 03-25 18:01:29.531 3085 3085 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971) 需要如何修改函數(shù)避免錯誤。
根據(jù)上面報錯定位到frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\PackageUtil.java 中的writeToParcel函數(shù)。
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(label.toString());
Bitmap bmp = getBitmapFromDrawable(icon);
dest.writeParcelable(bmp, 0);
}這個函數(shù)是將bmp文件轉(zhuǎn)為parcel blob報錯??赡茉蚴荁itmap 過大。解決辦法如下:
解決方案:
方案 1:壓縮 Bitmap 再傳遞
由于 writeParcelable 可能不適用于大 Bitmap,可以用 ByteArrayOutputStream 壓縮 Bitmap 成 byte[],然后傳輸:
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(label.toString());
Bitmap bmp = getBitmapFromDrawable(icon);
if (bmp != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
dest.writeByteArray(byteArray);
System.out.println("Compressed Bitmap size: " + byteArray.length + " bytes");
} else {
dest.writeByteArray(null);
}
}
在 readFromParcel 時,需要用 BitmapFactory.decodeByteArray() 還原 Bitmap:
byte[] byteArray = source.readByteArray(); Bitmap bmp = (byteArray != null) ? BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length) : null;
方案 2:限制 Bitmap 大小
如果你仍然要用 writeParcelable 傳輸 Bitmap,可以先縮小 Bitmap,比如:
public Bitmap getResizedBitmap(Bitmap bmp, int maxSize) {
int width = bmp.getWidth();
int height = bmp.getHeight();
float scale = Math.min((float) maxSize / width, (float) maxSize / height);
int newWidth = Math.round(scale * width);
int newHeight = Math.round(scale * height);
return Bitmap.createScaledBitmap(bmp, newWidth, newHeight, true);
}
然后在 writeToParcel 里:
Bitmap bmp = getBitmapFromDrawable(icon);
if (bmp != null) {
Bitmap resizedBmp = getResizedBitmap(bmp, 200); // 200px 限制大小
dest.writeParcelable(resizedBmp, flags);
}
方案 3:避免 Bitmap 傳輸,使用資源 ID
如果 Bitmap 是來自 Drawable 或 資源文件,最好傳遞資源 ID,而不是 Bitmap 本身:
dest.writeInt(iconResId);
然后在 readFromParcel 里:
int iconResId = source.readInt(); Drawable icon = context.getResources().getDrawable(iconResId, null);
總結(jié):
- 推薦方案 1:壓縮
Bitmap并使用writeByteArray()傳輸。 - 如果必須用
writeParcelable:限制Bitmap大?。ǚ桨?2)。 - 如果
Bitmap來源于資源:傳遞資源 ID 而不是Bitmap(方案 3)。
到此這篇關(guān)于Android14原生PackageInstaller安裝某些apk報錯問題的文章就介紹到這了,更多相關(guān)Android14原生PackageInstaller安裝apk報錯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
當ListView有Header時 onItemClick里的position不正確的原因
這篇文章主要介紹了當ListView有Header時 onItemClick里的position不正確的原因的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-07-07
Android使用RecyclerView實現(xiàn)投票系統(tǒng)
這篇文章主要為大家詳細介紹了Android使用RecyclerView實現(xiàn)投票系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-11-11
Android?自定義開源庫?EasyView實現(xiàn)詳解
這篇文章主要為大家介紹了Android自定義開源庫EasyView實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-04-04
Android中ListView下拉刷新的實現(xiàn)代碼
這篇文章主要介紹了Android中ListView下拉刷新的實現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-06-06
Android通過原生APi獲取所在位置的經(jīng)緯度
本篇文章主要介紹了Android通過原生APi獲取所在位置的經(jīng)緯度,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-07-07
Android RecycleView 實現(xiàn)左滑上下分層示例代碼(自定義功能)
這篇文章主要介紹了Android RecycleView 實現(xiàn)左滑上下分層示例代碼(自定義功能),具有一定的參考價值,感興趣的小伙伴們可以參考一下。2017-03-03
Android應用中設置alpha值來制作透明與漸變效果的實例
這篇文章主要介紹了Android應用中設置alpha值來制作透明與漸變效果的實例,展示了基礎的透明漸變動畫的編寫方法,需要的朋友可以參考下2016-04-04
Android 詳解自定義圓角輸入框和按鈕的實現(xiàn)流程
對于安卓程序員來說,自定義view簡直不要太重要,畢竟有很多功能,譬如圓形頭像這些,用單純的原生非常難以實現(xiàn),而用自定義view,簡直分分鐘,今天我們來實現(xiàn)自定義圓角輸入框和按鈕,大家可以跟著練習,掌握技巧2021-11-11

