Skip to content

自定义扩展

SDK支持自定义模块(Module), UI组件(Component)来扩展相应的功能。
Module用来扩展功能性接口,例如: ESToastModule, ESDeviceModule 等。
Component用来扩展界面组件,例如: qr-view, img-transition 等。

自定义Module

Android端代码:

点击查看源码
java
// 实现IEsModule接口
public class MyModule implements IEsModule {

    @Override
    public void init(Context context) {

    }

    public void showToast(String msg) {
        ToastUtils.showToastShort(msg);
    }

    @Override
    public void destroy() {

    }
}

// 向指定的IEsComponent或者IEsModule发送事件(全局事件)
private void sendNativeEvent() {
    EsMap esMap = new EsMap();
    esMap.pushInt("status", 1);
    EsProxy.get().sendNativeEventTraceable(this, "onStatusChanged", esMap);
}

// 注册到SDK
EsManager.get().registerModule(MyModule.class.getName());

Vue端调用代码:

点击查看源码
js
// 参数1: module名称  参数2: 方法名称  参数3: 方法参数
Vue.Native.callNative('MyModule', 'showToast', "hello");

// vue层接收回调信息
//注册:
ESApp.$on('onStatusChanged', this.onStatusChanged);

//取消注册:
ESApp.$off('onStatusChanged', this.onStatusChanged);

//处理回调
function onStatusChanged(e) {
   const status = e.status;
   console.log('接收到的状态码:' + status);     
}

自定义Component

Android端代码:

点击查看源码
java
// 实现IEsComponent接口
public class MyVideoComponent implements IEsComponent<VideoComponent.VideoView> {
    @Override
    public VideoView createView(Context context) {
        return new VideoView(context);
    }
    // 对应vue标签的属性 <video-player ref="video" :autoPlay=false />
    @EsComponentAttribute(index = 0) // 如果各属性之间存在顺序执行问题,可指定属性调用顺序
    public void autoPlay(VideoView view, boolean auto){
    }
    // 对应vue标签的属性  <video-player ref="video" :src=videoUrl />
    @EsComponentAttribute
    public void src(VideoView view, String url) {
    }

    // 对应vue标签的方法 this.$refs.video.pause()
    @Override
    public void dispatchFunction(VideoView view, String eventName, EsArray params, @Nullable EsPromise promise) {
        switch (eventName){
            case "play":
                String url = params.getString("url");
                break;
            case "pause":
                break;
            case "getPosition": // 获取播放进度
                if(promise != null) {
                    promise.resolve(view.getCurrentPlayPositioin());
                }
                break;
        }
    }
    
    // 对应vue标签的回调  <video-player @player-status-changed="onPlayerStatusChanged" />
    @Override
    public void onPlayerStatusChanged(int playerStatus) throws RemoteException {
         EsMap esMap = new EsMap();
         esMap.pushInt("playerStatus", playerStatus);
         //sendUIEvent方法:向UI控件发送事件  
         EsProxy.get().sendUIEvent(view.getId(), "onPlayerStatusChanged", esMap);
    }

    @Override
    public void destroy(VideoView view) {
    }

    // 实现IEsComponentView接口
    public static final class VideoView extends FrameLayout implements IEsComponentView{
        public VideoView(@NonNull Context context) {
            super(context);
        }
    }

    // 注册到SDK
    EsManager.get().registerComponent(MyVideoComponent.class.getName());
}

Vue端注册:

点击查看源码
js
function registerVideoPlayerView() {
    Vue.registerElement('MyVideoComponent', {
        component: {
            name: 'MyVideoComponent',
            processEventData(event, nativeEventName, nativeEventParams) {
                switch (nativeEventName) {
                    case 'onPlayerStatusChanged':
                        event.playerStatus = nativeEventParams.playerStatus;
                    break;
                }
                return event;
            },
        },
    });
    Vue.component('video-player', {
        methods: {
            play(data, callback) {
                Vue.Native.callUIFunction(this.$refs.MyVideoComponent, 'play', [data], (res) => {
                    callback(res)
                });
            },
            pause(callback) {
                Vue.Native.callUIFunction(this.$refs.MyVideoComponent, 'pause', [], (res) => {
                    callback(res)
                });
            },
            onPlayerStatusChanged(evt) {
                this.$emit('player-status-changed', evt);
            },
        },
        render(h) {
            const on = getEventRedirector.call(this, [
                ['player-status-changed', 'playerStatusChanged'],
            ]);
            return h('MyVideoComponent',
                {
                    ref: 'MyVideoComponent',
                }, this.$slots.default
            );
        },
    });
}

export default registerVideoPlayerView;

//相关方法

js
function capitalize(str) {
    if (typeof str !== 'string') {
        return '';
    }
    return `${str.charAt(0).toUpperCase()}${str.slice(1)}`;
}

function getEventRedirector(events) {
    const on = {};
    events.forEach((event) => {
        if (Array.isArray(event)) {
            const [exposedEventName, nativeEventName] = event;
            if (Object.prototype.hasOwnProperty.call(this.$listeners, exposedEventName)) {
                on[event] = this[`on${capitalize(nativeEventName)}`];
            }else{
            }
        } else if (Object.prototype.hasOwnProperty.call(this.$listeners, event)) {
            on[event] = this[`on${capitalize(event)}`];
        }
    });
    return on;
}

export {
    capitalize,
    getEventRedirector,
};

Vue端调用:

点击查看源码
js
<video-player class="video" ref="video" :autoPlay=false :src=videoUrl @player-status-changed='onPlayerStatusChanged' />

function onPlayerStatusChanged(e) {
   const playerStatus = e.playerStatus;
   console.log('接收到的播放状态:' + playerStatus);     
}