更新记录

2.0.20230108(2023-01-29)

1、修改了扫描接口回调结果,设备返回信息增加了设备唯一标识; 2、播放方法参数修改,使用设备唯一标识来指定设备; 3、增加了一些控制类接口;

1.0.20200413(2020-04-13)

增加获取本机IPV4地址的接口getIpAddress,解决有些小伙伴需要在手机上起http服务来进行投屏无法获取本机IP的问题。目前只在wifi环境下进行过测试。源码已经上传到码云上,有能力的小伙伴还是建议自己去编译打包调试,uniApp的生态还要靠大家去维护完善,感谢DCloud,希望做的越来越好。 qq:1193890771 有问题可留言、发邮件至qq邮箱或加qq咨询(加qq请备注“uniapp投屏”) 谢谢

1.0.20200408(2020-04-08)

1.修复安卓再次搜索搜索不到设备的bug;

查看更多

平台兼容性

Android Android CPU类型 iOS
适用版本区间:6.0 - 14.0 armeabi-v7a:支持,arm64-v8a:支持,x86:支持 适用版本区间:11 - 17

原生插件通用使用流程:

  1. 购买插件,选择该插件绑定的项目。
  2. 在HBuilderX里找到项目,在manifest的app原生插件配置中勾选模块,如需要填写参数则参考插件作者的文档添加。
  3. 根据插件作者的提供的文档开发代码,在代码中引用插件,调用插件功能。
  4. 打包自定义基座,选择插件,得到自定义基座,然后运行时选择自定义基座,进行log输出测试。
  5. 开发完毕后正式云打包

付费原生插件目前不支持离线打包。
Android 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/android
iOS 离线打包原生插件另见文档 https://nativesupport.dcloud.net.cn/NativePlugin/offline_package/ios

注意事项:使用HBuilderX2.7.14以下版本,如果同一插件且同一appid下购买并绑定了多个包名,提交云打包界面提示包名绑定不一致时,需要在HBuilderX项目中manifest.json->“App原生插件配置”->”云端插件“列表中删除该插件重新选择


2.0版本使用说明:

由于作者能力有限,此插件只在少量电视和盒子上进行过测试,若在使用中遇到问题或发现bug,可添:进行咨询反馈。

特别说明:

目前发现本插件和部分广告联盟(如腾讯优量汇)有冲突,打包会报错。如需使用本插件请取消勾选冲突的广告联盟,谢谢!

本插件在IOS16及以上系统存在搜索不到设备的问题,原因是由于IOS的权限控制,具体解决方法请参考

https://www.jianshu.com/p/c4bb6e

https://ask.dcloud.net.cn/article/

具体步骤说明:
1、使用苹果开发者主账号访问 https://developer.apple.com/contact/request/networking-multicast 申请组播权限;
2、大概3天左右查看开发者账号,会多一个Additional Capabilities,勾选Multicast Networking权限;
3、重新生成描述文件,下载新的描述文件
4、在uniapp工程的mainfest.json文件源码试图中增加如下配置
   在节点 "app-plus"->"distribute"->"ios"下
             "capabilities" : {
                        "entitlements" : {
                                "com.apple.developer.networking.multicast" : true
                        }
                }
5、使用新的描述文件重新打包。
本项目的源码也开源在码云上,有兴趣有能力的小伙伴可以自取:
安卓插件代码:https://gitee.com/qianj1991/uniapp_dlna_android
IOS插件代码:https://gitee.com/qianj1991/uniapp_dlna_ios
本插件通过DLNA协议实现了简易版的投屏功能,支持安卓和IOS,功能很简单,
相对于上个版本
1、修改了扫描接口回调结果,设备返回信息增加了设备唯一标识;
2、播放方法参数修改,使用设备唯一标识来指定设备;
3、增加了一些控制类接口;
目前共有以下几个接口:
扫 描 设 备:lyzmlDLNA.startSearch(callback);
投      屏:lyzmlDLNA.playVideo({udn:"",mediaURL:""},callback); 
暂 停 投 屏:lyzmlDLNA.pauseVideo(); 
继 续 投 屏:lyzmlDLNA.resumeVideo(second); 
结 束 投 屏:lyzmlDLNA.stopVideo();
设 置 监 听:lyzmlDLNA.setPlayMonitor(callback);
获取扫描结果:lyzmlDLNA.getSearchResult(callback);
获取本机 IP:lyzmlDLNA.getIpAddress(callback);
获取当前音量:lyzmlDLNA.getVolume();
设 置 音 量:lyzmlDLNA.setVolume(volume); 
获取当前播放进度:lyzmlDLNA.getPositionInfo();
获取视频总时长:lyzmlDLNA.getMediaDuration();
快进快退:lyzmlDLNA.seek(second);
获取状态:lyzmlDLNA.getTransportState();
1、在需要的页面上获取插件 const lyzmlDLNA = uni.requireNativePlugin('lyzml-DLNA');
2、开启扫描 
lyzmlDLNA.startSearch(resp=>{
    if(resp.code == 0){
        this.searchingText = "搜索中...";
    }else if(resp.code == 1){
        //返回扫描的结果,eg: [{ip:"192.168.0.108",name:"xiaomiTV",udn:"uuid:fdaa8cbfdc2de4e3fcb3865f08dea7d7b227df3fe1a8354c4ee4b"}]
        this.tvList = resp.result;
    }else if(resp.code == 2){
        this.searchingText = "搜索完成";
    }
});

注:该方法相对于1.0版本修改了返回参数格式,{code:0,result:[]};
code:0表示开始搜索,1表示扫描到可用设备并返回,2扫描结束,扫描一段时间(5s)自动结束。
扫描到新的设备都会触发此回调,可能会多次回调,返回的结果是所有扫描到的设备列表;
由于同一台设备上可能存在多个接收端,此版本增加了udn返回参数,以区别不同的接收端。
(1.0版本使用的是ip)
3、投屏接口,通过udn来指定投屏设备,将音视频的url投屏到设备上进行播放
lyzmlDLNA.playVideo({
  udn:"dsdsdfss111",
  mediaURL:url
},(resp)=>{
  //这里有个回调,可以不用 
  //返回信息{code:0,desc:"发送指令成功(并不代表投屏成功)"} 
  //code非0时为失败,desc返回失败原因 
  if(resp && 0!=resp.code){
    uni.showToast({
        icon: "none",
        title: "若投屏失败,请尝试重新扫描"
    });
  } 
});
4、继 续 投 屏:lyzmlDLNA.resumeVideo(second); 
参数为秒,暂停时可记录已播放的进度,pauseVideo()后的继续播放
5、设置监听,由于投屏发射端和接收端不能做到同步,发出的指令都是异步返回的。
lyzmlDLNA.setPlayMonitor((resp) => {
    switch (resp.code) {
        case 1:  //onGetTransportState,获取传输状态回调,
                         //参考项目中共有STOPPED、PLAYING、TRANSITIONING、PAUSED_PLAYBACK、PAUSED_RECORDING、RECORDING、NO_MEDIA_PRESENT、ERR
                                 //目前测试只发现以下3种状态,其他的不知道啥场景会触发
            let status = resp.result;
            this.currPlayState = status;
            if ("PLAYING" == status) {
                this.isPlaying = true;
            } else if ("PAUSED_PLAYBACK" == status || "STOPPED" == status) {
                this.isPlaying = false;
            }
            break;
        case 2: //onGetMediaDuration,获取视频时长回调
            this.durationSecond = resp.result;
            this.durationStr = ut.turnSSToHHMISS(this.durationSecond);
            break;
        case 3: //onPlay,开始播放回调
            this.isPlaying = true;
            break;
        case 4: //onPause,暂停播放回调
            this.isPlaying = false;
            break;
        case 5: //onStop,结束播放回调
            this.isPlaying = false;
            break;
                case 6: //d,音量变化回调
                        this.currVolume = resp.result;
                        break;
        case 7: //Updated,播放进度回调 
            this.currTimeSecond = resp.result;
            this.currTimeStr = ut.turnSSToHHMISS(this.currTimeSecond);
            break;
        case 8: //Complete,快进快退回调
            this.getTransportState();
            break;
        case 9: //onError,调用发生错误时的回调,可以打印出来看看,调试的时候可以看看,有时候莫名奇妙会不停回调错误
            break;
        default:
            break;
    }
});
5、可以主动调用接口获取扫描到的结果,这个接口就算是停止扫描后也可以获取到之前扫描的结果,返回的结果和startSearch的回调结果一致:
lyzmlDLNA.getSearchResult((devList)=>{
//返回扫描的结果,eg: [{ip:"192.168.0.108",name:"xiaomiTV","udn":"uuid:fdaa8cbfdc2de4e3fcb3865f08dea7d7b227df3fe1a8354c4ee4b"}]
});
6、获取本机IP:lyzmlDLNA.getIpAddress((ip)=>{
console.log("====getIPAddress====",ip);
});
参考资料(感谢github的开源项目):
https://github.com/ClaudeLi/DLNA_UPnP
https://github.com/zhangwenxue/CyberGarage4Android
https://gitee.com/feiser/M3U8Loader.git

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问