【问题标题】:What steps need to be performed to convert an Android Java module into a normal Java one?需要执行哪些步骤才能将 Android Java 模块转换为普通 Java 模块?
【发布时间】:2017-09-05 13:33:57
【问题描述】:

我有一个由两个模块组成的 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 量身定制的 目录结构。即 repo 目录如下所示:

    /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. ????
    n.利润

【问题讨论】:

    标签: java android gradle jar android-gradle-plugin


    【解决方案1】:

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

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

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

    如果您不这样做:您不能只将 Java 库转换为 Android 或其他方式。为给定平台编写的代码过多,而其他平台上没有。

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

    所以回答标题:

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

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

    将 SDK 转换为“正常”且惯用的 Java 库的适当步骤顺序是什么?

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

    注释

    您提供了注释列表。

    @Nullable

    工作正常

    @AnyThread

    安卓

    @NonNull

    工作正常

    @UiThread

    安卓

    @WorkerThread

    安卓

    @IntRange

    安卓

    @大小

    Looks fine

    @SuppressLint

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


    如果不清楚,上面标记为 Android 的注释在桌面 Java 上不起作用,这意味着它们是为 Android 编写的


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

    当您使用 Java 库时,它以 .jar 结尾。

    还有像 minSdkVersion 这样的东西吗?

    没有

    这个 jar 文件是否有可能具有“android 风格”,以防我们将来需要将 android 特定代码放入 SDK 中?

    没有


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

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

    【讨论】:

      【解决方案2】:

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

      对于其他 android 依赖类

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

      更多参考请看

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-03-10
        • 1970-01-01
        • 2017-09-04
        • 2011-11-30
        • 1970-01-01
        • 2010-12-18
        • 2021-12-18
        • 2011-02-13
        相关资源
        最近更新 更多