Flutter UI插件写法

dart(UI+控制器)


import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class EditLiveViewController {
  MethodChannel channel;
  BasicMessageChannel _basicMessageChannel;
  Function _onPlayStart;
  Function _onPlayStop;
  Function _onPlayChange;
  EditLiveViewController(){
    channel = const MethodChannel('edit_live_view_plugin');
    channel.setMethodCallHandler((call){
      if("onPlayStart" == call.method){
          if(_onPlayStart != null){
            _onPlayStart();
          }
      }else{

      }
      return null;
    });
    _basicMessageChannel = const BasicMessageChannel("basic_edit_live_view_plugin",  JSONMessageCodec());
    _basicMessageChannel.setMessageHandler((message){
      Map map = message as Map;
      String method = map['method'];
      if("onPlayChange" == method){
        int v = map['value'];
        if(_onPlayChange != null){
          _onPlayChange(v);
        }
      }else if("onPlayStop" == method){
        if(_onPlayStop != null){
          _onPlayStop();
        }
      }
      return null;
    });
  }

  ///监听进度
  setOnPlayStop(Function listener){
    _onPlayStop = listener;
  }
  ///监听进度
  setOnPlayStart(Function listener){
    _onPlayStart = listener;
  }
  ///监听进度
  setOnPlayChange(Function listener){
    _onPlayChange = listener;
  }

  ///播放时间线
  Future<void> playTimeline() {
    return channel.invokeMethod('playTimeline');
  }
  ///暂停时间线
  Future<void> pauseTimeline() {
    return channel.invokeMethod('pauseTimeline');
  }

  ///获取时间总长度
  Future<int> getTimelineDuration() {
    return channel.invokeMethod('getTimelineDuration');
  }
}

class EditLiveView extends StatefulWidget{
  const EditLiveView({
    Key key,
    this.paths,
    this.musicData,
    this.controller,
    this.onCreate
  }):super(key:key);
  final List<String> paths;
  final EditLiveViewController controller;
  final Function onCreate;
  final Map musicData;// 音乐对象 "path":"" "startTime":0, "endTime":0,


  @override
  State<StatefulWidget> createState() {
    return _EditLiveViewState();
  }

}
class _EditLiveViewState extends State<EditLiveView>{

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    if(defaultTargetPlatform == TargetPlatform.iOS){
      return UiKitView(
        key: UniqueKey(),
        viewType: "edit_live_view",//platform_text_view
        onPlatformViewCreated:_onPlatformViewCreated,
        creationParams: <String,dynamic>{
          "paths":widget.paths,
          "musicData":widget.musicData,
        },
        creationParamsCodec: const StandardMessageCodec(),//new StandardMessageCodec()
      );
    }else{
      return AndroidView(
          key: UniqueKey(),
          viewType: "edit_live_view",
          onPlatformViewCreated:_onPlatformViewCreated,
          creationParams: <String,dynamic>{
            "paths":widget.paths,
            "musicData":widget.musicData,

          },
          creationParamsCodec: const StandardMessageCodec()
      );
    }
  }

  void _onPlatformViewCreated(int id){
    if(widget.onCreate != null){
      widget.onCreate();
    }
  }

}

Android:

MyPlugs.java

import androidx.annotation.NonNull;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodChannel;

public class MyPlugs implements FlutterPlugin {

    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {

        LiveView.registerWithRegistrar(binding);
        VideoFirstView.registerWithRegistrar(binding);
        EditLiveView.registerWithRegistrar(binding);
        TimelineEditorView.registerWithRegistrar(binding);
    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {

    }
}

MainActivity.java

package com.meishe.sdkdemo;

import static com.meishe.sdkdemo.xg.MessageReceiver.*;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.nfc.Tag;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

//import com.flutter.flutter_app_upgrade.FlutterAppUpgradePlugin;

import com.dashan.meishi.util.NvAssetManager;
import com.meishe.sdkdemo.loader.FlutterXUpdatePlugin;
import com.meishe.sdkdemo.media.MediaUtils;
import com.meishe.sdkdemo.media.MusicInfo;
import com.meishe.sdkdemo.wxapi.WXEntryActivity;
import com.meishe.sdkdemo.xg.MessageReceiver;
import com.dashan.meishi.Utils;
import com.dashan.meishi.base.base.constants.AndroidOS;
import com.dashan.meishi.util.PermissionsChecker;
import com.dashan.meishi.view.MyPlugs;
import com.google.android.gms.wearable.MessageEvent;
import com.meicam.effect.sdk.NvsEffectSdkContext;
import com.meicam.sdk.NvsStreamingContext;
import com.tencent.android.tpush.XGIOperateCallback;
import com.tencent.android.tpush.XGPushConfig;
import com.tencent.android.tpush.XGPushManager;
import com.tencent.android.tpush.XGPushShowedResult;
import com.meishe.sdkdemo.media.MediaData;
import com.meishe.sdkdemo.media.MusicInfo;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.android.FlutterEngineProvider;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import pub.devrel.easypermissions.EasyPermissions;

public class MainActivity extends FlutterActivity{
    private FlutterEngine flutterEngine;
    private Activity self  = this;

