文章
博客 网店

 Android学习笔记3:UDP广播通信程序


关于android编程的认识不断的在更新,可能很快就会为小编这些菜鸟级文章感到不好意思,呵呵 。

手机远程关机程序终于搞定,为了加深印象也为了与大家分享,抽时间来写这篇文章了。




 
这个是windows上运行的服务程序,它监听PC机的UDP 9998端口,响应两个命令:

1.接收到"SCAN"时给对方发回计算机名称

2.接收到"CLOS"时直接关机

APP界面如下:





现在APP要做的就是:

1.按下[]扫描]按钮时广播发送UDP包"SCAN",并得到回应后将接收信息(也就是计算机名)显示到TextView。并记住对方IP地址。

2.按下[关机]按钮时,向记忆的IP地址发送“CLOS”实现远程关机。

 

首先实现了一个UDP收发功能的类

package cn.chipart.udptst;
 
import android.os.Message;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
 
 class UDPClient extends Thread{
    final static int udpPort = 9998;
    final static String hostIp = "192.168.1.255";//广播地址
    private static DatagramSocket socket = null;
    private static DatagramPacket packetSend, packetRcv;
    private boolean udpLife = true; //接收线程退出标志
    private byte[] msgRcv = new byte[1024]; //接收消息
    private InetAddress remoteAddress = null; //存储对方地址
    public MainActivity.MyHandler uiHandler;//向主UI发送消息的句柄
 
    public UDPClient() {
        super();
    }
 
    //返回udp生命线程因子是否存活
    public boolean isUdpLife() {
        if (udpLife) {
            return true;
        }
 
        return false;
    }
 
    //更改UDP生命线程因子
    public void setUdpLife(boolean b) {
        udpLife = b;
    }
 
    //发送广播消息
    public void sendBroadcast(String msgSend) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                InetAddress hostAddress = null;
 
                try {
                    hostAddress = InetAddress.getByName(hostIp);
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
 
                packetSend = new DatagramPacket(msgSend.getBytes(), msgSend.getBytes().length, hostAddress, udpPort);
 
                try {
                    socket.send(packetSend);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
 
        thread.start();
    }
 
    //回应消息
    public void sendResponse(String msgSend) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                packetSend = new DatagramPacket(msgSend.getBytes(), msgSend.getBytes().length, remoteAddress, udpPort);
 
                try {
                    socket.send(packetSend);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
 
        thread.start();
    }
 
    @Override
    public void run() {
        try
        {
            socket = new DatagramSocket();
            socket.setSoTimeout(3000);//设置超时为3s
        } catch (SocketException e)
        {
            e.printStackTrace();
        }
        packetRcv = new DatagramPacket(msgRcv, msgRcv.length);
        while (udpLife)
        {
            try
            {
                socket.receive(packetRcv);
                String RcvMsg = new String(packetRcv.getData(), packetRcv.getOffset(), packetRcv.getLength());
 
                remoteAddress = packetRcv.getAddress();//获取对方IP保存到remoteAddress
 
                //发送消息给UI线程
                Message message = new Message();
                message.what = 1;
                message.obj = RcvMsg;
                uiHandler.sendMessage(message);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
 
        socket.close();
    }
}

这个类继承自Thread,也就是有线程功能的,在线程的运行run函数中实现接收操作

另外两个重要的功能函数是sendBroadcast和sendResponse ,他们分别用于广播发送和向对方发送数据。

Activity中主要的代码如下:

    private UDPClient client = null;
    private final MyHandler myHandler = new MyHandler(this);
 
    public class MyHandler extends Handler{
        private  final WeakReference<MainActivity> mActivity;
        public MyHandler(MainActivity activity){
            mActivity = new WeakReference<MainActivity>(activity);
        }
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 1:
                    txt_Recv.setText(msg.obj.toString());
                    break;
                default:
                    break;
            }
        }
    }
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindWidget();   //控件绑定
        listening();    //监听事件
 
        client=new UDPClient();
        client.uiHandler = myHandler;//用于线程给activity发送消息
        client.start();
    }

关于消息接收处理的handler,据说这样写可以防止内存泄露,但总是有一条警告

警告: [deprecation] Handler中的Handler()已过时  public MyHandler(MainActivity activity){
                                               ^

不太明白是什么意思,至今没有解决。但这不影响编译生成可执行文件,暂时放一放了。

 

完整源代码:下载

芯艺工作室    蒙ICP备06005492号
Copyright© 2004-2023 ChipArt Studio All Rights Reserved