Using com.bea.xml.stream package on android

2019-01-20 11:39发布

问题:

For getting Apache POI to work on Android, I need to get Stack to work on Android. Following this question:Using JAXB with Google Android and @Sean Barbeau's answer. I successfully converted all the jar's to android compatible ones including the Apache POI library but it still gives me this run time error:

06-22 01:06:52.461  14865-14865/com.quizwiz.sharmakritya.poi E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.quizwiz.sharmakritya.poi, PID: 14865
    edu.usf.cutr.javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.EventFactory not found
            at edu.usf.cutr.javax.xml.stream.FactoryFinder.newInstance(FactoryFinder.java:72)
            at edu.usf.cutr.javax.xml.stream.FactoryFinder.find(FactoryFinder.java:176)
            at edu.usf.cutr.javax.xml.stream.FactoryFinder.find(FactoryFinder.java:92)
            at edu.usf.cutr.javax.xml.stream.XMLEventFactory.newInstance(XMLEventFactory.java:30)
            at org.apache.poi.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller.<clinit>(PackagePropertiesMarshaller.java:41)
            at org.apache.poi.openxml4j.opc.OPCPackage.init(OPCPackage.java:162)
            at org.apache.poi.openxml4j.opc.OPCPackage.<init>(OPCPackage.java:142)
            at org.apache.poi.openxml4j.opc.Package.<init>(Package.java:37)
            at org.apache.poi.openxml4j.opc.ZipPackage.<init>(ZipPackage.java:87)
            at org.apache.poi.openxml4j.opc.OPCPackage.open(OPCPackage.java:273)
            at org.apache.poi.xslf.usermodel.XMLSlideShow.empty(XMLSlideShow.java:103)
            at org.apache.poi.xslf.usermodel.XMLSlideShow.<init>(XMLSlideShow.java:75)
            at com.quizwiz.sharmakritya.poi.PPT.onCreate(PPT.java:16)
            at android.app.Activity.performCreate(Activity.java:5451)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1093)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2377)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2471)
            at android.app.ActivityThread.access$900(ActivityThread.java:175)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1308)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5602)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

The crux of the whole error is android is missing the package com.bea.xml.stream. How do I resolve this ?

I tried resolving this on my own by downloading an external jar from here. But that gave me strange errors:

06-22 01:10:42.906  20374-20374/com.quizwiz.sharmakritya.poi E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.quizwiz.sharmakritya.poi, PID: 20374
    java.lang.RuntimeException: Unable to instantiate application android.support.multidex.MultiDexApplication: java.lang.RuntimeException: Multi dex installation failed (Field dexElementsSuppressedExceptions not found in class dalvik.system.PathClassLoader).
            at android.app.LoadedApk.makeApplication(LoadedApk.java:516)
            at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4703)
            at android.app.ActivityThread.access$1600(ActivityThread.java:175)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5602)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.RuntimeException: Multi dex installation failed (Field dexElementsSuppressedExceptions not found in class dalvik.system.PathClassLoader).
            at android.support.multidex.MultiDex.install(MultiDex.java:178)
            at android.support.multidex.MultiDexApplication.attachBaseContext(MultiDexApplication.java:39)
            at android.app.Application.attach(Application.java:201)
            at android.app.Instrumentation.newApplication(Instrumentation.java:997)
            at android.app.Instrumentation.newApplication(Instrumentation.java:981)
            at android.app.LoadedApk.makeApplication(LoadedApk.java:511)
            at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4703)
            at android.app.ActivityThread.access$1600(ActivityThread.java:175)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1368)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5602)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

Note: removing the com.bea.stax.impl_1.2.0.jar from Gradle Dependencies gets me back to the first error.

Please help me find a way to use the package com.bea.xml.stream on android. UPDATE

The dependencies before your answer in gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

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

    defaultConfig {
        applicationId "com.quizwiz.sharmakritya.poi"
        minSdkVersion 16
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.android.support:multidex:1.0.0'
    compile files('libs/stax-api-android-1.0-2.jar')
    compile files('libs/stax2-api-android-3.1.1.jar')
    //compile files('libs/com.bea.stax.impl_1.2.0.jar')
    compile files('libs/poi-3.12-20150511.jar')
    compile files('libs/poi-ooxml-3.12-20150511.jar')
    compile files('libs/poi-ooxml-schemas-3.12-20150511.jar'){
    exclude group: 'stax', module: 'stax-api'
    }
    compile files('libs/xmlbeans-2.6.0.jar')
    compile files('libs/stax-1.2.0_rc2-dev.jar')
}

UPDATE #2 The error while compilation I get:

    Error:duplicate files during packaging of APK C:\Users\sharmakritya\AndroidStudioProjects\POI\app\build\outputs\apk\app-debug-unaligned.apk
    Path in archive: META-INF/services/javax.xml.stream.XMLInputFactory
    Origin 1: C:\Users\sharmakritya\AndroidStudioProjects\POI\app\build\intermediates\javaResources\debug\META-INF\services\javax.xml.stream.XMLInputFactory
    Origin 2: C:\Users\sharmakritya\.gradle\caches\modules-2\files-2.1\edu.usf.cutr.android.xml\aalto-xml-android\0.9.8\bf4e7339b028f92638b36ab9ac3cc3314a860d1\aalto-xml-android-0.9.8.jar
You can ignore those files in your build.gradle:
    android {
      packagingOptions {
        exclude 'META-INF/services/javax.xml.stream.XMLInputFactory'
      }
    }
Error:Execution failed for task ':app:packageDebug'.
> Duplicate files copied in APK META-INF/services/javax.xml.stream.XMLInputFactory
    File 1: C:\Users\sharmakritya\AndroidStudioProjects\POI\app\build\intermediates\javaResources\debug\META-INF\services\javax.xml.stream.XMLInputFactory
    File 2: C:\Users\sharmakritya\AndroidStudioProjects\POI\app\build\intermediates\javaResources\debug\META-INF\services\javax.xml.stream.XMLInputFactory

回答1:

Check FAQ #18:

This error indicates that the class XMLEventFactory does not provide functionality which POI is depending upon. There can be a number of different reasons for this:

Outdated xml-apis.jar, stax-apis.jar or xercesImpl.jar:

  • These libraries were required with Java 5 and lower, but are not actually required with spec-compliant Java 6 implementations, so try removing those libraries from your classpath. If this is not possible, try upgrading to a newer version of those jar files.

...

You probably need to exclude the stax:stax-api dependency through the build system that you use. I just solved a similar problem (same stack trace but from Groovy) by applying this method.

UPDATE: It is best if you use the dependencies from a Maven repository, it will largely simplify your dependencies section:

dependencies {
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.android.support:multidex:1.0.0'
    compile ('org.apache.poi:poi-ooxml:3.12') {
        exclude group: 'stax', module: 'stax-api'
    }
}

You can now also remove the extra libraries that you have under the libs directory.

The Apache POI FAQ answer indicates that stax may not be needed at all for some Java versions, especially above 6.



回答2:

Try using the pre-packaged JARs from the CUTR Maven repo for stax and Aalto:

apply plugin: 'com.android.application'

repositories {
    mavenCentral()
    maven {
        // CUTR SNAPSHOTs
        url "https://github.com/CUTR-at-USF/cutr-mvn-repo/raw/master/snapshots"
    }
    maven {
        // CUTR Releases
        url "https://github.com/CUTR-at-USF/cutr-mvn-repo/raw/master/releases"
    }
}

