需求:

1.一个android端的service后台运行的程序,作为socket的服务器端;用于接收Pc client端发来的命令,来处理数据后,把结果发给PC client

2.PC端程序,作为socket的客户端,用于给android手机端发操作命令

难点分析:

1.手机一定要有adb模式,即插上USB线时马上提示的对话框选adb。好多对手机的操作都可以用adb直接作。

不过,我发现LG GW880就没有,要去下载个

2.android默认手机端的IP为“127.0.0.1”

3.要想联通PC与android手机的sokcet,一定要用adb forward 来作下端口转发才能连上socket.

view plaincopy to clipboardprint?
Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086");
Thread.sleep(3000);
Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086");
Thread.sleep(3000);

4.android端的service程序Install到手机上容易,但是还要有方法来从PC的client端来启动手机上的service ,这个办法可以通过PC端adb命令来发一个Broastcast ,手机端再写个接收BroastcastReceive来接收这个Broastcast,在这个BroastcastReceive来启动service

pc端命令:

view plaincopy to clipboardprint?
Runtime.getRuntime().exec(
"adb shell am broadcast -a NotifyServiceStart");
Runtime.getRuntime().exec(
"adb shell am broadcast -a NotifyServiceStart");

android端的代码:ServiceBroadcastReceiver.java

view plaincopy to clipboardprint?
package com.otheri.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ServiceBroadcastReceiver extends BroadcastReceiver {
private static String START_ACTION = "NotifyServiceStart";
private static String STOP_ACTION = "NotifyServiceStop";

@Override
public void onReceive(Context context, Intent intent) {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive");

String action = intent.getAction();
if (START_ACTION.equalsIgnoreCase(action)) {
context.startService(new Intent(context, androidService.class));

Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive start end");
} else if (STOP_ACTION.equalsIgnoreCase(action)) {
context.stopService(new Intent(context, androidService.class));
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive stop end");
}
}

}
package com.otheri.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ServiceBroadcastReceiver extends BroadcastReceiver {
private static String START_ACTION = "NotifyServiceStart";
private static String STOP_ACTION = "NotifyServiceStop";

@Override
public void onReceive(Context context, Intent intent) {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive");

String action = intent.getAction();
if (START_ACTION.equalsIgnoreCase(action)) {
context.startService(new Intent(context, androidService.class));

Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive start end");
} else if (STOP_ACTION.equalsIgnoreCase(action)) {
context.stopService(new Intent(context, androidService.class));
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive stop end");
}
}

}

5.由于是USB连接,所以socket就可以设计为一但连接就一直联通,即在new socket和开完out,in流后,就用个while(true){}来循环PC端和android端的读和写

android的代码:

view plaincopy to clipboardprint?
public void run() {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "a client has connected to server!");
BufferedOutputStream out;
BufferedInputStream in;
try {
/* PC端发来的数据msg */
String currCMD = "";
out = new BufferedOutputStream(client.getOutputStream());
in = new BufferedInputStream(client.getInputStream());
// testSocket();// 测试socket方法
androidService.ioThreadFlag = true;
while (androidService.ioThreadFlag) {
try {
if (!client.isConnected()) {
break;
}

/* 接收PC发来的数据 */
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "will read......");
/* 读操作命令 */
currCMD = readCMDFromSocket(in);
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "**currCMD ==== " + currCMD);

/* 根据命令分别处理数据 */
if (currCMD.equals("1")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("2")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("3")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("4")) {
/* 准备接收文件数据 */
try {
out.write("service receive OK".getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}

/* 接收文件数据,4字节文件长度,4字节文件格式,其后是文件数据 */
byte[] filelength = new byte[4];
byte[] fileformat = new byte[4];
byte[] filebytes = null;

/* 从socket流中读取完整文件数据 */
filebytes = receiveFileFromSocket(in, out, filelength,
fileformat);

// Log.v(Service139.TAG, "receive data =" + new
// String(filebytes));
try {
/* 生成文件 */
File file = FileHelper.newFile("R0013340.JPG");
FileHelper.writeFile(file, filebytes, 0,
filebytes.length);
} catch (IOException e) {
e.printStackTrace();
}
} else if (currCMD.equals("exit")) {

}
} catch (Exception e) {
// try {
// out.write("error".getBytes("utf-8"));
// out.flush();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error111111");
}
}
out.close();
in.close();
} catch (Exception e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error222222");
e.printStackTrace();
} finally {
try {
if (client != null) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "client.close()");
client.close();
}
} catch (IOException e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error333333");
e.printStackTrace();
}
}
public void run() {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "a client has connected to server!");
BufferedOutputStream out;
BufferedInputStream in;
try {
/* PC端发来的数据msg */
String currCMD = "";
out = new BufferedOutputStream(client.getOutputStream());
in = new BufferedInputStream(client.getInputStream());
// testSocket();// 测试socket方法
androidService.ioThreadFlag = true;
while (androidService.ioThreadFlag) {
try {
if (!client.isConnected()) {
break;
}

/* 接收PC发来的数据 */
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "will read......");
/* 读操作命令 */
currCMD = readCMDFromSocket(in);
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "**currCMD ==== " + currCMD);

/* 根据命令分别处理数据 */
if (currCMD.equals("1")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("2")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("3")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("4")) {
/* 准备接收文件数据 */
try {
out.write("service receive OK".getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}

/* 接收文件数据,4字节文件长度,4字节文件格式,其后是文件数据 */
byte[] filelength = new byte[4];
byte[] fileformat = new byte[4];
byte[] filebytes = null;

/* 从socket流中读取完整文件数据 */
filebytes = receiveFileFromSocket(in, out, filelength,
fileformat);

// Log.v(Service139.TAG, "receive data =" + new
// String(filebytes));
try {
/* 生成文件 */
File file = FileHelper.newFile("R0013340.JPG");
FileHelper.writeFile(file, filebytes, 0,
filebytes.length);
} catch (IOException e) {
e.printStackTrace();
}
} else if (currCMD.equals("exit")) {

}
} catch (Exception e) {
// try {
// out.write("error".getBytes("utf-8"));
// out.flush();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error111111");
}
}
out.close();
in.close();
} catch (Exception e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error222222");
e.printStackTrace();
} finally {
try {
if (client != null) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "client.close()");
client.close();
}
} catch (IOException e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error333333");
e.printStackTrace();
}
}

