2

每当我尝试使用SeekableInMemoryByteChannelApache commons-compress 包中的类时,应用程序都会崩溃并出现java.lang.NoClassDefFoundError: org.apache.commons.compress.utils.SeekableInMemoryByteChannel异常。

至少对我来说,这其中特别有趣的部分是运行 Android 7+ 的设备上不会出现此问题,但在我测试过的所有其他版本上都会出现此问题。更具体地说,我观察到此问题发生在 Android 6.0.1、6.0、5.1.1 上,但不会发生在 Android 7.0 或 7.1.1 上。这些设备中的每一个都来自不同的供应商。

所以我面临着鬼级的严重案例。起初我认为这可能与我的应用程序使用 MultiDex 或构建过程配置不正确有关。但同样的情况也发生在没有这些功能的全新项目上。我尝试使用同一个包中的不同类,它们已成功解决。我将包添加到 ProGuard,但没有运气。

这是复制问题的代码:

package lt.kaz.compresstest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ZipArchiveEntry zipEntry = new ZipArchiveEntry("hello");
        zipEntry.setSize(600);

        SevenZArchiveEntry sevenZipEntry = new SevenZArchiveEntry();
        sevenZipEntry.setName("sevenZip");

        try {
            MainActivity.class.getClassLoader().loadClass("org.apache.commons.compress.utils.ChecksumCalculatingInputStream");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        SeekableInMemoryByteChannel channel = new SeekableInMemoryByteChannel(new byte[]{5, 10, 15, 10});
        // App never gets here prior to Android N
        Log.d("lt.kaz", channel.toString());
    }
}

...和gradle文件...

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.1"
    defaultConfig {
        applicationId 'lt.kaz.compresstest'
        minSdkVersion 19
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
    }
}

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:26.+'
    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    compile 'com.android.support:design:26.+'
    compile 'org.apache.commons:commons-compress:1.14'
    testCompile 'junit:junit:4.12'
}

...和ProGuard ...

-keep public class org.apache.commons.compress

任何帮助将非常感激。这种行为的原因可能是什么?如何解决?

4

1 回答 1

2

显然,包中的SeekableByteChannel接口仅适用于 Android API 级别 24(因此为 android N)。java.nio.channels

由于我最初的意图是使用SevenZFile该类,因此我的最终解决方案是将 commons-compress 降级到 1.12 版,因为那里的实现不使用SeekableByteChannel该类。

于 2017-08-17T15:33:47.087 回答