2013-04-04 28 views
4

我有一个使用谷歌地图(V1)的应用程序,并从崩溃报告,我看到这个例外不时:Android地图异常java.lang.NoClassDefFoundError:android.security.MessageDigest

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:513) 
at com.google.android.maps.MapActivity.onCreate(MapActivity.java:409) 

我已经定义

<uses-library 
      android:name="com.google.android.maps" 
      android:required="true" /> 

应用标签内,我延长MapActivity为好。该应用程序在大多数设备上都能正常工作,但也有一些不常见的例外,通常在Android 4.0.4上,如Woxter Tablet PC 90BL,TAB9008GBBK和其他通用名称。

从我在Stackoverflow中看到,它是ROM中的一个问题,它可以通过用户做一些高级技巧来解决,但我想要的是防止这种崩溃,因为我认为它不能解决,我只想通知用户(并且他会让他购买更好的设备:)并禁用地图功能而不是崩溃。但是我找不到处理这个错误的方法,或者使用我的设备进行测试。

此外,我的主要活动是基于MapActivity,所以我不知道如何在打开它之前处理这个异常。

回答

4

免责声明:我在任何应用程序/设备上都没有遇到过这个错误,但我解决了类似的问题。可能是同样的技术可以帮助你。

鉴于类是unavailable或加载类时发生异常,为什么不在应用程序启动时强制加载? Class.forName("android.security.MessageDigest")应该加载类,你可以捕获该通话抛出的Error。我知道它很脏,但它应该工作。您可以在清单上声明自定义的Application类来进行此检查。

类加载测试

try 
    { 
     Class.forName("android.security.MessageDigest"); 
    } 
    catch (Throwable e1) 
    { 
     e1.printStackTrace(); 
     //Bad device 
    } 

您还可以执行的试金石,检查类的功能应该为类加载消化简单String成功。

功能测试

try 
    { 
     MessageDigest digester = MessageDigest.getInstance("MD5"); 
     digester.update("test".getBytes("UTF-8")); 
     byte[] digest = digester.digest(); 
    } 
    catch (Throwable e1) 
    { 
     e1.printStackTrace(); 
     // Class available but not functional 
    } 

如果类加载/石蕊测试失败,更新共享偏好标志,让用户知道他的装置抽吸:)

+0

此类由Google地图库内部使用。在一些android版本中,maps库使用这个类,而在其他版本中,它使用另一个类。如果我在使用其他类的设备上执行此操作并且不存在该操作,则这并不意味着它将无法加载 – 2013-04-13 14:29:14

+0

True。根据[google产品论坛](http://productforfors.google.com/forum/#!category-topic/maps/google-maps-for-mobile/KinrGn9DcIE)上的一个主题,此开关是在HONEYCOMB上制作的。您仍然可以在<= HONEYCOMB上使用此测试,它是'Build.VERSION.SDK_INT <= 12'。我相信这应该工作。 – 2013-04-13 14:44:06

+2

其实,我在Android 4.0.4上看到它,罕见的设备,但经常 – 2013-04-13 17:32:18

2

尝试改变进口android.security.MessageDigestjava.security.MessageDigest

通过看这个链接:

What is 'android.security.MessageDigest''?

看起来android.security.MessageDigest已从Honeycomb中删除,因此将其更改为java。并检查此链接,以及:

http://productforums.google.com/forum/#!category-topic/maps/google-maps-for-mobile/KinrGn9DcIE

正如@XGouchet被建议有:

Try downloading the latest version of the Google Maps API and rebuild your application with targetSDK set to the highest available (as of today it should be 17/Jelly Bean).

+1

我无法更改导入,因为错误在Google Maps API中。另外,我已经在编译针对最新的SDK,但它似乎是一个操作系统问题,而不是图书馆问题。 – 2013-04-07 15:31:20

+0

是的,它位于Google Maps API中。我看到这些设备的错误报告:Lenco CoolTab-70,MIDC802(Polariod ?!)和MP1010,以及只有OS 4.04。所以它似乎是非常专用的设备和/或操作系统版本。 – Bachi 2013-08-29 17:15:26

1

android.security.MessageDigest是一个抽象类(见MessageDigest API)什么意味着它可以不会马上实例化。那么,什么情况是,任何时候的设备/应用程序无法找到这个类的一个实现,你会得到的异常以上,即

java.lang.NoClassDefFoundError: android.security.MessageDigest 

这是一个很好的问题,为什么会这样。可能有些电话供应商没有将他们的电话与实际实现这个抽象类的必需库一起发货。过去,我遇到过与TUN.ko模块类似的问题。

方法1

我应该帮助,如果你提供自己的(空)实现这个类,即“工具”抽象类和方法是这样的:

public class MessageDigestSpi extends Object { 
    byte[] engineDigest() { return new byte[0]; }    

    void engineReset() { } 

    void engineUpdate(byte[] input, int offset, int len) { } 

} 

public class MessageDigest extends MessageDigestSpi { 

} 

..并将这些类放入文件夹<src>/java/security/。因此,您可以通过这种方式提供自己的实现,该实现始终可以找到并可能包含一些代码,以便通知用户或提供替代实现。

所以剩下的问题是:如果系统也提供实现,应用程序又做了什么,以及如何控制系统实现是第一选择?

答案:选择哪个实现取决于导入顺序。看看Eclipse,您可以在项目属性,Java构建路径,Tab键顺序和导出中定义顺序。确保你有顶层的系统库,可能包括系统实现(很可能是Android库)。这样系统首先在这些库中搜索。如果没有发现你的类被加载和执行。

方法2

如在自己的抽象类,你当然可以简单地初始化MessageDigest类的替代实现,捕捉NoClassDefFoundError异常,并存储为以后的评价结果​​:

import android.security.MessageDigest; 

public class MessageDigestTester { 

    private static Boolean messageDigestAvailable = null; 

    public static Boolean isLibraryAvailable() { 
     if (messageDigestAvailable == null) { 
      try { 
       MessageDigest digest = MessageDigest.getInstance("MD5"); 

       messageDigestAvailable = true; 

      } catch (NoClassDefFoundError e) { 
       messageDigestAvailable = false; 
      } 

     } 

     return messageDigestAvailable; 
    } 
} 

然后在你的代码中使用if (MessageDigestTester.isLibraryAvailable()) { } else { }来封装这个库的用法并提供一个替代方案。

方法二更容易实现,而方法一是更复杂的解决方案。

希望这有帮助...干杯!

+0

我无法提供替代方案,因为它在Google地图库中使用,我无法访问 – 2013-04-15 12:00:16

+0

使用方法一您应该能够提供您自己的实践。你试过那个吗?如果您可以提供完整的示例应用程序,将更容易证明。 – Trinimon 2013-04-15 12:19:16

+0

我不能提供我自己的实现,因为我不知道库应该做什么,它已关闭,所以我看不到源代码。即使这个类存在并且它被实例化了,它也会在尝试从它获取一个值时失败。 – 2013-04-15 12:38:10