技术心得:打造自己的智能投屏体验——Android投屏开发入门

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 技术心得:打造自己的智能投屏体验——Android投屏开发入门

前言


目前音视频领域的应用已涉及到众多领域,而其中投屏功能,成为很多家庭影院、会议观看等的高频使用场景。为了尽享大屏体验,不妨自己来实现一个投屏功能


1、投屏原理简介


投屏,就是将一台设备上的媒体内容,通过一定的技术方案,在另外一台设备上显示。其中这个一定的技术方案,主要分为两种:


推送模式:主要用于投屏音视频。投屏之后手机可以关闭,电视(接收端)不会停止播放。核心原理就是通过指定协议,类似于蓝牙那样搜索匹配,并将音视频的播放地址传输过去,然后接收端播放这个地址的流媒体。常见的投屏协议有DLNA、Airplay。


镜像模式:所谓的镜像就是同屏,把手机(发送端)的屏幕内容同步传输到电视(接收端)上显示。核心原理就是一边录屏一遍发送给电视同步播放。常见协议有Miracast、Airplay。


一般来说我们常用的投屏是推送模式,本文主要也是介绍这个。


1.1 投屏协议——DLNA


DLNA代表“数字生活网络联盟”。DLNA使用通用即插即用(UPnP)协议。DLNA并不是真正的无线显示解决方案。相反,它只是一种在一个设备上获取内容并在另一台设备上播放内容的方法。也就是说他不是真正的投屏技术。


我们手机上爱奇艺APP、腾讯视频APP,在打开视频后,右上角有一个【TV】的小图标,你点击这个小图标,就会弹出“正在搜寻可投屏设备”,将会显示同一个Wi-Fi网络下能够发现的投屏设备,选择投屏的电视机后,电视机就会播放对应的视频。这里有一个注意点,就是当你在手机上是VIP会员时,你要想将VIP视频通过DLNA投屏到智能电视上时,是没法投屏的,因为爱奇艺或者腾讯将限制这种操作,避免手机VIP用户通过投屏来实现电视机播放VIP视频,原因就是DLNA协议要求最终还是需要智能电视自己去视频服务器获取视频,视频服务器可能会在流媒体地址的获取/解析等做限制。


1.2 投屏协议 —— Miracast


Miracast是Wi-Fi联盟制定的Wi-Fi投屏行业标准,实质上是对Apple AirPlay的回应。Miracast支持内置在Android 4.2+和Windows 8.1、Windows 10。允许Android智能手机、Windows平板电脑和笔记本电脑以及其他设备以无线方式传输到兼容Miracast的接收器比如智能电视、平板电脑等。当前已经有很多电视盒子都支持Miracast协议,比如小米盒子、荣耀盒子等等,小米手机、华为的手机也都支持Miracast协议,配合小米盒子、荣耀盒子即可实现投屏。


各品牌设备该功能名称可能不同,比如:无线显示、屏幕共享、多屏互动、Screen Mirroring等。可以看这个乐播关于设备的入口收集部分:


Miracast相比AirPlay来讲,有缺点也有优点,优点在于:


内置在Andorid和Windows中,不要求必须是苹果的终端设备。


Miracast可以在没有无线路由器的时候也能很好的工作,也就是说手机可以直接通过Wi-Fi连接到电视的Wi-Fi网卡上进行投屏(Wi-Fi Direct技术),在没有无线路由器的时候是比较方便的。


缺点在于:


只支持屏幕镜像模式投屏,而不支持流模式的投屏。当你在投屏的时候手机整个屏幕(包括状态栏等)会复制到电视机上,并且要始终保持手机屏幕是处于播放和显示状态。苹果的AirPlay则可以允许你在手机上一?边浏览网页,一边通过电视播放手机中的视频。


Miracast毕竟是一种行业标准,各个厂家实现良莠不齐,不同设备之间投屏可能出现体验不佳的问题。