6.如果是在PC端和android端的读写操作来while(true){}循环,这样socket流的结尾不好判断,不能用“-1”来判断,因为“-1”是只有在socket关闭时才作为判断结尾。

7.socket在out.write(bytes);时,要是数据太大时,超过socket的缓存,socket自动分包发送,所以对方就一定要用循环来多次读。最好的办法就是服务器和客户端协议好,比如发文件时,先写过来一个要发送的文件的大小,然后再发送文件;对方用这个大小,来循环读取数据。

android端接收数据的代码:

view plaincopy to clipboardprint?
/**
* 功能:从socket流中读取完整文件数据
*
* InputStream in:socket输入流
*
* byte[] filelength: 流的前4个字节存储要转送的文件的字节数
*
* byte[] fileformat:流的前5-8字节存储要转送的文件的格式(如.apk)
*
* */
public static byte[] receiveFileFromSocket(InputStream in,
OutputStream out, byte[] filelength, byte[] fileformat) {
byte[] filebytes = null;// 文件数据
try {
int filelen = MyUtil.bytesToInt(filelength);// 文件长度从4字节byte[]转成Int
String strtmp = "read file length ok:" + filelen;
out.write(strtmp.getBytes("utf-8"));
out.flush();

filebytes = new byte[filelen];
int pos = 0;
int rcvLen = 0;
while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) {
pos += rcvLen;
}
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read file OK:file size=" + filebytes.length);
out.write("read file ok".getBytes("utf-8"));
out.flush();
} catch (Exception e) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "receiveFileFromSocket error");
e.printStackTrace();
}
return filebytes;
}
/**
* 功能:从socket流中读取完整文件数据
*
* InputStream in:socket输入流
*
* byte[] filelength: 流的前4个字节存储要转送的文件的字节数
*
* byte[] fileformat:流的前5-8字节存储要转送的文件的格式(如.apk)
*
* */
public static byte[] receiveFileFromSocket(InputStream in,
OutputStream out, byte[] filelength, byte[] fileformat) {
byte[] filebytes = null;// 文件数据
try {
int filelen = MyUtil.bytesToInt(filelength);// 文件长度从4字节byte[]转成Int
String strtmp = "read file length ok:" + filelen;
out.write(strtmp.getBytes("utf-8"));
out.flush();

filebytes = new byte[filelen];
int pos = 0;
int rcvLen = 0;
while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) {
pos += rcvLen;
}
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read file OK:file size=" + filebytes.length);
out.write("read file ok".getBytes("utf-8"));
out.flush();
} catch (Exception e) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "receiveFileFromSocket error");
e.printStackTrace();
}
return filebytes;
}

8.socket的最重要的机制就是读写采用的是阻塞的方式,如果客户端作为命令发起者,服务器端作为接收者的话,只有当客户端client用out.writer()写到输出流里后,即流中有数据service的read才会执行,不然就会一直停在read()那里等数据。

9.还要让服务器端可以同时连接多个client,即服务器端用new thread()来作数据读取操作。

源码:

客户端(pc端):

testPcClient.java

view plaincopy to clipboardprint?
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class testPcClient {

/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
try {
Runtime.getRuntime().exec(
"adb shell am broadcast -a NotifyServiceStop");
Thread.sleep(3000);
Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086");
Thread.sleep(3000);
Runtime.getRuntime().exec(
"adb shell am broadcast -a NotifyServiceStart");
Thread.sleep(3000);
} catch (IOException e3) {
e3.printStackTrace();
}

Socket socket = null;
try {
InetAddress serverAddr = null;
serverAddr = InetAddress.getByName("127.0.0.1");
System.out.println("TCP 1111" + "C: Connecting...");
socket = new Socket(serverAddr, 12580);
String str = "hi,wufenglong";
System.out.println("TCP 221122" + "C:RECEIVE");
BufferedOutputStream out = new BufferedOutputStream(socket
.getOutputStream());
BufferedInputStream in = new BufferedInputStream(socket
.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
boolean flag = true;
while (flag) {
System.out.print("请输入1~6的数字,退出输入exit:");
String strWord = br.readLine();// 从控制台输入1~6
if (strWord.equals("1")) {
out.write("1".getBytes());
out.flush();
System.out.println("1 finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
System.out
.println("=============================================");
} else if (strWord.equals("2")) {
out.write("2".getBytes());
out.flush();
System.out.println("2 finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
System.out
.println("=============================================");
} else if (strWord.equals("3")) {
out.write("3".getBytes());
out.flush();
System.out.println("3 finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
System.out
.println("=============================================");
} else if (strWord.equals("4")) {
/* 发送命令 */
out.write("4".getBytes());
out.flush();
System.out.println("send file finish sending the CMD:");
/* 服务器反馈:准备接收 */
String strFormsocket = readFromSocket(in);
System.out
.println("service ready receice data:UPDATE_CONTACTS:"
+ strFormsocket);
byte[] filebytes = FileHelper.readFile("R0013340.JPG");
System.out.println("file size=" + filebytes.length);
/* 将整数转成4字节byte数组 */
byte[] filelength = new byte[4];
filelength = tools.intToByte(filebytes.length);
/* 将.apk字符串转成4字节byte数组 */
byte[] fileformat = null;
fileformat = ".apk".getBytes();
System.out
.println("fileformat length=" + fileformat.length);
/* 字节流中前4字节为文件长度,4字节文件格式,以后是文件流 */
/* 注意如果write里的byte[]超过socket的缓存,系统自动分包写过去,所以对方要循环写完 */
out.write(filelength);
out.flush();
String strok1 = readFromSocket(in);
System.out.println("service receive filelength :" + strok1);
// out.write(fileformat);
// out.flush();
// String strok2 = readFromSocket(in);
// System.out.println("service receive fileformat :" +
// strok2);
System.out.println("write data to android");
out.write(filebytes);
out.flush();
System.out.println("*********");

/* 服务器反馈:接收成功 */
String strread = readFromSocket(in);
System.out.println(" send data success:" + strread);
System.out
.println("=============================================");
} else if (strWord.equalsIgnoreCase("EXIT")) {
out.write("EXIT".getBytes());
out.flush();
System.out.println("EXIT finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
flag = false;
System.out
.println("=============================================");
}
}

} catch (UnknownHostException e1) {
System.out.println("TCP 331133" + "ERROR:" + e1.toString());
} catch (Exception e2) {
System.out.println("TCP 441144" + "ERROR:" + e2.toString());
} finally {
try {
if (socket != null) {
socket.close();
System.out.println("socket.close()");
}
} catch (IOException e) {
System.out.println("TCP 5555" + "ERROR:" + e.toString());
}
}
}

/* 从InputStream流中读数据 */
public static String readFromSocket(InputStream in) {
int MAX_BUFFER_BYTES = 4000;
String msg = "";
byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];
try {
int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");

tempbuffer = null;
} catch (Exception e) {
e.printStackTrace();
}
// Log.v(Service139.TAG, "msg=" + msg);
return msg;
}
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

public class testPcClient {

/**
* @param args
* @throws InterruptedException
*/
public static void main(String[] args) throws InterruptedException {
try {
Runtime.getRuntime().exec(
"adb shell am broadcast -a NotifyServiceStop");
Thread.sleep(3000);
Runtime.getRuntime().exec("adb forward tcp:12580 tcp:10086");
Thread.sleep(3000);
Runtime.getRuntime().exec(
"adb shell am broadcast -a NotifyServiceStart");
Thread.sleep(3000);
} catch (IOException e3) {
e3.printStackTrace();
}

Socket socket = null;
try {
InetAddress serverAddr = null;
serverAddr = InetAddress.getByName("127.0.0.1");
System.out.println("TCP 1111" + "C: Connecting...");
socket = new Socket(serverAddr, 12580);
String str = "hi,wufenglong";
System.out.println("TCP 221122" + "C:RECEIVE");
BufferedOutputStream out = new BufferedOutputStream(socket
.getOutputStream());
BufferedInputStream in = new BufferedInputStream(socket
.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(
System.in));
boolean flag = true;
while (flag) {
System.out.print("请输入1~6的数字,退出输入exit:");
String strWord = br.readLine();// 从控制台输入1~6
if (strWord.equals("1")) {
out.write("1".getBytes());
out.flush();
System.out.println("1 finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
System.out
.println("=============================================");
} else if (strWord.equals("2")) {
out.write("2".getBytes());
out.flush();
System.out.println("2 finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
System.out
.println("=============================================");
} else if (strWord.equals("3")) {
out.write("3".getBytes());
out.flush();
System.out.println("3 finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
System.out
.println("=============================================");
} else if (strWord.equals("4")) {
/* 发送命令 */
out.write("4".getBytes());
out.flush();
System.out.println("send file finish sending the CMD:");
/* 服务器反馈:准备接收 */
String strFormsocket = readFromSocket(in);
System.out
.println("service ready receice data:UPDATE_CONTACTS:"
+ strFormsocket);
byte[] filebytes = FileHelper.readFile("R0013340.JPG");
System.out.println("file size=" + filebytes.length);
/* 将整数转成4字节byte数组 */
byte[] filelength = new byte[4];
filelength = tools.intToByte(filebytes.length);
/* 将.apk字符串转成4字节byte数组 */
byte[] fileformat = null;
fileformat = ".apk".getBytes();
System.out
.println("fileformat length=" + fileformat.length);
/* 字节流中前4字节为文件长度,4字节文件格式,以后是文件流 */
/* 注意如果write里的byte[]超过socket的缓存,系统自动分包写过去,所以对方要循环写完 */
out.write(filelength);
out.flush();
String strok1 = readFromSocket(in);
System.out.println("service receive filelength :" + strok1);
// out.write(fileformat);
// out.flush();
// String strok2 = readFromSocket(in);
// System.out.println("service receive fileformat :" +
// strok2);
System.out.println("write data to android");
out.write(filebytes);
out.flush();
System.out.println("*********");

/* 服务器反馈:接收成功 */
String strread = readFromSocket(in);
System.out.println(" send data success:" + strread);
System.out
.println("=============================================");
} else if (strWord.equalsIgnoreCase("EXIT")) {
out.write("EXIT".getBytes());
out.flush();
System.out.println("EXIT finish sending the data");
String strFormsocket = readFromSocket(in);
System.out.println("the data sent by server is:/r/n"
+ strFormsocket);
flag = false;
System.out
.println("=============================================");
}
}

} catch (UnknownHostException e1) {
System.out.println("TCP 331133" + "ERROR:" + e1.toString());
} catch (Exception e2) {
System.out.println("TCP 441144" + "ERROR:" + e2.toString());
} finally {
try {
if (socket != null) {
socket.close();
System.out.println("socket.close()");
}
} catch (IOException e) {
System.out.println("TCP 5555" + "ERROR:" + e.toString());
}
}
}

/* 从InputStream流中读数据 */
public static String readFromSocket(InputStream in) {
int MAX_BUFFER_BYTES = 4000;
String msg = "";
byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];
try {
int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");

tempbuffer = null;
} catch (Exception e) {
e.printStackTrace();
}
// Log.v(Service139.TAG, "msg=" + msg);
return msg;
}
}

android服务器端:

主类androidService.java

view plaincopy to clipboardprint?
package com.otheri.service;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

/**
* 设置:android手机
*
*
* */
public class androidService extends Service {
public static final String TAG = "TAG";
public static Boolean mainThreadFlag = true;
public static Boolean ioThreadFlag = true;
ServerSocket serverSocket = null;
final int SERVER_PORT = 10086;
File testFile;
private sysBroadcastReceiver sysBR;

@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, Thread.currentThread().getName() + "---->" + " onCreate");
/* 创建内部类sysBroadcastReceiver 并注册registerReceiver */
sysRegisterReceiver();
new Thread() {
public void run() {
doListen();
};
}.start();
}

private void doListen() {
Log.d(TAG, Thread.currentThread().getName() + "---->"
+ " doListen() START");
serverSocket = null;
try {
Log.d(TAG, Thread.currentThread().getName() + "---->"
+ " doListen() new serverSocket");
serverSocket = new ServerSocket(SERVER_PORT);

boolean mainThreadFlag = true;
while (mainThreadFlag) {
Log.d(TAG, Thread.currentThread().getName() + "---->"
+ " doListen() listen");

Socket client = serverSocket.accept();

new Thread(new ThreadReadWriterIOSocket(this, client)).start();
}
} catch (IOException e1) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "new serverSocket error");
e1.printStackTrace();
}
}

/* 创建内部类sysBroadcastReceiver 并注册registerReceiver */
private void sysRegisterReceiver() {
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "sysRegisterReceiver");
sysBR = new sysBroadcastReceiver();
/* 注册BroadcastReceiver */
IntentFilter filter1 = new IntentFilter();
/* 新的应用程序被安装到了设备上的广播 */
filter1.addAction("android.intent.action.PACKAGE_ADDED");
filter1.addDataScheme("package");
filter1.addAction("android.intent.action.PACKAGE_REMOVED");
filter1.addDataScheme("package");
registerReceiver(sysBR, filter1);
}

/* 内部类:BroadcastReceiver 用于接收系统事件 */
private class sysBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase("android.intent.action.PACKAGE_ADDED")) {
// ReadInstalledAPP();
} else if (action
.equalsIgnoreCase("android.intent.action.PACKAGE_REMOVED")) {
// ReadInstalledAPP();
}
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "sysBroadcastReceiver onReceive");
}
}

