Android 原生SDK Flutter插件编写

   日期:2020-11-16     浏览:119    评论:0    
核心提示:CBS,http://123.108.164.71/etv2sb/phd27/playlist.m3u8CGNTV,rtmp://edge2.everyon.tv:1935/etv2/phd235CTIME,http://123.108.164.71/etv2sb/pld21/lihattv.m3u8CTS,rtmp://edge1.everyon.tv:1935/etv1/phd28

项目背景

本人前段时间负责公司一个Android SDK开发工作,并制定相关对接文档,开发完成之后,与一些合作方对接。

但是某些公司的项目是用Flutter编写,需要编写对应SDK的flutter插件提供给对方,啥?flutter?不会呀!

哈哈哈,但是作为无所畏惧的程序员来说,能认怂么,当然是不能(硬着头皮上)

 

最终一周内,将对应的Flutter插件开发完成并交付,以下是我学习开发Android SDK Flutter插件的总结

总结

万事都是开头难,但是在flutter大环境已经很成熟的情况下,完全不用慌。

第一步是弄明白flutter如何调用android原生代码

推荐一篇博客,还有很多好的博客可以自行搜索:https://developer.aliyun.com/article/697792

还有一个我认为写的比较好的开源flutter插件,可以拿来借鉴:https://github.com/OpenFlutter/Pangolin

 

安装环境

在 Windows 操作系统上安装和配置 Flutter 开发环境

创建插件项目

环境搭建完毕之后,打开Android studio ->File->new->new Flutter Project ->选择Flutter Plugin

创建成功之后,打开项目,看到这样的目录结构,我们更多关心的是写Android插件地方

编写插件

我们打开android目录下的FlutterPlugin文件,这是项目自己为我们生成的插件Demo,在这个窗口下,我们不难发现很多android原生代码会爆红,虽然不影响编译,

但是看着很难受,我们选择右上角Open for Editing in Android Studio,选择在另一个窗口打开就没事了。

我们看下它为我们自动生成的插件代码,这里是Kotlin语法,它实现了FlutterPlugin,MethodCallHandler


public class FlutterPlugin: FlutterPlugin, MethodCallHandler {
   ...
  private lateinit var channel : MethodChannel

  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "flutter_plugin")
    channel.setMethodCallHandler(this);
  }

...
  companion object {
    @JvmStatic
    fun registerWith(registrar: Registrar) {
      val channel = MethodChannel(registrar.messenger(), "flutter_plugin")
      channel.setMethodCallHandler(FlutterPlugin())
    }
  }

  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    if (call.method == "getPlatformVersion") {
      result.success("Android ${android.os.Build.VERSION.RELEASE}")
    } else {
      result.notImplemented()
    }
  }

  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
  }
}

其中,MethodCallHandler这个接口实现的onMethodCall(MethodCall call, MethodChannel.Result result) - 用于接受消息,

这里接收的消息就是来自于Flutter项目,call是消息内容,它有两个成员变量String类型的call.method表示调用的方法名,

Object 类型的call.arguments表示调用方法所传递的入参。

开始编码,在android的目录下的build.gradle加入我们自己Android项目的SDK依赖:

 implementation 'com.jayxu.android:***Sdk:1.0.1'

在自动生成的插件代码的基础上,进行我们项目的开发,在插件里,我还需要拿到当前的activity对象,用于原生Activity之间的跳转,

所以我还实现了ActivityAware,具体使用,请看代码(Kotlin写法)。


public class PedesxpluginPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {

    ...

    private lateinit var channel: MethodChannel
    private lateinit var applicationContext: Context
    private lateinit var activity: Activity

