Pod
Pod

Reputation: 4129

What steps need to be performed to convert an Android Java module into a normal Java one?

I have an Android project consisting of two modules: An 'SDK' and a 'demonstration Android app'.

Currently the SDK lives in /path/to/work/dir/sdk and the app in /path/to/work/dir/demo-app. Developers open '/path/to/work/dir/demo-app' in Android Studio and can see + edit the source code for both modules at the same time.

We have another Android app, but that includes the SDK as a compiled .aar file and it can't see or edit the "live" source, only the decompiled/debug-symbol-ed one, if that makes sense?

TL;DR I would like to make the SDK into a plain-Java library so that it can be used in non-Android apps, and yet still have it fully editable inside Android Studio as part of the demo app 'project'. How do I do this?

Details

Details of the SDK

The SDK's job is to control some hardware devices on the other end of a socket. It is almost entirely plain Java, but has a few incidental uses of the Android library:

Details of the app

The 'Android app' module appears to be normal Android app, e.g. it's using Activity classes and the Android libraries and Android Studio deploys it to devices just fine. There's these gradle scritps:

/path/to/work/dir/demo-app/build.gradle (Project: Demo-App)
/path/to/work/dir/demo-app/settings.gradle (Project Settings)
/path/to/work/dir/demo-app/app/build.gradle (Module: app)

settings.gradle

in it's entirety:

include ':app', ':Mobile-SDK-Android'
project(':Mobile-SDK-Android').projectDir = new File('/path/to/work/dir/sdk/app')

build.gradle

Doesn't contain anything relevant, that I can see?

app/build.gradle

containing these relevant bits:

apply plugin: 'com.android.application'
android {
    ... etc
}

dependencies {
    compile project(path: ':Mobile-SDK-Android', configuration: 'debug')
    ... etc
}

Required changes?

What is an appropriate sequence of steps to convert the SDK into a "normal" and idiomatic Java library?

e.g.:

  1. Convert all uses of android.util.Log to use e.g. SLF4J
  2. Convert all annotations to ???
  3. Re-implement or use alternatives for TextUtils and Pair?
  4. Perform some magic on the gradle scripts
    • So the output is .jar instead of .aar
      • and isn't called app-release.aar
    • Is it still possible to have things like minSdkVersion ?
    • Is it possible to have an 'android flavour' of this jar file, incase we need to put android specific code in the SDK in future?
  5. Possibly restructure the SDK's dir to remove the "app" dir?
  6. ????
    n. Profit

Upvotes: 2

Views: 261

Answers (2)

k3b
k3b

Reputation: 14755

It is easier to create an additional third new non-android-lib porject and move all classes that have no android dependencies from skd-lib-android to sdk-lib-common. sdk-lib-common can be used outside android.

for the other android dependent classes

  • either add the android source code for simple non dependent classes like Pair
  • or port them to non-android (i.e SLF4J instead of android.util.Log works on android, too)

For further reference see

Recommended ways to produce app portable between Android and "other platforms"

Upvotes: 1

Zoe - Save the data dump
Zoe - Save the data dump

Reputation: 28267

Android is a massive API, and has a lot of alternatives. As a result of this, and I want to be clear, there are no fixed rules for changing the library. Most of the code needs to be rewritten from scratch. A large amount of the code is basically "useless". Log.x, the class for printing is gone. This can be replaced either by a library, Logger or just System.out.

As for annotations, this depends on the source.

Library-annotations usually work on both desktop and Android, for an instance Lombok. Android specific annotations (@TargetApi) are gone. minSdk cannot be used (as it isn't a part of the API in Java). I hope you get the idea here.

And if you didn't: You can't just convert a Java library to Android or the other way around. There's too much code written for the given platform that isn't there on a different platform.

The solution is to create it from scratch. The Android framework runs an entirely different system compared to desktop Java making a lot of the code unusable. And the Activity system removes any of that code, then there are .xml resources. If you create a .xml parser for String resources you can continue using Strings.xml. Layouts would require far too much to create a processor. dp, the unit, is also gone.

So to answer the title:

What steps need to be performed to convert an Android Java module into a normal Java one?

Once you have the library running (or an idea) you need to rewrite it. In addition to the desktop Java (what you call normal java) being different in language, it also has different systems. There are no .xml resources (JavaFX uses .fxml for layouts, but JavaFX is an entirely different system) that come as default. You need to parse any files and handle locales for Strings yourself. Layouts, JavaFX.

What is an appropriate sequence of steps to convert the SDK into a "normal" and idiomatic Java library?

Start at the core, like with any other project. Create the main classes, and then expand out.

Annotations

You provided a list of annotations.

@Nullable

Works fine

@AnyThread

Android

@NonNull

Works fine

@UiThread

Android

@WorkerThread

Android

@IntRange

Android

@Size

Looks fine

@SuppressLint

SuppressLint doesn't exist in desktop Java. They have SuppressWarnings though (unrelated issue, but it explains what the annotation is)


If that wasn't clear, annotations marked as Android above doesn't work using desktop Java, meaning they are written for Android


So the output is .jar instead of .aar and isn't called app-release.aar

When you use a Java library, it ends up as .jar.

Is it still possible to have things like minSdkVersion ?

Nope

Is it possible to have an 'android flavour' of this jar file, incase we need to put android specific code in the SDK in future?

Nope


As for an order to resolve the situation, it isn't possible to make one. You can't, as I hope I have made clear by now, just convert code between Java and Android. There are too many differences, meaning you have to start from scratch. Therefore, how you set up the list is up to you. But you need to rewrite more or less the entire thing. There are places you can copy-paste, but there are few of those.

I have converted an Android project to Java (moved from native Android to LibGDX) and I had to rewrite the entire code. There were only some segments that were copy-pastable and that was mostly things like constructors and some fields, basic operations and so on. There is nothing in the way of copy-pasting basic Java, the problem is that any project doesn't have that much basic java (like constructors, fields, math operations and so on)

Upvotes: 2

Related Questions