将Android Java模块转换为普通Java模块需要执行哪些步骤?

时间:2017-09-05 13:33:57

标签: java android gradle jar android-gradle

我有一个包含两个模块的Android项目:“SDK”和“演示Android应用”。

目前,SDK位于/path/to/work/dir/sdk,应用位于/path/to/work/dir/demo-app。开发人员在Android Studio中打开'/ path / to / work / dir / demo-app',可以同时看到+编辑两个模块的源代码。

我们有另一个Android应用程序,但它包含SDK作为已编译的.aar文件,它无法查看或编辑“实时”源,只有反编译/调试符号编辑,如果这有意义?

TL; DR 我想将SDK变成普通的Java库,以便它可以在非Android应用程序中使用,但仍然可以在Android Studio中完全编辑它作为一部分演示应用程序'项目'。我该怎么做?

详细

SDK的详细信息

SDK的工作是控制套接字另一端的某些硬件设备。它几乎完全是普通的Java,但有一些偶然的Android库使用:

  • android.util.Log,类中关联的TAG常量,以及运行时检查以禁用日志消息(BuildConfig.DEBUG

  • 静态分析的注释:

    • @Nullable@AnyThread@NonNull@Nullable@UiThread@WorkerThread@IntRange@Size@SuppressLint
  • 偶尔使用缺少Java stdlib的库:

    • android.text.TextUtils
    • android.support.v4.util.Pair
  • 它的测试套件都是“测试”。有一个无用的“androidTest”可以删除。

  • Gradle构建环境仍然是针对Android定制的 目录结构。即repo dir看起来像这样:

    /path/to/work/dir/sdk   
    ├───.git
    │   └───...etc...
    ├───.gradle
    │   └───...etc...
    ├───app
    │   ├───app.iml
    │   ├───Mobile-SDK-Android.iml
    │   ├───proguard-rules.pro
    │   ├───build
    │   │   ├───generated
    │   │   │   └───...etc...
    │   │   ├───intermediates
    │   │   │   └───...etc...
    │   │   ├───outputs
    │   │   │   └───aar
    │   │   └───tmp
    │   │       ├─...
    │   ├───docs
    │   ├───libs
    │   └───src
    │       ├───androidTest
    │       │   └───java
    │       │       └───com
    │       │           └───...etc...
    │       ├───main
    │       │   ├───java
    │       │   │   └───com
    │       │   │       └───...etc...
    │       │   └───res
    │       │       └───values
    │       │           └───strings.xml
    │       └───test
    │           ├───java
    │           │   └───com
    │           │       └───...etc...
    │           └───resources
    ├───build
    │   ├───android-profile
    │   ├───generated
    │   └───intermediates
    └───gradle
        └───wrapper
    

    build.gradle如下:

    apply plugin: 'com.android.library'
    android {
    
        compileSdkVersion 25
        buildToolsVersion '25.0.2'
        defaultConfig {
            minSdkVersion 16
            targetSdkVersion 25
            versionCode 1
            versionName "0.7"
            testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
            debug {
                debuggable false
            }
        }
    
        packagingOptions {
            exclude 'META-INF/LICENSE'
            exclude 'META-INF/DEPENDENCIES'
            exclude 'META-INF/NOTICE'
            exclude 'META-INF/ASL2.0'
        }
    
        productFlavors {
        }
    
        publishNonDefault true
    }
    repositories {
        ... etc ...
    }
    dependencies {
        // For @Nullable/@NonNull
        compile 'com.android.support:support-annotations:25.3.1'
        testCompile 'junit:junit:4.12'
        ... etc ...
    }
    
  • “发布版本”说明包含以下内容:

    $ ./gradlew check
    $ ./gradlew assembleRelease
    # Then copies and packages app/build/outputs/aar/app-release.aar
    

应用程序的详细信息

“Android应用”模块似乎是普通的Android应用,例如它使用Activity类,Android库和Android Studio将它部署到设备就好了。有这些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

完整的:

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

build.gradle

不包含任何相关内容,我能看到吗?

app/build.gradle

包含这些相关位:

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

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

必要的更改?

什么是 将SDK转换为“普通”且惯用的Java库的适当步骤?

e.g:

  1. 转换android.util.Log的所有用途,例如使用SLF4J
  2. 将所有注释转换为???
  3. 重新实施或使用TextUtilsPair
  4. 的替代方案
  5. 在gradle脚本上执行一些魔术
    • 所以输出是.jar而不是.aar
      • 并不称为app-release.aar
    • 是否仍然可以使用minSdkVersion
    • 之类的内容
    • 是否有可能拥有此jar文件的'android flavor',因为我们需要在将来将特定于Android的代码放入SDK中?
  6. 可能重组SDK的目录以删除“app”目录?
  7. ????
    ñ。利润

2 个答案:

答案 0 :(得分:2)

Android是一个庞大的API,有很多替代品。因此,我希望明确,没有固定的规则来更改库。大多数代码需要从头开始重写。大量的代码基本上是无用的"。用于打印的Log.x, 类已不复存在。这可以由库Logger或仅System.out替换。

至于注释,这取决于来源。

对于Lombok实例,库注释通常适用于桌面和Android。 Android特定注释(@TargetApi)消失了。无法使用minSdk(因为它不是Java中API的一部分)。我希望你能在这里得到这个想法。

如果你没有:你不能只是将Java库转换为Android,反之亦然。为给定平台编写的代码太多,而不是在不同的平台上。

解决方案是从头开始创建它。与桌面Java相比,Android框架运行完全不同的系统,使得大量代码无法使用。并且Activity系统删除任何代码,然后有.xml资源。如果为String资源创建.xml解析器,则可以继续使用Strings.xml。布局需要太多才能创建处理器。单位dp也已消失。

所以回答标题:

  

将Android Java模块转换为普通Java模块需要执行哪些步骤?

一旦你运行了库(或想法),你需要重写它。除了桌面Java(你称之为普通java)语言不同之外,它还有不同的系统。没有.xml资源(JavaFX使用.fxml用于布局,但JavaFX是完全不同的系统),默认情况下。您需要自己解析任何文件并处理字符串的语言环境。布局,JavaFX。

  

将SDK转换为" normal"的适当步骤是什么?和惯用的Java库?

从核心开始,就像任何其他项目一样。创建主类,然后展开。

注解

您提供了注释列表。

  

@Nullable

工作正常

  

@AnyThread

的Android

  

@NonNull

工作正常

  

@UiThread

的Android

  

@WorkerThread

的Android

  

@IntRange

Android

  

@Size

Looks fine

  

@SuppressLint

SuppressLint不存在于桌面Java中。 They have SuppressWarnings虽然(不相关的问题,但它解释了注释是什么)

如果不清楚,标记为Android的注释在使用桌面Java时无效,这意味着它们是为Android编写的

  

所以输出是.jar而不是.aar并且不被称为app-release.aar

使用Java库时,它最终为.jar。

  

还有可能有像minSdkVersion这样的东西吗?

都能跟得上

  

是否有可能拥有' android风味'这个jar文件,我们将来需要在SDK中加入特定于Android的代码吗?

都能跟得上

至于解决这种情况的命令,不可能制作一个。你不能,因为我希望我现在已经说清楚了,只需在Java和Android之间转换代码。差异太多了,这意味着你必须从头开始。因此,您如何设置列表取决于您。但是你需要或多或少地重写整个事情。有些地方你可以复制粘贴,但很少有。

我已将Android项目转换为Java(从原生Android迁移到LibGDX),我不得不重写整个代码。只有一些段是可复制的,大多数是构造函数和一些字段,基本操作等等。复制粘贴基本Java的方式没有什么,问题是任何项目都没有那么多基本的java(比如构造函数,字段,数学运算等)

答案 1 :(得分:1)

更容易创建另外的第三个新的非android-lib项目并将所有没有android依赖项的类从skd-lib-android移动到sdk-lib-common。 sdk-lib-common可以在android之外使用。

用于其他Android依赖类

  • 为简单的非依赖类添加android源代码,如Pair
  • 或将它们移植到非android(即SLF4J而不是android.util.Log也适用于android)

有待进一步参考,请参阅

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