Uploaded image for project: 'Tika'
  1. Tika
  2. TIKA-3534

Latest Android Studio will fail building Android project with Tika Core 2.0.0 included - issues with MethodHandle API usage

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Won't Fix
    • 2.0.0
    • None
    • core
    • None

    Description

      I use Tika Core on top of my Android projects in order to detect mime types of files.

      Recently, build started to fail with this error:

      com.android.tools.r8.internal.m1: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
      

      MethodHandle API was included in Android Oreo. I could set minimum SDK version to Oreo, but I still have users with Android L,M,N (API level 21 to 25).

      By exploring Tika Core source code, I observed that the MethodHandle API is only used only on this class: [org.apache.tika.io.MappedBufferCleaner|https://github.com/apache/tika/blob/main/tika-core/src/main/java/org/apache/tika/io/MappedBufferCleaner.java] This class doesn't seem to be used anywhere else in the project. It also contains some huge hacks, with sun.misc.Unsafe (which is also unavailable on Android).

       

      What is the purpose of this class? Why is it here?

      Why is not used anywhere else inside the project?

      Can you please remove this class on the next Tika release?

       

      Dirty working workaround:

      In theory, one can use JarJar gradle plugin to modify contents of the imported Tika Core jar dependency:

      buildscript {
          dependencies {
              classpath 'org.anarres.jarjar:jarjar-gradle:1.0.1'
          }
      }
      
      dependencies {
          implementation jarjar.repackage {
              from 'org.apache.tika:tika-core:2.0.0'
              classDelete 'org.apache.tika.io.MappedBufferCleaner'
          }
      }
      

      However, JarJar gradle plugin is a bit outdated and I couldn't make it work. An alternative would be to tell gradle to download the jar file, create a modified jar file that includes all of the original jar's contents, excluding MappedBufferCleaner, then import the modified jar file:

      task tikaAndroidJar(type: Zip) {
          if (!buildDir.exists())
              buildDir.mkdir()
          def originalJarFile = new File("$buildDir/tika-core-original.jar")
          def originalJarUrl = 'https://repo1.maven.org/maven2/org/apache/tika/tika-core/2.0.0/tika-core-2.0.0.jar'
          new URL(originalJarUrl).withInputStream { i -> originalJarFile.withOutputStream{ o -> o << i }}
          from zipTree(originalJarFile)
          include '**/*.class'
          exclude 'org/apache/tika/io/MappedBufferCleaner.class'
          exclude 'org/apache/tika/io/MappedBufferCleaner$BufferCleaner.class'
          archiveName 'tika-core-modified.jar'
          destinationDir(file("$buildDir/"))
      }
      
      dependencies {
          implementation files("$buildDir/tika-core-modified.jar") {
              builtBy "tikaAndroidJar"
          }
      }
      

      Still, it's an ugly solution. The library works fine without MappedBufferCleaner class, the project builds and at runtime it can detect mime types of files.

      Attachments

        Activity

          People

            Unassigned Unassigned
            andob Andrei Dobrescu
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: