BoneMobile 容器 SDK
更新时间:2018-03-26 19:25:13
概述
BoneMobile 容器 SDK 为可选模块,提供了加载插件的功能。如果您需要开发或者使用插件,则需要在 App 中集成 BoneMobile 容器 SDK。
| 依赖SDK | 概述 |
|---|---|
| API 通道 | 提供API通道能力 |
初始化
初始化 BoneMobile 容器 SDK 前,请先初始化 API 通道 SDK,请参见:API 通道SDK - 初始化。请在 Application.onCreate 函数中,添加如下初始化代码:
String serverEnv = "production";//仅支持"production",即生产环境
String pluginEnv = "release";//"release"为生产环境,"test"为开发环境
// 初始化路由
RouterExternal.getInstance().init(application, pluginEnv);
// 初始化包管理器
{
BundleManager.instance(application).setPluginEnv(pluginEnv);
PluginConfigManager.getInstance().init(application);
PluginConfigManager.getInstance().addPluginConfigChangeListener(new PluginConfigManager.OnPluginConfigChangedListener() {
@Override
public void onChange(PluginConfigManager.PluginConfigData pluginConfig) {
if (null != pluginConfig) {
BundleManager.instance(application).notifyUpdate(JSON.toJSONString(pluginConfig));
}
}
});
PluginConfigManager.PluginConfigData data = PluginConfigManager.getInstance().getPluginConfigData();
if (null != data) {
BundleManager.instance(application).notifyUpdate(JSON.toJSONString(data));
}
}
// 初始化 BoneMobile RN 容器
InitializationHelper.initialize(application, pluginEnv, serverEnv);
// 添加基于 Fresco 的图片组件支持
InitializationHelper.addPackage(new FrescoPackage());
关于 pluginEnv 的概念, 需要联系控制台来理解:
在发布资源变更以前,可以把 pluginEnv 切换到开发环境来测试插件变更的效果。测试通过后,点击发布按钮后,插件的变更才会发布到生产环境。

使用方式
打开插件面板
请参考如下代码打开插件面板:
Router.getInstance().toUrl(context, "{插件ID}");
打开调试面板
请参考如下代码使用本地调试功能:
String ip = "{IP地址}"; //开发电脑上要开启 Bone 调试服务
new BoneDevHelper().getBundleInfoAsync(this, ip, new BoneDevHelper.OnBondBundleInfoGetListener() {
@Override
public void onSuccess(BoneDevHelper.BoneBundleInfo boneBundleInfo) {
BoneDevHelper.RouterInfo info = new BoneDevHelper().handleBundleInfo(MainActivity.this, boneBundleInfo);
if (null == info) {
return;
}
Router.getInstance().toUrl(MainActivity.this, info.url, info.bundle);
}
@Override
public void onError(String message, Exception e) {
Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
if (null != e) {
e.printStackTrace();
}
}
});
混淆配置
# component-rncontainer.begin
# react-native.begin
# keep class not found with httpclient
-dontwarn org.apache.http.**
-dontwarn android.net.http.AndroidHttpClient
-dontwarn android.util.FloatMath
-dontwarn okio.**
-dontwarn com.facebook.**
-dontwarn com.squareup.okhttp.**
-dontwarn okhttp3.internal.huc.DelegatingHttpsURLConnection
-dontwarn okhttp3.internal.huc.OkHttpsURLConnection
-dontwarn android.support.v8.renderscript.**
-keep class com.facebook.**{*;}
# react-native.end
-keep class * implements com.facebook.react.bridge.NativeModule {
public <methods>;
protected <methods>;
}
# keep view manager
-keep class * extends com.facebook.react.uimanager.ViewManager {
public <methods>;
protected <methods>;
}
# keep js module
-keep class * extends com.facebook.react.bridge.JavaScriptModule {
public <methods>;
}
# keep shadow node
-keep class * extends com.facebook.react.uimanager.ReactShadowNode{
public <methods>;
protected <methods>;
}
# keep ReactPackage
-keep class * implements com.facebook.react.ReactPackage{
public <methods>;
}
# keep interface class
-keep class com.aliyun.alink.alirn.RNContainer{
public <methods>;
public <fields>;
}
-keep class com.aliyun.alink.alirn.RNContainerConfig{
public <methods>;
public <fields>;
}
-keep class com.aliyun.alink.alirn.RNGlobalConfig{
public <methods>;
public <fields>;
}
# BoneDevHelper
-keep class com.aliyun.alink.alirn.dev.BoneDevHelper{
public <methods>;
}
-keep class com.aliyun.alink.alirn.dev.BoneDevHelper$RouterInfo{
public <fields>;
}
-keep class com.aliyun.alink.alirn.dev.BoneDevHelper$BoneBundleInfo{
public <fields>;
}
-keep class com.aliyun.alink.alirn.dev.BoneDevHelper$OnBondBundleInfoGetListener{
public <methods>;
}
# cache
-keep public class com.aliyun.alink.alirn.cache.**{
public <methods>;
}
# launch
-keep class com.aliyun.alink.alirn.launch.LaunchOptionsFactory{
public <methods>;
}
-keep class com.aliyun.alink.alirn.launch.OnLoadingStatusChangedListener{
public <methods>;
}
-keep class com.aliyun.alink.alirn.launch.LoadingStatus{
public <fields>;
}
#preload
-keep class com.aliyun.alink.alirn.preload.ReactInstanceManagerWrapperPool{
public <methods>;
}
-keep class com.aliyun.alink.alirn.preload.PreloadConfiguration{
public <methods>;
}
-keep public class com.aliyun.alink.alirn.preload.sdk.**{
public <methods>;
public <fields>;
}
# biz package
-keep class com.aliyun.alink.alirn.rnpackage.biz.BizPackageHolder{
public <methods>;
}
# ut
-keep class com.aliyun.alink.alirn.usertracker.IUserTracker{
public <methods>;
}
-keep class com.aliyun.alink.alirn.usertracker.UserTrackerHolder{
public <methods>;
}
#utils
-keep class com.aliyun.alink.alirn.utils.SimpleRNConfig{
public <methods>;
}
# component-rncontainer.end
# for BoneBridge @ Start
# keep bone api
-keep class * extends com.aliyun.alink.sdk.jsbridge.methodexport.BaseBonePlugin {
@com.aliyun.alink.sdk.jsbridge.methodexport.MethodExported <methods>;
public <fields>;
}
# for BoneBridge @ End
# for BundleManager @ begin
-dontwarn com.aliyun.iot.aep.component.bundlemanager.ocache.bean.**
-keep class com.aliyun.iot.aep.component.bundlemanager.ocache.BundleManager{
public <methods>;
}
-keep class com.aliyun.alink.page.rn.PluginConfigManager.PluginConfigData.** {}
# for BundleManager @ end
# for Router
-keep class com.aliyun.iot.aep.routerexternal.** {
public <methods>;
public <fields>;
}
更多功能
集成账号能力
插件中如果需要使用账号的登录,登出以及获取用户信息等功能,需要集成统一账号接口模块
初始化
LoginBusiness.init(context, new OALoginAdapter(getApplicationContext()), true, "ONLINE");
其中 adapter 不能为 null ,需要开发者自行实现 ILoginAdapter 接口,可以参考 DemoAPP 中的OALoginAdapter。
混淆配置
-keep class com.aliyun.iot.aep.sdk.login.**{*;}
图片库替换
为了减小 BoneKit 的 SDK 大小,降低接入成本及运行期的 CPU /内存/文件系统资源消耗。
BoneMobileRN容器允许开发者定制自己想用的图片库组件。
如果您已经有了成熟的 apk,并且使用了 Fresco 以外的图片库,请参考以下步骤替换图片库。
注意:因为各个图片库支持的 feature 有所差异,所以替换图片库的时候,请注意以下问题:
gif 的支持。请尽量使用支持 gif 动画的图片库或者自己实现对于 gif 的支持,否则可能导致部分 使用了 gif 图片的页面不能正确的展示
图片圆角的支持。请实现对于圆角的支持,否则部分设置了圆角的图片可能无法正常展示
1. 实现 ImageLoaderModule
实现 ImageLoaderModule,请参考 Facebook 的官方说明:Native Modules
请参考 Facebook 基于 Fresco 实现的ImageLoaderModule, 来实现您的 ImageLoaderModule。
2. 实现 ReactImageManager
实现 ReactImageManager,请参考 Facebook 的官方说明:Native UI Components
请参考 Facebook 基于 Fresco 实现的ReactImageManager.java,来实现您的 ReactImageManager。
3. 实现 ReactTextInlineImageViewManager
实现 ReactTextInlineImageViewManager 与实现 ReactImageViewManager 类似,都继承自 ViewManager,但差别在于,这次需要实现 ShadowNode。ShadowNode 需要继承自 ReactTextInlineImageShadowNode,请参考基于 Fresco 实现的 FrescoBasedReactTextInlineImageViewManager和 FrescoBasedReactTextInlineImageShadowNode 来实现您的 ReactTextInlineImageViewManager。
4. 实现 ImagePackage
ImagePackage 的实现比较简单,把前面步骤实现的 API 和组件暴露出来即可。
参考下面的代码:
public class FrescoPackage implements ReactPackage {
@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.<NativeModule>asList(
new ImageLoaderModule(reactContext)
);
}
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Arrays.<ViewManager>asList(
new ReactImageManager(),
new FrescoBasedReactTextInlineImageViewManager()
);
}
}
5. 注册 ImagePackage
最后把刚才实现的 ImagePackage 注册到 BoneKit 的全局配置即可:
// 添加你自己的图片组件支持
InitializationHelper.addBizPackage(new ImagePackage());
6. 删除 Fresco 的相关依赖和代码
删除 Fresco 的依赖,仅保留 BoneKit 的依赖,参考如下:
compile ('com.aliyun.iot.aep.page:rn:0.0.3.2-SNAPSHOT'){
exclude group:'com.aliyun.iot.aep.sdk', module:'rn-external-fresco' //移除Fresco的依赖
}
compile 'com.aliyun.alink.external:flog:1.0.0@aar'//ReactNative使用了Fresco内部的Flog相关类,Fresco移除后,需要额外添加flog
删除 FrescoPackage 的添加代码:
// 添加基于 Fresco 的图片组件支持
// InitializationHelper.addBizPackage(new FrescoPackage());