关于 android 投屏技术系列:
一、知识概念
这章主要讲一些基本概念, 那些 DLNA 类库都是基于这些概念来做的,了解这些概念能帮助你理清思路,同时可以提升开发效率,遇到问题也能有个解决问题的清晰思路。
二、手机与tv对接
这部分是通过Cling DLNA类库来实现发现设备的。
内容包括:
- 抽出发现设备所需接口
- 发现设备步骤的实现
- 原理的分析
三、手机与tv通信
这部分也是通过Cling DLNA类库来实现手机对tv的控制。
内容包括:
- 控制设备步骤
- 控制设备代码实现
- 手机如何控制tv
- tv将自己的信息如何通知手机
- 原理的分析
前言
上篇文章,我们聊了投屏技术所需的协议和概念。今天我们来实际操作。
神操作
何为发现设备?
android 手机投屏到 tv盒子 上,首先你要让 tv盒子 跟你的手机在同一个局域网中,然后要让手机能搜索到当前局域网内所有支持投屏的设备(如:tv盒子)这个过程 就是发现设备。
噢了~ 这篇文章分两部分:
action行动前,先分析一下 我们的需求:
- 手机 & tv盒子 都连上局域网
- 手机需要随时监听局域网中支持投屏设备的出现
- 手机跟支持投屏的 tv盒子 建立连接
首先,看 Cling库 的介绍:
Cling它主要由 core 和 support 两个部分构成。
- core: 包含了发现设备部分
- support: 包含的是控制设备部分
今天我们要用到的是 core 部分。
一切准备就绪,大哥,我们开始实现发现设备功能好不好?
不好也得好,就是这么任性,略略略
发现设备功能实现
首先我们要在 manifest 里加上以下权限(网络相关权限):
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
在 Cling 中针对 android 定义了一个 Service 来操作------>AndroidUpnpServiceImpl
它有以下方法:
public UpnpServiceConfiguration getConfiguration();
public ControlPoint getControlPoint();
public ProtocolFactory getProtocolFactory();
public Registry getRegistry();
public Router getRouter();
public IBinder onBind(Intent intent);
public void onDestroy();
不懂没关系。
现在你只需要知道:
- ControlPoint getControlPoint() 获取到控制点,通过控制点执行 search() 方法就可以发现设备了
- 然后就是 我们可以根据需求在 activity 里 bind 或者 unbind AndroidUpnpServiceImpl 这个 Service
接下来我们要在 manifest 里面定义这个 Service
<service android:name="org.fourthline.cling.android.AndroidUpnpServiceImpl"/>
下面是 activity:
public class BrowserActivity extends ListActivity {
private ArrayAdapter<DeviceDisplay> listAdapter;
// 监听设备发现,当一个新设备出现在网络时,会回调它
private BrowseRegistryListener registryListener = new BrowseRegistryListener();
private AndroidUpnpService upnpService;
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
upnpService = (AndroidUpnpService) service;
listAdapter.clear();
// 添加监听
upnpService.getRegistry().addListener(registryListener);
// 添加已知的设备
for (Device device : upnpService.getRegistry().getDevices()) {
registryListener.deviceAdded(device);
}
// 搜索所有的设备
upnpService.getControlPoint().search();
}
public void onServiceDisconnected(ComponentName className) {
upnpService = null;
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
listAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1);
setListAdapter(listAdapter);
// This will start the UPnP service if it wasn't already started
getApplicationContext().bindService(
new Intent(this, AndroidUpnpServiceImpl.class),
serviceConnection,
Context.BIND_AUTO_CREATE
);
}
@Override
protected void onDestroy() {
super.onDestroy();
if (upnpService != null) {
upnpService.getRegistry().removeListener(registryListener);
}
// This will stop the UPnP service if nobody else is bound to it
getApplicationContext().unbindService(serviceConnection);
}
// ...
}
这段代码就实现了两个功能:
- upnpService.getControlPoint().search(); 实现发现设备
- BrowseRegistryListener registryListener;
upnpService.getRegistry().addListener(registryListener);
实现了发现设备监听
其实 就这么简单,<b>但</b>搜索到的 并不是我们想要的结果,我要筛选到支持投屏渲染的设备:
public static final DeviceType DMR_DEVICE_TYPE = new UDADeviceType("MediaRenderer");
/**
* 获取支持投屏的设备
*
* @return 设备列表
*/
@Override
@Nullable
public Collection<Device> getDmrDevices() {
if (Utils.isNull(mUpnpService))
return null;
Collection<Device> devices = upnpService.getRegistry().getDevices(DMR_DEVICE_TYPE);
return devices;
}
噢了~~
点击查看详细代码
(* 详细代码里 做了一些封装)
下面我们进入正式环节-源码分析:
由于文章太长,我分开到下篇文章
网友评论