另一个问题是该标准不要求设备必须带有“ Miracast”品牌的商标。制造商已将其Miracast实现称为其他东西。例如,LG称其Miracast支持为“ SmartShare”,三星称其为“ AllShare Cast”,索尼称其为“屏幕镜像”,而松下称其为“显示镜像”。


1.3 投屏协议 ——Airplay


AIrplay协议是苹果的协议,主要局限在仅适用于 Apple 设备,我们在这里不做展开。


1.4 投屏协议 —— 其他第三方


最后就是很多专门投屏的投屏APP,这些APP要么是实现了上面几种协议,要么是自己实现一套私有协议。手机和智能电视都要安装这些APP,否则无法投屏。而前面几个协议都是标准协议,操作系统内置,无需安装。比较著名的投屏APP有乐播投屏、APowerMirror等,使用都很方便,一般是通过扫描智能电视显示的二维码来实现投屏到特定电视机上。这些投屏APP的另外一个好处就是:不局限在同一个局域网内,可以跨三层网络、甚至广域网。


2. 投屏功能开发实践


在这里我们选择用来保利威的官方Demo为例,之所以用它为例,是因为他也是一家视频提供商,并且提供了视频加密服务,也就是说,他可以做到提供主流视频厂商那样的VIP视频服务,并且其允许投屏。我们可以查看官方文档,借此探究Android投屏的开发实现。其基本都封装好了,我们可以复制过来改改就能应用到自己项目上,也可以参考实现。


2.1 投屏环境搭建和体验


1、注册第三方投屏SDK(可选)


第三方SDK往往和电视厂家有一定的合作,会内置支持,或者提供对应的电视端APP,可以拥有更良好的投屏体验。如果要自己实现投屏的话,还需要对实现协议对接,甚至还要开发对应的接收端APP,工作量上就大了不少。由于保利威的demo投屏功能是基于乐播的,如果需要集成到自己项目上,就需要在乐播上注册绑定包名生成key。当然我们直接运行demo,里面就内置了对应的key,体验的话可以忽略这一步。


2、 准备两台Android手机


因为开发者未必有电视,可以用另外一台Android设备充当电视接收端。接收端需要安装乐播的apk,乐播apk在安卓应用市场就能找到,如果应用市场没有,也可以去乐播官网进行下载乐播投屏电视版。


3、下载Demo工程


本文是基于Github Demo项目讲解,所以可以直接下载他们的Github项目运行体验。下载地址:


Demo中默认隐藏了投屏按钮,如果要体验的话,需要在PolyvPlayerActivity中取消注释


//投屏功能默认隐藏,如果需要请注释下面两行代码


// iv_screencast_search.setVisibility(View.GONE);


// iv_screencast_search_land.setVisibility(View.GONE);


然后,我们将两台手机(发送端和接收端),分别打开对应的APP,将其置于同一个wifi(局域网)之下,就可以开始投屏了。


2.2 投屏开发浅析


我们可以看下Demo结构中的投屏模块,其中widget是关于UI层的实现,主要是PolyvScreencastManager,封装了投屏功能。我们主要就是聚焦这个的实现。


//com/easefun/polyvsdk/cast


├── PolyvAllCast.java //乐播投屏二次封装类


├── PolyvIUIUpdateListener.java // 封装的投屏状态回调监听器


├── PolyvScreencastManager.java //投屏封装工具类,操作投屏功能使用。等同于旧版的PolyvScreencastHelper


└── widget


├── PolyvScreencastSearchLayout.java //搜索投屏Layout


└── PolyvScreencastStatusLayout.java //投屏状态管理Layout


2.2.1 初始化


从官方文档中可以知道初始化要设置AppSecret。这是乐播提供的服务中,把投屏sdk与包名绑定了,如果更换了包名我们就要重新注册,否则包名错误就会导致校验失败。然后会因此无法搜索到设备。


//appId和appSecret需与包名绑定,获取方式请到乐播官网注册获取


