Android - APK安装卸载流程及瘦身方案

43 阅读4分钟

APK安装和卸载的基本流程

APK 安装流程

graph TD
    A[开始安装] --> B[复制APK到临时目录]
    B --> C[解析AndroidManifest.xml]
    C --> D[验证签名]
    D --> E[检查系统版本和权限]
    E --> F[创建应用数据目录]
    F --> G[拷贝APK到系统目录]
    G --> H[更新系统包数据库]
    H --> I[发送安装完成广播]
    I --> J[结束安装]

主要步骤:

  1. 复制 APK 到 /data/local/tmp/
  2. 解析清单文件,验证签名和权限
  3. 创建应用数据目录
  4. 拷贝 APK 到 /data/app/
  5. 更新包数据库,发送广播

APK 卸载流程

graph TD
    A[开始卸载] --> B[停止应用进程]
    B --> C[删除应用数据目录]
    C --> D[删除系统目录中的APK]
    D --> E[更新系统包数据库]
    E --> F[发送卸载完成广播]
    F --> G[结束卸载]

主要步骤:

  1. 停止应用所有进程
  2. 删除 /data/data/包名 目录
  3. 删除 /data/app/ 中的 APK
  4. 更新系统数据库
  5. 发送卸载完成广播

关键目录

  • /data/app/: APK 存储目录
  • /data/data/: 应用数据目录
  • /data/dalvik-cache/: 优化后的 dex 文件

这就是 Android APK 安装卸载的核心流程,实际过程中还会涉及更多细节,如权限检查、签名验证等。

APK瘦身优化方向

1. 🗜️ 资源优化

1.1 图片资源优化

android {
    // 启用 PNG 压缩
    aaptOptions {
        cruncherEnabled = true
    }
}
  1. 图片格式选择

    • 🔄 将 PNG 转换为 WebP
    cwebp -q 75 image.png -o image.webp
    
    • 🎨 使用 SVG 替代多个分辨率的图片
    • 📊 合理使用 9-patch 图片
  2. 图片压缩工具

    • 使用 tinypng
    • pngquant
    • ImageOptim
    • Compress.io
  3. 矢量图使用

<!-- vector drawable -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
</vector>

1.2 资源文件优化

  1. 移除未使用资源
android {
    buildTypes {
        release {
            shrinkResources true
            minifyEnabled true
        }
    }
}
  1. 资源文件分包
android {
    // splits 用于配置 APK 分包策略
    splits {
        // density 配置密度分包,即针对不同屏幕密度生成不同的 APK
        density {
            // 启用密度分包功能
            enable true
            
            // 排除指定密度的资源文件,这些密度的设备将使用更高密度的资源进行缩放
            // ldpi: 低密度屏幕 (120dpi)
            // mdpi: 中等密度屏幕 (160dpi)
            exclude "ldpi", "mdpi"
            
            // 指定兼容的屏幕尺寸
            // normal: 正常尺寸屏幕 (~470dp x ~320dp)
            // large: 大尺寸屏幕 (~640dp x ~480dp)
            // xlarge: 超大尺寸屏幕 (~960dp x ~720dp)
            compatibleScreens 'normal', 'large', 'xlarge'
        }
    }
}
  1. 语言资源优化
android {
    defaultConfig {
        resConfigs "zh", "en"
    }
}

2. 📦 代码优化

2.1 ProGuard 配置

android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
                    'proguard-rules.pro'
        }
    }
}
  1. 自定义 ProGuard 规则
# 保留某些类
-keep class com.example.important.** { *; }

# 移除日志
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}

2.2 R8 优化

android {
    buildTypes {
        release {
            // 启用 R8
            minifyEnabled true
            // 启用 R8 完全模式
            useProguard false
        }
    }
}

3. 🎯 动态化方案

3.1 动态功能模块

// 动态特性模块
dynamic-feature {
    implementation project(":app")
}
  1. Play Core Library
val request = SplitInstallRequest.newBuilder()
    .addModule("dynamic_feature")
    .build()

