Android Java Library both ways compatible - java

I've made an API Wrapper with Android Studio, mainly to be used with Android Apps. I would like to make a .JAR file out of it, so that Java applications may also use it.
Is that possible? If so, how?
I've looked at how to make .JAR files out of Android Pojects, but not much came out of it. I also don't understand how is the Java application going to handle the Android net import, for example.

you can add a "jar" task to your lib-s build.gradle to generate a jar like this:
apply plugin: 'android-library'
android {
...
}
task jar(type: Jar) {
from android.sourceSets.main.java
}
dependencies {
...
}
You have to keep in mind that ordinary non-android java apps cannot use classes that directly or inderectly depend on namespaces android.*
I prefer to create an ordinary non android-dependant java-library-subproject in android-studio that generates a jar file and that can be consumed by your android-app.
One additional benefit of seperation non-android-lib from android-app is that you can write junit-4 tests for them.
Ordinary android-junit tests depend on junit3. Executing android-junit-tests requires to launch the emulator/android-device which is timeconsuming.
An ordinary non-android-junit-test runs much faster because it does not need emulator/android-device

Related

How to detect which library or code depends on a native library (libmupdf.so)

I'm trying to reduce the APK of an android app. I found that there is a native library (libmupdf_java.so) used causes the APK to become larger than the expected size (It added 20MB extra size to the APK please check the attached image). The project has a lot of dependencies (and libraries) I couldn't find which library uses libmupdf_java.so.
Solutions I tried
In .gradle(app) file
exclude 'lib/armeabi-v7a/libmupdf_java.so'
exclude 'lib/arm64-v8a/libmupdf.so'
exclude 'lib/armeabi/libmupdf.so'
}
The app builds successfully but I didn't know if it will fail during the runtime and crash or if it's successfully built means that all things are correct and no need to worry about any failure.
In .gradle(app) file in release section of build types
ndk {
abiFilters 'arm64-v8a'
}
The app builds successfully but I target only the ARMv8-A based CPUs instead of targeting all three architectures (armeabi-v7a, arm64-v8a, armeabi)
I don't know what's the best or preferred solution.
Gradle dependencies most of them are jar files. One of them may be using the libmupdf.so :
Jar files names:
DO_AndroidSDK_v2.4.9.jar
BixolonPrinterV234.jar
ZSDK_ANDROID_API.jar
commons-io-2.2.jar
commons-net-3.0.1.jar
commons-validator-1.4.0.jar
httpcore-4.3.jar
jackson-core-2.2.3.jar
httpmime-4.3.2.jar
jackson-annotations-2.2.3.jar
jackson-databind-2.2.3.jar
opencsv-2.2.jar
jackson-core-2.2.3.jar
snmp6_1.jar
Please, help me if you could.

How to run only one (current) file and ignore others in intellij gradle project?

This must be a very simple task for many of you. Let me explain the scenario.
I recently started practicing questions on HackerRank. But, I found the platform not so friendly for debugging. No online platform is or can be because of its own limitations. HackerRank provides question and stub code for many of the problems on its problem page.
For example, let us consider, https://www.hackerrank.com/challenges/java-datatypes/problem
But, because of it's debugging limitations I can't make the best use of portal. Hence, I wrote a PHP script to scrape all the content from the website and generated problem statements in HTML/PDF formats and solutions in java format.
Here's the GitHub project for the same.
https://github.com/saint1729/hr-idea-integration
The main intention of this activity is to have an integration of the website with an IDE like Intellij IDEA. This is now complete.
I created a gradle project with existing sources. But, the project contains many java files (almost 500+ files and each file has it's own main method). My intention is to solve one problem at a time and see if it compiles and submit it using a REST API provided by HackerRank.
But, when I am trying to Right Click and Click on Solution.main() for every file, it tries to compile all files in the project and because there are some compilation issues with the project, I am unable to test my code for the current file. This is not productive for me.
Please let me know if it's possible to compile and run a single file in IDEA (without compiling the whole project). If the idea of creating a gradle project for this activity is not necessary, can somebody recommend me another efficient solution?
NOTE: Every scraped java file contains it's own main method. I know that a project can contain only 1 main method. But, I don't know a coherent solution to solve my problem.
If you want to continue using gradle, you create a module per solution.
Let's suppose you have 3 solutions. canyouaccess, duplicateword and java1darray.
So your repository looks like this:
java
canyouaccess
src/main/java
package
Solution.java
duplicateword
src/main/java
package
Solution.java
java1darray
src/main/java
package
Solution.java
build.gradle
settings.gradle
Each module can have its own main. Inside a settings.gradle file the modules can be defined or disabled by commenting it out.
Your build.gradle looks like this:
...
subprojects { project ->
apply plugin: "java"
sourceCompatibility = 11
}
...
For the settings.gradle looks like this:
include 'java:canyouaccees'
include 'java:dublicateword'
include 'java:java1darray'
Each module can be build separately, you could even group modules by creating a sub module structure.
And each module can have it's own debug configuration, where the module and the main is selected. If your set them as shared, they are stored in xml format under .idea/runConfigurations. So your script can create them as well.
Each module needs it's own gradle.build file, where the main class is declared.
jar {
manifest {
attributes('Main-Class': 'your.main.class.goes.here')
}
}
Something like this should do.

Gradle: Exclude from compile, but still have Autocompletion

First of all some background:
I'm currently refactoring our application for Internal Tools and Scripts, and got into 'beauty problems' some would call it.
The base structure of the application should not include the scripts that are being created, those will be downloaded by the application on request. Imagine it like an AppStore for Internal Tools.
But to give developers in the new repository the Option to create those scripts, with auto completion, I'm searching for a way to include an external folder to the indexed files in IntelliJ, that doesn't add the whole folder to the compile task.
Folder structure is like that:
(1) ./ScriptSuite/scripts/
(2) ./src/main/
Where in (2) are all the backend sources, including Utilities and database connections etc. And in (1) are groovy script files, that can be loaded dynamically on request.
I want to avoid having the scripts in (2) cause this led to confusion earlier, because sometimes we couldn't differ if it's a script compiled at app start or a script downloaded from our server after app start.
I tried adding (1) to the build.gradle via:
sourceSets {
main {
groovy {
srcDirs {
'src/main/groovy'
}
srcDir {
'ScriptSuite/scripts'
}
}
}
}
But then the Files would be included in the compilation at App Start, which I'm trying to avoid, since those should be compiled at runtime by the GroovyScriptEngine. Also (1) is excluded from push into the repository, we host those on our S3 Bucket and other tools are in place for version control.
What did work, was adding (1) as a module source folder in IntelliJ itself, but this is only client side and won't get pushed into the repository, so everyone would have to configure it for himself (not good).
Any idea how to solve this problem with gradle ? I appreciate every help or tip !

Using the Toothpick DI framework be used with a Java (only) project

I started a small proof of concept exercise to make us of the Toothpick DI framework with an existing Gradle based Java project. I have read quite a few claims that you can use Toothpick with Java (meaning the JRE, OpenJDK, JDK or JSE - No Android) ... However, every example I've been able to check/work through has at some point a dependency on Android in some way, shape or configuration.
With the most (partially) successful effort so far has been to use an experimental, throw-away Android mocking package to have my Java project at least compile without error. That said it comes-up blank on resolving any should-be generated dependencies, such as the:
generated MemberInjectorRegistry
generated FactoryRegistry
The Toothpick sample project itself and the simpler of the available examples all use an Android configuration and often as not dependencies on other Android specifics.
update Two
I took direction to the Toothpick sample project, a Java project
https://github.com/stephanenicolas/toothpick/tree/master/toothpick-sample
The Tootpick wiki and the sample project use the Java compile option:
compileJava {
options.annotationProcessorPath = configurations.annotationProcessor
options.compilerArgs = ['-Atoothpick_registry_package_name=experiments.toothpick',]
}
That gave me a warning that turned-out to be a mismatch in Gradle and plugins. And I needed a new build with --refresh-dependencies (hint: make sure you compile the TestsPackages).
After fixing that the sample compiles and passes the Unit Tests. The generated files are under build/generated and I managed to encourage Netbeans to find them with this:
sourceSets {
generated {
java {
srcDirs = [ 'build/generated/source/apt/main' ];
}
}
}
Sadly Netbeans continues to put little red-lines under the generated symbols. At least it runs. Netbeans support could be better.
My earlier experiment looked on the Toothpick Smoothie which is an Android example. Kind of interesting as an intellectual exercise ...
Smoothie sample
That build.gradle file relies on Android. So I tried mock substitutes for missing components. The project compiles but can't find (any) generated code.
I would have considered by now that there might be at least ONE successful Java JRE/JDK Toothpick project example 'out there'.
update One
I decided to tackle this from the other end and look to the common Java annotation processing examples. This works as far as I got, with Gradle v4.7 (and also I think v4.6).
In your (sub-)project build.gradle ...
plugins {
id "net.ltgt.apt" version "0.15"
}
:
dependencies {
annotationProcessor (
dep_toothpickCompiler
)
:
}
The dep_toothpickCompiler is defined earlier as:
// Annotation Processor
dep_toothpickCompiler = "com.github.stephanenicolas.toothpick:toothpick-compiler:${ver_toothpick}"
results ...
This step at least managed to create a
build/generated folder
Unfortunately no generated output so far. There is light at the end of the tunnel, I'm sure. I'll post updates here if/as I get closer to a solution.
learning examples (GitHub)
I've identified some 'reliable' Toothpick examples. So far they want Android in there some place. Either as Android targeted modules or using related dependencies.
https://github.com/davidbcn/ToothpickWorkshop
https://github.com/WarrenFaith/Toothpick-Sample
https://github.com/wongcain/okuki
https://github.com/search?l=Java&q=toothpick&type=Repositories
Given (or assuming) that a pure Java / Toothpick project can build, debug and run on the desktop or from the command line; it doesn't seem to be a popular choice as far as my googling went ...
--
You should look at the TP sample, it is pure Java.
https://github.com/stephanenicolas/toothpick/tree/master/toothpick-sample
Smoothie is actually the android specific part of TP.

How can I add a continuous integration check for Java library compatibility on Android?

I have a number of Java libraries that are targeted at being used on both the desktop Java environment and Android Java environment.
I'd like to be able to integrate some sort of Gradle-based lint check in the Java libraries to make sure that I don't use classes/methods unavailable on Android. I've seen that the Android Lint utility can check such things (and output what the minimum Android kit would be to allow it to work).
I know that pulling in the whole Android SDK would work, but it'd be preferable to do it without that on the smaller base libraries that are intended to be shared outside of the Android world.
One reason for this is that I'd like to use Java 8 features that are available through retrolambda but be warned at continuous integration time that I was using an API unavailable in a prior SDK.
Proguard appears to be able to do an effective job of sanity-checking that all classes referenced are present. It does a bunch of other things that I do not need it to do, however it can be configured to do the following:
take an input jar/classpath (the newly compiled Java library)
not require an output jar (no need to save the optimized/obfuscated version)
take a set of input libraries to resolve references
allowing the runtime libraries from Java 7 to be used as a base reference
This allows me to compile using Java 8 features with a reasonable amount of certainty that it should be compatible on Android - either via retrolambda or the new Jack compiler.
Gradle sections to use Proguard for this use:
buildscript {
dependencies {
classpath 'net.sf.proguard:proguard-base:5.2.1'
}
}
task proguardCheck(type: proguard.gradle.ProGuardTask, dependsOn: assemble) {
injars project.jar.archivePath
libraryjars files(System.getenv("JAVA7_HOME") + "/jre/lib/rt.jar")
libraryjars files(System.getenv("JAVA7_HOME") + "/jre/lib/jce.jar")
libraryjars files(configurations.compile)
// Don't really try to do anything, we just want this tool for it's bytecode lint
dontshrink
dontobfuscate
dontoptimize
// Don't fail if LambdaMetafactory is missing - it would be handled by Retrolambda / Jack
dontwarn 'java.lang.invoke.LambdaMetafactory'
}
A strong guarantee of compatibility would be to reference the android.jar for the given minimum-compatible version of Android to be targetted. However without pulling in the Andorid SDK, Java 6 is a good target for really old Android and Java 7 for Android SDK >= 4.4 (although NIO 2.0 is missing and probably other APIs as well).

Categories

Resources