PolyvScreencastManager.init(, );


//初始化单例


PolyvScreencastManager.getInstance(this);


//PolyvAllCast.java


private void initLelinkService(Context context, String appid, String appSecret) {


LelinkSourceSDK.getInstance()


.setBindSdkListener(new IBindSdkListener() {


@Override


//代码效果参考:http://hnjlyzjd.com/hw/wz_24846.html

public void onBindCallback(boolean result) {

//绑定,并且返回绑定的结果


Log.e(TAG, "Polyv Cast SDK Init Result :" + result);


if (result) {


LelinkSourceSDK.getInstance().setOption(IAPI.OPTION_5, false);


LelinkSourceSDK.getInstance().setDebugMode(true);


LelinkSourceSDK.getInstance().enableLogCache(true);


}


}


})


.setSdkInitInfo(context, appid, appSecret)


.bindSdk();


}


我们可以看见在PolyvAllCast中进行了投屏SDK的初始化与绑定服务,并且返回了结果。这种绑定服务往往依赖于网络,最好就在Application中就进行初始化,避免网络延迟导致投屏服务异常。


2.2.2 三大回调监听


如果有蓝牙开发经验的,其实可以很容易理解,这和蓝牙的搜索匹配以及数据传输流程,基本一致。投屏模块的核心实现在于把握投屏的最基本的几个流程:初始化 → 搜索设备 →(返回设备列表)→ 连接设备 → (返回连接监听) → 开始投屏 → (返回投屏状态回调) → 停止投屏 → 断开连接。


初始化在前面已经提到过了,然后就是基本的三大回调:


搜索设备回调


连接状态回调


投屏状态回调


在PolyvScreencastManager中已经实现三大回调监听,然后经过转发到PolyvIUIUpdateListener,把这三大回调状态分割成不同的状态码,回调到上层。


public interface PolyvIUIUpdateListener {


int STATE_SEARCH_SUCCESS = 1;//搜索成功


int STATE_SEARCH_ERROR = 2;//搜索失败


int STATE_SEARCH_NO_RESULT = 3;//搜索设备无结果


int STATE_CONNECT_SUCCESS = 10;//链接成功


int STATE_DISCONNECT = 11;// 连接断开


int STATE_CONNECT_FAILURE = 12;// 连接失败


//下面是投屏状态,如播放暂停完成等


int STATE_PLAY = 20;


int STATE_PAUSE = 21;


int STATE_COMPLETION = 22;


int STATE_STOP = 23;


int STATE_SEEK = 24;


int STATE_POSITION_UPDATE = 25;


int STATE_PLAY_ERROR = 26;


int STATE_LOADING = 27;


int STATE_INPUT_SCREENCODE = 28;


int RELEVANCE_DATA_UNSUPPORT = 29;


void onUpdateState(int state, Object object);


void onUpdateText(String msg);


}


在调用screencastManager.browse/stopBrowse ()时候就会开始/停止搜索。我们可以看一下搜索设备回调,返回了 resultCode,是里面解析了各个 resultCode 对应的含义,并将其通过 handler 回调到主线程。包括IConnectListener、ILelinkPlayerListener 也是如此,这两个就不作展开。


//PolyvScreencastManager.java


/


投屏搜索监听


/


