Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various complications with Java 13 #792

Open
firefligher opened this issue Aug 2, 2020 · 6 comments
Open

Various complications with Java 13 #792

firefligher opened this issue Aug 2, 2020 · 6 comments

Comments

@firefligher
Copy link

Good evening/night (at least here in Germany 😁),

after a very long debugging session (started around 11:00 PM), I got your Maven plugin finally working together with Java 13 and succeeded building and running a simple app (empty Activity class). Since I thought that my approach may be useful for somebody else, I decided to document it here.

Disclaimer: Heavy patching of JAR files in your local Maven repository is required.
Also note: I used version 4.6.0 of this plugin and built an app with minimumSdkVersion = 26.

Fixing dex

I don't know, if this was the very first problem that I had, but it was one of the first: I needed to pass additional command-line arguments to dex as otherwise it would fail with the same issues as documented here. Aftwards the build section of my pom looked like this:

<build>
   <pluginManagement>
      <plugins>
         <plugin>
            <groupId>com.simpligility.maven.plugins</groupId>
            <artifactId>android-maven-plugin</artifactId>
            <version>4.6.0</version>
            <extensions>true</extensions>
         </plugin>
      </plugins>
   </pluginManagement>
   <plugins>
      <plugin>
         <groupId>com.simpligility.maven.plugins</groupId>
         <artifactId>android-maven-plugin</artifactId>
         <configuration>
            <sdk>
               <platform>26</platform>
            </sdk>
            <dex>
               <dexArguments>--min-sdk-version=26</dexArguments>
            </dex>
         </configuration>
      </plugin>
   </plugins>
</build>

Adding the XML serialization APIs as dependency

The next problem that occurred is pretty well-known to all developers that migrated from Java 8 to Java 9+: Oracle somehow modularized their platform, this broke a lot of dependencies. In this case, those were the XML serialzation APIs (as already documented here).

The simplest, but also quick-and-dirtiest, solution was to manually patch the pom.xml of your plugin inside my local Maven repository. (Of course, this is only possible after the plugin has been downloaded by Maven.)

In my case, I patched the file at HOME_DIR\.m2\repository\com\simpligility\maven\plugins\android-maven-plugin\4.6.0\android-maven-plugin-4.6.0.pom and the pom.xml that is stored inside the android-maven-plugin-4.6.0.jar (same directory). Both times I added the following lines to the dependencies-section:

<dependency>
   <groupId>javax.xml.bind</groupId>
   <artifactId>jaxb-api</artifactId>
   <version>2.3.1</version>
</dependency>
<dependency>
   <groupId>org.glassfish.jaxb</groupId>
   <artifactId>jaxb-runtime</artifactId>
   <version>2.3.2</version>
</dependency>

Afterwards, I recomputed the SHA1 checksums of both modified files and stored them in the corresponding .sha1 file (again, in the same directory).

Patching sdklib

After the last step, the next Maven execution resulted in a ClassNotFoundException that was not that easy to fix: The android-maven-plugin depends on the sdklib that is part of the AOSP. The plugin depends on the com.android.sdklib.internal.build.SignedJarBuilder class, which imports sun.* classes. Those classes are missing in the newer Java versions as already mentioned here. Unfortunately, I was not able to provide those sun-classes (pun not intended 😄) in an alternative way, because the Java compiler did not let me compile classes of the sun-package.

Thus, I decided to patch my local copy of sdklib and created a modified version of the SignedJarBuilder.java (diff only):

22,28d21
< import sun.misc.BASE64Encoder;
< import sun.security.pkcs.ContentInfo;
< import sun.security.pkcs.PKCS7;
< import sun.security.pkcs.SignerInfo;
< import sun.security.x509.AlgorithmId;
< import sun.security.x509.X500Name;
< 
107c100
<     private BASE64Encoder mBase64Encoder;
---
>     private java.util.Base64.Encoder mBase64Encoder;
177c170
<             mBase64Encoder = new BASE64Encoder();
---
>             mBase64Encoder = java.util.Base64.getEncoder();
330c323
<             attr.putValue(DIGEST_ATTR, mBase64Encoder.encode(mMessageDigest.digest()));
---
>             attr.putValue(DIGEST_ATTR, mBase64Encoder.encodeToString(mMessageDigest.digest()));
342c335
<         BASE64Encoder base64 = new BASE64Encoder();
---
>         java.util.Base64.Encoder base64 = java.util.Base64.getEncoder();
351c344
<         main.putValue(DIGEST_MANIFEST_ATTR, base64.encode(md.digest()));
---
>         main.putValue(DIGEST_MANIFEST_ATTR, base64.encodeToString(md.digest()));
364c357
<             sfAttr.putValue(DIGEST_ATTR, base64.encode(md.digest()));
---
>             sfAttr.putValue(DIGEST_ATTR, base64.encodeToString(md.digest()));
383a377
> 			/*
397a392
> 		*/

(NOTE: For some reason I used this file as base. (Fastest compatible Google result))

After compiling this class with javac, I patched the HOME_DIR\.m2\repository\com\android\tools\sdklib\25.3.0\sdklib-25.3.0.jar in my local Maven repository. Again, this also required replacing the existing SHA1 hash.

Manual signature

This time, Maven completed my build successfully. However installing the app on an Android phone did not work because Android noticed the missing signature (the previous file patch removed the signature logic). So, i tried to perform this step manually by entering these shell commands:

keytool -genkey -keyalg RSA -alias CERT -keystore myKeystore -validity 360
jarsigner -keystore myKeystore -verbose target\my.apk CERT

And it worked.

Additional notes:

I attempted to use d8 instead of dex, but the following configuration did not work:

<plugins>
   <plugin>
      <groupId>com.simpligility.maven.plugins</groupId>
      <artifactId>android-maven-plugin</artifactId>
      <configuration>
         <sdk>
            <platform>26</platform>
         </sdk>
         <dexCompiler>d8</dexCompiler>
         <d8>
            <minApi>26</minApi>
         </d8>
      </configuration>
   </plugin>
</plugins>

The Maven build process always ended with an exception because some command-line argument returned with a non-zero status code. I guess, there's something wrong with the command, but I'm too tired for further investigations...

Maybe I'm going to write a real patch for your project and create a pull request, if I have the time.

Cheers. (It took about 1h to collect and write down all the information 😄)

@lyubomyr-shaydariv
Copy link
Contributor

@firefligher

The Maven build process always ended with an exception because some command-line argument returned with a non-zero status code. I guess, there's something wrong with the command, but I'm too tired for further investigations...

Just wondering, do you happen to face with the following log entries while attempting to use d8:

[INFO] Convert classes to Dex : PROJECT_PATH/target
[INFO] no main manifest attribute, in ANDROID_SDK_PATH/build-tools/VERSION/lib/d8.jar

?

@firefligher
Copy link
Author

firefligher commented Aug 22, 2020

@lyubomyr-shaydariv It's been a while since I opened this issue and in the mean time I've worked on some other things, but if I remember correctly I also encountered this message. I don't know, but I guess that the AOSP had modified that binary in the past. (But I haven't had a closer look on it, so I cannot guarantee that this is true.)

@lyubomyr-shaydariv
Copy link
Contributor

lyubomyr-shaydariv commented Aug 23, 2020

@firefligher thank you for the reply.

I don't know, but I guess that the AOSP had modified that binary in the past.

This assumption makes sense. I submitted another issue (#793) asking the project members to clarify that point, and I hope they would put comments for both issues.

@mosabua
Copy link
Member

mosabua commented Aug 25, 2020

I am not sure if Java 13 is supported by the Anddroid SDK but it certainly has never been tested with the Maven plugin. I would strongly suggest to use Java 11. Beyond that I am not sure if it works with a current Android SDK and also do not have time to check that out.

@firefligher
Copy link
Author

Just a quick note on this: The d8.bat (located at ANDROID_SDK_PATH/build-tools/VERSION/d8.bat) executes d8 by specifying an additional main class:

java -cp d8.jar com.android.tools.r8.D8

@rkraneis
Copy link

rkraneis commented Jan 9, 2021

A somewhat less intrusive interim solution would be

        <profile>
            <id>sun-classes</id>
            <activation>
                <jdk>[11,)</jdk>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.simpligility.maven.plugins</groupId>
                        <artifactId>android-maven-plugin</artifactId>
                        <version>${android.maven.version}</version>
                        <dependencies>
                            <dependency>
                                <groupId>javax.xml.bind</groupId>
                                <artifactId>jaxb-api</artifactId>
                                <version>2.3.0</version>
                            </dependency>
                            <dependency>
                                <groupId>com.sun.xml.bind</groupId>
                                <artifactId>jaxb-core</artifactId>
                                <version>2.3.0</version>
                            </dependency>
                            <dependency>
                                <groupId>com.sun.xml.bind</groupId>
                                <artifactId>jaxb-impl</artifactId>
                                <version>2.3.0</version>
                            </dependency>
                            
                            <dependency>
                                <groupId>javax.activation</groupId>
                                <artifactId>javax.activation-api</artifactId>
                                <version>1.2.0</version>
                            </dependency>
                            
                            <dependency>
                                <groupId>sun</groupId>
                                <artifactId>misc</artifactId>
                                <version>1</version>
                                <scope>system</scope>
                                <systemPath>«some-path»/sun-misc/sun-misc.jar</systemPath>
                            </dependency>
                        </dependencies>
                    </plugin>
                </plugins>
            </build>
        </profile>

(in your android project).
To get the missing sun.misc classes we further need to do the following:

$ cd «some-path»
$ mkdir -p sun-misc/classes
$ cd sun-misc/classes
$ jar xf «path-to-java-8»/jre/lib/rt.jar sun/misc/BASE64Encoder sun/misc/BASE64Decoder sun/misc/CharacterEncoder
$ jar cf ../sun-misc.jar .

Running the plugin was tested with JDKs 11 to 15; max source/target was only 9, as nothing higher is supported by the available d8 in platform level 28 or dex in platform level 30. d8 in platform level 29/30 should be able to handle newer java classes (tested: up to Java 11).

Edit: On a side note, I tried upgrading the internal android libraries from 2.3.0 (builder) / 25.3.0 (tools) and gave up at 3.5.4 (builder) / 26.5.4 (tools) as some integration tests of the plugin were still complaining about missing tools.jar when running with later JDKs and the API changes in the libraries (Google moved stuff over to Kotlin, for example, and taylored the used APIs more and more to IntelliJ) became just too much. I guess to really bring the plugin up to speed one would have to have a look at the Gradle plugin and basically rewrite large parts of.
In the mean time a “fix” could be to depend on jaxb libraries and an additional jar that contains the three missing classes from sun.misc as shown above (unfortunately none exists on maven central). Packaging should be no problem as these classes are GPL v2 licensed. It might still be that not all goals would work (missing tools.jar in some integration tests; lint goal and aar iirc), but that's also the case for the hack with the profile above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants