UnsatisfiedLinkError(com.esri.core.runtime.LicenseImpl.nativeIsClientIdValid)

时间:2015-02-23 03:40:24

标签: android arcgis unsatisfiedlinkerror

在设备中运行应用程序时出错:

    java.lang.UnsatisfiedLinkError: Native method not found: com.esri.core.runtime.LicenseImpl.nativeIsClientIdValid:(Ljava/lang/String;)Z
        at com.esri.core.runtime.LicenseImpl.nativeIsClientIdValid(Native Method)
        at com.esri.core.runtime.LicenseImpl.a(Unknown Source)
        at com.esri.android.a.b.b(Unknown Source)

相关代码:

import com.esri.android.runtime.ArcGISRuntime;

public class MainActivity extends FragmentActivity implements NavigationDrawerFragment.NavigationDrawerCallbacks {

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

        ArcGISRuntime.setClientId("xxxxxxxxxxxxxxxx");

......

的build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "21.1.2"

    defaultConfig {
        applicationId "xxx.xxxx.xxxxx"
        minSdkVersion 17
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true
    }

    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/LGPL2.1'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/NOTICE'
    }

    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    output.outputFile = new File(output.outputFile.parent, "xxxx-release.apk")
                }
            }
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:support-v4:21.0.3'
    compile 'com.google.android.gms:play-services:6.5.87'
}

proguard的-rules.txt:

-keep class android.view.** { *; }
-keep class com.esri.** { *; }
-keep class javax.servlet.** { *; }
-keep class jcifs.http.** { *; }
-keep class org.apache.http.** { *; }
-keep class org.joda.time.** { *; }
-keep class org.w3c.dom.bootstrap.** { *; }
-keep class org.xmlpull.v1.** { *; }

-dontwarn javax.servlet.**
-dontwarn jcifs.http.**
-dontwarn org.apache.http.**
-dontwarn org.joda.time.**
-dontwarn org.w3c.dom.bootstrap.**
-dontwarn org.xmlpull.v1.**

logcat的:

03-04 18:06:19.213  13255-13255/xxx.xxxx.xxxxx D/dalvikvm﹕ GC_FOR_ALLOC freed 360K, 17% free 35228K/42136K, paused 17ms, total 17ms
03-04 18:06:19.283  13255-13255/xxx.xxxx.xxxxx D/dalvikvm﹕ GC_FOR_ALLOC freed 368K, 16% free 35516K/42136K, paused 14ms, total 14ms
03-04 18:06:19.343  13255-13753/xxx.xxxx.xxxxx D/dalvikvm﹕ GC_FOR_ALLOC freed 408K, 15% free 35859K/42136K, paused 14ms, total 14ms
03-04 18:06:19.353  13255-13753/xxx.xxxx.xxxxx W/dalvikvm﹕ Failed processing annotation value
03-04 18:06:19.353  13255-13753/xxx.xxxx.xxxxx W/dalvikvm﹕ Exception Ljava/lang/NoSuchFieldError; thrown while initializing Lorg/b/a/d/e/z;
03-04 18:06:19.353  13255-13753/xxx.xxxx.xxxxx W/dalvikvm﹕ Exception Ljava/lang/NoSuchFieldError; thrown while initializing Lorg/b/a/d/an;
03-04 18:06:19.353  13255-13753/xxx.xxxx.xxxxx W/dalvikvm﹕ Exception Ljava/lang/NoSuchFieldError; thrown while initializing Lcom/esri/core/internal/util/d;
03-04 18:06:19.353  13255-13754/xxx.xxxx.xxxxx I/dalvikvm﹕ Rejecting re-init on previously-failed class Lcom/esri/core/internal/util/d; v=0x0
03-04 18:06:19.423  13255-13255/xxx.xxxx.xxxxx D/dalvikvm﹕ GC_FOR_ALLOC freed 776K, 15% free 35950K/42136K, paused 14ms, total 14ms
03-04 18:06:19.443  13255-13756/xxx.xxxx.xxxxx I/dalvikvm﹕ Rejecting re-init on previously-failed class Lcom/esri/core/internal/util/d; v=0x0
03-04 18:06:19.453  13255-13755/xxx.xxxx.xxxxx I/dalvikvm﹕ Rejecting re-init on previously-failed class Lcom/esri/core/internal/util/d; v=0x0

我使用:Android Studio 1.0.2和ArcGIS SDK 10.2.5

如果应用程序由Android Studio运行,则没有问题。如果应用程序在APK中生成,安装在设备中,然后运行,则会出错。

有没有解决方案?

非常感谢!

Similar question答案无效。

4 个答案:

答案 0 :(得分:2)

您的问题在于ProGuard。当您在发布模式下部署应用程序时,ProGuard会启动并缩小您的所有方法/类/变量/等。这意味着如果某个方法曾被称为“doSomething()”,它将被重命名为类似“a()”。这很好,因为当你的所有代码都出现这种情况时,它会使你的代码更小更快。

这可能是使用NDK的问题,因为本机库与Java方法通信的方式是通过反射,这需要命名一致性(方法可以通过文本名称找到。如果名称更改,则无法找到方法)。

您可以通过编辑ProGuard文件来排除某些类来解决此问题。

例如,在您的情况下,我会在ProGuard文件中添加以下行:

-keep class com.esri.core.runtime.LicenseImpl { *; }

实际上,您可以使此规则更具体,仅排除有问题的方法:

-keep class com.esri.core.runtime.LicenseImpl { 
    public void nativeIsClientIdValid(...);
}

ProGuard在确定代码的哪些部分缩小或非缩小时非常强大,所以我建议reading up on it.

可能有其他类需要以类似的方式从ProGuard中排除,因此如果在添加此修复后继续获得类似错误,只需添加更多ProGuard规则,具体取决于哪些方法/类不在找到。

修改

根据你得到的新错误,似乎是重构注释,这可能是你的新错误的原因。添加以下标志以排除注释:

-keepattributes *Annotation*

编辑2:

根据this blog about migrating projects to Android studio in the Esri website,他们似乎尚未找到克服ProGuard问题的方法,因为他们建议将enableMinify设置为false。这可能意味着Esri包在此时根本不适用于缩小,或者他们没有花时间去弄清楚如何解决问题。

答案 1 :(得分:1)

将此添加到您的proguard文件中。这不会对您的图书馆进行模糊处理

-keep class com.esri.** { *; }
-keep interface com.esri.** { *; }

答案 2 :(得分:1)

-keep class com.esri.** { *; }
-keep interface com.esri.** { *; }
-keep class org.codehaus.jackson.** { *; }
-dontwarn org.codehaus.jackson.map.ext.**
-dontwarn jcifs.http.**

为我工作。

答案 3 :(得分:0)

我遇到了同样的问题并按this link on Esri GeoNet中解释的那样解决了。

根据EsriStaff所写的内容:

  

是的,我同意这很有可能发生了什么。我可以在上面的路径中看到涉及arm64路径,并且上面还有一条注释表明事情正常,直到添加了另一个依赖项。鉴于这两点,您很可能会遇到问题,一旦Android加载了64位本机库,它就不再加载32位库。 [...] ArcGIS Runtime SDK提供32位armeabi-v7a库,通常在64位运行时加载,因为它向前兼容,这可以解释为什么在添加更多内容之前您可以找到正常的内容依赖。

由于EsriGeoNet中链接的SO question建议解决方案是在app.gradle文件中添加此内容:

android {
    ....
    defaultConfig {
        ....
        ndk {
            abiFilters "armeabi", "armeabi-v7a", "x86", "mips"
        }
    }
}

此时运行gradle构建应该为您提供NDK弃用的集成错误,您可以通过在gradle.properties(全局属性)文件中添加它来解决此问题:

android.useDeprecatedNdk = true

我已在使用Android 6.0.1的Samsung S6上测试过并且工作正常。

除此之外,我发现ArcGis Android SDK v10.2.3中已存在该问题,并且升级到最新的v10.2.8.1无法解决问题。

下周,我们的工作人员将与Esri意大利办事处进行预定会面,并且我会询问有关此错误的详细信息以及是否/何时将其修复。

希望这可以帮助您和其他任何有此问题的人。