private IBrowseListener mBrowseListener = new IBrowseListener() {


@Override


public void onBrowse(int resultCode, List list) {


PolyvCommonLog.d(TAG, "onSuccess size:" + (list == null ? 0 : list.size()));


mInfos = list;


if (resultCode == IBrowseListener.BROWSE_SUCCESS) {


//...


if (null != mUIHandler) {


// 发送文本信息


mUIHandler.sendMessage(buildTextMessage(buffer.toString()));


if (mInfos.isEmpty()) {


mUIHandler.sendMessage(buildStateMessage(PolyvIUIUpdateListener.STATE_SEARCH_NO_RESULT));


} else {


mUIHandler.sendMessage(buildStateMessage(PolyvIUIUpdateListener.STATE_SEARCH_SUCCESS));


}


}


}


} else {


if(resultCode == IBrowseListener.BROWSE_STOP){


return;


}


if (null != mUIHandler) {


// 发送文本信息


PolyvCommonLog.d(TAG, "browse error:Auth error");


String text = "";


if(resultCode == IBrowseListener.BROWSE_ERROR_AUTH){


text = "授权失败";


} else if(resultCode == IBrowseListener.BROWSE_ERROR_AUTH_TIME){


text = "授权失败次数超限";


} else {


text = "搜索错误";


}


mUIHandler.sendMessage(buildTextMessage(text));


mUIHandler.sendMessage(buildStateMessage(PolyvIUIUpdateListener.STATE_SEARCH_ERROR));


}


}


}


};


/


投屏连接状态监听


/


private IConnectListener mConnectListener = new IConnectListener() {


@Override


public void onConnect(final LelinkServiceInfo serviceInfo, final int extra) {


}


@Override


public void onDisconnect(LelinkServiceInfo serviceInfo, int what, int extra) {


}


};


/*


投屏播放监听


*/


private ILelinkPlayerListener mPlayerListener = new ILelinkPlayerListener() {


@Override


public void onLoading() {


}


@Override


public void onStart() {


}


@Override


public void onPause() {


}


//。。。省略


};


2.2.3 视频播放


播放视频投屏主要是通过playNetMedia方法。其中通过setType和setUrl设置流媒体的类型和流媒体地址。从下面的代码中就可以看出其投屏的API,实际上是推送模式,把流媒体地址传输到接收端去解析播放的。


//PolyvScreencastManager.java


public void playNetMedia(LelinkPlayerInfo lelinkPlayerInfo, String playPath, int type, String screenCode, int seconds) {


currentPlayPath = playPath;


lelinkPlayerInfo.setType(type);


lelinkPlayerInfo.setUrl(playPath);


String userAgent = "PolyvAndroidScreencast-lelink" + BuildConfig.VERSION_NAME;


lelinkPlayerInfo.setHeader("{\"user-agent\":\" " + userAgent + "\"}");


lelinkPlayerInfo.setLoopMode(LelinkPlayerInfo.LOOP_MODE_DEFAULT);


lelinkPlayerInfo.setOption(IAPI.OPTION_6, screenCode);


lelinkPlayerInfo.setStartPosition(seconds);


mAllCast.playNetMediaWithHeader(lelinkPlayerInfo);


}


在Demo中,他还设置了Header,一般可以通过这个来设置参数,如user-agent等,可以借此跟踪发送端设备参数。但是这个LelinkPlayerInfo 是乐播提供的实体,这种Header的设置,只能在乐联协议中生效!而在DLNA连接中其实是无法生效的。更好的解决方案,是通过playPath中追加参数。


乐联协议:也就是上面说的第三方投屏协议,这是乐播自己修改兼容的投屏协议。


以上基本就是PolyvScreencastManager提供的投屏封装的功能了,关于基本使用可以查看文档。


3. 加密视频投屏


前面有说到,很多视频站都有VIP视频,这些视频往往投屏之后也不支持解析播放。那保利威中的加密视频是如何做到投屏播放的呢?


我们可以追查到PolyvScreencastSearchLayout#loadInfoAndPlay方法,它通过一个PolyvScreencastHelper.getInstance().transformPlayObject()方法,将LelinkPlayerInfo对象转化成为了支持解密的对象。


//PolyvScreencastSearchLayout#loadInfoAndPlay


LelinkPlayerInfo lelinkPlayerInfo = new LelinkPlayerInfo();


