You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Android设备所有已安装应用Base APK的哈希值?

获取所有已安装应用Base APK哈希值的可行方案

好问题!你完全不需要依赖SecurityLog(以及它要求的设备所有者权限和应用启动触发条件),直接读取APK文件并计算哈希值就能实现需求。下面是具体的实现思路和代码示例:

核心思路

  1. 获取已安装应用列表:通过PackageManager获取设备上所有已安装应用的PackageInfo,从中提取Base APK的文件路径。
  2. 计算APK文件哈希:针对每个APK文件,使用Java/Kotlin标准库的MessageDigest类计算指定算法(如SHA-256)的哈希值。

步骤实现

1. 添加必要权限

在AndroidManifest.xml中添加权限,确保能获取所有已安装应用的信息:

<!-- Android 11+ 必须声明此权限才能获取所有已安装应用 -->
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
    tools:ignore="QueryAllPackagesPermission" />

注意:在Google Play上架时,需要说明使用QUERY_ALL_PACKAGES权限的必要性,否则可能被拒绝。如果只需要查询特定应用,可以用<queries>标签替代,避免申请该权限。

2. 代码实现示例

以下是Kotlin和Java版本的代码,你可以根据项目需求选择:

Java版本

import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.Log;

import androidx.appcompat.app.AppCompatActivity;

import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "APKHashUtils";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 建议在后台线程执行,避免主线程阻塞
        new Thread(this::fetchAllApkHashes).start();
    }

    private void fetchAllApkHashes() {
        PackageManager pm = getPackageManager();
        List<PackageInfo> installedApps = pm.getInstalledPackages(PackageManager.GET_META_DATA);

        for (PackageInfo appInfo : installedApps) {
            String packageName = appInfo.packageName;
            String apkPath = appInfo.applicationInfo.sourceDir;
            String sha256Hash = calculateFileHash(apkPath, "SHA-256");

            if (sha256Hash != null) {
                Log.d(TAG, String.format("包名: %s | SHA-256哈希: %s", packageName, sha256Hash));
            } else {
                Log.w(TAG, "无法计算哈希值: " + packageName);
            }
        }
    }

    private String calculateFileHash(String filePath, String algorithm) {
        try (FileInputStream fis = new FileInputStream(filePath)) {
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            byte[] buffer = new byte[8192];
            int bytesRead;

            while ((bytesRead = fis.read(buffer)) != -1) {
                digest.update(buffer, 0, bytesRead);
            }

            byte[] hashBytes = digest.digest();
            StringBuilder hexBuilder = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() == 1) hexBuilder.append('0');
                hexBuilder.append(hex);
            }
            return hexBuilder.toString();

        } catch (NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

Kotlin版本

import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.FileInputStream
import java.security.MessageDigest

class MainActivity : AppCompatActivity() {
    private val TAG = "APKHashUtils"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 使用协程在后台执行
        GlobalScope.launch(Dispatchers.Main) {
            fetchAllApkHashes()
        }
    }

    private suspend fun fetchAllApkHashes() = withContext(Dispatchers.IO) {
        val pm = packageManager
        val installedApps = pm.getInstalledPackages(PackageManager.GET_META_DATA)

        installedApps.forEach { appInfo ->
            val packageName = appInfo.packageName
            val apkPath = appInfo.applicationInfo.sourceDir
            val sha256Hash = calculateFileHash(apkPath, "SHA-256")

            sha256Hash?.let {
                Log.d(TAG, "包名: $packageName | SHA-256哈希: $it")
            } ?: run {
                Log.w(TAG, "无法计算哈希值: $packageName")
            }
        }
    }

    private fun calculateFileHash(filePath: String, algorithm: String): String? {
        return try {
            val digest = MessageDigest.getInstance(algorithm)
            FileInputStream(filePath).use { fis ->
                val buffer = ByteArray(8192)
                var bytesRead: Int
                while (fis.read(buffer).also { bytesRead = it } != -1) {
                    digest.update(buffer, 0, bytesRead)
                }
            }
            val hashBytes = digest.digest()
            hashBytes.joinToString("") { "%02x".format(it) }
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
}

注意事项

  • 性能优化:计算大量APK的哈希值会消耗CPU和时间,务必在后台线程(如协程、AsyncTask、WorkManager)中执行,避免主线程阻塞导致ANR。
  • 哈希算法选择:推荐使用SHA-256(安全性较高),如果只是用于APK识别,MD5或SHA-1也可以,但不建议用于安全验证场景。
  • 系统应用访问:部分系统应用的APK路径可能存在权限限制,无法读取,但绝大多数第三方应用和普通系统应用都能正常获取。

内容的提问来源于stack exchange,提问作者Teun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:05:52