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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 开发 Android 空调遥控器涉及以下几个方面的工作: 1. 界面设计:首先要设计一个用户友好的界面,确保用户能够轻松理解和使用遥控器功能。界面应该包括温度调节、风速选择、模式选择、定时开关机等功能。 2. 通信协议:需要与空调进行通信,以发送控制指令和接收状态信息。可以使用红外线技术或 Wi-Fi 等无线技术实现通信。对于红外线通信,需要调研并找到特定空调品牌和型号的红外线控制指令集。对于 Wi-Fi 通信,需要设计与空调通信的网络协议。 3. 状态更新和同步:在用户调节遥控器参数后,需要及时将设置的参数发送给空调,并确保空调收到指令后做出相应的操作。同时,还需要定期从空调读取当前的工作状态,例如温度、风速等,并更新到遥控器界面上,便于用户实时监控和调节。 4. 兼容性考虑:考虑到不同品牌和型号的空调具有不同的控制方式和功能设置,开发需要充分考虑兼容性。可以通过提供用户可自定义的参数配置功能,让用户可以在遥控器上选择对应的空调品牌和型号,以及支持的功能,从而适配各种空调设备。 5. 其他功能增强:最后,可以考虑为遥控器增加一些实用的功能,例如支持语音控制、场景模式设置、设备联动等,以提升用户体验。 总体而言,开发 Android 空调遥控器需要通过界面设计、通信协议、状态更新、兼容性考虑和功能增强等多个方面的工作来实现。这些工作需要结合具体的需求和技术要求进行设计和开发,最终提供给用户一个方便、易用且功能丰富的空调遥控器应用。 ### 回答2: Android空调遥控器开发是基于Android操作系统的智能设备遥控应用程序。该应用程序可以与用户的空调设备进行无线连接,通过无线信号与空调设备进行通信,并模拟空调遥控器的功能,实现远程控制空调设备的操作。 在进行Android空调遥控器开发时,首先需要实现与空调设备的无线连接功能。可以利用蓝牙、红外线或者Wi-Fi等通信方式实现设备连接。通过与空调设备建立连接之后,可以获取设备的状态和参数信息,从而实现对空调设备的遥控操作。用户可以通过触摸屏幕上的操作按钮或者滑动条,调节空调的温度、风速、模式等参数,同时也可以进行定时、定位、控制多个空调等特殊功能。 在开发过程中,需要使用Android开发工具,如Android Studio,并结合空调设备的通信协议,编写相应的代码实现连接和与空调设备的通信。此外,还需要设计应用程序的用户界面,包括各种操作按钮和界面布局等。应用程序还应该具备良好的用户体验,保证操作的简单易懂和流畅性能。 Android空调遥控器开发可以带来许多便利性和舒适性。用户可以随时随地通过手机对家中的空调设备进行远程控制,无需亲临现场进行操作。而且可以利用智能手机的多媒体功能,进行更加个性化的设置和控制。 总之,Android空调遥控器开发是一项基于Android操作系统的智能设备遥控应用程序的开发工作。通过与空调设备的无线连接和通信,实现对空调设备的遥控操作,提供更加方便和舒适的使用体验。 ### 回答3: 开发 Android 空调遥控器是为了实现通过手机控制空调的功能。首先,我们需要设计一个用户友好的界面,包括一些基本的控制按钮,如开、关、调温、调风等。通过与空调的通信接口,我们可以将用户在手机上的操作指令传输到空调设备上。 在开发过程中,我们需要注意以下几点: 1. 兼容性:确保该遥控器应用程序能够支持主流的 Android 手机和智能设备。 2. 连接性:通过蓝牙、Wi-Fi 或红外线技术,实现手机与空调之间的无线连接。 3. 控制功能:在应用程序中提供各种必要的控制功能,如调节温度、调整风向、设置定时功能等。 4. 数据传输安全性:确保用户在使用手机遥控器时的数据传输是安全的,防止他人恶意干扰。 5. 自定义设置:为用户提供自定义选项,使他们能够根据自己的需求进行个性化设置,如添加多个设备、命名等。 6. 易于使用:设计简单直观的用户界面,使用户能够轻松地理解和操作。 通过上述开发,用户将能够通过他们的 Android 手机方便地操控空调,无需再去寻找遥控器或靠近空调设备。这将为用户带来更多的便利性和舒适感。随着智能家居的发展,这样的应用程序也能与其他智能设备进行连接,实现更智能化的家庭控制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值