@Override
public void onDestroy() {
super.onDestroy();

// 关闭线程
mainThreadFlag = false;
ioThreadFlag = false;
// 关闭服务器
try {
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "serverSocket.close()");
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "**************** onDestroy****************");
}

@Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, Thread.currentThread().getName() + "---->" + " onStart()");
super.onStart(intent, startId);

}

@Override
public IBinder onBind(Intent arg0) {
Log.d(TAG, " onBind");
return null;
}

}
package com.otheri.service;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;

/**
* 设置:android手机
*
*
* */
public class androidService extends Service {
public static final String TAG = "TAG";
public static Boolean mainThreadFlag = true;
public static Boolean ioThreadFlag = true;
ServerSocket serverSocket = null;
final int SERVER_PORT = 10086;
File testFile;
private sysBroadcastReceiver sysBR;

@Override
public void onCreate() {
super.onCreate();
Log.v(TAG, Thread.currentThread().getName() + "---->" + " onCreate");
/* 创建内部类sysBroadcastReceiver 并注册registerReceiver */
sysRegisterReceiver();
new Thread() {
public void run() {
doListen();
};
}.start();
}

private void doListen() {
Log.d(TAG, Thread.currentThread().getName() + "---->"
+ " doListen() START");
serverSocket = null;
try {
Log.d(TAG, Thread.currentThread().getName() + "---->"
+ " doListen() new serverSocket");
serverSocket = new ServerSocket(SERVER_PORT);

boolean mainThreadFlag = true;
while (mainThreadFlag) {
Log.d(TAG, Thread.currentThread().getName() + "---->"
+ " doListen() listen");

Socket client = serverSocket.accept();

new Thread(new ThreadReadWriterIOSocket(this, client)).start();
}
} catch (IOException e1) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "new serverSocket error");
e1.printStackTrace();
}
}