PolyvScreencastHelper.getInstance().transformPlayObject(lelinkPlayerInfo, video,


bitrate, playPath, new PolyvScreencastHelper.PolyvCastTransformCallback() {


@Override


public void onSucceed(Object object, String newPlayPath) {


PolyvCommonLog.d(TAG, "cast: " + newPlayPath);


int videoPosition = screencastStatusLayout.getCurrentPlayPosition();


play((LelinkPlayerInfo) object, newPlayPath, bitrate, videoPosition);


screencastStatusLayout.resetBitRateView(bitrate);


}


@Override


public void onFailed(Throwable e) {


}


});


}


});


无疑这个也是通过乐联协议去匹配的。乐播的文档中也提供了接口


lelinkPlayerInfo.setAesKey(String key)


lelinkPlayerInfo.setAesIv(String iv)


那么一个加密视频的播放,往往就需要在发送端和接收端都要去做一定的兼容,或者直接使用这种第三方SDK提供接口,通过约定的加解密协议方式,去对视频进行解密,然后再渲染播放。


4. 扩展:WifiDisplay介绍


前面说到的投屏分为Miracast和DLNA。上面一直说的都是DLNA的推送模式,那么关于镜像模式又是如何实现的呢?


镜像投屏,核心技术原理和WifiDisplay有关。它的本质和DLNA其实相似,都是建立连接然后传输数据,只是这里的数据是屏幕数据,数据量和交互都比较大,所以形成了一套协议方案。


WifiDIsplay涉及的技术和协议比较多,包括了WIFI P2P技术、RTSP及RTP技术、流媒体技术以及音视频编解码相关的技术等等。


我们可以通过 Wi-Fi 直连创建点对点连接,然后在这个基础上从传输文件到传输音视频。大致的原理就是将Source端(发送端)的音视频数据投屏到Sink端(接收端)。


以上可以简单拆分为几个过程:


1、设备(Source/Sink端)发现彼此:实际上属于P2P Device的彼此发现(涉及到WifiP2pManager.discoverPeers + (WifiP2pService) )


2、发起connect:WFD支持能力的协商,如双方设备支持的分辨率,还有会话的建立(WFD Capalibility Negotiation + WFD Session Establish)


3、Source端的Vedio/Audio 的capture 以及 encoder:(涉及到 Vedio Driver + Audio driver + Audio Capture)


4、上面的音视频数据从Soure端到Sink端。


看似做起来有点麻烦,那么能使用第三方的SDK吗?可以的,就是乐播他们要收费,所以不做探究。


-----------------------------------------------------------------------------------------------------------------------------------------------------------


作者:白帽子耗子


链接:


来源:简书


