1.10.2.3.6 BoneMobile 容器 SDK

优质
小牛编辑
131浏览
2023-12-01

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 切换到开发环境来测试插件变更的效果。测试通过后,点击发布按钮后,插件的变更才会发布到生产环境。

undefined | center

使用方式

打开插件面板

请参考如下代码打开插件面板:

            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 有所差异,所以替换图片库的时候,请注意以下问题:

  1. gif 的支持。请尽量使用支持 gif 动画的图片库或者自己实现对于 gif 的支持,否则可能导致部分 使用了 gif 图片的页面不能正确的展示

  2. 图片圆角的支持。请实现对于圆角的支持,否则部分设置了圆角的图片可能无法正常展示

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 实现的 FrescoBasedReactTextInlineImageViewManagerFrescoBasedReactTextInlineImageShadowNode 来实现您的 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());