5

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 
18
  • Actually - did you try repackaging POI into a new JAR, with the same class name swap as you used in the Stax/Aalto JARs? Just noticed that these don't appear to be modified (i.e., they are the desktop JARs) in your dependencies. Commented Jul 1, 2015 at 18:44
  • Nope I did modify POI as well. I just didn't put the android tag as the names were getting too big. PS: Proof look at the dump it is from edu.usf.cutr.javax.xml.stream and I did reach this by far cause of that solution provided by you only. Commented Jul 2, 2015 at 7:48
  • Gotcha - ok, so my only other suggestions are in my edited answer below. Let me know if you figure it out! Commented Jul 2, 2015 at 13:09
  • 1
    @StaxMan would you be able to take a look at this? In short, kritya is trying to use Apache POI (which seems to use JSR173 API internally) to parse Microsoft XML documents on Android. kritya has rebundled stax-api and stax2-api for Android, and Apache POI seemed to pick up these classes (see edu.usf.cutr... in stack trace). Problem seems to be that it can't find a provider. How is Aalto or Woodstox normally registered with the platform as a JSR173 provider? XML parsing worked for me on Android, but I was using Jackson. Any wisdom? Commented Jul 8, 2015 at 13:28
  • 1
    @kritya Apparently there is a known issue in Android build tools that may be stripping out the META-INF/services/javax.xml.stream.XMLInputFactory from the JAR/APK when building your app. If this file is missing in your build, then Aalto won't be registered as a JSR173 provider, and including Aalto (or any JSR173 provider, including BEA) won't fix your original error. Try my edited answer, which uses CUTR JAR files from Maven repo, and includes a workaround for the Android build tools bug. Commented Jul 13, 2015 at 17:22

5 Answers 5

5

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.

Sign up to request clarification or add additional context in comments.

20 Comments

you mean I can exclude out the stax api and include its implementation only ? Note: I am using this on android. Sorry if you know this already but. Android doesn't have the Stack Api weather you run it on Java 5 or 6
Check the update for the dependencies I am using in my gradle project. And can you please tell me which ones did you keep and which ones did you remove. Thanks
Yes, I did read the POI faq and especially that question. But I need to attach it as android deliberately doesn't include it the stream package. So I need to attach the extra jar's for that only.
the dependency snipit gives an error gradle dsl function exclude not found
What I meant was: your problem is coming from the line final XMLEventFactory f = XMLEventFactory.newInstance(); in POI. Instead of calling XMLEventFactory.newInstance(), you can directly create the XMLEventFactory implementation via constructor from your stax dependency (class called XMLEventFactoryImpl, I guess). You should repeat this for every XML***Factory.newInstance() in POI's source, as obviously that factory method with dynamic locate does not work well on Android.
|
5

Add the following to your gradle file:

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

And relax...

Comments

3

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:

16 Comments

Sorry, maybe I don't get what I should exactly do. Because I don't know how to repackage the FasterXML in the required form. I tried adding the alto-xml-jar-0.9.6.jar from woodstox website. And it still says implementation not found. So can you please help me on what I need to do
Sorry, I wasn't clear. I just changed the answer above - you'd need to process the aalto-xml JAR file to change the namespace, just like you did with the stax JARs, and add it to your dependencies. I was hoping that aalto would register itself, but now I'm realizing that you're not using Jackson, and all parsing happens within Apache POI library. So, I'm not sure if it will work (because Apache POI doesn't necessarily know about Aalto being packaged with the app). But, its worth a try.
I tried repackaging the aalto-xml the way you said. Still gives the same error of Provider not found. The error is generated in the javax.xml.stream.* and not in the POI. So I guess error must not lie at POI end or should not depend on it. Also, sorry if I sound stupid. But the alto-xml doesn't contain any package as com.bea.* that is actually needed by the stax api. Correct me if it doesn't work this way. Thanks
Yeah, I was afraid of that. POI is simply using the JSR173 API internally, which assumes that the platform (in your case Android) has a registered JSR173 provider. But, Android doesn't know about Aalto, because its bundled with your app. You'd need to find a way to register Aalto with the JSR173 implementation that POI is calling - seems like the easiest way to do this is to modify Apache POI? I'll update my answer saying this - also, I found a few links that might help you, as it appears others have gotten portions of POI to work on Android.
Ok, so this bug may be affecting "pickFirst" - code.google.com/p/android/issues/detail?id=158630. Can you please make sure you're running the latest version of Android Studio, and update your local tools and Android Gradle plugin to make sure you're running the most recent version of the tools? This might be fixed in 1.3 RC1 - tools.android.com/download/studio/canary/latest.
|
1

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' } 

3 Comments

Thanks for answering, have you tested this ? If yes, on which Android API?
Yes, I have tested it. I was able to run from Eclipse but not from the jar file generated by Gradle. Once we removed the dependency in the build.gradle we have been able to run from the jar file.
I am not running on Android, I am running on PC, Java 1.8. I wanted to point out that it was a XMLEventFactory dependency at run time the cause of the problem.
0

for me adding

implementation 'com.android.support:multidex:1.0.0', implementation 'com.fasterxml:aalto-xml:1.0.0' 

and

multiDexEnabled true in defaultConfig

solve the problem

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.