巴法云 SDK for Java & Android 实战指南,让你轻松接入巴法云

巴法云 Java & Android SDK 实战指南,让你轻松接入巴法云

这是《巴法云 SDK》系列的第二篇。上一篇《高二学生写了 15273 行代码,就为把"接巴法云"的重复活儿包圆》聊了为什么写这个 SDK、把哪些"重复活"包了。这篇不绕弯,直接带你从加依赖跑到第一个请求,JVM 和 Android 都给完整示例,顺带把几个接入时容易忽略、或者我在设计上特意处理过的使用须知讲清楚。

看完这篇,你能搞定这几件事:

  • 10 分钟内把 SDK 接进自己的 JVM / Android 项目;
  • 用 Builder 链式构建任意一个巴法云 API 并发起请求;
  • 绕开 SLF4J 冲突、混淆、线程模型这几个最常见的坑。

一、先一句话回顾项目

Bemfa SDK 是巴法云的 Java / Android 开发工具包。你用 Builder 链式调用把请求拼好,拿回来的是解析好的强类型业务对象——不用自己拼 URL,也不用手写 JSON 解析,更不用手动判断错误码。坐标已经发到 Maven Central:

io.github.nebulagate:bemfa-api:1.0.0
io.github.nebulagate:bemfa-jvm:1.0.0       // JVM 环境
io.github.nebulagate:bemfa-android:1.0.0  // Android 环境

它适合谁、能省什么,我用一张表带过(细节都在第一篇):

它能帮你 适合谁
不发 HTTP、不写 JSON 解析,直接拿业务对象 想快速接入巴法云、不想啃文档的同学
一套调用代码,JVM / Android 共用(SPI 自动适配平台) 学生党(课设 / 毕设 / 电子竞赛)
Android 请求跟随 Activity 生命周期自动取消,防内存泄漏 自己写 APP 接入巴法云的 Android 开发者
错误码统一成枚举,一个姿势处理失败 个人开发者 & 创客做物联网小工具

📌 适用边界:这是 Java / Android 这一侧的方案——能在 JVM(含树莓派等能跑 Java 的环境)和 Android 上使用,适合做客户端。Arduino / ESP8266 / ESP32 这类单片机不是 Java 运行环境,暂时用不上


二、先感受差距:不用 SDK vs 用了

看代码最直观。拿"获取主题列表"来说,不用 SDK 时你得自己揽一大堆活:

// 不用 SDK:自己拼 URL、自己建 OkHttp、自己 parse JSON、自己判 code
Request request = new Request.Builder()
    .url("https://api.bemfa.com/api/...").build();
Response response = client.newCall(request).execute();
JSONObject obj = new JSONObject(response.body().string());
if (obj.getInt("code") != 0) { 
    /* 自己映射错误 */ 
}
JSONArray arr = obj.getJSONArray("data"); // 还得记清这回字段叫 data 还是 array

用了 SDK 之后:

// 用了 SDK:直接拿强类型业务对象
BemfaClient.init(config);
TopicInfos result = BemfaClient.getHttpClient().executeSync(
    BemfaRequestApis.v1.Device.getAllTopicApiBuilder()
        .topicType(TopicType.MQTT)
        .build()
);
System.out.println(result.getTopics()); // 不用解析 JSON,字段已是对象

拼 URL、解析 JSON、判错误码这些脏活、累活,SDK 一次性全包了。


三、JVM 环境:5 步跑通

1. 加依赖(Gradle)

dependencies {
    implementation('io.github.nebulagate:bemfa-api:1.0.0')
    implementation('io.github.nebulagate:bemfa-jvm:1.0.0')
}

已发布到 Maven Central,不需要像 JitPack 那样额外配仓库。用 Maven 的话把 bemfa-api + bemfa-jvm 两个依赖写进 pom.xml 即可。

2. 初始化

BemfaConfig config = new BemfaConfig();
config.setLogLevel(LogLevel.INFO); // 想看 SDK 日志就开
BemfaClient.init(config);

3. 登录

// 手机号登录(也支持邮箱登录)
BemfaClient.getHttpClient().executeSync(
    BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build()
);
// 也可以 UID 登录:
// BemfaClient.loginByUid("yourUid");

4. 建主题 + 推消息(完整一条龙)

HttpClient client = BemfaClient.getHttpClient();

// 创建设备主题
client.executeSync(
    BemfaRequestApis.v1.Device.createTopicApiBuilder()
        .topicId("yourTopic")
        .topicType(TopicType.MQTT)
        .nickname("客厅灯")
        .build()
);

// 推送消息
client.executeSync(
    BemfaRequestApis.v1.Device.pushMessageApiBuilder()
        .topicId("yourTopic")
        .topicType(TopicType.MQTT)
        .message("开灯")
        .build()
);

// 获取所有主题,直接拿强类型 TopicInfos
TopicInfos topics = client.executeSync(
    BemfaRequestApis.v1.Device.getAllTopicApiBuilder()
        .topicType(TopicType.MQTT)
        .build()
);
System.out.println(topics.getTopics());

5. 关闭

BemfaClient.close();

到这 JVM 就跑通了。后台任务里同步调用不阻塞,直接 executeSync 最省事。


四、Android 环境:注意线程

1. 加依赖(Gradle)

dependencies {
    implementation('io.github.nebulagate:bemfa-api:1.0.0')
    implementation('io.github.nebulagate:bemfa-android:1.0.0')
}

📌 AndroidX 依赖:SDK 的 Android 模块用了 AndroidX 的 Lifecycle 特性,仅支持 AndroidX 项目。若还在用旧版 Support Library(android.support.*),需先迁移到 AndroidX 才能接入。

2. 初始化(建议开启生命周期管理)

AndroidBemfaConfig config = new AndroidBemfaConfig();
config.setHttpLifecycleAutoManaged(true); // 开启后请求自动跟随 Activity 生命周期
BemfaClient.init(config);

开启后,把 Activity 作为 tag 传进请求,页面 onDestroy() 时 SDK 自动取消该页面名下的在途请求,你不用手写取消逻辑。

3. 后台线程登录(同步会阻塞,必须在后台线程)

new Thread(() -> {
    BemfaClient.getHttpClient().executeSync(
        BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
            .phone("yourPhone")
            .password("yourPassword")
            .area("86")
            .build()
    );
}).start();

4. 带 Activity tag 请求(页面销毁自动取消)

new Thread(() -> {
    try {
        TopicInfo topic = BemfaClient.getHttpClient().executeSync(
            BemfaRequestApis.v1.Device.getTopicApiBuilder()
                .topicId("yourTopic")
                .topicType(TopicType.MQTT)
                .build(),
            MainActivity.this   // 传入 Activity 作为 tag,页面销毁时自动取消
        );
        runOnUiThread(() -> textView.setText("主题昵称:" + topic.getNickname()));
    } catch (RequestCanceledException e) {
        // 页面已销毁,请求被自动取消,无需处理
    } catch (BemfaSdkException e) {
        runOnUiThread(() -> showError(e));
    }
}).start();

5. 异步请求(主线程发起,回调需切回 UI)

BemfaClient.getHttpClient().executeAsync(
    BemfaRequestApis.v1.Device.getTopicApiBuilder()
        .topicId("yourTopic")
        .topicType(TopicType.MQTT)
        .build(),
    new RequestCallback<TopicInfo>() {
        @Override
        public void onSuccess(TopicInfo topic) {
            runOnUiThread(() -> textView.setText("主题昵称:" + topic.getNickname()));
        }
        @Override
        public void onError(BemfaSdkException e) {
            runOnUiThread(() -> textView.setText("请求失败:" + e.getMessage()));
        }
    }
);

⚠️ Android 线程模型:同步 executeSync 会阻塞当前线程,必须在后台线程执行;异步 executeAsync 调用本身可在主线程发起(网络在 SDK 内部线程池跑),但回调运行在后台线程,更新 UI 一定要 runOnUiThread(...) 包起来。


五、请求怎么构建(Builder 三种写法)

所有 API 都是 Builder 链式构造,编译期强校验,漏填参数直接编译不过。三种写法你可以挑顺手的:

// 一:用集中访问点(推荐,IDE 自动补全最友好)
BemfaRequestApi<Void> apiA = BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build();

// 二:直接用对应的 API Builder
LoginWithPhoneApi apiB = LoginWithPhoneApi.builder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build();

// 三:执行时现写(最简洁)
BemfaClient.getHttpClient().executeSync(
    BemfaRequestApis.v1.User.loginWithPhoneApiBuilder()
        .phone("yourPhone")
        .password("yourPassword")
        .area("86")
        .build()
);

目前已封装 41 个 API,按功能分了类:Device(设备管理)、User(用户认证)、Timer(定时任务)、Image(图片)、WeChat(微信通知)、Share(设备分享)、Firmware(OTA)、Voice(语音)、Time(校时)。返回值都是强类型对象(TopicInfoTimerInfos 等),不是 JSON 字符串。


六、同步还是异步

HttpClient client = BemfaClient.getHttpClient();
BemfaRequestApi<String> api = BemfaRequestApis.v1.Time
        .getCurrentTimeApiBuilder()
        .type(1)
        .build();

// 同步:阻塞当前线程,直接返回结果,try-catch 捕获异常
String time = client.executeSync(api);

// 异步:不阻塞,结果在回调里返回,可按错误类型分别处理
client.executeAsync(api, new RequestCallback<String>() {
  @Override
  public void onSuccess(String result) {
    System.out.println("成功:" + result);
  }

  @Override
  public void onBusinessError(BemfaSdkErrorCode errorCode, ApiBusinessException e) {
    System.err.println("业务错误:" + e.getMessage());
  }

  @Override
  public void onNetworkError(NetworkException e) {
    System.err.println("网络错误:" + e.getMessage());
  }

  @Override
  public void onResponseParseError(String responseBody, ApiResponseException e){
    System.err.println("响应解析错误:" + e.getMessage());
  }

  @Override
  public void onError(BemfaSdkException e) {
    System.err.println("其他错误:" + e.getMessage());
  }
});
// 如果对请求产生的错误不关心,也可以只实现回调接口的成功方法
client.executeAsync(api, new RequestCallback<String>() {
  @Override
  public void onSuccess(String result) {
    System.out.println("成功:" + result);
  }
});

具体用同步还是异步,看你调用方在哪个线程、要不要当场等结果——前面两段代码已经写清楚了。


七、接入前你需要留意的几点(使用须知)

下面几个点,是接入时容易忽略、或者我在设计上特意帮你处理过、也有需要你配合一下的地方:

1. SLF4J 绑定:SDK 已经帮你选好默认实现
为了开箱即用,bemfa-jvm 默认绑定 slf4j-jdk14bemfa-android 默认绑定 slf4j-android。如果你的项目已经接了 Logback / Log4j2 / Logback-Android,会出现「SLF4J 检测到多个绑定」的冲突警告——这时排除掉 SDK 的默认绑定、引你自己的即可:

implementation('io.github.nebulagate:bemfa-jvm:1.0.0') {
    exclude group: 'org.slf4j', module: 'slf4j-jdk14'
}

// Android
implementation('io.github.nebulagate:bemfa-android:1.0.0') {
    exclude group: 'org.slf4j', module: 'slf4j-android'
}

slf4j-api 门面由 bemfa-api 自动传递,不用手动声明。)

2. 混淆(R8 / ProGuard):已内置规则
Android 模块通过 consumer-rules.pro 内置了混淆规则,开启混淆的 Release 构建会自动合并 SDK 的 -keep 规则,一般不用你额外配置。

3. 配置需按平台选择类(当前版本的设计取舍)
这块是我目前还没做干净的地方——初始化时 JVM 用 BemfaConfig、Android 必须用 AndroidBemfaConfig;取配置也得你自己传平台类。理想情况是这两步像选 HTTP 客户端那样由 SDK 内部自动判断,但受 Java 类型擦除 + 静态构造限制,暂时没找到干净的实现,这版只好先保留手动选择,接入时按平台选对类就行。大佬们要是有更顺的思路,欢迎去 Gitee Issue / GitHub Issue 聊。

4. 错误处理分层:异常类型已为你规划好
SDK 把失败归成了明确的异常类型,按需捕获即可,不用你自己去解析错误码:

错误类型 异常类 说明
参数校验错误 InvalidArgumentException 构建请求时参数不合法
网络连接错误 NetworkException 无网络、超时等
HTTP 状态错误 ApiHttpException 服务器返回非 2xx
响应解析错误 ApiResponseException JSON 解析失败等
请求被取消 RequestCanceledException 生命周期销毁或手动取消
业务逻辑错误 ApiBusinessException 后端业务错误码(如主题不存在)
客户端状态错误 IllegalClientStateException 未登录
未初始化错误 UninitializedException 未初始化 SDK
SPI 错误 ServiceProviderException 平台适配器加载失败

同步调用用 try-catch 捕获,异步调用在 onError / 各分类回调里统一处理。

5. Android 同步必须在后台线程
这是 Android 平台的线程约束(不是 SDK 的限制,但 SDK 会如实遵守):executeSync 会阻塞当前线程,务必包在 new Thread(...) / 协程 / Executors 里,别在主线程调。


八、结尾 & 相关阅读

这一篇就到这,"怎么接"应该讲清楚了。系列两篇是这样分工的:

  • 第一篇:为什么写这个 SDK、把哪些重复活包了(初衷、设计思路、已知缺陷都在那);
  • 这一篇:从依赖到跑通请求,JVM / Android 完整示例 + 避坑。

我是个高二学生,这个 SDK 是课余时间一点点堆出来的。要是它帮你省掉了手拼 HTTP / JSON 那堆活儿,欢迎来:

完整用法、41 个 API 参考和更多示例,都在 GitHub README。后面真要写 TCP / MQTT 长连接那篇,我还会在这个系列更,感兴趣可以留意一下。

posted @ 2026-08-06 19:45  云阙(NebulaGate)  阅读(1)  评论(0)    收藏  举报