    @Override
    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        flutterEngine = getFlutterEngine();
        flutterEngine.getPlugins().add(new MyPlugs());
    }
 
}

EditLiveView.java

import android.content.Context;
import android.graphics.Point;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.dashan.meishi.Utils;
import com.dashan.meishi.util.NvsStreamUtil;
import com.meicam.sdk.NvsAudioClip;
import com.meicam.sdk.NvsAudioResolution;
import com.meicam.sdk.NvsAudioTrack;
import com.meicam.sdk.NvsColor;
import com.meicam.sdk.NvsLiveWindowExt;
import com.meicam.sdk.NvsRational;
import com.meicam.sdk.NvsStreamingContext;
import com.meicam.sdk.NvsTimeline;
import com.meicam.sdk.NvsVideoClip;
import com.meicam.sdk.NvsVideoFx;
import com.meicam.sdk.NvsVideoResolution;
import com.meicam.sdk.NvsVideoTrack;
import com.meicam.sdk.NvsVolume;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.JSONMessageCodec;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;

public class EditLiveView extends PlatformViewFactory implements PlatformView {


    private static NvsLiveWindowExt mLiveWindow;
    private static BinaryMessenger messenger;
    public static MethodChannel methodChannel;
    private static BasicMessageChannel basicMessageChannel;

    private static EditLiveView instance;
    private Handler mainHandler = new Handler(Looper.getMainLooper());

    private EditLiveView() {
        super(StandardMessageCodec.INSTANCE);
    }
    public static void registerWithRegistrar(@NonNull FlutterPlugin.FlutterPluginBinding binding){
        methodChannel = new MethodChannel(binding.getBinaryMessenger(),"edit_live_view_plugin");
        methodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @Override
            public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
                if("playTimeline".equals(call.method)){//播放时间轴  开始播放/恢复播放
                    if(instance != null){
                        instance.playTimeline();
                    }
                }else if("pauseTimeline".equals(call.method)){//暂停时间轴
                    if(instance != null){
                        instance.pauseTimeline();
                    }
                }else if("getTimelineDuration".equals(call.method)){
                    if(instance != null){
                       result.success(instance.getTimelineDuration());
                    }
                }


            }
        });

        basicMessageChannel = new BasicMessageChannel(binding.getBinaryMessenger(),"basic_edit_live_view_plugin", JSONMessageCodec.INSTANCE);
        basicMessageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler() {
            @Override
            public void onMessage(@Nullable Object message, @NonNull BasicMessageChannel.Reply reply) {

            }
        });

        if(instance == null){
            instance = new EditLiveView();
        }
        messenger = binding.getBinaryMessenger();
        binding.getPlatformViewRegistry().registerViewFactory("edit_live_view",instance);
    }

    //播放时间线
    private void playTimeline(){
        if(mStreamingContext != null && mTimeline != null){
            Log.e("test","" + mTimeline.getDuration());
            Log.e("test","" + mStreamingContext.getTimelineCurrentPosition(mTimeline));
            long duration = mStreamingContext.getTimelineCurrentPosition(mTimeline) - mTimeline.getDuration();
            duration = Math.abs(duration);
            if(duration < 30000){
                mStreamingContext.playbackTimeline(mTimeline,0, mTimeline.getDuration(), NvsStreamingContext.VIDEO_PREVIEW_SIZEMODE_LIVEWINDOW_SIZE, true, 0);
                if(methodChannel != null){
                    methodChannel.invokeMethod("onPlayStart",null);
                }
            }else{
                mStreamingContext.playbackTimeline(mTimeline, mStreamingContext.getTimelineCurrentPosition(mTimeline), mTimeline.getDuration(), NvsStreamingContext.VIDEO_PREVIEW_SIZEMODE_LIVEWINDOW_SIZE, true, 0);
            }

        }
    }
    //停止时间线
    private void pauseTimeline(){
        if(mStreamingContext != null && mTimeline != null){
            mStreamingContext.pausePlayback();
        }
    }
    //
    private long getTimelineDuration(){
        if(mTimeline != null){
            return mTimeline.getDuration();
        }else{
            return 0;
        }
    }


    @Override
    public View getView() {
        return mLiveWindow;
    }
    @Override
    public void dispose() {

    }



    @Override
    public PlatformView create(@Nullable Context context, int viewId, @Nullable Object args) {
        mLiveWindow = new NvsLiveWindowExt(context);
        Map<String,Object> map = (Map<String, Object>) args;
        List<String> paths = (List<String>)  map.get("paths");// 视频列表
        Map musicData =(Map) map.get("musicData");  // 音乐数据

        System.out.println("edit接收的音乐:"+musicData);
        //todo 初始化函数
        initView(paths,musicData);
        //todo 测试函数
//        test();
        return instance;
    }

    //获取当前引擎状态
    private int getCurrentEngineState() {
        return mStreamingContext.getStreamingEngineState();
    }

}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容