Android14 原生PackageInstaller安装某些apk报错问题

embedded/2025/4/1 4:04:51/

 最近遇到Android14安装客户一个大型app的时候,执行到开始安装的时候就直接闪退了,查看log发现下面报错:

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) 需要如何修改函数避免错误。

根据上面报错定位到frameworks\base\packages\PackageInstaller\src\com\android\packageinstaller\PackageUtil.java 中的writeToParcel函数。
 

public void writeToParcel(@NonNull Parcel dest, int flags) {dest.writeString(label.toString());Bitmap bmp = getBitmapFromDrawable(icon);dest.writeParcelable(bmp, 0);}

这个函数是将bmp文件转为parcel blob报错。可能原因是Bitmap 过大。解决办法如下:
 

解决方案:

方案 1:压缩 Bitmap 再传递

由于 writeParcelable 可能不适用于大 Bitmap,可以用 ByteArrayOutputStream 压缩 Bitmapbyte[],然后传输:

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);

总结:

  • 推荐方案 1:压缩 Bitmap 并使用 writeByteArray() 传输。

  • 如果必须用 writeParcelable:限制 Bitmap 大小(方案 2)。

  • 如果 Bitmap 来源于资源:传递资源 ID 而不是 Bitmap(方案 3)。


http://www.ppmy.cn/embedded/177642.html

相关文章

当了5年牛马,我开始划水了。。。

我现在的这份工作,比上一份要好很多,首先薪资直接涨了一倍,7k到16.5k,13薪,朝九晚六,从不加班,项目也简单,包括我在内测试组一共有6个同事,但是每个人分到的任务真的很少…

Copilot完全指南:AI编程助手的革命性实践

一、智能编程新时代:从代码补全到AI结对编程 1.1 Copilot的进化历程 2021年GitHub Copilot的诞生标志着编程辅助工具进入新纪元。与传统IDE补全工具相比,Copilot展现出三大革命性特征: 语义理解:基于GPT模型理解代码上下文跨文…

高级数据结构01BST树

文章目录 1.BST树介绍2.数据结构3.遍历方式 1.BST树介绍 // BST树.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 //#include "pch.h" // BST.cpp : 定义控制台应用程序的入口点。 //#include <iostream> #include <queue> #i…

环境试验中温湿度循环测试的常见盲区分析

在环境试验中&#xff0c;温湿度循环测试的常见盲区主要包括试验条件设定不合理、传感器位置错误、设备校准不及时。其中&#xff0c;试验条件设定不合理尤为关键&#xff0c;它往往导致测试结果无法准确反映真实使用环境&#xff0c;进而可能引发后续产品故障和可靠性问题。例…

【万字总结】前端全方位性能优化指南(六)——Memory>SW>Disk>CDN联动策略、预测性缓存、版本指纹比对

前言 在突破网络传输的物理极限后,缓存技术正经历从「被动存储」到「主动预测」的范式革命。2025年的前沿实践表明:智能缓存体系可使应用性能产生阶跃式提升——字节跳动某核心业务通过本章方案,将首屏资源加载耗时从1.2s压缩至0.3s,缓存命中率突破98%。这一进化包含三大技…

数据结构和算法简介 以及 顺序表

数据结构和算法简介 一, 数据结构和算法的定义 数据结构的定义: 概述: 就是存储和组织数据的方式, 分为:线性结构和非线性结构. 算法的定义: 概述: 就是解决问题的思路和方法, 它具有独立性, 即,:它不依赖语言&#xff0c;而是解决问题的思路.Java能做Python也能做 特性…

工程数字建造管理系统平台有哪些?好的数字建造管理系统推荐

一、什么是工程数字建造管理系统平台&#xff1f; 工程数字建造管理系统平台是一种集成了先进信息技术&#xff08;如云计算、大数据、物联网等&#xff09;的综合性管理工具&#xff0c;它旨在通过数字化手段提升工程建造全过程的管理效率和决策水平。这一平台不仅覆盖了工程…

五子棋游戏

五子棋 - deveco <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>五子棋 - deveco</title>…