Android adb 安装应用失败(安装次数限制)

adb安装应用失败

前言

Android Debug Bridge (ADB) 是一个功能强大的命令行工具,用于与 Android 设备通信。
安装 APK 文件:

  • 使用命令 adb install <apk文件路径> 可以将 APK 文件安装到设备上。
  • 如果需要覆盖安装,可以使用 adb install -r <apk文件路径>。
  • 如果需要降级安装,可以使用 adb install -d <apk文件路径>。
  • 想要在安装时自动授予权限,可以使用 adb install -g <apk文件路径>。

调试android应用的过程, 突然出现安装失败的问题, 检查了各种环境, 重启了开发工具和目标设备依然无法解决.

平台

名称 信息
Android 7.1
主控 RK3288
主机 Ubuntu 20.04
AndroidStudio Build #AI-241.15989.150.2411.11948838, built on June 11, 2024 Runtime version: 17.0.10+0-17.0.10b1087.21-11609105 amd64 VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
adb Android Debug Bridge version 1.0.41 Version 35.0.2-12147458

安装失败现象

在AndroidStudio中尝试失败后, 又使用终端输入命令尝试:

bash 复制代码
adb install -r ~/adb/apk/Muzei.apk 
Performing Streamed Install
adb: failed to install /home/xxx/adb/apk/Muzei.apk: 
Exception occurred while executing:
java.lang.IllegalStateException: Too many active sessions for UID 2000
	at com.android.server.pm.PackageInstallerService.createSessionInternal(PackageInstallerService.java:523)
	at com.android.server.pm.PackageInstallerService.createSession(PackageInstallerService.java:420)
	at com.android.server.pm.PackageManagerShellCommand.doCreateSession(PackageManagerShellCommand.java:1380)
	at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:201)
	at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:109)
	at android.os.ShellCommand.exec(ShellCommand.java:96)
	at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:22745)
	at android.os.Binder.shellCommand(Binder.java:594)
	at android.os.Binder.onTransact(Binder.java:492)
	at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2679)
	at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:3804)
	at android.os.Binder.execTransact(Binder.java:697)

从LOG中可以看到关键的报错信息:Too many active sessions for UID 2000:

按图索骥可以在对应的源码目录下查到LOG的源头:

frameworks/base/services/core/java/com/android/server/pm/PackageInstallerService.java

java 复制代码
            final int sessionId;
            final PackageInstallerSession session;
            synchronized (mSessions) {
                // Sanity check that installer isn't going crazy
                final int activeCount = getSessionCount(mSessions, callingUid);
                if (mContext.checkCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES)
                        == PackageManager.PERMISSION_GRANTED) {
                    if (activeCount >= MAX_ACTIVE_SESSIONS_WITH_PERMISSION) {
                        throw new IllegalStateException(
                                "Too many active sessions for UID " + callingUid);
                    }
                } else if (activeCount >= MAX_ACTIVE_SESSIONS_NO_PERMISSION) {
                    throw new IllegalStateException(
                            "Too many active sessions for UID " + callingUid);
                }
                final int historicalCount = mHistoricalSessionsByInstaller.get(callingUid);
                if (historicalCount >= MAX_HISTORICAL_SESSIONS) {
                    throw new IllegalStateException(
                            "Too many historical sessions for UID " + callingUid);
                }
    
                sessionId = allocateSessionIdLocked();
            }
            
            private static int getSessionCount(SparseArray<PackageInstallerSession> sessions,
                int installerUid) {
            int count = 0;
            final int size = sessions.size();
            for (int i = 0; i < size; i++) {
                final PackageInstallerSession session = sessions.valueAt(i);
                if (session.getInstallerUid() == installerUid) {
                    count++;
                }
            }
            return count;
        }
java 复制代码
    @GuardedBy("mSessions")
    private void writeSessionsLocked() {
        if (LOGD) Slog.v(TAG, "writeSessionsLocked()");

        FileOutputStream fos = null;
        try {
            fos = mSessionsFile.startWrite();

            XmlSerializer out = new FastXmlSerializer();
            out.setOutput(fos, StandardCharsets.UTF_8.name());
            out.startDocument(null, true);
            out.startTag(null, TAG_SESSIONS);
            final int size = mSessions.size();
            for (int i = 0; i < size; i++) {
                final PackageInstallerSession session = mSessions.valueAt(i);
                session.write(out, mSessionsDir);
            }
            out.endTag(null, TAG_SESSIONS);
            out.endDocument();

            mSessionsFile.finishWrite(fos);
        } catch (IOException e) {
            if (fos != null) {
                mSessionsFile.failWrite(fos);
            }
        }
    }

从代码中可以看到, 安装的过程中, 系统会记录下对应UID的安装数量等信息.

于是可以从设备端中查看记录的内容: /data/system/install_sessions.xml

java 复制代码
rk3288:/data/system # cat install_sessions.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<sessions>
<session sessionId="4538363" userId="0" installerUid="2000" createdMillis="1358505151252" sessionStageDir="/data/app/vmdl4538363.tmp" prepared="true" sealed="false" mode="1" installFlags="4150" installLocation="1" sizeBytes="-1" originatingUid="-1" installRason="0" />
<session sessionId="12795577" userId="0" installerUid="2000" createdMillis="1358499734290" sessionStageDir="/data/app/vmdl12795577.tmp" prepared="true" sealed="false" mode="1" installFlags="4150" installLocation="1" sizeBytes="-1" originatingUid="-1" installRason="0" />
<session sessionId="13071720" userId="0" installerUid="2000" createdMillis="1358502763745" sessionStageDir="/data/app/vmdl13071720.tmp" prepared="true" sealed="false" mode="1" installFlags="4150" installLocation="1" sizeBytes="-1" originatingUid="-1" installRason="0" />
<session sessionId="13187387" userId="0" installerUid="2000" createdMillis="1358519315394" sessionStageDir="/data/app/vmdl13187387.tmp" prepared="true" sealed="false" mode="1" installFlags="4150" installLocation="1" sizeBytes="-1" originatingUid="-1" installRason="0" />
<session sessionId="14248417" userId="0" installerUid="2000" createdMillis="1358518925167" sessionStageDir="/data/app/vmdl14248417.tmp" prepared="true" sealed="false" mode="1" installFlags="4150" installLocation="1" sizeBytes="-1" originatingUid="-1" installRason="0" />
<session sessionId="16520263" userId="0" installerUid="2000" createdMillis="1358506871037" sessionStageDir="/data/app/vmdl16520263.tmp" prepared="true" sealed="false" mode="1" installFlags="4150" installLocation="1" sizeBytes="-1" originatingUid="-1" installRason="0" />
....

文件的内容很多, 这里只摘取了一部分.

回到源码中, 可以看到配置的SESSION 数量: 1024

java 复制代码
    /** Upper bound on number of active sessions for a UID that has INSTALL_PACKAGES */
    private static final long MAX_ACTIVE_SESSIONS_WITH_PERMISSION = 1024;
    /** Upper bound on number of active sessions for a UID without INSTALL_PACKAGES */
    private static final long MAX_ACTIVE_SESSIONS_NO_PERMISSION = 50;

也就是说, 这个问题是因为使用ADB安装应用的次数超过了1024个

解决

  1. 有权限的情况下, 修改或删除 /data/system/install_sessions.xml 的内容, 重启后即可
  2. 没有权限恢复出厂设置, 清除数据即可.
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone3 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui