ynchuan / blog

https://github.com/ynchuan/blog/issues
http://ynchuan.github.io/blog
0 stars 0 forks source link

前端开源说明 #16

Closed ynchuan closed 5 years ago

ynchuan commented 6 years ago

初步

接入小程序SDK后,前端swan.js是集成在SDK中的,SDK接入的APP(以下简称“宿主”)默认无需关心SDK上swan.js的更新/运行,但是宿主需要扩展swan对于小程序开发者的API/组件时,则需要为js运行时编写特定逻辑。

扩展

扩展都能做什么

目前编写扩展,可以给宿主带来三种能力:

  1. 扩展运行在当前宿主上的swan的API,运行在该宿主上的小程序开发者,可以在小程序运行在该宿主时,使用特定的API,如:swan.tieba.publishThread()
  2. 扩展运行时在当前宿主上的组件,运行在该宿主上的小程序开发者,可以在小程序运行在该宿主时,使用特定的组件,如:<bilibili-video></bilibili-video>
  3. 宿主可以将统计逻辑,添加在extension.js中。

扩展的编写

如果宿主需要在swan上扩展API或是扩展组件的话,则需要进行两步的操作:

  1. 在客户端,需要xxx;
  2. 在前端,需要编写一个extension.js,并上传到百度(目前可以以文件的形式提供给百度)。

extension.js的基础格式

// 宿主的extension.js逻辑
module.exports = {
    name: 'tieba',
    // 扩展API
    methods: {
        publishThread: function (id) {}
    },
    // 扩展组件
    components: {
       'video': {}
    },
    // 扩展私有的统计逻辑
    customLog: function () {}
});

三方写的extension.js中,可以扩展的有:API/组件/统计逻辑。此js会被编译成如下格式:

define('swan-extension', ['swanx', 'swan', 'boxjs'], function (swanx, swan, boxjs) {
    module.exports = {
        name: 'tieba',
        // 扩展API
        methods: {
            publishThread: function (id) {}
        },
        // 扩展组件
        components: {
           'video': {
               template: '<div>video</div>',
               depandencies: ['swaninterface'],
               attached() {
                   boxjs.xxxx
               }
           }
        },
        // 扩展私有的统计逻辑
        customLog: function (swanEventFlow) {
            swanEventFlow.onMessage('appShow', () => {
                // 宿主打印日志的逻辑
            });
        }
    });
});

给extension.js中提供的接口

在extension.js中,因为需要与宿主客户端进行交互,所以会提供一些开发者所没有的特定接口,编写extension.js的开发人员可以使用这些API,编写特定逻辑。其中,extension.js中可以使用的API如下:

API 描述
swanx 为extension.js开发者提供的扩展API集合对象
boxjs 开发者无法访问的私有能力的接口集合
swan 为小程序开发者提供的全局的swan对象(对应的API列表,可以在官网上找到)

swanx中的方法:

API 参数 描述
swanx.invoke scheme:String 开发者可以调用此API,直接调起自己宿主客户端实现的接口。

swanx中scheme的格式如下:

扩展API方法 extension.jsmethods对象中的所有字段,会自动被merge到相对应的命名空间下,并在全局对象swan上提供给小程序开发者,如:'swan.tieba.publishThread()' 。

// 宿主的extension.js逻辑
module.exports = {
    name: 'tieba',
    // 扩展API
    methods: {
        publishThread: function (id) {
            swan.invoke('');
        }
    }
};

开发者可以在逻辑中直接编写scheme,与宿主客户端进行交互。

扩展组件方法

extension.jscomponents对象中的所有字段,将会自动生成对应的组件,并被加上命名空间为前缀,如上面的video,会被swan.js扩展为<bilibili-video>提供给小程序开发者。

在实现组件之前,请extension.js的编写人员,要了解一下组件的基本知识,

即:原生组件是普通的HTML组件在 各阶段生命周期/事件触发 中调用端能力,进行实现的。所以,如果宿主需要做一个普通的HTML组件,则直接编写普通组件逻辑即可(仅编写前端代码)。如果需要编写NA组件,则需要在客户端进行相应实现,并通过前端swanx.invoke()进行相应通讯。

module.exports = {
    name: 'tieba',
    // 扩展组件
    components: {
       'video': {
              template: '<div>video</div>',
              depandencies: ['swaninterface'],
              attached() {
                  boxjs.xxxx
              }
          }
    }
}

组件的基本描述与生命周期,请参见san框架的官网描述:san框架

自定义日志

extension.js中,开发者可以写一个名为customLog的函数,swan.js框架会在启动时调用宿主开发的customLog函数,并给开发者的扩展代码传入swanEventFlow事件流对象,该事件流对象支持接口如下:

接口名称 作用 参数
swanEventFlow.onMessage 监听某一事件 type:String, handler:Function, options:Object
swanEventFlow.delHandler 移除事件流上的某一个事件监听 type:String, handler:Function
swanEventFlow.fireMessage 在当前事件流上派发事件

由上我们可以看出,宿主可以使用swanEventFlow对象,对小程序的各个生命周期关键事件发生节点进行监听。那么开发者可以具体利用的生命周期都有哪些呢?请参见以下列表:

生命周期名称 触发时机 携带参数
onAppShow 小程序展示时(包含当前页面第一次展示/小程序切换到前台/覆盖在该页面上的其他页面销毁) {query:string, path:string}
onAppHide 小程序隐藏时(包含home键切换到后台/被其他页面覆盖)
onAppLaunch 小程序首次进入 {query:string, path:string}
onPageLoad 小程序的某个页面加载 {slaveId:number, query:string, path:string}
onPageReady 小程序的某个页面渲染完成
onPageShow 小程序的某个页面进行展示 {slaveId:number, query:string, path:string}
onPageHide 小程序的某个页面进行隐藏

Android 开源说明

名词解释

名词 解释
宿主 特指承载百度小程序的第三方宿主应用
小程序 特指百度小程序
Swan-Native 特指百度小程序端上NA SDK。
SwanJS 特指百度小程序前端JS SDK,又称SwanCore,用于和端上通信的桥梁、小程序API、组件实现的基础。
Scheme协议 指SwanJS和Swan-Native通信的标准协议
端能力 特指Swan-Native对SwanJS中某一API的实现

小程序lib说明

lib 说明
demo 小程序的demo示例,具有基本的运行小程序的能力。包含接入小程序需要做的初始化工作 & 小程序能力接口的实现(目前是空实现)
lib-aopannotation-empty 启动耗时性能监控用的,小程序的core代码里用到了这个库里的Annocation,这里为了编译通过,仅仅带上这个空工程。真正的耗时逻辑是通过gradle插件实现,这里没用到,仅用于手百上,外部不需要处理。
lib-ar 小程序里提供了AR相机的能力,直接集成了AR的jar包,如果不需要可以自行去掉。
lib-bdwebview 小程序使用的WebView组件,目前是通过Sailor SDK直接桥接的系统WebView。(注意:系统WebView在Android5.0一下有问题,小程序需要从Adnroid5.0及以上开始支持)。
lib-browser-base 小程序内部浏览器框架的分类,目前为了和手百保持一致,直接扣取的代码,第三方不用关心,直接集成即可。
lib-event-bus 小程序内部使用到了RxJava和对RxJava封装的RxBus,这个库作为基础提供。
lib-multiprocess 如果使用手百的UBC(天幕)打点系统(下边的lib-ubc lib),才需要这个库,进行跨进程打点用的。
lib-ng-aiapps 小程序的core代码,这个是小程序的主lib,其他lib都是为他服务的。
lib-ng-aiapps-download 小程序sdk从Server拉取SwanJs和小程序包的下载能力,直接接入手百的APS后台,内部直接集成。
lib-ng-aiapps-menu 小程序内部使用的菜单View。
lib-ng-aiapps-ubc-empty 如果不使用百度的UBC打点,需要依赖这个库(不用依赖lib-ubc),所有的打点会空实现。
lib-no-proguard 小程序里有一部分代码不能混淆,是通过实现了这个库里的NoProGuard接口完成的,在打包的时候需要配置混淆规则,详见demo/proguard-rules.pro。
lib-process-ipc 由于小程序是运行在独立进程的,需要多进程间通信,这个lib是用来多进程通信的。
lib-runtime 小程序SDK的运行时环境,需要在app启动的时候调用,详情参考 初始化说明。
lib-slide 小程序内部使用到了侧滑返回页面的能力,这个库提供侧滑功能。
lib-ubc 如果要使用手百的UBC打点,将统计打到天幕平台,需要使用这个lib,这个lib需要依赖lib-multiprocess(lib-ubc 和 lib-ng-aiapps-ubc-empty 二选一,如果需要统计就用lib-ubc,否则就用lib-ng-aiapps-ubc-empty)。
lib-united-scheme-core 小程序内部的通信是使用Scheme协议完成的,这个是小程序内部的通信框架。
lib-v4-fragment 下程序使用到了fragment,但是不同版本的v4包有bug,这里使用了自带的fragment,而不是用系统的v4包提供的。
lib-websocket 小程序里的webSocket能力

第三方依赖库说明

说明
com.baidu.searchbox:http:1.0.9 百度封装的http库,在手百的maven仓库。
com.squareup.okhttp3:okhttp:3.11.0 okhttp3.11.0 在手百的maven仓库。
com.baidu.searchbox:httpdns:1.0.1 百度的HttpDns 在手百的maven仓库。
com.airbnb.android:lottie:2.3.1 lottie2.3.1
io.reactivex:rxjava:1.2.3 rxjava 1.2.3
io.reactivex:rxandroid:1.2.0 rxandroid 1.2.0
com.google.code.gson:gson:2.8.0 gson
com.android.support:support-v4:26.1.0

com.android.support:appcompat-v7:26.1.0

com.android.support:recyclerview-v7:26.1.0

com.android.support:support-annotations:26.1.0

com.facebook.fresco:fresco:1.2.0

com.baidu.android.common:galaxy-full:2.1.0

com.baidu.pyramid:pyramid-annotation:0.1.2

小程序的金字塔注入插件,用于IOC的 在手百的maven仓库。

具体配置参考settings.gradle

需要接入方实现的功能

1 二维码扫描

功能说明

调起客户端扫码界面,扫码成功后返回对应的结果。

原理

小程序调用 swan.scanCode API时,应该跳转到二维码扫描界面,二维码扫描结果应该通过返回给调起的小程序。

接口设计

相关函数说明

/**
 * 调起二维码扫描界面
 *
 * @param context  上下文
 * @param callback 扫码的结果回调
 */
void scanCode(Context context, IScanResultCallback callback);

IScanResultCallback说明

回调定义:

public interface IScanResultCallback {

    /**
     * 扫码结果
     *
     * @param data       结果数据
     * @param resultCode 结果码
     */
    void onResult(JSONObject data, int resultCode);
}

data返回结构:

{"codeType":"QR_CODE","encoding":"GBK","result":"https://v.yunpub.cn/books/zngm"}
参数名 类型 说明
codeType String 扫码类型(二维码类型:QR_CODE)
encoding String 编码方式(GBK,UTF-8等)
result String 扫码的内容

2 位置

功能说明

设计原理

接口设计

参考实现

无,完全有第三方自己实现,没有固定格式和规范

3 分享

功能说明

小程序菜单点击分享,调起宿主分享功能,此功能需要宿主实现,调用宿主的分享面板

原理

SwanJS 传递分享参数到 Swan-Native 后,Swan-Native 通过接口调起宿主分享功能

标准协议必要字段:

参数名 类型 必填 说明
title String 分享标题
content String 分享内容
imageUrl String 分享图标
path String 页面 path ,必须是以 / 开头的完整路径

实现

需要实现以下接口,完成分享功能

当前接口非终版接口,后面会标准化

/**
 * 调起分享
 *
 * @param title    分享标题
 * @param content  分享内容
 * @param imageUrl 分享图标
 * @param path     页面回流 path
 * @param ext      其它信息
 * @param listener 分享回调
 */
void share(String title, String content, String imageUrl, String path, String ext, OnShareResultListener listener);

4 图片

功能说明

图片功能主要分为图片预览图片选择

实现细节

图片预览

小程序调用 swan.previewImage API时,小程序框架传入图片URL信息尝试调起接入方图片浏览页面。

图片选择

小程序调用 swan.chooseImage API时,小程序传入选择图片基本参数尝试调起接入方图片选择页面。用户完成图片选择后图片选择页面应该将选择的图片信息返回给调起小程序

接入说明

图片预览接入说明
图片选择接入说明

接入方法

/**
 * 打开图片浏览器
 *
 * @param context       小程序上下文
 * @param pictureParams 图片信息
 */
public void launchPictureBrowser(Context context, JSONObject pictureParams);

pictureParams参数格式

{"url":["https:\/\/image.jpg","https:\/\/preview-image-2.png"],"index":"0"}

pictureParams参数说明

参数名 类型 说明
url String[] 图片url数组
index String 当前显示图片的链接
/**
 * 选择图片
 *
 * @param context  小程序上下文
 * @param maxCount 要选择的图片最大张数
 * @param callback 结果回调
 */
public void chooseImage(Context context, int maxCount, ChooseImageAction.OnImageChooseResultCallback callback);

OnImageChooseResultCallback说明

/**
 * 图片选择的结果回调
 */
public interface OnImageChooseResultCallback {
    /**
     * 结果回调
     * @param success 是否成功
     * @param msg 附带信息
     * @param paths 图片的路径信息
     */
    public void onResult(boolean success, String msg, List<String> paths);
}
参数名 类型 说明
msg String 选择图片页面携带回的信息,主要是图片选择失败时,失败原因等信息
paths List 用户所选择的本地图片路径

5 地图

功能说明

设计原理

接口设计

参考实现

其他说明

参考代码只提供大概框架,具体细节未提供。

6 地址、发票

功能说明

地址、发票功能指 swan.chooseAddressswan.chooseInvoiceTitle 能力以及和宿主配套的地址、发票管理中心,管理中心一般包含添加、删除、编辑等能力

使用示例:外卖小程序,填写配送地址时,可以调用 swan.chooseAddress能力直接选择宿主管理的地址,获取信息后直接填写相关信息

原理

小程序调用 swan.chooseInvoiceTitle API时,会跳转到宿主发票管理中心,选择对应发票后返回发票信息到调起的小程序。

流程

小程序调用 swan.chooseInvoiceTitle -> SwanJS -> Scheme -> 端能力 -> 管理中心 -> 选择后携带信息 -> 端能力 -> Scheme -> SwanJS -> 小程序

实现

发票

当前非最终版接口

/**
 * 选择发票信息
 *
 * @return 发票,里面包含详细字段定义
 */
Invoice getInvoiceTitle();

Invoice对象说明:

参数名 类型 说明
type String 抬头类型(0:单位,1:个人)
title String 抬头名称
taxNumber String 抬头税号
companyAddress String 单位地址
telephone String 手机号码
bankName String 银行名称
bankAccount String 银行账号
地址

当前非最终版接口

/**
 * 获取地址
 *
 * @return 地址信息
 */
Address getAddress();

Address对象说明:

参数名 类型 说明
userName String 收货人姓名
postalCode String 邮编
provinceName String 国标收货地址第一级地址
cityName String 国标收货地址第二级地址
countyName String 国标收货地址第三级地址
detailInfo String 详细收货地址信息
telNumber String 收货人手机号码

3.7 夜间模式

功能说明

夜间模式指小程序夜间模式功能,主要需要实现和宿主夜间模式的状态联动,同时需要宿主维护夜间模式状态

原理

小程序夜间模式使用蒙层压黑的方式实现 小程序运行与独立的进程,跨进程状态实现通过小程序内置的CS通信机制(Messenger实现),涉及AiAppsMessengerServiceAiAppsMessengerClient

实现

主进程 -> 小程序进程 在宿主夜间模式发生变化时,调用:

AiAppsMessengerService service = AiAppsMessengerService.getServiceObject();
if (service != null) {
    service.sendMessageToAllClients(AiAppsMessengerService.MSG_TYPE_SC_NIGHT_MODE_CHANGED);
}

同时需要实现以下接口:

当前接口和百度App夜间模式实现原理有关,后续应该会改造成设置状态、获取状态两个接口

设置夜间模式开关状态,当前功能和 forceSyncNightModeState(boolean enable),功能重复,后续会整合

/**
 * 设置夜间模式开关状态
 *
 * @param enable true/false
 */
void setNightModeSwitcherState(boolean enable);

主进程和小程序进程间,夜间模式状态强制同步,通过 Messenger 实现

/**
 * 强制同步夜间模式状态
 *
 * @param enable true/false
 */
void forceSyncNightModeState(boolean enable);

获取夜间模式状态

/**
 * 获取夜间模式开关状态
 *
 * @return boolean
 */
boolean getNightModeSwitcherState();

此接口和百度App夜间模式机制实现有关,后续标准接口时会去除

/**
 * 订阅夜间模式事件
 *
 * @param tag                     tag
 * @param nightModeChangeListener 监听器
 */
void subscribeNightModeChangeEvent(Object tag, AiAppNightModeChangeListener nightModeChangeListener);

此接口和百度App夜间模式机制实现有关,后续标准接口时会去除

/**
 * 取消夜间模式状态订阅
 *
 * @param tag tag
 */
void unsubscribeNightModeChangedEvent(Object tag);

8 支付

暂时未确定开源方式,后续补充

9 文档

功能说明

设计原理

接口设计

在打开文档前,先检查打开文档的插件是否可用

/**
 * 阅读类插件是否可用
 *
 * @param mimeType 文件的mimeType
 */
boolean isReadPluginAvailable(Context context, String mimeType);

调起打开文档的插件展示文档

/**
 * 处理文件打开
 *
 * @param activity activity
 * @param path     文件对应的uri
 * @param mimeType 文件的mimeType
 */
void openDocument(Activity activity, Uri path, String mimeType);

参考实现

@Override
public void openDocument(final Activity activity, Uri path, String mimeType) {
    Intent intent = new Intent(activity, PluginPaperViewerActivity.class);
    intent.setAction(Intent.ACTION_VIEW);
    intent.setDataAndType(path, mimeType);
    intent.putExtra(PluginPaperViewerActivity.ENABLE_FALLBACK_FINISH_KEY, true);
    // 不要新增加task
    activity.startActivity(intent);
}

10 用户反馈

功能说明

设计原理

接口设计

调起反馈

/**
 * 调启反馈页面
 *
 * @param params   反馈参数
 * @param callback 反馈结果
 */
void feedback(Bundle params, OnFeedbackResultCallback callback);

/**
 * 反馈结果回调
 */
interface OnFeedbackResultCallback {
    /**
     * 反馈的结果
     *
     * @param data 反馈结果数据
     */
    void onResult(String data);
}

参考实现

11 直播

功能说明

小程序提供视频直播的能力,可以支持播放器在线推流的视频。对应开发者接口是swan.createLivePlayerContext,通过这个接口创建一个LivePlayerContext对象,后续对直播组件的操作均可通过该对象完成。 对应的组件是<live-player/>,支持的操作如下

实现原理

播放:

LivePlayerContext.play()

停止:

LivePlayerContext.stop()

静音:

LivePlayerContext.mute()

暂停:

LivePlayerContext.pause()

恢复:

LivePlayerContext.resume()

进入全屏:

LivePlayerContext.requestFullScreen(Object object)

退出全屏:

LivePlayerContext.exitFullScreen()

设计原理

开发者通过swan.createLivePlayerContext(string id)创建直播对象,参数 id 是<live-player/>标签的 id。创建的同时请求绑定相应的直播组件,随后在客户端创建一个AiAppsLivePlayer对象。

接口设计

涉及到的端能力:LivePlayerAction

接口

public interface IAiAppLiveIoc {

    /**
     * 打开直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 停止直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean stop(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 静音直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean mute(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 全屏直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean setFullScreen(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 继续直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean resume(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
}

12 背景音乐

功能说明

小程序提供了背景音频播放能力,通过swan.getBackgroundAudioManager()创建BackgroundAudioManager对象,后续对背景音频的操作均是通过此接口执行。 注:背景音频是小程序全局唯一的控件,即在任何一个小程序中控制都会影响到其他小程序的使用。

支持以下操作:

播放:

BackgroundAudioManager.play()

暂停。暂停后的音频再播放会从暂停处开始播放:

BackgroundAudioManager.pause()

停止。停止后的音频再播放会从头开始播放:

InnerAudioContext.stop()

跳转到指定位置:

BackgroundAudioManager.seek(number position)

监听音频进入可以播放状态的事件,但不保证后面可以流畅播放:

InnerAudioContext.onCanplay(function callback)

监听音频播放事件:

InnerAudioContext.onPlay(function callback)

监听音频暂停事件:

InnerAudioContext.onPause(function callback)

监听音频停止事件:

InnerAudioContext.onStop(function callback)

监听音频自然播放至结束的事件:

InnerAudioContext.onEnded(function callback)

监听音频播放进度更新事件:

InnerAudioContext.onTimeUpdate(function callback)

监听音频播放错误事件:

InnerAudioContext.onError(function callback)

监听音频加载中事件,当音频因为数据不足,需要停下来加载时会触发

InnerAudioContext.onWaiting(function callback)

监听音频进行跳转操作的事件

InnerAudioContext.onSeeking(function callback)

监听音频完成跳转操作的事件

InnerAudioContext.onSeeked(function callback)

设计原理

开发者通过调用通过swan.getBackgroundAudioManager()创建BackgroundAudioManager对象。通过swan/backgroundAudio/open端能力在客户端创建音频播放器对象,后续通过update接口更细你参数,对播放器的播放、暂停、定位时间点等常用操作均通过BackgroundAudioManager完成。

接口设计

涉及到的端能力:AudioPlayerAction

目前百度智能小程序底层是通过 Android 系统的 MediaPlayer 实现音频播放,第三方可以根据自己的需求自行替换。

接口如下:

public interface IAiAppAudioIoc {
    /**
     * 打开音频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新音频参数
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 停止
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean stop(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
    * 快进
    * @param context 上下文
    * @param entity scheme实体
    * @param handler scheme处理器
    * @param aiApp 小程序实体
    * @return 是否成功
    */
    public boolean seekTo(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

   /**
     * 获取参数值
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean getParamSync(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
}

13 视频

功能说明

智能小程序提供了视频播放能力,通过实现 video 抽象接口就可以轻松让您的小程序拥有定制化的视频播放器,让小程序的的产品体验及产品功能更加完善。 开发者通过swan.createVideoContext来创建一个播放器实例,后续有关播放器的操作均在此对象上完成。

对应的组件是

<video/>

支持的操作如下:

播放视频:

VideoContext.play()

暂停视频:

VideoContext.pause()

停止视频:

VideoContext.stop()

跳转到指定位置:

VideoContext.seek(number position)

发送弹幕:

VideoContext.sendDanmu(Object data)

进入全屏:

VideoContext.requestFullScreen(Object object)

退出全屏:

VideoContext.exitFullScreen()

设计原理

小程序调用swan.createVideoContext时,swan-core 会通知客户端创建 MediaPlayer 对象。通过swan/video/open接口传入初始化参数,后续可以通过 update 接口更新参数。对播放器的播放、暂停、拖拽等常用操作均通过 videoContext 完成。

接口设计

涉及到的端能力:VideoOpenAction

以下是需要实现的基础播放器接口

public interface IAiAppVideoIoc {

    /**
     * 打开视频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放视频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 快进
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean seekTo(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 全屏
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean setFullScreen(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 设置弹幕
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean sendDanmu(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 手机back键被按下
     * @return 是否处理back键
     */
    public boolean onKeyBack();
}

14 音频

功能说明

小程序提供了通用音频播放能力,通过swan.createInnerAudioContext()创建audioContext对象,后续对 audio 的操作均是通过此接口执行。 对应的组件是

<audio/>

支持以下操作:

播放:

InnerAudioContext.play()

暂停。暂停后的音频再播放会从暂停处开始播放:

InnerAudioContext.pause()

停止。停止后的音频再播放会从头开始播放:

InnerAudioContext.stop()

跳转到指定位置:

InnerAudioContext.seek(number position)

销毁当前实例:

InnerAudioContext.destroy()

监听音频进入可以播放状态的事件,但不保证后面可以流畅播放:

InnerAudioContext.onCanplay(function callback)

取消监听音频进入可以播放状态的事件,但不保证后面可以流畅播放:

InnerAudioContext.offCanplay(function callback)

监听音频播放事件:

InnerAudioContext.onPlay(function callback)

取消监听音频播放事件:

InnerAudioContext.offPlay(function callback)

监听音频暂停事件:

InnerAudioContext.onPause(function callback)

取消监听音频暂停事件:

InnerAudioContext.offPause(function callback)

监听音频停止事件:

InnerAudioContext.onStop(function callback)

取消监听音频停止事件:

InnerAudioContext.offStop(function callback)

监听音频自然播放至结束的事件:

InnerAudioContext.onEnded(function callback)

取消监听音频自然播放至结束的事件:

InnerAudioContext.offEnded(function callback)

监听音频播放进度更新事件:

InnerAudioContext.onTimeUpdate(function callback)

取消监听音频播放进度更新事件:

InnerAudioContext.offTimeUpdate(function callback)

监听音频播放错误事件:

InnerAudioContext.onError(function callback)

取消监听音频播放错误事件:

InnerAudioContext.offError(function callback)

监听音频加载中事件,当音频因为数据不足,需要停下来加载时会触发

InnerAudioContext.onWaiting(function callback)

取消监听音频加载中事件,当音频因为数据不足,需要停下来加载时会触发

InnerAudioContext.offWaiting(function callback)

监听音频进行跳转操作的事件

InnerAudioContext.onSeeking(function callback)

取消监听音频进行跳转操作的事件

InnerAudioContext.offSeeking(function callback)

监听音频完成跳转操作的事件

InnerAudioContext.onSeeked(function callback)

取消监听音频完成跳转操作的事件

InnerAudioContext.offSeeked(function callback)

设计原理

开发者通过调用通过swan.createInnerAudioContext()创建audioContext对象,并传入 id 绑定相应的audio标签。通过swan/audio/open端能力在客户端创建 MediaPlayer 对象,后续通过 update 接口更新参数,对播放器的播放、暂停、定位时间点等常用操作均通过audioContext完成。

接口设计

涉及到的端能力:AudioPlayerAction

目前百度智能小程序底层是通过Android系统的MediaPlayer实现音频播放,第三方可以根据自己的需求自行替换。

接口如下:

public interface IAiAppAudioIoc {
    /**
     * 打开音频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新音频参数
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 停止
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean stop(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
    * 快进
    * @param context 上下文
    * @param entity scheme实体
    * @param handler scheme处理器
    * @param aiApp 小程序实体
    * @return 是否成功
    */
    public boolean seekTo(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

   /**
     * 继续
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean resume(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
}

15 端能力回调说明

接口中回调函数说明

示例

.需要接入方实现的服务

1 登录

功能说明

小程序登录功能(调用宿主登录),和宿主强相关

原理

需要宿主维护自己的账号体系

实现

标准接口,后续提供

2 授权

功能说明

在符合法务要求的情况下赋予小程序调用必要功能的权限,比如用户信息、直播、地理位置等 敏感功能权限风控,可以随时由用户或者云端平台撤回授权 用户的敏感信息都从开放平台统一输出

原理

暂无,后续提供

实现

暂无,后续提供

5.小程序核心结构、流程

暂无

6.第三方接入步骤说明

在小程序正式开源前,会随时更新,不保证时效性,当前为百度内部接入流程

小程序SDK的仓库地址

http://icode.baidu.com/repos/baidu/searchbox-android/aiapps/tree/master

小程序结构说明

初始化说明

接入方实现功能

示例模板

#### 功能说明
功能介绍

#### 原理

实现的原理说明

#### 实现

具体实现,包含接口说明等

#### 调试
调试方法,确保功能的正确性

二维码扫描

功能说明:调起客户端扫码界面,扫码成功后返回对应的结果。

原理:小程序调用 swan.scanCode API时,应该跳转到二维码扫描界面,二维码扫描结果应该通过返回给调起的小程序。

接口设计

相关函数说明

/**
 * 调起二维码扫描界面
 *
 * @param context  上下文
 * @param callback 扫码的结果回调
 */
void scanCode(Context context, IScanResultCallback callback);

IScanResultCallback说明

回调定义:

public interface IScanResultCallback {
    /**
     * 扫码结果
     *
     * @param data       结果数据
     * @param resultCode 结果码
     */
    void onResult(JSONObject data, int resultCode);
}

data返回结构:

{"codeType":"QR_CODE","encoding":"GBK","result":"https:\/\/v.yunpub.cn\/books\/zngm"}
参数名 类型 说明
codeType String 扫码类型(二维码类型:QR_CODE)
encoding String 编码方式(GBK,UTF-8等)
result String 扫码的内容

位置

功能说明

参数名 类型 必填 说明
title String 分享标题
content String 分享内容
imageUrl String 分享图标
path String 页面 path ,必须是以 / 开头的完整路径

实现

需要实现以下接口,完成分享功能。

当前接口非终版接口,后面会标准化。

/**
 * 调起分享
 *
 * @param title    分享标题
 * @param content  分享内容
 * @param imageUrl 分享图标
 * @param path     页面回流 path
 * @param ext      其它信息
 * @param listener 分享回调
 */
void share(String title, String content, String imageUrl, String path, String ext, OnShareResultListener listener);

图片

功能说明:图片功能主要分为图片预览和图片选择。

实现细节:

接入说明:

参数名 类型 说明
url String Array 图片url数组
index String 当前显示图片的链接
参数名 类型 说明
msg String 选择图片页面携带回的信息,主要是图片选择失败时,失败原因等信息。
paths String List 用户所选择的本地图片路径

地图

功能说明

设计原理

接口设计

/**
    * 创建地图
    * @param context 小程序宿主activity context
    * @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
    * @param handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
    * @param aiApp 小程序环境,包含了小程序运行时的所有信息
    * @return 返回处理结果,处理ok返回true,出现问题返回false
    */
public boolean create(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp) {
    return false;
}
    /**
        * 更新地图
        * @param context 小程序宿主activity context
        * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
        * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
        * @param aiApp 包含了小程序运行时的所有信息
        * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 删除地图
        * @param context 小程序宿主activity context
        * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
        * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
        * @param aiApp 包含了小程序运行时的所有信息
        * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean remove(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 移动指定的Marker标记,可以设置动画时间
        * @param context 小程序宿主activity context
        * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
        * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
        * @param aiApp 包含了小程序运行时的所有信息
        * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
public boolean translateMarker(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 移动到定位位置,showLocation字段必须为true才生效
        * @param context 小程序宿主activity context
        * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
        * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
        * @param aiApp 包含了小程序运行时的所有信息
        * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean moveToLocation(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 缩放视野包含给定的所有点坐标
        * @param context 小程序宿主activity context
        * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
        * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
        * @param aiApp 包含了小程序运行时的所有信息
        * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean includePoints(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 获取当前的缩放比例
        * @param context 小程序宿主activity context
        * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
        * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
        * @param aiApp 包含了小程序运行时的所有信息
        * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean getScale(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 获取当前的视野矩形坐标
        * @param context 小程序宿主activity context
        * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
        * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
        * @param aiApp 包含了小程序运行时的所有信息
        * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean getRegion(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp); 
    /**
    * 获取地图中心点坐标
    * @param context 小程序宿主activity context
    * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
    * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
    * @param aiApp 包含了小程序运行时的所有信息
    * @return 返回处理结果,处理ok返回true,出现问题返回false
    */
    public boolean getCenterLocation(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);  
    /**
        * 在页面resume的时候通知地图
        * @param manager 指定要resume的webView页面,可以通过这个获取到应该要通知的地图view
        */
    public void resume(AiAppsSlaveManager manager);
    /**
        * 在页面销毁的时候通知地图
        *  @param manager 通知指定slave上的地图,又manager可以找到指定的地图view
        */
    public void release(AiAppsSlaveManager manager);

*在新的页面打开指定的经纬度在地图上显示

    /**
        * 打开指定位置
        * @param context 小程序宿主activity context
    * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
    * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
    * @param aiApp 包含了小程序运行时的所有信息
    * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean openLocation(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 打开选择位置的页面
        * @param context 小程序宿主activity context
    * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
    * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
    * @param aiApp 包含了小程序运行时的所有信息
    * @return 返回处理结果,处理ok返回true,出现问题返回false      */
    public boolean chooseLocation(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 打开步行导航
        * @param context 小程序宿主activity context
    * @param @param entity scheme实体,包含创建地图的scheme所有信息,从中可以取出所有地图相关的信息(上文文档里出现的所有字段都在)
    * @param handler handler scheme结果回调,不论处理的结果成功还是失败,**都必须** 使用这个handler告诉SwanJS处理结果,前端的逻辑全部都严重依赖Android端上的回调。
    * @param aiApp 包含了小程序运行时的所有信息
    * @return 返回处理结果,处理ok返回true,出现问题返回false
        */
    public boolean openWalkNavigation(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
    /**
        * 顶层目前是不是步行导航的fragment
        * 因为百度地图的步行导航目前只是支持actiivty,退出的时候会把真个actiivty finish,导致小程序本身也被finish了,
        * 所以需要在导航退出的时候特殊处理
        * @return 如果最上层是导航的fragment返回true
        */
    public boolean isTopWalkNavFragment();

参考实现

public boolean create(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp) {
    // 1.解析参数
    MapModel model = getModel(entity);
    if (model == null) {
        AiAppsLog.e("map", "parse error, model is null");
        entity.result = wrapResult(UnitedSchemeStatusCode.ERR_PARAMS_PARSE_FAIL);
        return false;
    }
    // 2.如果slaveId为空,先使用当前的webview序列号; 需要前端支持传递slaveId
    if (TextUtils.isEmpty(model.slaveId)) {
        String webViewId = AiAppsUtils.getTopWebViewId();
        if (!TextUtils.isEmpty(webViewId)) {
            model.slaveId = webViewId;
        }
        AiAppsLog.w("map", "webView id is empty, use current webView");
    }
    // 3.从webView的id获取对应的webView
    WebView slaveWv = getBdWebView(entity, model.slaveId);
    if (slaveWv == null) {
        entity.result = wrapResult(UnitedSchemeStatusCode.ERR_PARAMS_PARSE_FAIL);
        AiAppsLog.e("map", "can not find weiView by id " + model.slaveId);
        return false;
    }
    // 5.根据执行情况返回
    JSONObject params = new JSONObject();
    if (!doAction(context, model, slaveWv, aiApp, params, entity, handler)) {
        entity.result = wrapResult(UnitedSchemeStatusCode.ERR_EXECUTE_FAIL);
        AiAppsLog.e("map", "doAction  fail ");
        return false;
    }
    callBackWithParams(entity, handler, params.length() <= 0 ? null : params);
    return true;
}

// 真正执行具体逻辑的操作
protected boolean doAction(Context context, MapModel model, WebView webView, AiApp aiApp, JSONObject params,
                            UnitedSchemeEntity entity, CallbackHandler handler) {
    AiAppsLog.i("map", "MapCreateAction start");
    // 1.必要性校验
    if (webView == null || mapModel == null || !mapModel.isValid()) {
        AiAppsLog.e(MapUtils.MODEL_TAG, "model data is invalid");
        return false;
    }
    // 2.获取webView对应的manager
    AiAppsWebViewManager manager = AiAppsController.getInstance().getWebViewManager(mapModel.slaveId);
    if (manager == null || !(manager instanceof AiAppsSlaveManager)) {
        return false;
    }
    // 3.将组件扔给当前salve中的helper管理
    final MapViewHelper helper = getMapViewHelper((AiAppsSlaveManager) manager);

    MapViewItem item = helper.find(mapModel.id);
    // 已经存在,直接返回
    if (item != null) {
        return false;
    }
    // 4.新创建一个地图组件
    item = MapViewItem.makeOne(context, mapModel);
    if (item == null) {
        return false;
    }
    // 5.嵌套CoverView,并附着在ViewTree上
    AiAppsNAViewContainer container = new AiAppsNAViewContainer(webView.getContext());
    boolean insert = container.insertView(item.mapView, mapModel);
    if (!insert) {
        return false;
    }
    // 6.保存组件
    if (!helper.insert(item)) {
        return false;
    }
    // 7.根据传入的属性初始化
    MapViewInitHelper.initMapView(context, item, mapModel, helper);
    return true;
}

/**
    * 从发送过来的信息里组装需要的model
    *
    * @param entity scheme发送过来的信息载体
    *
    * @return MapModel对象,代表这个组件的所有属性
    */
protected MapModel getModel(UnitedSchemeEntity entity) {
    if (entity == null) {
        return null;
    }
    MapModel model = null;
    Map<String, String> params = entity.getParams();
    if (params == null || params.isEmpty()) {
        AiAppsLog.e("map", "entity get Params is empty");
        return null;
    }
    String jsonModel = params.get("data");
    if(jsonModel == null){
        AiAppsLog.e("map", "params string is empty");
        return null;
    }
    try {
        JSONObject json = new JSONObject(jsonModel);
        model = new MapModel();
        model.parseFromJson(json);
    } catch (JSONException e) {
        e.printStackTrace();
        AiAppsLog.e("map", "params json parse error");
    }
    return model;
}

/**
    * 统一包装返回msg
    *
    * @param resultCode 返回码
    *
    * @return msg
    */
protected JSONObject wrapResult(int resultCode) {
    return UnitedSchemeUtility.wrapCallbackParams(resultCode);
}

/**
    * Scheme的结果回调
    *
    * @param entity    scheme实体
    * @param handler   回调handler
    * @param json      参数数据
    */
protected void callBackWithParams(UnitedSchemeEntity entity, CallbackHandler handler, JSONObject json) {
    entity.result = UnitedSchemeUtility.callCallback(handler, entity,
            UnitedSchemeUtility.wrapCallbackParams(json, UnitedSchemeStatusCode.ERR_OK));
}

/**
    * 获取指定的WebVIew
    * @param entity 参数实体
    * @param slaveId 当前webView的slaveId
    * @return 返回找到的webView,找不到返回null
    */
protected WebView getBdWebView(UnitedSchemeEntity entity, String slaveId) {
    WebView ngWebView = AiAppsUtils.getBdWebViewBySlaveId(slaveId);
    if (ngWebView == null) {
        entity.result = wrapResult(UnitedSchemeStatusCode.ERR_EXECUTE_FAIL);
        return null;
    }
    return ngWebView;
}

其他说明:参考代码只提供大概框架,具体细节未提供。

地址、发票

功能说明

地址、发票功能指 swan.chooseAddressswan.chooseInvoiceTitle 能力以及和宿主配套的地址、发票管理中心,管理中心一般包含添加、删除、编辑等能力

使用示例:外卖小程序,填写配送地址时,可以调用 swan.chooseAddress能力直接选择宿主管理的地址,获取信息后直接填写相关信息

原理

小程序调用 swan.chooseInvoiceTitle API时,会跳转到宿主发票管理中心,选择对应发票后返回发票信息到调起的小程序。

流程

小程序调用 swan.chooseInvoiceTitle -> SwanJS -> Scheme -> 端能力 -> 管理中心 -> 选择后携带信息 -> 端能力 -> Scheme -> SwanJS -> 小程序

实现

发票

当前非最终版接口

/**
 * 选择发票信息
 *
 * @return 发票,里面包含详细字段定义
 */
Invoice getInvoiceTitle();

Invoice参数说明:

参数名 类型 说明
type String 抬头类型(0:单位,1:个人)
title String 抬头名称
taxNumber String 抬头税号
companyAddress String 单位地址
telephone String 手机号码
bankName String 银行名称
bankAccount String 银行账号
地址

当前非最终版接口

/**
 * 获取地址
 *
 * @return 地址信息
 */
Address getAddress();

Address返回参数说明:

参数名 类型 说明
userName String 收货人姓名
postalCode String 邮编
provinceName String 国标收货地址第一级地址
cityName String 国标收货地址第二级地址
countyName String 国标收货地址第三级地址
detailInfo String 详细收货地址信息
telNumber String 收货人手机号码

3.7 夜间模式

功能说明

夜间模式指小程序夜间模式功能,主要需要实现和宿主夜间模式的状态联动,同时需要宿主维护夜间模式状态

原理

小程序夜间模式使用蒙层压黑的方式实现 小程序运行与独立的进程,跨进程状态实现通过小程序内置的CS通信机制(Messenger实现),涉及AiAppsMessengerServiceAiAppsMessengerClient

实现

主进程 -> 小程序进程 在宿主夜间模式发生变化时,调用:

AiAppsMessengerService service = AiAppsMessengerService.getServiceObject();
if (service != null) {
    service.sendMessageToAllClients(AiAppsMessengerService.MSG_TYPE_SC_NIGHT_MODE_CHANGED);
}

同时需要实现以下接口:

当前接口和手百夜间模式实现原理有关,后续应该会改造成设置状态、获取状态两个接口

设置夜间模式开关状态,当前功能和 forceSyncNightModeState(boolean enable),功能重复,后续会整合

/**
 * 设置夜间模式开关状态
 *
 * @param enable true/false
 */
void setNightModeSwitcherState(boolean enable);

主进程和小程序进程间,夜间模式状态强制同步,通过 Messenger 实现

/**
 * 强制同步夜间模式状态
 *
 * @param enable true/false
 */
void forceSyncNightModeState(boolean enable);

获取夜间模式状态

/**
 * 获取夜间模式开关状态
 *
 * @return boolean
 */
boolean getNightModeSwitcherState();

此接口和手百夜间模式机制实现有关,后续标准接口时会去除

/**
 * 订阅夜间模式事件
 *
 * @param tag                     tag
 * @param nightModeChangeListener 监听器
 */
void subscribeNightModeChangeEvent(Object tag, AiAppNightModeChangeListener nightModeChangeListener);

此接口和手百夜间模式机制实现有关,后续标准接口时会去除

/**
 * 取消夜间模式状态订阅
 *
 * @param tag tag
 */
void unsubscribeNightModeChangedEvent(Object tag);

3.8 支付

暂时未确定开源方式,后续补充

3.9 文档

功能说明

设计原理

接口设计

在打开文档前,先检查打开文档的插件是否可用

/**
 * 阅读类插件是否可用
 *
 * @param mimeType 文件的mimeType
 */
boolean isReadPluginAvailable(Context context, String mimeType);

调起打开文档的插件展示文档

/**
 * 处理文件打开
 *
 * @param activity activity
 * @param path     文件对应的uri
 * @param mimeType 文件的mimeType
 */
void openDocument(Activity activity, Uri path, String mimeType);

参考实现

@Override
public void openDocument(final Activity activity, Uri path, String mimeType) {
    Intent intent = new Intent(activity, PluginPaperViewerActivity.class);
    intent.setAction(Intent.ACTION_VIEW);
    intent.setDataAndType(path, mimeType);
    intent.putExtra(PluginPaperViewerActivity.ENABLE_FALLBACK_FINISH_KEY, true);
    // 不要新增加task
    activity.startActivity(intent);
}

3.10 用户反馈

功能说明

设计原理

接口设计

调起反馈

/**
 * 调启反馈页面
 *
 * @param params   反馈参数
 * @param callback 反馈结果
 */
void feedback(Bundle params, OnFeedbackResultCallback callback);

/**
 * 反馈结果回调
 */
interface OnFeedbackResultCallback {
    /**
     * 反馈的结果
     *
     * @param data 反馈结果数据
     */
    void onResult(String data);
}

参考实现

3.11 直播

功能说明

小程序提供视频直播的能力,可以支持播放器在线推流的视频。对应开发者接口是swan.createLivePlayerContext,通过这个接口创建一个LivePlayerContext对象,后续对直播组件的操作均可通过该对象完成。 对应的组件是,支持的操作如下

实现原理

播放:

LivePlayerContext.play()

停止:

LivePlayerContext.stop()

静音:

LivePlayerContext.mute()

暂停:

LivePlayerContext.pause()

恢复:

LivePlayerContext.resume()

进入全屏:

LivePlayerContext.requestFullScreen(Object object)

退出全屏:

LivePlayerContext.exitFullScreen()

设计原理

开发者通过swan.createLivePlayerContext(string id)创建直播对象,参数id是标签的id。创建的同时请求绑定相应的直播组件,随后在客户端创建一个AiAppsLivePlayer对象。

接口设计

涉及到的端能力:LivePlayerAction

接口

public interface IAiAppLiveIoc {

    /**
     * 打开直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 停止直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean stop(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 静音直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean mute(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 全屏直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean setFullScreen(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 继续直播
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean resume(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
}

3.12 背景音乐

功能说明

小程序提供了背景音频播放能力,通过swan.getBackgroundAudioManager()创建BackgroundAudioManager对象,后续对背景音频的操作均是通过此接口执行。 注:背景音频是小程序全局唯一的控件,即在任何一个小程序中控制都会影响到其他小程序的使用。

支持以下操作:

播放:

BackgroundAudioManager.play()

暂停。暂停后的音频再播放会从暂停处开始播放:

BackgroundAudioManager.pause()

停止。停止后的音频再播放会从头开始播放:

InnerAudioContext.stop()

跳转到指定位置:

BackgroundAudioManager.seek(number position)

监听音频进入可以播放状态的事件,但不保证后面可以流畅播放:

InnerAudioContext.onCanplay(function callback)

监听音频播放事件:

InnerAudioContext.onPlay(function callback)

监听音频暂停事件:

InnerAudioContext.onPause(function callback)

监听音频停止事件:

InnerAudioContext.onStop(function callback)

监听音频自然播放至结束的事件:

InnerAudioContext.onEnded(function callback)

监听音频播放进度更新事件:

InnerAudioContext.onTimeUpdate(function callback)

监听音频播放错误事件:

InnerAudioContext.onError(function callback)

监听音频加载中事件,当音频因为数据不足,需要停下来加载时会触发

InnerAudioContext.onWaiting(function callback)

监听音频进行跳转操作的事件

InnerAudioContext.onSeeking(function callback)

监听音频完成跳转操作的事件

InnerAudioContext.onSeeked(function callback)

设计原理

开发者通过调用通过swan.getBackgroundAudioManager()创建BackgroundAudioManager对象。通过swan/backgroundAudio/open端能力在客户端创建音频播放器对象,后续通过update接口更细你参数,对播放器的播放、暂停、定位时间点等常用操作均通过BackgroundAudioManager完成。

接口设计

涉及到的端能力:AudioPlayerAction

目前百度智能小程序底层是通过Android系统的MediaPlayer实现音频播放,第三方可以根据自己的需求自行替换。

接口如下:

public interface IAiAppAudioIoc {
    /**
     * 打开音频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新音频参数
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 停止
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean stop(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
    * 快进
    * @param context 上下文
    * @param entity scheme实体
    * @param handler scheme处理器
    * @param aiApp 小程序实体
    * @return 是否成功
    */
    public boolean seekTo(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

   /**
     * 获取参数值
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean getParamSync(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
}

3.13 视频

功能说明

智能小程序提供了视频播放能力,通过实现video抽象接口就可以轻松让您的小程序拥有定制化的视频播放器,让小程序的的产品体验及产品功能更加完善。 开发者通过swan.createVideoContext来创建一个播放器实例,后续有关播放器的操作均在此对象上完成。

对应的组件是

<video/>

支持的操作如下:

播放视频:

VideoContext.play()

暂停视频:

VideoContext.pause()

停止视频:

VideoContext.stop()

跳转到指定位置:

VideoContext.seek(number position)

发送弹幕:

VideoContext.sendDanmu(Object data)

进入全屏:

VideoContext.requestFullScreen(Object object)

退出全屏:

VideoContext.exitFullScreen()

设计原理

小程序调用swan.createVideoContext时,swan-core会通知客户端创建MediaPlayer对象。通过swan/video/open接口传入初始化参数,后续可以通过update接口更新参数。对播放器的播放、暂停、拖拽等常用操作均通过videoContext完成。

接口设计

涉及到的端能力:VideoOpenAction

以下是需要实现的基础播放器接口

public interface IAiAppVideoIoc {

    /**
     * 打开视频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放视频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 快进
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean seekTo(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 全屏
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean setFullScreen(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 设置弹幕
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean sendDanmu(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 手机back键被按下
     * @return 是否处理back键
     */
    public boolean onKeyBack();
}

3.14 音频

功能说明

小程序提供了通用音频播放能力,通过swan.createInnerAudioContext()创建audioContext对象,后续对audio的操作均是通过此接口执行。 对应的组件是

<audio/>

支持以下操作:

播放:

InnerAudioContext.play()

暂停。暂停后的音频再播放会从暂停处开始播放:

InnerAudioContext.pause()

停止。停止后的音频再播放会从头开始播放:

InnerAudioContext.stop()

跳转到指定位置:

InnerAudioContext.seek(number position)

销毁当前实例:

InnerAudioContext.destroy()

监听音频进入可以播放状态的事件,但不保证后面可以流畅播放:

InnerAudioContext.onCanplay(function callback)

取消监听音频进入可以播放状态的事件,但不保证后面可以流畅播放:

InnerAudioContext.offCanplay(function callback)

监听音频播放事件:

InnerAudioContext.onPlay(function callback)

取消监听音频播放事件:

InnerAudioContext.offPlay(function callback)

监听音频暂停事件:

InnerAudioContext.onPause(function callback)

取消监听音频暂停事件:

InnerAudioContext.offPause(function callback)

监听音频停止事件:

InnerAudioContext.onStop(function callback)

取消监听音频停止事件:

InnerAudioContext.offStop(function callback)

监听音频自然播放至结束的事件:

InnerAudioContext.onEnded(function callback)

取消监听音频自然播放至结束的事件:

InnerAudioContext.offEnded(function callback)

监听音频播放进度更新事件:

InnerAudioContext.onTimeUpdate(function callback)

取消监听音频播放进度更新事件:

InnerAudioContext.offTimeUpdate(function callback)

监听音频播放错误事件:

InnerAudioContext.onError(function callback)

取消监听音频播放错误事件:

InnerAudioContext.offError(function callback)

监听音频加载中事件,当音频因为数据不足,需要停下来加载时会触发

InnerAudioContext.onWaiting(function callback)

取消监听音频加载中事件,当音频因为数据不足,需要停下来加载时会触发

InnerAudioContext.offWaiting(function callback)

监听音频进行跳转操作的事件

InnerAudioContext.onSeeking(function callback)

取消监听音频进行跳转操作的事件

InnerAudioContext.offSeeking(function callback)

监听音频完成跳转操作的事件

InnerAudioContext.onSeeked(function callback)

取消监听音频完成跳转操作的事件

InnerAudioContext.offSeeked(function callback)

设计原理

开发者通过调用通过swan.createInnerAudioContext()创建audioContext对象,并传入id绑定相应的audio标签。通过swan/audio/open端能力在客户端创建MediaPlayer对象,后续通过update接口更细你参数,对播放器的播放、暂停、定位时间点等常用操作均通过audioContext完成。

接口设计

涉及到的端能力:AudioPlayerAction

目前百度智能小程序底层是通过Android系统的MediaPlayer实现音频播放,第三方可以根据自己的需求自行替换。

接口如下:

public interface IAiAppAudioIoc {
    /**
     * 打开音频
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean open(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 更新音频参数
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean update(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 播放
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean play(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 停止
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean stop(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
     * 暂停
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean pause(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

    /**
    * 快进
    * @param context 上下文
    * @param entity scheme实体
    * @param handler scheme处理器
    * @param aiApp 小程序实体
    * @return 是否成功
    */
    public boolean seekTo(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);

   /**
     * 继续
     * @param context 上下文
     * @param entity scheme实体
     * @param handler scheme处理器
     * @param aiApp 小程序实体
     * @return 是否成功
     */
    public boolean resume(Context context, UnitedSchemeEntity entity, CallbackHandler handler, AiApp aiApp);
}

3.15 端能力回调说明

接口中回调函数说明

示例

4.需要接入方实现的服务

4.1 登录

功能说明

小程序登录功能(调用宿主登录),和宿主强相关

原理

需要宿主维护自己的账号体系

实现

标准接口,后续提供

4.2 授权

功能说明

在符合法务要求的情况下赋予小程序调用必要功能的权限,比如用户信息、直播、地理位置等 敏感功能权限风控,可以随时由用户或者云端平台撤回授权 用户的敏感信息都从开放平台统一输出

原理

暂无,后续提供

实现

暂无,后续提供

5.小程序核心结构、流程

暂无

6.第三方接入步骤说明

在小程序正式开源前,会随时更新,不保证时效性,当前为百度内部接入流程

小程序SDK的仓库地址

http://icode.baidu.com/repos/baidu/searchbox-android/aiapps/tree/master

小程序结构说明

初始化说明

iOS 开源说明

小程序依赖第三方库

外部开源库

说明
Lottie.framework 动画库,animationView组件使用,属于手百小程序特有能力。
AFNetworking.framework 网络库,小程序包、swanCore包,request端能力使用到。
SDWebImage.framework 网络图片库。
TurboNet.framework 网络库。
Masonry.framework 自动布局库。
MJRefresh.framework 下拉刷新库,小程序下拉刷新。
MBProgressHUD.framework loading加载框库。
YYCache.framework 缓存库,小程序runtime webView使用到。
FMDatabase.framework 数据库
ZipArchive.framework 小程序解压使用
BaiduB64OC.framework 加解密库

手百内部基础库

说明
BBAFoundation.framework 基础库
BBAUIKit.framework 基础视图库
BBASchemeDispatcher.framework 路由分发库
Pyramid.framework 组件解耦合库,金字塔模型
BBAAPIRequest.framework 手百网络库
BBANetwork.framework 手百网络库
SmartHttpDns.framework DNS网络库
BoxKit.framework 手百公参数库
BBASettings.framework Storage.framework
UBC.framework 日志统计库
ApsManager.framework 下载小程序、swanCore包
BBAUpdate.framework/RIButtonItem.framework/BBACommonCrypto.framework 加密库

小程序接入说明

  1. 将所有依赖库添加到工程文件配置中。
  2. 在appDelegate中的didFinishLaunchingWithOptions方法中 添加小程序初始化代码。如下:
    // 调起协议插件注册
    [BBASchemeDispatcher setRegisterPlistName:@"SDPluginNameInfo"];
    // 小程序引擎初始化
    BBPContext *context = [[[BBPContext alloc] init] autorelease];
    context.application = application;
    context.launchOptions = launchOptions;
    context.homeLaunchedDelayTime = 0.1f;
    [PyramidInstance setContext:context];
    // appID为宿主app在iTunes上的appID
    // scheme是宿主app自定义的,小程序调起协议头。如:tiebaclient
    [BBAMNPManager registerDispatcherAppID:@"appID" version:@"33" schemes:@[@"scheme"]];
  3. 在宿主app中,添加一个子project,并且添加xxxxModule文件,遵守并实现pyramid的BBPModuleProtocol协议。
    // .m文件中添加该宏命令
    ModuleDefine(xxxxModule类名)
  4. 实现BBPModuleProtocol中的moduleRegister方法,注册宿主实现的功能及服务。
    - (void)moduleRegister:(BBPContext *)context {
        /* 注册功能及服务,以BBAMNPPlatformProtocol举例
           BBAMNPPlatformProtocol是要注册的协议,所有协议由小程序提供,可见小程序代码中的adapter文件夹。
           XXXXXPlatformImplement是宿主app对BBAMNPPlatformProtocol的实现类,其他protocol同。
           (小程序的功能有部分需要依赖宿主app去实现才能正常工作,具体实现列表可见其他文档,宿主app只需要创建对应的implement文件,并实现对应的协议即可)
           BBAMNP_PLATFORM_PYRAMID_IDENTIFITER是BBAMNPPlatformProtocol提供的标识常量,直接使用即可。
        */
        [Pyramid registerExternService:NSProtocolFromString(@"BBAMNPPlatformProtocol") implClass:XXXXXPlatformImplement.class identifier:BBAMNP_PLATFORM_PYRAMID_IDENTIFITER];
    }

    接入方需实现的功能和服务

1. 分享

功能说明

小程序菜单点击分享,调起宿主分享功能,此功能需要宿主实现,调用宿主的分享面板

相关协议

BBAMNPPlatformProtocol

接入方法

遵循BBAMNPPlatformProtocol协议,并实现协议中的分享接口

当前接口非终版接口,后面会标准化

/**
 * @param command 承载分享内容的对象
 */
- (void)callshare:(BBASchemeDispatcher *)command;

示例


- (void)callshare:(BBASchemeDispatcher *)command {
    NSDictionary *options = command.optionsDict;
    NSString *title = options[@"title"]; // 分享标题
    NSString *content = options[@"content"]; // 分享内容
    NSString *imageUrl = options[@"imageUrl"]; // 分享图标
    NSString *path = options[@"path"]; // 页面path

    // 根据获得的分享内容定制分享逻辑
    // Your code
}

2. 图片

功能说明

相关协议

接入方法

使用方法

遵循BBAMNPPhotoProtocol协议,并实现协议中的图片选择接口。


/**
 * Present photo picker controller to get images.
 * @discussion Not recommend to use `limitSize` parameter, pass `nil` to use internal default value will be better.
 *             Even if you have passed a limit value, it maybe return a image that size does not match what you want.
 *             See also PHImageManager `requestImageForAsset:targetSize:contentMode:options:resultHandler:`.
 *
 * @param maxNumber          The limit count of images.
 * @param originalImageBlock Get original image call back.
 * @param webImagesBlock     Get compressed image call back.
 * @param cancelBlock        Cancel action call back.
 * @param limit              The limit image side.
 * @return Photo picker controller.
 */
+ (UIViewController *)createPhotoPickerViewController:(NSInteger)maxNumber
                                       originalImages:(void (^)(NSDictionary *result))originalImageBlock
                                            webImages:(void (^)(NSDictionary *result))webImagesBlock
                                               cancel:(void (^)(NSDictionary *result))cancelBlock
                                            limitSize:(NSNumber *)limit;
使用方法

遵循BBAMNPPlatformProtocol协议,并实现协议中的图片预览接口

/**
 * @param command 承载图片信息的对象
 */
+ (BOOL)previewImage:(BBASchemeDispatcher *)command;
示例

- (void)previewImage:(BBASchemeDispatcher *)command {
    NSDictionary *options = command.optionsDict;
    NSArray *urls = options[@"urls"]; // 所有预览图片的url
    NSString *current = options[@"current"]; // 当前预览图片的url

    // 根据获得的图片信息定制预览逻辑
    Your code
}

3. 地图

功能说明

相关协议

接入方法

1、地图绘制、交互

 /**
 绑定上下文信息
 */
@property(nonatomic,strong)id context;
/**
 地图ID
 */
@property(nonatomic,copy)NSString *mapID;

/**
 比例尺的位置,设定坐标以MapView左上角为原点,向右向下增长
 */
@property (nonatomic) CGPoint mapScaleBarPosition;
/**
 代理
 */
@property(nonatomic,weak)id<BBAMapKitControllerDelegate> delegate;

/**
 获取mapView

 @return 地图View
 */
- (UIView *)mapView;

/**
 创建map组件

 @param mapAttr map 配置
 @return 地图View
 */
- (UIView *)mapViewWithAttribute:(BBAMapKitMap *)mapAttr;
/**
 销毁map组件
 */
- (BOOL)destroyMap;
/**
 移动地图中心点到location位置 无动画

 @param location location
 */
- (void)moveToLocation:(CLLocationCoordinate2D)location;

/**
 移动地图中心点到location位置

 @param location
 @param animated
 */
- (void)moveToLocation:(CLLocationCoordinate2D)location animated:(BOOL)animated;
/**
 获取当前地图的视野范围,返回西南角,东北角的经纬度

 @return @[西南角,东北角]
 */
- (NSArray<CLLocation*> *)getRegion;
/**
 获取当前地图的缩放级别

 @return float
 */
- (float)getScale;
/**
 获取当前地图中心的经纬度

 @return
 */
- (CLLocationCoordinate2D)getCenterLocation;

/**
 在地图上显示圆

 @param aCircle
 */
- (BOOL)showCircle:(BBAMapKitCircle *)aCircle;
/**
 在地图上画线 指定一系列坐标点,从数组第一项连线至最后一项

 @param polyline
 */
- (BOOL)showPolyline:(BBAMapKitPolyline *)polyline;
/**
 添加标记

 @param marker
 */
- (BOOL)showMark:(BBAMapKitMarker *)marker;
/**
 在地图上添加控件

 @param control
 */
- (void)showControl:(BBAMapKitControl *)control;
/**
 显示用户位置

 @param show
 */
- (void)showUserLocation:(BOOL)show;
/**
 用户所在位置经纬度

 @return
 */
- (CLLocationCoordinate2D)userLocation;

/**
 更新map配置

 @param attr
 */
- (void)updateMapAttr:(BBAMapKitMap *)attr;
/**
 设置map参数

 @param attr
 */
- (void)setMapAttr:(BBAMapKitMap *)attr;

/**
 平移marker

 @param markid markid
 @param destination destination 要移动到的点的坐标
 @param autoRotate 是否自动旋转 暂不支持
 @param rotate rotate 旋转角度 暂不支持
 @param duration duration 动画时长
 @param finish finish 动画完成回调

 */
- (void)translateMarker:(NSString *)markid
            destination:(CLLocationCoordinate2D)destination
             autoRotate:(BOOL)autoRotate
                 rotate:(double)rotate
               duration:(double)duration
                  finsh:(void(^)(void))finish;

/**
 缩放视野展示所有经纬度

 @param points 经纬度列表
 @param padding 坐标点形成的矩形边缘到地图边缘的距离
 @return
 */
- (BOOL)includePoints:(NSArray<CLLocation *> *)points padding:(UIEdgeInsets)padding;

/**
 获取当前用户位置

 @return id<BBAMapKitUserLocationProtocol>
 */
- (id<BBAMapKitUserLocationProtocol> )curUserLocation;

/**
 *当mapview即将被显式的时候调用,恢复之前存储的mapview状态。
 */
-(void)viewWillAppear;

/**
 *当mapview即将被隐藏的时候调用,存储当前mapview的状态。
 */
-(void)viewWillDisappear;

/**
 计算2个坐标的直线距离

 @param coordinate
 @param otherCoordinate
 @return CLLocationDistance
 */
- (CLLocationDistance)distanceBetween:(CLLocationCoordinate2D)coordinate
                        andCoordinate:(CLLocationCoordinate2D)otherCoordinate;

/**
 添加默认大头针标注

 @param coordinate
 @return YES 添加成功
 */
- (BOOL)addPointAnnotation:(CLLocationCoordinate2D)coordinate;

/**
 比例尺的宽高

 @return 比例尺的宽高
 */
- (CGSize) mapScaleBarSize;

/**
 返回地图的logo图片名称

 @return 地图的logo图片名称
 */
- (NSString *)logoImageName;

/**
 地图默认配置
 配置显示比例尺 地图logo位置等 
 @param mapView
 @param zoomLevel 缩放级别
 */
+ (void)configMapView:(UIView*)mapView zoomLevel:(float)zoomLevel;
   /**

 获取相对路径的全路径

 @param controller

 @param path

 @return

 */

- (NSString *)mapKitController:(id<BBAMNPMapProtocol>)controller

        fullPathOfRelativePath:(NSString *)path;

/**

 定位授权
 @param complete

 */

- (void)requestLocationAuthFinish:(void(^)(BOOL result))complete;

@optional

/**

 控件点击回调

 */

- (void)mapKitController:(id<BBAMNPMapProtocol>)controller didClickedControl:(BBAMapKitControl *)control;

//点击标记点时触发

- (void)mapKitController:(id<BBAMNPMapProtocol>)controller didClickedMarker:(BBAMapKitMarker *)marker;

//当点击annotation view弹出的泡泡时,调用此接口

- (void)mapKitController:(id<BBAMNPMapProtocol>)controller didClickedCallOut:(BBAMapKitMarker *)callOut;

//视野发生变化

- (void)regionWillChange:(id<BBAMNPMapProtocol>)controller;

//视野发生变化时触发

- (void)regionDidChange:(id<BBAMNPMapProtocol>)controller;

//渲染完成

- (void)mapViewDidFinishRendering:(id<BBAMNPMapProtocol>)controller;

//地图点击

- (void)mapKitController:(id<BBAMNPMapProtocol>)controller didClickedMap:(CLLocationCoordinate2D)coordinate;

//用户位置改变

- (void)userLocationChanged:(id<BBAMNPMapProtocol>)controller;

2、地图上显示路线、步行导航

   //显示路线

-(void)showRouteWithStartCoordinate:(CLLocationCoordinate2D)start

                      endCoordinate:(CLLocationCoordinate2D)end

                      mapController:(id<BBAMNPMapProtocol>)mapController;

// 获取当前位置

- (void)getCurrentLocation:(void (^)(CLLocationCoordinate2D startCoordinate))completion;

// 步行导航

- (void)startWalkNavigationFromStartCordinate:(CLLocationCoordinate2D)startCordinate toEndCordinate:(CLLocationCoordinate2D)endCordinate callBack:(void (^)(BBAMNPMapWalkNaviPlanRouteErrorCode errorCode))callBack;

typedef NS_ENUM(NSUInteger, BBAMNPMapWalkNaviPlanRouteErrorCode) {

    BBAMNPMapWalkNaviPlanRoutesuccess  = 1000,//算路成功

    BBAMNPMapWalkNaviPlanRouteError    = 1004,//算路失败

    BBAMNPMapWalkNaviPlanRouteNavLess  = 1005,//距离太近

    BBAMNPMapWalkNaviPlanRouteNavMore  = 1006 //距离太远

};

3、检索

   @property(nonatomic,weak)id<BBAMapKitSearchControllerDelegate> delegate;

/**

 逆地理编码搜索结果

 @param coordinate

 */

- (void)reverseGeoSearch:(CLLocationCoordinate2D)coordinate;

/**

 poi检索
 @param key

 @param city

 @param pageIndex

 @param pageCapacity

 */

- (void)searchPoiWithQuery:(NSString *)key

                      city:(NSString *)city

                 pageIndex:(int)pageIndex

              pageCapacity:(int)pageCapacity;

示例

4. 定位

功能说明

相关协议

接入方法

        /**
        * 获取位置信息-异步
        * @discussion 根据指定坐标系类型异步获取定位信息
        * @param type          坐标系类型
        * @param completion    定位结果的callback
        */
        + (void)getLocationWithType:(BBAMNPLocationCoordinateType)type completion:(BBAMNPLocationCompletion)completion;
        /**
        * 获取位置信息-同步
        * @discussion 根据指定坐标系类型同步获取定位信息,
        * @param type          坐标系类型
        * @param completion    定位结果的callback
        * @return 定位结果BBAMNPLocationData,可以为nil
        */
        + (BBAMNPLocationData *)getLocationWithType:(BBAMNPLocationCoordinateType)type;

示例

5. 支付

功能说明

相关协议

BBAMNPPaymentProtocol

接入方法

        /**
        * 百度钱包
        * @discussion 直接调起百度钱包支付,订单信息和支付回调的数据都是透传,小程序框架不做特殊处理
        * @param orderInfo     订单信息,由业务小程序生成,小程序框架透传给宿主app,宿主app直接传给百度钱包API即可
        * @param success       支付成功回调,payResult需要宿主app直接透传给小程序框架
        * @param failure       支付失败回调,payResult需要宿主app直接透传给小程序框架
        */
        + (void)requestBDWalletWithOrderInfo:(NSString *)orderInfo
                                     success:(void(^)(NSString *payResult))successBlock
                                     failure:(void(^)(NSString *payResult))failureBlock;
        /**
        * 支付宝
        * @discussion 直接调起支付宝支付,订单信息和支付回调的数据都是透传,小程序框架不做特殊处理
        * @param orderInfo     订单信息,由业务小程序生成,小程序框架透传给宿主app,宿主app直接传给支付宝API即可
        * @param completion    支付回调,其中status和payResult需要宿主app直接透传给小程序框架
        */
        + (void)requestAlipayWithOrderInfo:(NSString *)orderInfo
                                completion:(void(^)(NSInteger status, NSDictionary *payResult))completionBlock;

示例

6. 直播

功能说明

小程序提供视频直播的能力,可以支持播放器在线推流的视频。对应开发者接口是swan.createLivePlayerContext,通过这个接口创建一个LivePlayerContext对象,后续对直播组件的操作均可通过该对象完成。

相关协议

BBAMNPLiveProtocol

接入方法

非最终方案

1.使用方需要实现直播能力,且直播对象需要实现BBAMNPMessageItemProtocol协议 2.遵循BBAMNPMessageIMManagerProtocol协议,实现相关接口(返回直播对象)。

// BBAMNPMessageIMManagerProtocol.h

/**
 * @ret id<BBAMNPMessageItemProtocol> 拥有直播能力的实例
 */

+ (id<BBAMNPMessageItemProtocol>)getMessageItemInstance;
// BBAMNPMessageItemProtocol.h

typedef NSArray<NSDictionary *> BBAMNPLiveMessage;
typedef void(^BBAMessageMNPLiveMessageHandler)(BBAMNPLiveMessage *messages);
typedef void(^BBAMessageMNPLiveMessageCompletion)(NSError *error);
typedef void(^BBAMessageMNPLiveMessageSendCompletion)(NSDictionary *message, NSError *error);
typedef void(^BBAMessageMNPLiveMessageFetchCompletion)(BBAMNPLiveMessage *messages, NSError *error);

@protocol BBAMNPMessageItemProtocol <NSObject>

+ (NSNumber *)yuk;

// 直播间注册监听者
- (void)registerListener;

// 移除监听者
- (void)removeListener;

/**
 *  @brief 加入直播间
 *
 *  @param roomInfo 直播间相关信息
 *  @param messageHandler 新消息接收回调
 *  @param completion 失败回调
 */
- (void)joinRoom:(NSString *)mcastID
      commentUrl:(NSString *)commentUrl
  messageHandler:(BBAMessageMNPLiveMessageHandler)messageHandler
      completion:(BBAMessageMNPLiveMessageCompletion)completion;

/**
 *  @brief 加入直播间
 *
 *  @param msgInfo 需要发送的消息
 *  @param completion 发送完成回调
 */
- (void)sendMessage:(NSString *)msg
         completion:(BBAMessageMNPLiveMessageSendCompletion)completion;

/**
 *  @brief 加入直播间
 *
 *  @param fetchInfo 拉去消息所需相关信息
 *  @param completion 拉取完成回调
 */
- (void)fetchMessagesWithAppId:(int64_t)appId
                        useruk:(int64_t)useruk
                     contacter:(int64_t)contacter
                         begin:(int64_t)beginMsgId
                           end:(int64_t)endMsgId
                         count:(NSInteger)count
                    completion:(BBAMessageMNPLiveMessageFetchCompletion)completion;

7. 视频

功能说明

智能小程序提供了视频播放能力,通过实现video抽象接口就可以轻松让您的小程序拥有定制化的视频播放器,让小程序的的产品体验及产品功能更加完善。 开发者通过swan.createVideoContext来创建一个播放器实例,后续有关播放器的操作均在此对象上完成。

相关协议

BBAMNPVideoProtocol

接入方法

遵循BBAMNPVideoProtocol协议,实现相关接口

/**

 播放视频

 @param superView 父视图

 @param frame frame

 @param videoInfo 视频信息

 @param downloadInfo 下载信息

 @param delegate BBAMNPVideoHandleDelegate

 @return 是否当前要播放的视频已经播放了

 */

+ (BOOL)playVideoInView:(UIView *)superView

              withFrame:(CGRect)frame

              videoInfo:(NSDictionary *)videoInfo

           downloadInfo:(NSDictionary *)downloadInfo

               delegate:(id<BBAMNPVideoHandleDelegate>)delegate;

/// 暂停播放器

+ (void)pause;

/// 停止

+ (void)stopPlayer;

/// 关闭播放器

+ (void)closePlayer;

/// 重新播放视频

+ (void)replay;

/// 跳到指定时间播放

+ (void)seek:(double)seconds;

/// 进入全屏

+ (void)enterFullScreen;

/// 退出全屏

+ (void)exitFullScreen;

/// 播放器代理

+ (id)delegate;

/// 播放器当前播放模式

+ (NSUInteger)currentPlayerMode;

/// 发送弹幕信息

+ (void)sendBarrage:(NSDictionary *)barrage;

/// 更新弹幕信息

+ (void)updateBarrageMeta:(NSDictionary *)barrageMeta;

/// 外部更新弹幕信息

+ (void)updateBarrageList:(NSArray *)barrageList;

/// 更新播放器的数据

+ (void)updateVideoInfo:(NSDictionary *)videoInfo;

/// 播放器的父视图

+ (UIView *)currentPlayerSurperView;

/// 当前播放状态

+ (int)currentPlayerStatus;

/// 是否包含在自定义player在视图中

+ (BOOL)containCustomPlayerInView:(UIView *)view;

/// 是否正在播放

+ (BOOL)currentIsPlaying;

/// 是否全屏模式

+ (BOOL)currentIsFullMode;

/// 更新播放器frame

+ (void)updatePlayerFrame:(CGRect)frame vid:(NSString *)vid;

4.需要宿主提供的基础信息

背景

为了小程序能区分不同的宿主app,需要宿主提供一系列app基础信息,以维持小程序的正常运行。

提供方法

需要提供的信息都在BBAMNPPlatformProtocol中定义了接口,宿主app实现这些接口即可

    /**
     * 获取小程序的根导航栈
     * @discussion 获取小程序的根导航栈
     * @return 小程序即将push进入的UINavigationControlle
     */
    + (UINavigationController *)rootNavigationController;
    + (NSString *)userAgentForRequest;
    + (NSString *)userAgentForWebView;
    + (NSString *)userAgentForMNP;
    + (NSString *)composeParameters;
    + (NSString *)hostName;
    + (NSString *)hostVersion;
ynchuan commented 5 years ago

test