20

I'm using Android studio 1.5.1

I'd like to include the org.apache.poi-ooxml library in my android project. To include that library I needed to include some other library dependencies, among which the stax-api library.

The problem with stax api is that it has all the packages in javax.* which is a "core library". Java jdk has all these libraries included, so if I were to use it in Java SE, I wouldn't need that stax-api library. Android, on the other hand, has a "partial" stax-api library. For android I only need the javax.xml.stream.* package. That means that I need to extract the stax-api, remove everything except the javax.xml.stram package, and repackage it again.

So I guess it is safe to use this modified library in Android. But, it has the javax.* package, which, according to Android studio is a core library, so Android Studio (or whatever component in Android Studio) gives me a warning:

trouble processing "javax/xml/stream/EventFilter.class":

Ill-advised or mistaken usage of a core class (java.* or javax.*) when not building a core library.

This is often due to inadvertently including a core library file in your application's project, when using an IDE (such as Eclipse). If you are sure you're not intentionally defining a core class, then this is the most likely explanation of what's going on.

However, you might actually be trying to define a class in a core namespace, the source of which you may have taken, for example, from a non-Android virtual machine project. This will most assuredly not work. At a minimum, it jeopardizes the compatibility of your app with future versions of the platform. It is also often of questionable legality.

If you really intend to build a core library -- which is only appropriate as part of creating a full virtual machine distribution, as opposed to compiling an application -- then use the "--core-library" option to suppress this error message.

If you go ahead and use "--core-library" but are in fact building an application, then be forewarned that your application will still fail to build or run, at some point. Please be prepared for angry customers who find, for example, that your application ceases to function once they upgrade their operating system. You will be to blame for this problem.

If you are legitimately using some code that happens to be in a core package, then the easiest safe alternative you have is to repackage that code. That is, move the classes in question into your own package namespace. This means that they will never be in conflict with core system classes. JarJar is a tool that may help you in this endeavor. If you find that you cannot do this, then that is an indication that the path you are on will ultimately lead to pain, suffering, grief, and lamentation.

So, I'd like to use this --core-library option. But where to set it?

I already looked at Android Studio ignore --core-library flag which didn't help me. I think those answers are outdated, and that's why I'm asking a new question.

What I did try:

  1. build.gradle:

    dexOptions {
      coreLibrary true;
    }
    
  2. build.gradle:

    dexOptions {
      preDexLibraries = false
    }
    
    project.tasks.withType(com.android.build.gradle.tasks.Dex) {
      additionalParameters=['--core-library']
    }
    
  3. File --> Other Settings --> Default Settings --> Compilers --> Android Compilers and check the 'Add --core-library flag'

None of these worked. Is there any way to set that option?


EDIT: Why do I need STAX: I'm doing some stuff with Workbook, Sheet, Columns, Cells for .xlsx files. When I include only poi-ooxml-3.14-beta1-20151223.jar I get an error in build time saying class file for org.apache.poi.ss.usermodel.Workbook not found.

Upon including poi-3.14-beta1-20151223.jar on runtime I get, among others, Could not find method org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorkbook.isSetBookViews, referenced from method org.apache.poi.xssf.usermodel.XSSFWorkbook.

Upon including poi-ooxml-schemas-3.14-beta1-20151223.jar during runtime I get , among others, Failed resolving Lorg/openxmlformats/schemas/spreadsheetml/x2006/main/CTWorkbook; interface 59 'Lorg/apache/xmlbeans/XmlObject; and java.lang.VerifyError: org/apache/poi/xssf/usermodel/XSSFWorkbook

Upon including xmlbeans-2.6.0.jar during runtime I get, among others, Could not find method javax.xml.stream.events.Namespace.getPrefix, referenced from method org.apache.poi.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller.getQName and java.lang.NoClassDefFoundError: javax.xml.stream.XMLEventFactory at org.apache.poi.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller.<clinit>(PackagePropertiesMarshaller.java:41)

UPDATE So, from http://poi.apache.org/faq.html#faq-N1017E

18. Why do I get a java.lang.NoClassDefFoundError: javax/xml/stream/XMLEventFactory.newFactory()

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.
  • Running IBM Java 6 (potentially as part of WebSphere Application Server): IBM Java 6 does not provide all the interfaces required by the XML standards, only IBM Java 7 seems to provide the correct interfaces, so try upgrading your JDK.
  • Sun/Oracle Java 6 with outdated patchlevel: Some of the interfaces were only included/fixed in some of the patchlevels for Java 6. Try running with the latest available patchlevel or even better use Java 7/8 where this functionality should be available in all cases.