splitInstallManager.startInstall(request)
  1. 按需加载
class DynamicFeatureActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 检查模块是否需要安装
        if (splitInstallManager.installedModules.contains("dynamic_feature")) {
            loadFeature()
        } else {
            installFeature()
        }
    }
}

4. 📱 SO 库优化

4.1 ABI 选择

android {
    defaultConfig {
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a'
        }
    }
}

4.2 动态加载

System.loadLibrary("native-lib")

5. 🛠️ 构建优化

5.1 启用 AndroidX

android {
    useAndroidX = true
    enableJetifier = true
}

5.2 依赖优化

dependencies {
    // 使用精简版依赖
    implementation 'com.google.android.material:material:1.5.0'
    
    // 排除不需要的传递依赖
    implementation('library') {
        exclude group: 'com.unused', module: 'unused-module'
    }
}

6. 🌐 网络资源优化

6.1 资源按需下载

class ResourceManager {
    fun downloadResourcesIfNeeded() {
        if (!isResourceDownloaded()) {
            downloadResources()
        }
    }
}

6.2 CDN 加速

const val BASE_URL = "https://cdn.example.com/resources/"

7. 📊 监控与分析

7.1 APK Analyzer

# 使用命令行分析 APK
apkanalyzer size app-release.apk

7.2 自定义监控

class ApkSizeMonitor {
    fun trackResourceSize() {
        // 统计各类资源大小
    }
}

8. 🎨 实践建议

  1. 资源命名规范
<!-- 统一命名规范 -->
<string name="feature_title">标题</string>
<dimen name="feature_margin">16dp</dimen>
  1. 代码复用
// 使用扩展函数减少代码重复
fun Context.dpToPx(dp: Float): Float {
    return dp * resources.displayMetrics.density
}
  1. 懒加载实现
private val heavyResource by lazy {
    // 延迟加载大资源
    loadResource()
}

9. 📈 效果评估

9.1 大小对比

fun compareApkSize() {
    val oldSize = getOldApkSize()
    val newSize = getNewApkSize()
    val reduction = oldSize - newSize
    println("减少了 ${reduction}MB")
}

9.2 性能监控

class PerformanceMonitor {
    fun trackStartupTime() {
        val startTime = System.currentTimeMillis()
        // 应用启动
        val endTime = System.currentTimeMillis()
        println("启动耗时:${endTime - startTime}ms")
    }
}

10. 🎯 优化清单

  1. 编译期优化

    • 启用 R8
    • 配置 ProGuard
    • 移除未使用资源
    • 启用资源压缩
  2. 资源优化

    • 图片压缩
    • 资源文件整理
    • 多语言优化
    • 动态资源加载
  3. 代码优化

    • 代码混淆
    • 依赖优化
    • 动态加载
    • 代码复用
  4. 构建优化

    • ABI 选择
    • 依赖管理
    • 构建变体
    • 多渠道打包

11. 📝 优化效果评估

class OptimizationMetrics {
    fun calculateMetrics() {
        val metrics = mutableMapOf<String, Long>()
        
        // 统计各项指标
        metrics["apkSize"] = getApkSize()
        metrics["startupTime"] = getStartupTime()
        metrics["memoryUsage"] = getMemoryUsage()
        
        // 输出报告
        generateReport(metrics)
    }
}

12. 🚀 持续优化建议

  1. 建立监控系统

    • APK 大小趋势
    • 启动时间监控
    • 内存使用监控
    • 崩溃率监控
  2. 优化流程规范

    • 代码审查规范
    • 资源提交规范
    • 依赖管理规范
    • 发布流程规范
  3. 团队协作

    • 定期优化评审
    • 技术分享
    • 优化经验沉淀
    • 工具链完善

通过以上这些方案的综合运用,可以有效地实现 APK 瘦身。记住,APK 瘦身是一个持续的过程,需要在开发过程中不断关注和优化。同时,要平衡好 APK 大小和应用功能之间的关系,确保在减小 APK 体积的同时不影响用户体验。