/* 创建内部类sysBroadcastReceiver 并注册registerReceiver */
private void sysRegisterReceiver() {
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "sysRegisterReceiver");
sysBR = new sysBroadcastReceiver();
/* 注册BroadcastReceiver */
IntentFilter filter1 = new IntentFilter();
/* 新的应用程序被安装到了设备上的广播 */
filter1.addAction("android.intent.action.PACKAGE_ADDED");
filter1.addDataScheme("package");
filter1.addAction("android.intent.action.PACKAGE_REMOVED");
filter1.addDataScheme("package");
registerReceiver(sysBR, filter1);
}

/* 内部类:BroadcastReceiver 用于接收系统事件 */
private class sysBroadcastReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equalsIgnoreCase("android.intent.action.PACKAGE_ADDED")) {
// ReadInstalledAPP();
} else if (action
.equalsIgnoreCase("android.intent.action.PACKAGE_REMOVED")) {
// ReadInstalledAPP();
}
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "sysBroadcastReceiver onReceive");
}
}

@Override
public void onDestroy() {
super.onDestroy();

// 关闭线程
mainThreadFlag = false;
ioThreadFlag = false;
// 关闭服务器
try {
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "serverSocket.close()");
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
Log.v(TAG, Thread.currentThread().getName() + "---->"
+ "**************** onDestroy****************");
}

@Override
public void onStart(Intent intent, int startId) {
Log.d(TAG, Thread.currentThread().getName() + "---->" + " onStart()");
super.onStart(intent, startId);

}

@Override
public IBinder onBind(Intent arg0) {
Log.d(TAG, " onBind");
return null;
}

}

用于接收PC发来的Broastcast并启动主类service的ServiceBroadcastReceiver.java

view plaincopy to clipboardprint?
package com.otheri.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ServiceBroadcastReceiver extends BroadcastReceiver {
private static String START_ACTION = "NotifyServiceStart";
private static String STOP_ACTION = "NotifyServiceStop";

@Override
public void onReceive(Context context, Intent intent) {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive");

String action = intent.getAction();
if (START_ACTION.equalsIgnoreCase(action)) {
context.startService(new Intent(context, androidService.class));

Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive start end");
} else if (STOP_ACTION.equalsIgnoreCase(action)) {
context.stopService(new Intent(context, androidService.class));
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive stop end");
}
}

}
package com.otheri.service;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

public class ServiceBroadcastReceiver extends BroadcastReceiver {
private static String START_ACTION = "NotifyServiceStart";
private static String STOP_ACTION = "NotifyServiceStop";

@Override
public void onReceive(Context context, Intent intent) {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive");

String action = intent.getAction();
if (START_ACTION.equalsIgnoreCase(action)) {
context.startService(new Intent(context, androidService.class));

Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive start end");
} else if (STOP_ACTION.equalsIgnoreCase(action)) {
context.stopService(new Intent(context, androidService.class));
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "ServiceBroadcastReceiver onReceive stop end");
}
}

}

用于新socket连接的读写线程类ThreadReadWriterIOSocket.java

view plaincopy to clipboardprint?
package com.otheri.service;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import android.content.Context;
import android.util.Log;

import com.otheri.util.FileHelper;
import com.otheri.util.MyUtil;

/**
* 功能:用于socket的交互
*
* @author wufenglong
*
*/
public class ThreadReadWriterIOSocket implements Runnable {
private Socket client;
private Context context;

ThreadReadWriterIOSocket(Context context, Socket client) {

this.client = client;
this.context = context;
}

@Override
public void run() {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "a client has connected to server!");
BufferedOutputStream out;
BufferedInputStream in;
try {
/* PC端发来的数据msg */
String currCMD = "";
out = new BufferedOutputStream(client.getOutputStream());
in = new BufferedInputStream(client.getInputStream());
// testSocket();// 测试socket方法
androidService.ioThreadFlag = true;
while (androidService.ioThreadFlag) {
try {
if (!client.isConnected()) {
break;
}

/* 接收PC发来的数据 */
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "will read......");
/* 读操作命令 */
currCMD = readCMDFromSocket(in);
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "**currCMD ==== " + currCMD);

/* 根据命令分别处理数据 */
if (currCMD.equals("1")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("2")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("3")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("4")) {
/* 准备接收文件数据 */
try {
out.write("service receive OK".getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}

/* 接收文件数据,4字节文件长度,4字节文件格式,其后是文件数据 */
byte[] filelength = new byte[4];
byte[] fileformat = new byte[4];
byte[] filebytes = null;

/* 从socket流中读取完整文件数据 */
filebytes = receiveFileFromSocket(in, out, filelength,
fileformat);

// Log.v(Service139.TAG, "receive data =" + new
// String(filebytes));
try {
/* 生成文件 */
File file = FileHelper.newFile("R0013340.JPG");
FileHelper.writeFile(file, filebytes, 0,
filebytes.length);
} catch (IOException e) {
e.printStackTrace();
}
} else if (currCMD.equals("exit")) {

}
} catch (Exception e) {
// try {
// out.write("error".getBytes("utf-8"));
// out.flush();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error111111");
}
}
out.close();
in.close();
} catch (Exception e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error222222");
e.printStackTrace();
} finally {
try {
if (client != null) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "client.close()");
client.close();
}
} catch (IOException e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error333333");
e.printStackTrace();
}
}
}

/**
* 功能:从socket流中读取完整文件数据
*
* InputStream in:socket输入流
*
* byte[] filelength: 流的前4个字节存储要转送的文件的字节数
*
* byte[] fileformat:流的前5-8字节存储要转送的文件的格式(如.apk)
*
* */
public static byte[] receiveFileFromSocket(InputStream in,
OutputStream out, byte[] filelength, byte[] fileformat) {
byte[] filebytes = null;// 文件数据
try {
in.read(filelength);// 读文件长度
int filelen = MyUtil.bytesToInt(filelength);// 文件长度从4字节byte[]转成Int
String strtmp = "read file length ok:" + filelen;
out.write(strtmp.getBytes("utf-8"));
out.flush();

filebytes = new byte[filelen];
int pos = 0;
int rcvLen = 0;
while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) {
pos += rcvLen;
}
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read file OK:file size=" + filebytes.length);
out.write("read file ok".getBytes("utf-8"));
out.flush();
} catch (Exception e) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "receiveFileFromSocket error");
e.printStackTrace();
}
return filebytes;
}