android {
    compileSdkVersion 21
    buildToolsVersion "21.1.2"

    packagingOptions{
        // exclude 'META-INF/DEPENDENCIES'  <--- and try commenting this out, I don't believe it should be needed
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        pickFirst 'META-INF/services/javax.xml.stream.XMLInputFactory'
    }

    defaultConfig {
        applicationId "com.quizwiz.sharmakritya.poi"
        minSdkVersion 16
        targetSdkVersion 21
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}
dependencies {
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile files('libs/poi-3.12-20150511.jar')
    compile files('libs/poi-ooxml-3.12-20150511.jar')
    compile files('libs/poi-ooxml-schemas-3.12-20150511.jar'){
    compile files('libs/xmlbeans-2.6.0.jar')
    // JSR173 APIs
    compile 'edu.usf.cutr.android.xml:stax2-api-android:3.1.1'
    compile 'edu.usf.cutr.android.xml:stax-api-android:1.0-2'
    // JSR173 provider implementation - Aalto
    compile 'edu.usf.cutr.android.xml:aalto-xml-android:0.9.8'
}

I believe the main issue here is that Apache POI depends on JSR173 Streaming API for XML, which depends on the platform (in our case Android) being able to provide an implementation and underlying XML parsing provider. Android doesn't support JSR173, so it can't find a provider - com.bea.xml.stream.EventFactory is the default provider, and it can't even find that one (see JAXB marshalling exception javax.xml.stream.FactoryConfigurationError running with Java 5 for more details on this topic).

Aalto is an open-source JSR173 provider, so you should be able to use this in place of the BEA implementation (com.bea.xml.stream.EventFactory). The Aalto archive (JAR file) includes the necessary registration (under META-INF/services/javax.xml.stream.XMLInputFactory file, that points to the Aalto class com.fasterxml.aalto.stax.InputFactoryImpl) that should allow a Java platform to recognize it as a JSR173 implementation. As a result, you should no longer get the edu.usf.cutr.javax.xml.stream.FactoryConfigurationError: Provider com.bea.xml.stream.EventFactory not found error, because Android should recognize that Aalto is an available provider, and use Aalto instead.

Note - apparently there are bugs with previous versions of ADT for Eclipse and Gradle plugin < 0.7.0 that strips the /META-INF/* files from the JARs during the build process. It seems like >= v0.7.0 shouldn't have the problem according to Google, but from others' reports it sounds like it still may be problematic, and could potentially remove the META-INF/services/javax.xml.stream.XMLInputFactory file, which is required for the platform to register Aalto.

If the above doesn't work, try the workaround mentioned in AOSP issue 59658 comment 22:

  1. right click on /src/main (where you have /java and /res folders),
  2. select New > Folder > Java Resources Folder,
  3. click Finish (do not change Folder Location),
  4. right click on new /resources folder,
  5. select New > Directory
  6. enter "META-INF" (without quotes),
  7. right click on /resources/META-INF folder,
  8. select New > Directory
  9. enter "services" (without quotes)
  10. copy any file you need into /resources/META-INF/services

For you, in step 10 above you'd need to copy this file (javax.xml.stream.XMLInputFactory) into /resources/META-INF/services.

If the above doesn't work, I also noticed that you have a exclude 'META-INF/DEPENDENCIES' in your packagingOptions - I'd remove this, as I don't believe you should need that line, and it may be causing problems with registering Aalto as well.

You could also check out some other solutions/work that people have done trying to get Apache POI working on Android:

  • Trying to port Apache POI to Android
  • Apache POI with Android — How to Create ,Read , Write, Delete PowerPoint Presentations?
  • Creating/Reading an Excel file in Android


回答3:

After upgrading POI from 3.9 to 3.15 we were getting a:

javax.xml.stream.FactoryConfigurationError: Provider for class javax.xml.stream.XMLEventFactory cannot be created

Besides POI, our build included:

compile ('com.msopentech.odatajclient:odatajclient-engine:0.9.0')

it turned out that the odatajclient jar included a java.xml.stream.XMLEventFactory file in its META-INF\services, the contain of that file was com.fasterxml.aalto.stax.EventFactoryImpl but the aalto included in odatajclient was old and com.fasterxml.aalto.stax.EventFactoryImpl was finally inheriting from com.msopentech.javax.xml.stream.XMLEventFactory instead of java.xml.stream.XMLEventFactory class.

At run time POI was using the java.xml.stream.XMLEventFactory, the class loader returned com.fasterxml.aalto.stax.EventFactoryImpl and the cast to java.xml.stream.XMLEventFactory failed.

The solution was excluding the module that included the old aalto:

compile ('com.msopentech.odatajclient:odatajclient-engine:0.9.0')
{
   exclude group: 'com.msopentech.odatajclient', module: 'odatajclient-engine-xml'
}


回答4:

Add the following to your gradle file:

implementation 'com.fasterxml:aalto-xml:1.0.0'

And relax...