So, if I read this correctly, in Android, I do need a "truncated" STAX api.

Community
  • 1
  • 1
SlumpA
  • 882
  • 12
  • 24
  • STAX isn't required by the most recent versions of Apache POI. What happens if you try upgrading? – Gagravarr Jan 07 '16 at 11:40
  • I updated the question to "justify" the use of STAX – SlumpA Jan 07 '16 at 16:04
  • See [the Apache POI components page](http://poi.apache.org/overview.html#components) for details of what bits of POI have what dependencies - following the advice there will fix your missing class issues – Gagravarr Jan 07 '16 at 16:07
  • I read that. I think I still need the STAX api on Android – SlumpA Jan 07 '16 at 16:19
  • This sounds to me like you have version conflicts. Why don't you use maven and put exclusions on those sub-libraries that are in conflict? I'm not a gradle user, but I'm sure there is away to exclude specific libraries there too, as in any other modern dependency management tool. – Vanja Lee Jan 07 '16 at 19:52
  • From http://poi.apache.org/overview.html#components : `The OOXML jars require a stax implementation, but now that Apache POI requires Java 6, that dependency is provided by the JRE and no additional stax jars are required.` Android has a "partial STAX api". It doesnt have the javax.xml.streams.* package. So I needed to repackage the STAX api to exclude everything else. But I still need to override the "core library" warning/error. – SlumpA Jan 07 '16 at 19:57
  • By the way, in order to use POI, nowadays one usually needs following libraries: poi, poi-ooxml and ooxml-schemas. Do you have all those on your classpath? – Vanja Lee Jan 07 '16 at 19:59
  • I do. Check the "EDIT: Why do I need STAX" section in my question – SlumpA Jan 07 '16 at 20:02
  • To circumvent this... Would it be against the apache license to download the source of the stax api and all the libraries that use the stax api, rename all the packages and references from `javax.xml.stream` to `jav.xml.stream`, recompile it and use them like that for commercial purposes? – SlumpA Jan 08 '16 at 02:21
  • @SlumpA I don't think so. In fact, I would do the same. And by mentioning [JarJar](https://code.google.com/p/jarjar/) in that lengthy error message above, AndroidStudio, too, encourages you to do this kind of repackaging. After all, it's certainly the preferable approach over setting the `--core-library` switch. – morido Jan 13 '16 at 23:41

2 Answers2

3

There are a number of problems when you try to use Apache POI and it's depending libraries in an Android Application. Among others there are duplicate classes in xmlbeans.jar, the "javax.*" packages are prohibited by the Android compiler and a few others.

There are currently two projects which try to fix those issues:

android5xlsx provides ready-made jar-files to include in your application, but currently uses a somewhat outdated version of POI. poi-on-android is based on POI 3.15-beta1 and can be recompiled for newer versions of POI fairly easily. Both projects are for Android 5+ and come with sample code and should allow basic usage of Apache POI on Android.

centic
  • 15,565
  • 9
  • 68
  • 125
  • Thanks for your hard work! May I ask you two questions? Firstly, why most such projects support only Android 5+? Any problem to support lower versions at the same time? Secondly, if I need to write for Android 4.4 and up, which project would be best for me? I saw you also mentioned AndroidReadXLSX in some other answer. (The app needs to read both XLS and XLSX!) – Jenix Mar 09 '18 at 10:40
  • Oh, I forgot to ask this question too. Have you experienced any memory issue using those projects? I have no experience with Excel files on Android so somewhat worried about low-end devices. – Jenix Mar 09 '18 at 10:45
  • ad Android support: I don't have a lot of experience with Android, but I think there were some things that are not possible in earlier versions, e.g. multidex is required and the number of classes is very high. – centic Mar 11 '18 at 10:46
  • ad memory: you need to try with your actual files. Large Excel files can consume a lot of memory in POI for large or complex files, so it depends on lot on the actual files. – centic Mar 11 '18 at 10:47
  • Thanks! For my current app, I think I need another workaround but I'll definitely try yours soon. Thank you so much :) – Jenix Mar 11 '18 at 14:47
2

Add implementation 'javax.xml.stream:stax-api:1.0' in you app build.gradle, as some core class missed