/* 读取命令 */
public static String readCMDFromSocket(InputStream in) {
int MAX_BUFFER_BYTES = 2048;
String msg = "";
byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];
try {
int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");
tempbuffer = null;
} catch (Exception e) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "readFromSocket error");
e.printStackTrace();
}
// Log.v(Service139.TAG, "msg=" + msg);
return msg;
}
}
package com.otheri.service;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

import android.content.Context;
import android.util.Log;

import com.otheri.util.FileHelper;
import com.otheri.util.MyUtil;

/**
* 功能:用于socket的交互
*
* @author wufenglong
*
*/
public class ThreadReadWriterIOSocket implements Runnable {
private Socket client;
private Context context;

ThreadReadWriterIOSocket(Context context, Socket client) {

this.client = client;
this.context = context;
}

@Override
public void run() {
Log.d(androidService.TAG, Thread.currentThread().getName() + "---->"
+ "a client has connected to server!");
BufferedOutputStream out;
BufferedInputStream in;
try {
/* PC端发来的数据msg */
String currCMD = "";
out = new BufferedOutputStream(client.getOutputStream());
in = new BufferedInputStream(client.getInputStream());
// testSocket();// 测试socket方法
androidService.ioThreadFlag = true;
while (androidService.ioThreadFlag) {
try {
if (!client.isConnected()) {
break;
}

/* 接收PC发来的数据 */
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "will read......");
/* 读操作命令 */
currCMD = readCMDFromSocket(in);
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "**currCMD ==== " + currCMD);

/* 根据命令分别处理数据 */
if (currCMD.equals("1")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("2")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("3")) {
out.write("OK".getBytes());
out.flush();
} else if (currCMD.equals("4")) {
/* 准备接收文件数据 */
try {
out.write("service receive OK".getBytes());
out.flush();
} catch (IOException e) {
e.printStackTrace();
}

/* 接收文件数据,4字节文件长度,4字节文件格式,其后是文件数据 */
byte[] filelength = new byte[4];
byte[] fileformat = new byte[4];
byte[] filebytes = null;

/* 从socket流中读取完整文件数据 */
filebytes = receiveFileFromSocket(in, out, filelength,
fileformat);

// Log.v(Service139.TAG, "receive data =" + new
// String(filebytes));
try {
/* 生成文件 */
File file = FileHelper.newFile("R0013340.JPG");
FileHelper.writeFile(file, filebytes, 0,
filebytes.length);
} catch (IOException e) {
e.printStackTrace();
}
} else if (currCMD.equals("exit")) {

}
} catch (Exception e) {
// try {
// out.write("error".getBytes("utf-8"));
// out.flush();
// } catch (IOException e1) {
// e1.printStackTrace();
// }
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error111111");
}
}
out.close();
in.close();
} catch (Exception e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error222222");
e.printStackTrace();
} finally {
try {
if (client != null) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "client.close()");
client.close();
}
} catch (IOException e) {
Log.e(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read write error333333");
e.printStackTrace();
}
}
}

/**
* 功能:从socket流中读取完整文件数据
*
* InputStream in:socket输入流
*
* byte[] filelength: 流的前4个字节存储要转送的文件的字节数
*
* byte[] fileformat:流的前5-8字节存储要转送的文件的格式(如.apk)
*
* */
public static byte[] receiveFileFromSocket(InputStream in,
OutputStream out, byte[] filelength, byte[] fileformat) {
byte[] filebytes = null;// 文件数据
try {
in.read(filelength);// 读文件长度
int filelen = MyUtil.bytesToInt(filelength);// 文件长度从4字节byte[]转成Int
String strtmp = "read file length ok:" + filelen;
out.write(strtmp.getBytes("utf-8"));
out.flush();

filebytes = new byte[filelen];
int pos = 0;
int rcvLen = 0;
while ((rcvLen = in.read(filebytes, pos, filelen - pos)) > 0) {
pos += rcvLen;
}
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "read file OK:file size=" + filebytes.length);
out.write("read file ok".getBytes("utf-8"));
out.flush();
} catch (Exception e) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "receiveFileFromSocket error");
e.printStackTrace();
}
return filebytes;
}

