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

标签 java android gradle jar android-gradle-plugin

我有一个 Android 项目,由两个模块组成:“SDK”和“演示 Android 应用程序”。

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

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

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 量身定制的 目录结构。即存储库目录如下所示:

    /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 脚本:

/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 库的适当步骤顺序是什么?

例如:

  1. android.util.Log 的所有使用转换为使用例如SLF4J
  2. 将所有注释转换为 ???
  3. 重新实现或使用 TextUtilsPair 的替代方案?
  4. 对 gradle 脚本施展一些魔法
    • 因此输出是 .jar 而不是 .aar
      • 并且不名为 app-release.aar
    • 是否仍然可以拥有像 minSdkVersion 这样的东西?
    • 这个 jar 文件是否有可能具有“android 风格”,以防我们将来需要将 Android 特定代码放入 SDK 中?
  5. 是否可以重组 SDK 的目录以删除“app”目录?
  6. ???
    名词利润

最佳答案

Android 是一个庞大的 API,并且有很多替代方案。因此,我想澄清的是,更改库没有固定的规则。大部分代码需要从头开始重写。大量的代码基本上是“无用的”。 Log.x,用于打印的类消失了。这可以由库、Logger 或仅 System.out 替换。

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

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

如果您没有:您不能将 Java 库转换为 Android 或反之亦然。为给定平台编写的代码太多,而在其他平台上则没有。

解决方案是从头开始创建它。与桌面 Java 相比,Android 框架运行一个完全不同的系统,导致很多代码无法使用。 Activity 系统会删除任何该代码,然后就有 .xml 资源。如果您为字符串资源创建 .xml 解析器,则可以继续使用 Strings.xml。创建处理器需要太多的布局。单位dp也消失了。

所以回答标题:

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

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

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

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

注释

您提供了注释列表。

@Nullable

工作正常

@AnyThread

安卓

@NonNull

工作正常

@UiThread

安卓

@WorkerThread

安卓

@IntRange

安卓

@Size

Looks fine

@SuppressLint

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


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


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

当您使用 Java 库时,它最终会成为 .jar。

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?

没有


至于下达命令来解决问题,那是不可能下达的。正如我希望我现在已经明确表示的那样,您不能仅在 Java 和 Android 之间转换代码。差异太多,意味着你必须从头开始。因此,如何设置该列表取决于您。但你或多或少需要重写整个事情。有些地方可以复制粘贴,但这样的地方很少。

我已将 Android 项目转换为 Java(从 native Android 移至 LibGDX),并且必须重写整个代码。只有一些段是可复制粘贴的,主要是构造函数和一些字段、基本操作等。没有什么可以复制粘贴基本Java的方式,问题是任何项目都没有那么多基本Java(如构造函数、字段、数学运算等)

关于java - 将 Android Java 模块转换为普通 Java 模块需要执行哪些步骤?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46056343/

相关文章:

java - 在 JavaFX Controller 中获取被单击对象的 ID 的更好方法

java - 几秒钟后HBase崩溃

javascript - Webview不加载javascript获取内容

android - Gradle 同步失败 : Could not find com. google.http-client :google-http-client-parent:1. 24.1。在以下位置搜索:

java - 如何在 build.gradle 文件中使用 GitHub secret 或 GitHub 环境变量

java - 如何迭代位于运行的 .jar 文件外部的文件夹

java - 为什么我不能将 View 类型的对象转换为 KeyboardView

android - 移动实时同步(如 Trello) : sockets?

java - 想要抛出打开新 Activity 的 Intent ,但不断崩溃

java - 如何将 build.gradle 文件拆分为具有较小任务的文件