如何获取APK签名?Android新手求助Java实现问题
获取已安装APK签名的正确方法
你的代码存在几个关键问题,导致无法正常获取有效签名:
PackageManager.GET_SIGNATURES从Android 9(API 28)开始已被弃用,高版本系统中使用它可能无法正确获取签名信息signatures[0].toString()返回的是Signature对象的默认字符串(格式类似android.content.pm.Signature@xxxx),并非实际的签名哈希值- Android 11及以上系统需要额外权限才能查询其他应用的信息
以下是兼容各版本的正确实现:
1. 配置权限
在AndroidManifest.xml中添加对应权限:
- 如果是Android 11(API 30)及以上,需要添加全局查询权限(或仅声明需要查询的特定包):
<!-- 全局查询权限,可忽略lint警告 --> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:ignore="QueryAllPackagesPermission" /> <!-- 或者仅声明需要查询的特定包,更合规 --> <queries> <package android:name="com.example.targetapp" /> <!-- 替换为目标包名 --> </queries>
- 低版本系统无需额外权限
2. 核心实现代码
import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.content.pm.SigningInfo; import android.os.Build; import android.util.Log; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SignatureUtils { // 获取指定应用的签名哈希(默认SHA-1,可替换为SHA-256) public static String getAppSignatureHash(PackageManager packageManager, String packageName) { try { Signature[] signatures; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { // API 28及以上使用新的SigningInfo API SigningInfo signingInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNING_CERTIFICATES).signingInfo; // 判断是否有多个签名者,优先取APK内容签名者 signatures = signingInfo.hasMultipleSigners() ? signingInfo.getApkContentsSigners() : signingInfo.getSigningCertificateHistory(); } else { // 低版本使用旧API PackageInfo packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); signatures = packageInfo.signatures; } if (signatures == null || signatures.length == 0) { Log.e("SignatureUtils", "未获取到签名信息"); return null; } // 将Signature转换为可读的哈希字符串(这里用SHA-1,可换成SHA-256) MessageDigest md = MessageDigest.getInstance("SHA-1"); byte[] digest = md.digest(signatures[0].toByteArray()); StringBuilder hexBuilder = new StringBuilder(); for (byte b : digest) { String hex = Integer.toHexString(0xFF & b); if (hex.length() == 1) { hexBuilder.append('0'); } hexBuilder.append(hex); } return hexBuilder.toString().toUpperCase(); } catch (PackageManager.NameNotFoundException e) { Log.e("SignatureUtils", "包名不存在:" + e.getMessage()); return null; } catch (NoSuchAlgorithmException e) { Log.e("SignatureUtils", "哈希算法不存在:" + e.getMessage()); return null; } } }
3. 在Activity中调用
// 替换为目标应用的包名 String targetPackage = "com.example.targetapp"; String signatureHash = SignatureUtils.getAppSignatureHash(getPackageManager(), targetPackage); if (signatureHash != null) { sig.setText(signatureHash); } else { sig.setText("获取签名失败"); }
关键说明
- 优先使用
SigningInfoAPI适配高版本系统,避免因旧API弃用导致的兼容性问题 - 转换为哈希字符串才是实际可用的签名标识(比如用于第三方平台校验),而非直接使用
Signature的toString()结果 - 根据需求选择哈希算法,常见的有SHA-1和SHA-256,大部分第三方平台会指定使用哪种
内容的提问来源于stack exchange,提问作者Farhan Ali
相关产品推荐
相关产品推荐

