安卓原生工具

本文面向 Android Java 原生组件的开发与维护,介绍 android/nativescipt-common 中的 HttpRequest 和 Utils。它们随公共 JAR 提供,用于原生模块内部复用;本文不提供 NativeScript TS 调用入口或接口代理示例。

业务 TS 使用 通用工具 或 安卓工具类。密钥管理与加解密单独见 KeyStore 与 AES。当前 demo-app 最低 Android 8.0(API 26),Java 工程使用 Java 8 源码与目标兼容配置。

联网权限

HTTP 请求要求宿主在 AndroidManifest.xml 的 <manifest> 下声明 INTERNET 权限,无需运行时申请:

<uses-permission android:name="android.permission.INTERNET" />

HttpRequest:后台 GET 与 JSON POST

原生类:com.ajaxjs.nativescript.android.utils.HttpRequest。此类供 Android 原生组件内部使用,本文以 Java 调用说明,不作为面向业务 TS 的工具 API。

方法 参数说明 返回值
get(url, callback) 默认网络;正文回调 void
get(url, callback, headerConsumer) 默认网络;发送前配置请求头 void
get(url, callback, network, headerConsumer) 可指定 android.net.Network;请求头回调可为空 void
get(url, callback, network, headerConsumer, onError) 增加错误回调 void
post(url, body, callback, network, onError) JSON 文本;网络可为空;错误回调可为空 void
readInputStream(input) UTF-8 输入流,可为空 去除首尾空白后的字符串;输入流为空时为空字符串;读取失败抛出 UncheckedIOException

回调参数使用 Java java.util.function.Consumer:正文与错误回调接受字符串;headerConsumer 接受 HttpURLConnection。以下示例供 Android Java 原生代码调用:

import android.util.Log;
import com.ajaxjs.nativescript.android.utils.HttpRequest;
import java.util.function.Consumer;

Consumer<String> success = body -> Log.d("HTTP_DEMO", "Response length: " + body.length());
Consumer<String> failure = error -> Log.e("HTTP_DEMO", error);

HttpRequest.get("https://example.com/api/status", success, null,
        connection -> connection.setRequestProperty("Accept", "application/json"), failure);
HttpRequest.post("https://example.com/api/command", "{\"command\":\"stop\"}",
        success, null, failure);

示例语句放在 Java 方法体内,URL 替换为实际服务。请求通过进程级单线程 Executor 串行执行,成功和错误回调均在后台线程、连接释放后调用。更新原生 UI 应通过主线程 Handler 或 Activity.runOnUiThread 调度;耗时回调会延迟后续请求,组件没有取消接口。回调自身的异常不会被当作请求失败或再次触发错误回调。

GET 的连接 / 读取超时分别为 5 / 10 秒;POST 分别为 55 / 50 秒。GET 可在发送前配置请求头;POST 当前没有自定义请求头参数,非空 body 自动设置 Content-Type: application/json 并按 UTF-8 写入,但不验证正文是否为合法 JSON。空 body 不写入请求体,也不设置该 Content-Type。

HTTP 2xx 触发成功回调;非 2xx 或请求异常触发 onError,未传错误回调时仅记录日志,不调用成功回调。正文读取会去掉首尾空白,并将逐行内容重组为换行分隔文本,不适合依赖原始字节、签名、二进制或精确空白的响应。

网络参数为 null 时使用系统默认网络;非空时通过 Network.openConnection 使用指定网络,本工具不负责获取或绑定网络。宿主应声明 INTERNET 权限。工具未强制 HTTPS,也未主动禁用重定向,实际行为受 HttpURLConnection 和宿主网络安全配置影响。

原生实现会记录 URL、响应正文及错误信息,不要用它传输秘密主密钥或敏感响应。密钥获取应使用插件现有的 HTTPS 配置接口,详见 KeyStore 与 AES,该接口有独立的协议与校验流程。

Utils:时间与随机字符串

原生类:com.ajaxjs.nativescript.android.utils.Utils,供原生代码使用,与 NativeScript 的同名 TS 工具不同。

方法 参数 返回值 / 异常
now() 无 设备当前时区的 yyyy-MM-dd HH:mm:ss 文本,不包含时区信息
generateRandomString(length) 非负整数,Java int 大小写英文字母和数字组成的指定长度字符串;0 返回空字符串;负数抛出异常
import com.ajaxjs.nativescript.android.utils.Utils;

String time = Utils.now();
String requestId = Utils.generateRandomString(16);

示例语句放在 Java 方法体内。

随机字符串使用进程级 SecureRandom,在 62 个字符中逐位选择。它不是 AES 密钥的标准 Base64,也不是 12 字节 GCM nonce;AES nonce 由加密接口自动生成。MQTT 报文的 UTC Unix epoch 毫秒时间戳在 Java 中使用 System.currentTimeMillis(),不要用 now() 的本地时间文本替代。

组件基础名称可由 com.ajaxjs.nativescript.android.AjNativescript.getName() 获取,固定返回 "aj-nativescript",不代表版本号。

原生工程与构建

源码位于独立 Gradle 工程:

android/nativescipt-common/aj-nativescript/src/main/java/com/ajaxjs/nativescript/android/
├── AjNativescript.java
├── utils/
│   ├── Helper.java
│   ├── MarketRedirect.java
│   ├── HttpRequest.java
│   └── Utils.java
└── crypto/
    ├── AesKeyStore.java
    ├── JsonBodyCipher.java
    ├── EncryptedBody.java
    └── RobotKeyDerivation.java

在 nativescript-plugin/nativescipt-common 目录执行:

npm run build:native
npm run build

build:native 调用独立 Gradle 工程的 JAR 构建任务,复制产物到插件 platforms/android/aj-nativescript.jar;build 编译 TS。构建 Java 时仅引用 Android SDK 的 android.jar,不把 SDK 类打包到插件中。

Windows 使用 gradlew.bat,macOS / Linux 使用 Gradle shell 包装脚本。SDK 路径可通过 ANDROID_HOME、ANDROID_SDK_ROOT 或原生工程 local.properties 的 sdk.dir 指定;当前默认编译 SDK 为 35,Java 源码和目标兼容版本为 8。

完整 npm 打包与发布流程见组件 README。npm pack 会重建 Android JAR;iOS 产物的生成与复用按 iOS 构建脚本处理,Windows 不编译 Xcode 工程。更新后使用现有 demo-app 重新编译 Android App,通过“测试”tab 验证 Toast 和 AES 功能。

本文按当前源码整理接口与实现行为,不表示所有厂商市场、权限场景和 HTTP 服务都已完成实机验证。