智能电视局域网手机遥控实现
来源:互联网 发布:国内云计算发展现状 编辑:程序博客网 时间:2024/06/09 23:54
好久没写博客了,今天来写一篇之前实现过的,算是温故而知新吧。
先说下功能:在局域网内,手机来遥控智能电视,都是基于Android系统的,有些手机自带红外线功能,可以不用网络连接,此处不讨论
(此文只讨论手机端实现)
手机与TV之前通过局域网通信,先要建立Socket连接,但手机怎么知道电视的 IP呢?
解决方案有多种,如果只有一个路由器,可以采用UDP广播来实现,如果跨路由器了,这种方式不可行,因为路由器隔离广播,可以采用遍历扫描指定端口方式
此种采用UDP广播来实现手机找到电视IP地址,另一种方式,可以参照 局域网内扫描打开指定端口IP(请点击我),有时间我再把Android手机扫描指定端口整理下
先说下简单流程:
接下来,上代码
手机发UDP广播:
public void sendData(DatagramSocket ds, byte[] str)throws UnknownHostException {if (ds.isClosed()) {return;}byte[] buf = new byte[1000];DatagramPacket packet = new DatagramPacket(buf, buf.length);//// 创建要发送的数据包DatagramPacket dp = new DatagramPacket(str, str.length,InetAddress.getByName("255.255.255.255"),NetTools.RECV_BCAST_PORT);// 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号try {ds.send(dp);Log.i(TAG, dp.toString());ds.receive(packet);String tem = new String(buf);Log.i(TAG, "get server string =" + tem);NetTools.SERVER_IP = packet.getAddress().getHostAddress();Log.i(TAG, "get server ip =" + NetTools.SERVER_IP);ds.close();ds = null;sendBroadcast(new Intent(NetTools.ACTION_FOUND_IP));timer.cancel();timer = null;System.gc();stopSelf();} catch (IOException e) {Log.i(TAG, "IOException");// ds.close();// stopSelf();// Intent mIntent = new Intent(this, NetServer.class);// startService(mIntent);e.printStackTrace();}// ds.close();}发UPD广播后,TV收到该广播,返回一个数据包,解析该数据包,获取 TV IP
有了 TV IP,建立Socket进行通信:
class MyReceiver extends BroadcastReceiver {public MyReceiver() {IntentFilter filter = new IntentFilter();filter.addAction(NetTools.ACTION_FOUND_IP);registerReceiver(this, filter);}@Overridepublic void onReceive(Context context, Intent intent) {// TODO Auto-generated method stubtv.setText(NetTools.SERVER_IP);if (thread != null) {thread = null;}thread = new ClientThread();thread.start();}}// 内部类,新线程class ClientThread extends Thread {public OutputStream out;public InputStream in;@Overridepublic void run() {// 建立连接通道,取出双向流try {mSocket = new Socket(NetTools.SERVER_IP,NetTools.RECV_INFO_PORT);mSocket.setKeepAlive(true);mSocket.setSoTimeout(NetTools.BACKLOG * 1000);out = mSocket.getOutputStream();// 取出双向流in = mSocket.getInputStream();if (mSocket.isConnected()) {NetTools.isAlive = true;// tv.setText("mSocket is connect,ip=" +// NetTools.SERVER_IP);Message msg = Message.obtain(mHandler,NetTools.MSG_UP_TEXT, "mSocket is connect,ip="+ NetTools.SERVER_IP);msg.sendToTarget();}if (mHeardThread != null) {mHeardThread = null;}mHeardThread = new HeardThread();mHeardThread.start();byte[] buff = new byte[8];while (NetTools.isAlive) {sb.delete(0, sb.length());try {in.read(buff);for (int i = 0; i < buff.length; i++) {sb.append(buff[i]);sb.append(":");}Message msg = Message.obtain(mHandler,NetTools.MSG_UP_TEXT,"msocket is alive,get packet:" + sb.toString());msg.sendToTarget();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();Message msg = Message.obtain(mHandler,NetTools.MSG_UP_TEXT,"Socket read time out,close the socket");msg.sendToTarget();NetTools.isAlive = false;try {mSocket.close();mHeardThread = null;} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}// try {// sleep(NetTools.BACKLOG * 1000);// } catch (InterruptedException e) {// // TODO Auto-generated catch block// e.printStackTrace();// }}} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e2) {// TODO Auto-generated catch blocke2.printStackTrace();}Log.i(TAG, "ClientThread stop");}}
保持心跳,(有些路由器可能会断开长时间没连接的Socket,心跳机制就是为了防止断开的)
class HeardThread extends Thread {@Overridepublic void run() {// TODO Auto-generated method stubsuper.run();while (NetTools.isAlive) {if (heard_flag) {Log.i(TAG, "HeardThread run::sendHeardPacket");sendHeardPacket();try {sleep(NetTools.BACKLOG * 1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}} else {Log.i(TAG, "HeardThread sendHeardPacket pause");try {synchronized (mHeardThread) {wait();}} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}Log.i(TAG, "end heardthread");}}
遥控操作:
public void doClick(View v) {int keyCode = 0;switch (v.getId()) {case R.id.btn_up: {keyCode = KeyEvent.KEYCODE_DPAD_UP;}break;case R.id.btn_down: {keyCode = KeyEvent.KEYCODE_DPAD_DOWN;}break;case R.id.btn_left: {keyCode = KeyEvent.KEYCODE_DPAD_LEFT;}break;case R.id.btn_right: {keyCode = KeyEvent.KEYCODE_DPAD_RIGHT;}break;case R.id.btn_ok: {keyCode = KeyEvent.KEYCODE_ENTER;}break;case R.id.btn_power: {keyCode = KeyEvent.KEYCODE_POWER;}break;case R.id.btn_mute: {// keyCode = KeyEvent.KEYCODE_VOLUME_MUTE;keyCode = 164;}break;case R.id.btn_menu: {keyCode = KeyEvent.KEYCODE_MENU;}break;case R.id.btn_ch_up: {// keyCode = KeyEvent.KEYCODE_CHANNEL_UP;keyCode = 166;}break;case R.id.btn_ch_down: {// keyCode = KeyEvent.KEYCODE_CHANNEL_DOWN;keyCode = 167;}break;case R.id.btn_home: {keyCode = KeyEvent.KEYCODE_HOME;}break;case R.id.btn_back: {keyCode = KeyEvent.KEYCODE_BACK;}break;case R.id.btn_voice_up: {keyCode = KeyEvent.KEYCODE_VOLUME_UP;}break;case R.id.btn_voice_down: {keyCode = KeyEvent.KEYCODE_VOLUME_DOWN;}break;case R.id.btn_connect: {Intent mIntent = new Intent(this, NetServer.class);startService(mIntent);return;}case R.id.btn_finish: {this.finish();return;}}sendKey(keyCode);}public void sendKey(int keyCode) {if (mSocket == null) {Log.i(TAG, "mSocket==null");return;}if (mSocket.isClosed() || !mSocket.isConnected()) {Log.i(TAG, "mSocket is not connected");return;}if (thread == null) {Log.i(TAG, "thread is null");return;}// 暂停心跳包发送heard_flag = false;synchronized (mHeardThread) {mHeardThread.notify();}try {value[0] = (byte) 02;value[1] = (byte) 00;value[2] = (byte) 00;value[3] = (byte) 00;value[4] = (byte) keyCode;value[5] = (byte) 00;value[6] = (byte) 00;value[7] = (byte) 00;thread.out.write(value, 0, value.length);thread.out.flush();// Log.i(TAG, new String(value));sb.delete(0, sb.length());sb.append("send packet:");for (int i = 0; i < value.length; i++) {sb.append(value[i]);sb.append(":");}Message msg = Message.obtain(mHandler, NetTools.MSG_UP_TEXT,sb.toString());msg.sendToTarget();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}mHandler.postDelayed(new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubheard_flag = true;if (mHeardThread == null) {return;}synchronized (mHeardThread) {mHeardThread.notify();}}}, NetTools.BACKLOG * 1000);sb.delete(0, sb.length());}public void sendHeardPacket() {if (mSocket == null) {Message msg = Message.obtain(mHandler, NetTools.MSG_UP_TEXT,"mSocket is null");msg.sendToTarget();return;}if (mSocket.isClosed() || !mSocket.isConnected()) {Message msg = Message.obtain(mHandler, NetTools.MSG_UP_TEXT,"mSocket is not connect");msg.sendToTarget();return;}if (thread == null) {Message msg = Message.obtain(mHandler, NetTools.MSG_UP_TEXT,"thread is null");msg.sendToTarget();return;}try {thread.out.write(NetTools.KEEPALIVE, 0, NetTools.KEEPALIVE.length);thread.out.flush();Message msg = Message.obtain(mHandler, NetTools.MSG_UP_TEXT,"send heard packet");msg.sendToTarget();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}sb.delete(0, sb.length());}public void sendValue(byte[] value) {if (mSocket == null || mSocket.isClosed() || !mSocket.isConnected()) {Log.i(TAG, "mSocket is not connected");return;}if (thread == null) {Log.i(TAG, "thread is null");return;}try {thread.out.write(value, 0, value.length);thread.out.flush();Log.i(TAG, new String(value));} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}sb.delete(0, sb.length());}
完整代码下载地:请点击我
0 0
- 智能电视局域网手机遥控实现
- 手机、平板、PC与智能电视实现数据大统一
- 手机一秒变智能遥控器,遥控所有家电
- 手机电视的实现技术
- 智能电视TV开发---手机直播视频客户端与智能电视通信
- 智能电视
- 电脑、手机、投影仪、智能电视相互投屏
- 红外遥控智能小车
- 手机电视
- 通过手机实现远程遥控的方案(资料大派送)
- 【STM32 .Net MF开发板学习-20】蓝牙遥控智能小车(手机模式)
- 【STM32 .Net MF开发板学习-20】蓝牙遥控智能小车(手机模式)
- HI3518E网络摄像机应用于智能车门遥控(RF发射,315接收,手机APP)
- 智能电视TV开发---直播视频客户端结构设计和实现
- 智能电视TV开发---输入框的迭代实现
- 智能电视TV开发---如何实现程序省电
- android,手机 遥控,
- 手机遥控PPT
- HDU5437 结构体排序和优先队列
- C++ 左值、右值、右值引用
- VS2013+QT5.5配置小结
- android shap 画图
- Android fragment解析2
- 智能电视局域网手机遥控实现
- 【数据挖掘结果】大数据企业的汇总信息
- 第18回一般人不能理解Socket的奥妙
- java通用分页工具类
- html乱码/设置html编辑模式/tab设置
- PAT_乙级1021
- java.lang.NoClassDefFoundError: com/google/common/reflect/Invokable
- iOS8开始默认语言有变化
- innodb的redo log以及与binary log的区别