/* 读取命令 */
public static String readCMDFromSocket(InputStream in) {
int MAX_BUFFER_BYTES = 2048;
String msg = "";
byte[] tempbuffer = new byte[MAX_BUFFER_BYTES];
try {
int numReadedBytes = in.read(tempbuffer, 0, tempbuffer.length);
msg = new String(tempbuffer, 0, numReadedBytes, "utf-8");
tempbuffer = null;
} catch (Exception e) {
Log.v(androidService.TAG, Thread.currentThread().getName()
+ "---->" + "readFromSocket error");
e.printStackTrace();
}
// Log.v(Service139.TAG, "msg=" + msg);
return msg;
}
}

后面是两个辅助类:

view plaincopy to clipboardprint?
package com.otheri.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import com.otheri.service.androidService;

import android.util.Log;

public class FileHelper {
// private static String FILEPATH = "/data/local/tmp";

private static String FILEPATH = "/sdcard";

// private static String FILEPATH = "/tmp";

public static File newFile(String fileName) {
File file = null;
try {
file = new File(FILEPATH, fileName);
file.delete();
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return file;
}

public static void writeFile(File file, byte[] data, int offset, int count)
throws IOException {

FileOutputStream fos = new FileOutputStream(file, true);
fos.write(data, offset, count);
fos.flush();
fos.close();
}

public static byte[] readFile(String fileName) throws IOException {
File file = new File(FILEPATH, fileName);
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int leng = bis.available();
Log.v(androidService.TAG, "filesize = " + leng);
byte[] b = new byte[leng];
bis.read(b, 0, leng);
// Input in = new Input(fis);
// byte[] ret = in.readAll();
// in.close();
bis.close();
return b;

}
}
package com.otheri.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import com.otheri.service.androidService;

import android.util.Log;

public class FileHelper {
// private static String FILEPATH = "/data/local/tmp";

private static String FILEPATH = "/sdcard";

// private static String FILEPATH = "/tmp";

public static File newFile(String fileName) {
File file = null;
try {
file = new File(FILEPATH, fileName);
file.delete();
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return file;
}

public static void writeFile(File file, byte[] data, int offset, int count)
throws IOException {

FileOutputStream fos = new FileOutputStream(file, true);
fos.write(data, offset, count);
fos.flush();
fos.close();
}

public static byte[] readFile(String fileName) throws IOException {
File file = new File(FILEPATH, fileName);
file.createNewFile();
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
int leng = bis.available();
Log.v(androidService.TAG, "filesize = " + leng);
byte[] b = new byte[leng];
bis.read(b, 0, leng);
// Input in = new Input(fis);
// byte[] ret = in.readAll();
// in.close();
bis.close();
return b;

}
}

view plaincopy to clipboardprint?
package com.otheri.util;

import java.io.InputStream;

import android.util.Log;

import com.otheri.service.androidService;

public class MyUtil {
/* byte[]转Int */
public static int bytesToInt(byte[] bytes) {
int addr = bytes[0] & 0xFF;
addr |= ((bytes[1] << 8) & 0xFF00);
addr |= ((bytes[2] << 16) & 0xFF0000);
addr |= ((bytes[3] << 24) & 0xFF000000);
return addr;
}

/* Int转byte[] */
public static byte[] intToByte(int i) {
byte[] abyte0 = new byte[4];
abyte0[0] = (byte) (0xff & i);
abyte0[1] = (byte) ((0xff00 & i) >> 8);
abyte0[2] = (byte) ((0xff0000 & i) >> 16);
abyte0[3] = (byte) ((0xff000000 & i) >> 24);
return abyte0;
}




}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wufenglong/archive/2010/07/31/5778862.aspx

更多相关文章

  1. cocos2dx android mk 2.0.2编译文件目录以及导入库问题
  2. 【Android适配问题集锦-文件类】获取Android机型设备信息的适配
  3. android aar 包含静态库的打包
  4. Android应用程序大小上限增至4.05GB
  5. Android应用程序Zipalign化 -- 如何让Android应用程序更有效率的
  6. Android数据回传---装备选择
  7. Android(安卓)C2DM学习——服务器端代码开发
  8. recovery的一些开发点滴
  9. android lib项目注意的事项

随机推荐

  1. 【Android】Android的消息机制
  2. [Android问答] 开发环境问题集锦
  3. Android NDK下编译google protocol buffe
  4. Java转Android开发不得不知的一些经验
  5. Linux/Android——Input系统之InputMappe
  6. Android悬浮窗开发招式集合
  7. Android对象序列化(Activity之间传递对象,P
  8. Android圆形控件
  9. Android共享元素
  10. Android最快的模拟器Genymotion试用小结