什么是'android.security.MessageDigest''?

时间:2012-07-10 06:20:30

标签: android

数千名客户中有一位在我的某个应用中报告错误。错误是:

java.lang.NoClassDefFoundError - android.security.MessageDigest

我不在我的应用中使用该类/方法。谷歌Mapkey必须是好的,因为有数千个人使用相同的版本快乐地运行相同的应用程序。这是堆栈跟踪:

java.lang.NoClassDefFoundError: android.security.MessageDigest
at com.google.android.maps.KeyHelper.getSignatureFingerprint(KeyHelper.java:60)
at com.google.android.maps.MapActivity.createMap(MapActivity.java:552)
at com.google.android.maps.MapActivity.onCreate(MapActivity.java:422)
at xx.yyy.zzzz.MyMapActivity.onCreate(MyMapActivity.java:41)
at xx.yyy.zzzz.TheMap.onCreate(TheMap.java:89)
at android.app.Activity.performCreate(Activity.java:4465)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
at android.app.ActivityThread.access$600(ActivityThread.java:123)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

这是什么?

提前致谢。

3 个答案:

答案 0 :(得分:20)

我花了一些时间来研究这个问题,我正在记录我在这里找到的东西,希望能为其他人省去一些麻烦。

错误是设备制造商或ROM创建者使用旧版地图库和新版Android的结果。通常情况下,这是孤立的模糊片剂,但它理论上可以出现在其他情况下。可以使用以下步骤在模拟器中重新创建此问题:

  1. 为包含Google API的旧API(10或更低版本)创建并加载模拟器
  2. 从模拟器中提取地图jar: adb pull /system/framework/com.google.android.maps.jar <destination_folder> 完成此操作后,您可以关闭模​​拟器。
  3. 为包含Google API的新API(11或更高版本)创建并加载模拟器
  4. 模拟器中的重新装入/系统,以便您可以写入:adb remount
  5. 将提取的地图jar放入新的模拟器中:adb push <destination_folder>/com.google.android.maps.jar /system/framework
  6. 重新启动模拟器。这应该是adb reboot可行的,但只是挂起了模拟器。相反,您需要杀死具有相同效果的特定进程。在Eclipse / DDMS中,它将被称为system_process,你可以在那里杀死它。或者,您可以运行此命令:adb shell ps | grep system_server | awk '{print $2}' | xargs adb shell kill
  7. 重启后,您可以像往常一样使用模拟器。使用嵌入式Google地图运行任何应用都将失败。
  8. 此过程不是永久性的。重新启动仿真器会将其恢复到正常工作状态。

    可以通过反射调用地图库中的KeyHelper.getSignatureFingerprint()方法并调用它来检测此问题 - 将PackageManager和您的包名称作为参数传递。或者,您可以在onCreate()中捕获错误并改为加载新活动。

答案 1 :(得分:9)

MessageDigest类是一个辅助类,用于使用常见方法(如MD5或SHA-1)对密钥进行编码/解码。

似乎android.security.MessageDigest类已从Honeycomb及更高版本的Android中删除,必须替换为java.security.MessageDigest(see this page

尝试下载最新版本的Google Maps API并重新设置应用程序,并将targetSDK设置为可用的最高版本(截至今日它应为16 / Jelly Bean)。

答案 2 :(得分:9)

我找到了简单的解决方法!只需在src目录包中创建android \ security并将MessageDigest.java放在里面。

package android.security;

import java.security.NoSuchAlgorithmException;

public class MessageDigest
{
    private java.security.MessageDigest instance;

    public MessageDigest() {}

    private MessageDigest(java.security.MessageDigest instance)
    {
        this.instance = instance;
    }

    public static MessageDigest getInstance(String algorithm) throws NoSuchAlgorithmException
    {
        if (algorithm == null) return null;

        try
        {
            if (algorithm.equals("SHA-1"))
                return (MessageDigest) Class.forName("android.security.Sha1MessageDigest").newInstance();
            else if (algorithm.equals("MD5"))
                return (MessageDigest) Class.forName("android.security.Md5MessageDigest").newInstance();
        }
        catch (Exception e) {}

        return new MessageDigest(java.security.MessageDigest.getInstance(algorithm));
    }

    public void update(byte[] input)
    {
        instance.update(input);
    }

    public byte[] digest()
    {
        return instance.digest();
    }

    public byte[] digest(byte[] input)
    {
        return instance.digest(input);
    }
}

这是有效的,但由于地图库不匹配Android版本,可能会产生其他异常!