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. 没有权限恢复出厂设置, 清除数据即可.
相关推荐
朱涛的自习室4 小时前
我给 Gemini 4 和 DeepSeek 搞了套「末位淘汰」,AI 干活会更猛吗?(Day 3)
android·前端·后端
应用市场10 小时前
离线小游戏做“每日挑战”:日期当随机种子,整局存成 JSON,再加一个“我不是机器人”
android·kotlin·游戏开发
一铭1119911 小时前
海豹办公 1.9.15 跨端办公软件实践 文档兼容 Access 数据库与移动 WebView 排错
android·数据库·electron·开源软件·access
geats人山人海12 小时前
java 7异常
android·java·开发语言
2601_9620710013 小时前
Kimi K3 vs DeepSeek V4-Pro实测对比:2026年同一入口十道题,耗时与token消耗差在哪
android·java·数据库
右手吉他14 小时前
高通平台IA APN问题分析之二
android·物联网
yeflx14 小时前
Ubuntu22.04安装Mysql Workbench
数据库·mysql·adb
夜雪一千14 小时前
MySQL 自增 ID 的底层原理与坑点
android·mysql·adb
不浪费一个字节15 小时前
一个纯 Python 实现的 APK 解析与设备操控工具箱
android
itmigrate15 小时前
PHP 导出大 CSV 时内存溢出的一次排查
android·开发语言·php