    override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
        onAttachedToEngine(flutterPluginBinding.applicationContext, flutterPluginBinding.binaryMessenger)

    }

    fun onAttachedToEngine(applicationContext: Context, messenger: BinaryMessenger) {
        this.applicationContext = applicationContext
        channel = MethodChannel(messenger, "pedesxplugin")
        channel.setMethodCallHandler(this)
    }

    fun onAttachedToEngine(applicationContext: Context, messenger: BinaryMessenger, activity: Activity) {
        this.applicationContext = applicationContext
        channel = MethodChannel(messenger, "pedesxplugin")
        channel.setMethodCallHandler(this)
        this.activity = activity
    }


   ...

    companion object {
        @JvmStatic
        fun registerWith(registrar: Registrar) {
            val instance = PedesxpluginPlugin()
            instance.onAttachedToEngine(registrar.context(), registrar.messenger(), registrar.activity())
        }
    }

    
    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
        if (call.method == "getPlatformVersion") {
            result.success("Android ${android.os.Build.VERSION.RELEASE}")
        } else if (call.method == "registerPedesx") {
            val appId: String? = call.argument("appId")
            val shelf_id: String? = call.argument("shelf_id")
            val csj_appId: String? = call.argument("csj_appId")
            val csj_video_id: String? = call.argument("csj_video_id")

            //初始化SDK
            PedesxUtil.init(applicationContext, appId, shelf_id, csj_appId, csj_video_id)
        } else if (call.method == "registerPedesxUser") {
            val uid: String? = call.argument("uid")
            val oaid: String? = call.argument("oaid")

            //初始化SDK的User信息
            PedesxUtil.initUser(applicationContext, uid, oaid)
        } else if (call.method == "startPedesxVideoActivity") {

            //跳转我们自己SDK的界面1
            ActivityUtils.startActivity(activity, Demo1Activity::class.java)
        } else if (call.method == "startPedesxWelfareActivity") {

            //跳转我们自己SDK的界面2
            ActivityUtils.startActivity(activity, Demo2Activity::class.java)
        } else {
            result.notImplemented()
        }
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }

    override fun onDetachedFromActivity() {

    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {

    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        this.activity = binding.activity
    }

    override fun onDetachedFromActivityForConfigChanges() {

    }
}

 

到此Android 插件部分就全部写好了,是不是很简单。

如何使用插件

插件写好了,那么Flutter项目如何使用我们的插件呢,我们的工作还在继续

回到flutter插件项目,我们在lib目录下,新建一个dart文件,以下为代码示例,没有写全,基本的写法都差不多,这个文件主要是将Android插件部分的代码,再次封装给我们的example项目使用。

...

MethodChannel _channel = MethodChannel('pedesxplugin')
  ..setMethodCallHandler(_methodHandler);

StreamController<BasePedesxResponse> _pedesxResponseEventHandlerController =
    new StreamController.broadcast();

Stream<BasePedesxResponse> get pedesxResponseEventHandler =>
    _pedesxResponseEventHandlerController.stream;

Future _methodHandler(MethodCall methodCall) {
  var response =
      BasePedesxResponse.create(methodCall.method, methodCall.arguments);
  _pedesxResponseEventHandlerController.add(response);
  return Future.value();
}

Future<bool> initPedesxSdk({
  @required String appId, //SDK APPId
  @required String shelf_id, //注释1
  @required String csj_appId, //注释2
  @required String csj_video_id, //注释3

}) async {
  return await _channel.invokeMethod("registerPedesx", {
    "appId": appId,
    "shelf_id": shelf_id,
    "csj_appId": csj_appId,
    "csj_video_id": csj_video_id,
  });
}

Future<bool> initPedesxSdkUser({
  @required String uid,
  @required String oaid,
}) async {
  return await _channel
      .invokeMethod("registerPedesxUser", {"uid": uid, "oaid": oaid});
}

Future<bool> startPedesxVideoActivity() async {
  return await _channel.invokeMethod("startPedesxVideoActivity");
}

Future<bool> startPedesxWelfareActivity() async {
  return await _channel.invokeMethod("startPedesxWelfareActivity");
}

...

这里我们将Android插件的部分代码与flutter调用插件的部分代码进行比较,有没有很清晰

android 插件代码:

override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    ...        
    if (call.method == "registerPedesx") {
            val appId: String? = call.argument("appId")
            val shelf_id: String? = call.argument("shelf_id")
            val csj_appId: String? = call.argument("csj_appId")
            val csj_video_id: String? = call.argument("csj_video_id")

            //初始化SDK
            PedesxUtil.init(applicationContext, appId, shelf_id, csj_appId, csj_video_id)
        }
    ...
 }


-----------------------这是一条分界线---------------------------

flutter代码:

Future<bool> initPedesxSdk({
  @required String appId, //SDK APPId
  @required String shelf_id, //货架ID
  @required String csj_appId, //穿山甲APPID
  @required String csj_video_id, //穿山甲激励视频ID

}) async {
  return await _channel.invokeMethod("registerPedesx", {
    "appId": appId,
    "shelf_id": shelf_id,
    "csj_appId": csj_appId,
    "csj_video_id": csj_video_id,
  });
}

最终example项目调用插件的部分dart代码:

  _initPedesxSdk() async{
    

    await Pedesxplugin.initPedesxSdk(
        appId: "***",
        shelf_id: "***********",
        csj_appId: "*****",
        csj_video_id: "*******",
    );
  }

因为部分代码,涉及项目隐私,不能全部贴出,有问题童鞋的可以去看看https://github.com/OpenFlutter/Pangolin这个项目,强烈推荐。

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服