Android开发之无线遥控器
最近弄了一个UDP/TCP的小东西,主要需要实现的功能如下(服务器端):
1、基于局域网
2、服务器端网络接口为无线与有线
3、服务器端接收到客户端的数据需要模拟按键进行处理
4、开机自启动
5、使用UDP进行连接,TCP进行通讯
基于以上几点,我们开始分析:
1.需要获取当前的网络IP地址,这里枚举了本机所有的网络地址,只返回ipv4
1 public String getAddressIP() { 2 //检查网络是否连接 3 while (!isNetWorkConnected()) { 4 //等待网络连接 5 } 6 ip = getLocalIpAddress(); 7 return ip; 8 } 9 10 public String getLocalIpAddress() { 11 String address = null; 12 try { 13 for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { 14 NetworkInterface intf = en.nextElement(); 15 for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) { 16 InetAddress inetAddress = enumIpAddr.nextElement(); 17 if (!inetAddress.isLoopbackAddress()) {//127.0.0.1 18 address = inetAddress.getHostAddress().toString(); 19 //ipV6 20 if(!address.contains("::")){ 21 return address; 22 } 23 } 24 } 25 } 26 } catch (SocketException ex) { 27 Log.e("getIpAddress Exception", ex.toString()); 28 } 29 return null; 30 } 31 32 private boolean isNetWorkConnected() { 33 // TODO Auto-generated method stub 34 try{ 35 connectivity = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 36 if(connectivity != null){ 37 netWorkinfo = connectivity.getActiveNetworkInfo(); 38 if(netWorkinfo != null && netWorkinfo.isAvailable()){ 39 if(netWorkinfo.getState() == NetworkInfo.State.CONNECTED){ 40 isConnected = true; 41 return true; 42 } 43 } 44 } 45 }catch(Exception e){ 46 Log.e("UdpService : ",e.toString()); 47 return false; 48 } 49 return false; 50 }
2.获得IP之后,创建一个多播组
1 try { 2 3 while(ip == null){ 4 ip = getAddressIP(); 5 } 6 7 inetAddress = InetAddress.getByName(BROADCAST_IP);//多点广播地址组 8 multicastSocket = new MulticastSocket(BROADCAST_PORT);//多点广播套接字 9 multicastSocket.setTimeToLive(1); 10 multicastSocket.joinGroup(inetAddress); 11 12 } catch (UnknownHostException e) { 13 e.printStackTrace(); 14 } catch (IOException e) { 15 e.printStackTrace(); 16 }
这里设置一组特殊网络地址作为多点广播地址,第一个多点广播地址都被看作是一个组,当客户端需要发送接收广播信息时,加入该组就可以了。
IP协议为多点广播提供这批特殊的IP地址,这些IP地址范围是224.0.0.0---239.255.255.255,其中224.0.0.0为系统自用。
下面BROADCAST_IP是自己声明的一个String类型的变量,其范围也是前面所说的IP范围,比如BROADCAST_IP="224.224.224.224"。
1 private static int BROADCAST_PORT = 1234; 2 private static int PORT = 4444; 3 private static String BROADCAST_IP = "224.0.0.1";
3.服务端开始发送本机IP地址广播,如果网络断开,则结束掉此线程,并设置标识
1 public class UDPBoardcastThread extends Thread { 2 public UDPBoardcastThread() { 3 this.start(); 4 } 5 6 @Override 7 public void run() { 8 DatagramPacket dataPacket = null; 9 //将本机的IP地址放到数据包里 10 byte[] data = ip.getBytes(); 11 dataPacket = new DatagramPacket(data, data.length, inetAddress, BROADCAST_PORT); 12 //判断是否中断连接了 13 while (isNetWorkConnected()) { 14 try { 15 multicastSocket.send(dataPacket); 16 Thread.sleep(5000); 17 Log.i("UDPService:","再次发送ip地址广播"); 18 } catch (Exception e) { 19 e.printStackTrace(); 20 } 21 } 22 isConnected = false; 23 Message msg = new Message(); 24 msg.what = 0x0001; 25 mHandler01.sendMessage(msg); 26 27 } 28 }
4.新开一个线程,等待客户端连接,使用TCP进行通讯
1 new Thread() { 2 @Override 3 public void run() { 4 try { 5 //建立一个线程池,每次收到一个客户端,新开一个线程 6 mExecutorService = Executors.newCachedThreadPool(); 7 Socket client = null; 8 mList.clear(); 9 while (isConnected) { 10 11 client = server.accept(); 12 //把客户端放入客户端集合中 13 if (!connectOrNot(client)) { 14 mList.add(client); 15 Log.i("UDPService","当前连接数:"+mList.size()); 16 } 17 mExecutorService.execute(new Service(client)); 18 } 19 //释放客户端 20 for(int i = 0 ; i < mList.size() ; i++) 21 mList.get(i).close(); 22 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } 26 } 27 }.start();
5.新开一个客户端的线程,处理客户端发送过来的数据等
1 //客户端线程,组成线程池 2 class Service implements Runnable { 3 private Socket socket; 4 private BufferedReader in = null; 5 private String msg = ""; 6 7 public Service(Socket socket) { 8 this.socket = socket; 9 } 10 11 @Override 12 public void run() { 13 try { 14 in = new BufferedReader(new InputStreamReader(socket.getInputStream())); 15 //等待接收客户端发送的数据 16 while (isConnected) { 17 18 if ((msg = in.readLine()) != null) { 19 20 // 创建一个Instrumentation对象,调用inst对象的按键模拟方法 21 Instrumentation inst = new Instrumentation(); 22 try{ 23 int codeKey = Integer.parseInt(msg); 24 //codeKey对应键值参照KeyCodeTable.txt文件,在客户端中实现 25 inst.sendKeyDownUpSync(codeKey); 26 27 //发送回执 28 this.sendmsg(socket); 29 }catch(Exception ex){ 30 ex.printStackTrace(); 31 } 32 33 } 34 } 35 } catch (Exception e) { 36 e.printStackTrace(); 37 } 38 } 39 40 private void sendmsg(Socket socket2) { 41 // TODO Auto-generated method stub 42 PrintWriter pout = null; 43 44 try { 45 pout = new PrintWriter(new BufferedWriter( 46 new OutputStreamWriter(socket2.getOutputStream())), true); 47 pout.println("I am ok"); 48 } catch (IOException e) { 49 // TODO Auto-generated catch block 50 e.printStackTrace(); 51 } 52 53 } 54 55 }
这里使用了Instrumentation()对象来模拟按键的处理,在实际使用中,效率还行,没有很严重的延时,若真有延时,感觉也是网络方面的。
使用了socket.getInputStream()与socket.getOutputStream()方法来进行socket数据的接收与发送
6.最后新开一个Handler对网络断开时进行处理,也可以监听系统网络变化的广播,有时间研究下service的生命周期
1 private Handler mHandler01 = new Handler(){ 2 3 @Override 4 public void handleMessage(Message msg) { 5 // TODO Auto-generated method stub 6 super.handleMessage(msg); 7 switch(msg.what){ 8 //连接失败 9 case 0x0001: 10 initData(); 11 break; 12 } 13 } 14 15 };
7.开机自启动,继承BroadcastReceiver,监听系统开机广播就ok了,记得在AndroidManifest.xml文件中声明BOOT_COMPLETED属性
1 if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED")){ 2 Intent intent2 = new Intent(context, UdpService.class); 3 context.startService(intent2); 4 }
8.还有一个问题,如果我们就这样直接编译,输出apk到电视中,会出现权限不足的error,原因是apk不是系统应用,只有uid为system id才可以去模拟按键事件,所以在
AndroidManifest.xml中加上android:sharedUserId="android.uid.system",以及<uses-permission android:name="android.permission.INJECT_EVENTS" />
再编写Android.mk,最后在android源码中使用mm命令编译apk,这样就ok了。
服务器端的流程差不多是这样了,附上完整源码,包含服务器端与客户端Demo:
http://download.csdn.net/detail/u012062785/9684842
thread与runnable的区别:https://www.oschina.net/question/565065_86563
转载于:https://www.cnblogs.com/pngcui/p/6068983.html
Android开发之无线遥控器相关推荐
- Android环境搭建和Android HelloWorld—Android开发环境搭建
Android_Android开发环境搭建-搭建Android的开发环境 1.我考虑先下载JDK7.0,在JDK的安装中,考虑一般SDK都是向上兼容的,于是选择了最高的版本7.0 这里是我总结的详细的 ...
- java安卓开发工具_推荐几个非常实用的Android开发工具
工欲善其事,必先利其器.我们进行Android开发也要有好的开发工具辅助才能更好更高效的完成各种开发,为用户提供更实用的应用程序.本文就为大家推荐几个非常实用的Android开发工具,及几个常用的编辑 ...
- android 网络编程实现,Android开发使用HttpURLConnection进行网络编程详解【附源码下载】...
本文实例讲述了Android开发使用HttpURLConnection进行网络编程.分享给大家供大家参考,具体如下: --HttpURLConnection URLConnection已经可以非常方便 ...
- linux 浏览器源码下载,Android开发:图片浏览器源码
Android 图片浏览器源码,是你学习Android很好的例子,希望对你的学习有帮助. main.xml android:layout_width="fill_parent" a ...
- 2017-2018-2 20165236 实验四《Android开发基础》实验报告
2017-2018-2 20165236 实验四<Android开发基础>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:郭金涛 ...
- Android开发权威指南(第2版)新书发布
<Android 开发权威指南(第二版)>是畅销书<Android开发权威指南>的升级版,内容更新超过80%,是一本全面介绍Android应用开发的专著,拥有45 章精彩内容供 ...
- indows上的android开发环境软件架构5
(二)实验要求: ? 修改按下button 显示的内容中添加上自己的学号姓名: ? 添加一个按钮,按钮名称为"退出",并且为这个按钮添加事件代码,使得点击这个按钮后退 出程序.事件 ...
- 折叠屏就要来了,适配逼死 Android 开发?
1. 异型屏还没适配好,折叠屏就要来了,Android 的碎片化,让开发者又多掉了不少头发. 北京时间 11 月 8 日,三星在旧金山向开发者发布了一款可折叠屏幕手机.并表示,新技术需要开发者调整其 ...
- 《ArcGIS Runtime SDK for Android开发笔记》——(6)、基于Android Studio的ArcGIS Android工程结构解析...
1.前言 Android Studio 是第一个Google官方的 Android 开发环境.其他工具,例如 Eclipse,在 Android Studio 发布之前已经有了大规模的使用.为了帮助开 ...
最新文章
- redhat nginx php mysql_redhat7+nginx+mysql+php
- php里isset的属性,测试PHP中变量是否存在的最佳方法;isset()显然已损坏
- 会计行业被计算机取代马云,会计人:为什么我神烦“人工智能取代说”?
- 使用RMAN传输表空间复制数据
- 熊猫分发_熊猫下降列和行
- 对于scanf的新理解
- MVC学习笔记三:WebGrid控件的简单使用
- 美团斗鱼百度笔试概录
- 白话区块链~Pow,PoS,DPos
- 使用SSH工具链接本地虚拟机
- 虚拟机win 7 上安装VWware Tools提示升级系统到SP1
- win7电脑怎样修改环境变量
- 【python学习】python的面向对象编程
- kettle报错 Driver class ‘org.gjt.mm.mysql.Driver‘ could not be found, make sure the ‘MySQL‘ driver
- BOXI3 SDK 检索所有使用了某个universe object的报表
- 栈和队列的区别与栈和堆的区别
- java.lang.RuntimeException: java.lang.RuntimeException: org.codehaus.plexus.component.repository.exc
- 【吴恩达机器学习笔记】第十一章 机器学习系统的设计
- 特效师新人作品指引。
- UL1017是什么标准?吸尘器UL1017报告
热门文章
- 易语言发信服务器没有反应,还不会使用易语言连接发信服务器发送邮件的朋友看过来...
- [讲座论坛] 经济林之核桃类
- mysql好考还是office好考_计算机二级最好考哪个 office难考吗
- 《孤独六讲》-蒋勋 摘录2
- Microsoft Office Word 2003 稿纸加载项卸载不了 怎么处理
- cache相关概念及工作原理介绍
- Unity 动态生成球体模型
- 饿了么多人订餐时计算费用bug(饿了么商品促销优惠金额分摊计算规则)
- 华为云 · 云桌面 Workspace(介绍)
- jquery日历插件 途牛_11个实用jQuery日历插件