智能电视局域网手机遥控实现

来源:互联网 发布:国内云计算发展现状 编辑:程序博客网 时间: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
原创粉丝点击