著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章
|
5天前
|
IDE Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【9月更文挑战第27天】在移动应用开发的世界中,Android和iOS是两个主要的操作系统平台。每个系统都有其独特的开发环境、工具和用户群体。本文将深入探讨这两个平台的关键差异点,并分析这些差异如何影响应用的性能、用户体验和最终的市场表现。通过对比分析,我们将揭示选择正确的开发平台对于确保项目成功的重要作用。
|
2天前
|
开发框架 移动开发 Android开发
安卓与iOS开发中的跨平台解决方案:Flutter入门
【9月更文挑战第30天】在移动应用开发的广阔舞台上,安卓和iOS两大操作系统各自占据半壁江山。开发者们常常面临着选择:是专注于单一平台深耕细作,还是寻找一种能够横跨两大系统的开发方案?Flutter,作为一种新兴的跨平台UI工具包,正以其现代、响应式的特点赢得开发者的青睐。本文将带你一探究竟,从Flutter的基础概念到实战应用,深入浅出地介绍这一技术的魅力所在。
18 7
|
5天前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台解决方案
【9月更文挑战第27天】在移动应用开发的广阔天地中,安卓和iOS两大操作系统如同双子星座般耀眼。开发者们在这两大平台上追逐着创新的梦想,却也面临着选择的难题。如何在保持高效的同时,实现跨平台的开发?本文将带你探索跨平台开发的魅力所在,揭示其背后的技术原理,并通过实际案例展示其应用场景。无论你是安卓的忠实拥趸,还是iOS的狂热粉丝,这篇文章都将为你打开一扇通往跨平台开发新世界的大门。
|
2天前
|
缓存 Java Linux
探索安卓开发:从新手到专家的旅程
【9月更文挑战第30天】在这篇文章中,我们将一起踏上一段激动人心的旅程,探索安卓开发的广阔世界。无论你是刚入门的新手,还是希望提升技能的开发者,本文都将为你提供宝贵的知识和指导。我们将深入探讨安卓开发的基础知识、关键概念、实用工具和最佳实践,帮助你在安卓开发领域取得更大的成功。让我们一起开启这段精彩的旅程吧!
|
3天前
|
监控 安全 Java
Kotlin 在公司上网监控中的安卓开发应用
在数字化办公环境中,公司对员工上网行为的监控日益重要。Kotlin 作为一种基于 JVM 的编程语言,具备简洁、安全、高效的特性,已成为安卓开发的首选语言之一。通过网络请求拦截,Kotlin 可实现网址监控、访问时间记录等功能,满足公司上网监控需求。其简洁性有助于快速构建强大的监控应用,并便于后续维护与扩展。因此,Kotlin 在安卓上网监控应用开发中展现出广阔前景。
7 1
|
7天前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
|
9天前
|
监控 Android开发 iOS开发
深入探索安卓与iOS的系统架构差异:理解两大移动平台的技术根基在移动技术日新月异的今天,安卓和iOS作为市场上最为流行的两个操作系统,各自拥有独特的技术特性和庞大的用户基础。本文将深入探讨这两个平台的系统架构差异,揭示它们如何支撑起各自的生态系统,并影响着全球数亿用户的使用体验。
本文通过对比分析安卓和iOS的系统架构,揭示了这两个平台在设计理念、安全性、用户体验和技术生态上的根本区别。不同于常规的技术综述,本文以深入浅出的方式,带领读者理解这些差异是如何影响应用开发、用户选择和市场趋势的。通过梳理历史脉络和未来展望,本文旨在为开发者、用户以及行业分析师提供有价值的见解,帮助大家更好地把握移动技术发展的脉络。
|
13天前
|
开发工具 Android开发 iOS开发
掌握安卓与iOS应用开发:关键技术与未来展望
本文深入探讨了安卓和iOS平台下的应用开发技术,重点比较了两大平台的架构、开发工具和市场策略。通过分析最新的技术趋势和开发者社区的反馈,文章为读者提供了一个全面的对比视角,旨在帮助开发者做出更明智的平台选择和开发决策。
|
7天前
|
存储 开发工具 Android开发
使用.NET MAUI开发第一个安卓APP
【9月更文挑战第24天】使用.NET MAUI开发首个安卓APP需完成以下步骤:首先,安装Visual Studio 2022并勾选“.NET Multi-platform App UI development”工作负载;接着,安装Android SDK。然后,创建新项目时选择“.NET Multi-platform App (MAUI)”模板,并仅针对Android平台进行配置。了解项目结构,包括`.csproj`配置文件、`Properties`配置文件夹、平台特定代码及共享代码等。
|
8天前
|
安全 Java Android开发
掌握安卓与iOS应用开发中的关键技术
本文深入探讨了安卓和iOS平台上应用开发的关键性技术,包括平台特性、开发工具选择、性能优化技巧及跨平台开发的可行性分析。通过对比两种平台的开发环境与实践案例,旨在为开发者提供全面的视角以理解和把握移动应用开发的核心技术。无论是安卓的Java与Kotlin之争,还是iOS的Swift语言革命,本文都将一一解析其优势与应用场景,帮助开发者在技术选型上有更明智的决策。此外,文章还将触及到当前流行的跨平台框架如React Native和Flutter,评估它们在项目实施中的实用性和限制,为有意进行多平台同步开发的团队提供参考。通过对这些关键技术的梳理,本文期望能够启发开发者深化对移动平台开发的理解,并
下一篇
无影云桌面