关于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){
^
不太明白是什么意思,至今没有解决。但这不影响编译生成可执行文件,暂时放一放了。
完整源代码:下载
|
|