intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);
registerReceiver(mWifip2pReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//注销广播
unregisterReceiver(mWifip2pReceiver);
mWifip2pReceiver = null;
}
@Override
public void wifiP2pEnabled(boolean enabled) {
Log.e(TAG, “传输通道是否可用:” + enabled);
}
@Override
public void onConnection(WifiP2pInfo wifiP2pInfo) {
if (wifiP2pInfo != null) {
mWifiP2pInfo = wifiP2pInfo;
Log.e(TAG, “WifiP2pInfo:” + wifiP2pInfo);
}
}
@Override
public void onDisconnection() {
Log.e(TAG, “连接断开”);
}
@Override
public void onDeviceInfo(WifiP2pDevice wifiP2pDevice) {
Log.e(TAG, “当前的的设备名称” + wifiP2pDevice.deviceName);
}
@Override
public void onPeersInfo(Collection wifiP2pDeviceList) {
for (WifiP2pDevice device : wifiP2pDeviceList) {
Log.e(TAG, “连接的设备信息:” + device.deviceName + “--------” + device.deviceAddress);
}
}
@Override
public void onChannelDisconnected() {
}
}
四、客户端创建
创建一个SendFileActivity作为客户端的Activity,继承自BaseActivity,作为客户端。客户端发送信息到服务端,服务端需要提供组群信息,供客户端连接,关于服务端组群信息之后会有处理,这里先知道如何搜索服务端设备,然后配对连接,连接成功后就可以把所需要传输的文件信息以socket的形式发送给服务端,服务端监听socket端口,获取信息流,写入文件,这就是整个传输信息中客户端和服务端的交互过程。按照这样的步骤,客户端需要实现以下几点:
-
搜索设备信息
-
选择设备连接服务端组群信息
-
选择要传输的文件路径
-
把该文件通过socket发送到服务端
我们就按照这四点一步步实现:
1、搜索设备信息
通过mWifiP2pManager的discoverPeers方法进行搜索,有搜索成功和搜索失败的回调,搜索到设备时候会触发WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION 广播,此时就可以调用 requestPeers 方法获取设备列表信息,在回调方法onPeersInfo中可以得到设备信息。
[java] view plain copy
-
mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
-
@Override
-
public void onSuccess() {
-
Log.e(TAG, ”搜索设备成功”);
-
}
-
@Override
-
public void onFailure(int reasonCode) {
-
Log.e(TAG, ”搜索设备失败”);
-
}
-
});
mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.e(TAG, “搜索设备成功”);
}
@Override
public void onFailure(int reasonCode) {
Log.e(TAG, “搜索设备失败”);
}
});
2、选择设备连接服务端组群信息
搜索到的设备信息肯能不止一个,所以需要选择一个设备进行连接,当选择好设备之后,手动调用mWifiP2pManager.connect方法,进行设备连接,会触发WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION的广播,收到连接成功和失败的回调,在回到中可以得到WifiP2pInfo信息。
[java] view plain copy
-
WifiP2pConfig config = new WifiP2pConfig();
-
if (wifiP2pDevice != null) {
-
//需要将address,WpsInfo.PBC信息包装成WifiP2pConfig
-
config.deviceAddress = wifiP2pDevice.deviceAddress;
-
config.wps.setup = WpsInfo.PBC;
-
mWifiP2pManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
-
@Override
-
public void onSuccess() {
-
Log.e(TAG, ”连接成功”);
-
Toast.makeText(SendFileActivity.this, “连接成功”, Toast.LENGTH_SHORT).show();
-
}
-
@Override
-
public void onFailure(int reason) {
-
Log.e(TAG, ”连接失败”);
-
Toast.makeText(SendFileActivity.this, “连接失败”, Toast.LENGTH_SHORT).show();
-
}
-
});
-
}
WifiP2pConfig config = new WifiP2pConfig();
if (wifiP2pDevice != null) {
//需要将address,WpsInfo.PBC信息包装成WifiP2pConfig
config.deviceAddress = wifiP2pDevice.deviceAddress;
config.wps.setup = WpsInfo.PBC;
mWifiP2pManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.e(TAG, “连接成功”);
Toast.makeText(SendFileActivity.this, “连接成功”, Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reason) {
Log.e(TAG, “连接失败”);
Toast.makeText(SendFileActivity.this, “连接失败”, Toast.LENGTH_SHORT).show();
}
});
}
3、选择要传输的文件
指的是sd卡的文件路径,如下跳转到文件管理,进行选择:
[java] view plain copy
-
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
-
intent.setType(”*/*”);
-
intent.addCategory(Intent.CATEGORY_OPENABLE);
-
startActivityForResult(intent, 10);
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(“/”);
intent.addCategory(Intent.CATEGORY_OPENABLE);
startActivityForResult(intent, 10);
对于文件封装成FileBean,封装为三个参数:路径、文件大小、文件的MD5,如下:
[java] view plain copy
-
public class FileBean implements Serializable{
-
public static final String serialVersionUID = “6321689524634663223356”;
-
public String filePath;
-
public long fileLength;
-
//MD5码:保证文件的完整性
-
public String md5;
-
public FileBean(String filePath, long fileLength, String md5) {
-
this.filePath = filePath;
-
this.fileLength = fileLength;
-
this.md5 = md5;
-
}
-
}
public class FileBean implements Serializable{
public static final String serialVersionUID = “6321689524634663223356”;
public String filePath;
public long fileLength;
//MD5码:保证文件的完整性
public String md5;
public FileBean(String filePath, long fileLength, String md5) {
this.filePath = filePath;
this.fileLength = fileLength;
this.md5 = md5;
}
}
选择好之后会回调onActivityResult方法,可以在这里进行判断:
[java] view plain copy
-
@Override
-
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-
super.onActivityResult(requestCode, resultCode, data);
-
if (requestCode == 10) {
-
if (resultCode == RESULT_OK) {
-
Uri uri = data.getData();
-
if (uri != null) {
-
String path = FileUtils.getAbsolutePath(this, uri);
-
if (path != null) {
-
final File file = new File(path);
-
if (!file.exists() || mWifiP2pInfo == null) {
-
Toast.makeText(SendFileActivity.this,“文件路径找不到”,Toast.LENGTH_SHORT).show();
-
return;
-
}
-
String md5 = Md5Util.getMd5(file);
-
FileBean fileBean = new FileBean(file.getPath(), file.length(), md5);
-
String hostAddress = mWifiP2pInfo.groupOwnerAddress.getHostAddress();
-
new SendTask(SendFileActivity.this, fileBean).execute(hostAddress);
-
}
-
}
-
}
-
}
-
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 10) {
if (resultCode == RESULT_OK) {
Uri uri = data.getData();
if (uri != null) {
String path = FileUtils.getAbsolutePath(this, uri);
if (path != null) {
final File file = new File(path);
if (!file.exists() || mWifiP2pInfo == null) {
Toast.makeText(SendFileActivity.this,“文件路径找不到”,Toast.LENGTH_SHORT).show();
return;
}
String md5 = Md5Util.getMd5(file);
FileBean fileBean = new FileBean(file.getPath(), file.length(), md5);
String hostAddress = mWifiP2pInfo.groupOwnerAddress.getHostAddress();
new SendTask(SendFileActivity.this, fileBean).execute(hostAddress);
}
}
}
}
}
4、把该文件通过socket发送到服务端
获取到文件后,就可以通过socket发送文件到服务端,在创建socket的时候需要ip,ip地址可以从WifiP2pInfo获取到,WifiP2pInfo在回调方法中可以获取到,当设备连接上的时候会触发这个回调,在这里进行了初始化WifiP2pInfo。
Socket的发送是需要操作IO流的,比较耗时的操作,这里使用AsyncTask在子线程里面进行操作。同时为了监听读取进度,读取完成等情况,来跟新UI进度条,需要定义发送回调接口如下:
[java] view plain copy
-
public interface ProgressSendListener {
-
//当传输进度发生变化时
-
void onProgressChanged(File file, int progress);
-
//当传输结束时
-
void onFinished(File file);
-
//传输失败时
-
void onFaliure(File file);
-
}
public interface ProgressSendListener {
//当传输进度发生变化时
void onProgressChanged(File file, int progress);
//当传输结束时
void onFinished(File file);
//传输失败时
void onFaliure(File file);
}
回调接口在socket的操作中进行设置回调数据,关于socket的完整代码如下:
[java] view plain copy
-
public class SendSocket {
-
public static final String TAG = “SendSocket”;
-
public static final int PORT = 10000;
-
private FileBean mFileBean;
-
private String mAddress;
-
private File mFile;
-
private ProgressSendListener mlistener;
-
private Handler mHandler = new Handler(Looper.getMainLooper()) {
-
@Override
-
public void handleMessage(Message msg) {
-
super.handleMessage(msg);
-
switch (msg.what) {
-
case 10:
-
int progress = (int) msg.obj;
-
if (mlistener != null) {
-
mlistener.onProgressChanged(mFile, progress);
-
}
-
break;
-
case 20:
-
if (mlistener != null) {
-
mlistener.onFinished(mFile);
-
}
-
break;
-
case 30:
-
if (mlistener != null) {
-
mlistener.onFaliure(mFile);
-
}
-
break;
-
}
-
}
-
};
-
public SendSocket(FileBean fileBean, String address, ProgressSendListener listener) {
-
mFileBean = fileBean;
-
mAddress = address;
-
mlistener = listener;
-
}
-
public void createSendSocket() {
-
try {
-
Socket socket = new Socket();
-
InetSocketAddress inetSocketAddress = new InetSocketAddress(mAddress, PORT);
-
socket.connect(inetSocketAddress);
-
OutputStream outputStream = socket.getOutputStream();
-
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
-
objectOutputStream.writeObject(mFileBean);
-
mFile = new File(mFileBean.filePath);
-
FileInputStream inputStream = new FileInputStream(mFile);
-
long size = mFileBean.fileLength;
-
long total = 0;
-
byte bytes[] = new byte[1024];
-
int len;
-
while ((len = inputStream.read(bytes)) != -1) {
-
outputStream.write(bytes, 0, len);
-
total += len;
-
int progress = (int) ((total * 100) / size);
-
Log.e(TAG, ”文件发送进度:” + progress);
-
Message message = Message.obtain();
-
message.what = 10;
-
message.obj = progress;
-
mHandler.sendMessage(message);
-
}
-
outputStream.close();
-
objectOutputStream.close();
-
inputStream.close();
-
socket.close();
-
mHandler.sendEmptyMessage(20);
-
Log.e(TAG, ”文件发送成功”);
-
} catch (Exception e) {
-
mHandler.sendEmptyMessage(30);
-
Log.e(TAG, ”文件发送异常”);
-
}
-
}
-
}
public class SendSocket {
public static final String TAG = “SendSocket”;
public static final int PORT = 10000;
private FileBean mFileBean;
private String mAddress;
private File mFile;
private ProgressSendListener mlistener;
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 10:
int progress = (int) msg.obj;
if (mlistener != null) {
mlistener.onProgressChanged(mFile, progress);
}
break;
case 20:
if (mlistener != null) {
mlistener.onFinished(mFile);
}
break;
case 30:
if (mlistener != null) {
mlistener.onFaliure(mFile);
}
break;
}
}
};
public SendSocket(FileBean fileBean, String address, ProgressSendListener listener) {
mFileBean = fileBean;
mAddress = address;
mlistener = listener;
}
public void createSendSocket() {
try {
Socket socket = new Socket();
InetSocketAddress inetSocketAddress = new InetSocketAddress(mAddress, PORT);
socket.connect(inetSocketAddress);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(mFileBean);
mFile = new File(mFileBean.filePath);
FileInputStream inputStream = new FileInputStream(mFile);
long size = mFileBean.fileLength;
long total = 0;
byte bytes[] = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
total += len;
int progress = (int) ((total * 100) / size);
Log.e(TAG, “文件发送进度:” + progress);
Message message = Message.obtain();
message.what = 10;
message.obj = progress;
mHandler.sendMessage(message);
}
outputStream.close();
objectOutputStream.close();
inputStream.close();
socket.close();
mHandler.sendEmptyMessage(20);
Log.e(TAG, “文件发送成功”);
} catch (Exception e) {
mHandler.sendEmptyMessage(30);
Log.e(TAG, “文件发送异常”);
}
}
}
设置好回调信息后,让AsyncTask实现该接口,更新UI,核心代码如下:
[java] view plain copy
-
@Override
-
protected Void doInBackground(String… strings) {
-
mSendSocket = new SendSocket(mFileBean, strings[0], this);
-
mSendSocket.createSendSocket();
-
return null;
-
}
@Override
protected Void doInBackground(String… strings) {
mSendSocket = new SendSocket(mFileBean, strings[0], this);
mSendSocket.createSendSocket();
return null;
}
就这样客户端的功能完成。
五、服务端创建
服务端创主要用监听客户端发送过来的文件,接收传送过来的文件。建一个服务端的ReceiveFileActivity继承自BaseActivity,作为服务端的界面,需要实现以下功能:
-
创建组群信息,供客户端连接
-
移除组群信息
-
监听客户端发送过来的文件信息
接下来分别实现以上三个功能。
1、创建组群信息,供客户端连接
使用WifiP2pManager的createGroup方法进行设置,有设置成功和失败的回调。
[java] view plain copy
-
mWifiP2pManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {
-
@Override
-
public void onSuccess() {
-
Log.e(TAG, ”创建群组成功”);
-
Toast.makeText(ReceiveFileActivity.this, “创建群组成功”, Toast.LENGTH_SHORT).show();
-
}
-
@Override
-
public void onFailure(int reason) {
-
Log.e(TAG, ”创建群组失败: ” + reason);
-
Toast.makeText(ReceiveFileActivity.this, “创建群组失败,请移除已有的组群或者连接同一WIFI重试”, Toast.LENGTH_SHORT).show();
-
}
-
});
mWifiP2pManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.e(TAG, “创建群组成功”);
Toast.makeText(ReceiveFileActivity.this, “创建群组成功”, Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reason) {
Log.e(TAG, "创建群组失败: " + reason);
Toast.makeText(ReceiveFileActivity.this, “创建群组失败,请移除已有的组群或者连接同一WIFI重试”, Toast.LENGTH_SHORT).show();
}
});
2、移除组群信息
使用WifiP2pManager的removeGroup方法进行设置,也有设置成功和失败的回调。
[java] view plain copy
-
mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {
-
@Override
-
public void onSuccess() {
-
Log.e(TAG, ”移除组群成功”);
-
Toast.makeText(ReceiveFileActivity.this, “移除组群成功”, Toast.LENGTH_SHORT).show();
-
}
-
@Override
-
public void onFailure(int reason) {
-
Log.e(TAG, ”移除组群失败”);
-
Toast.makeText(ReceiveFileActivity.this, “移除组群失败,请创建组群重试”, Toast.LENGTH_SHORT).show();
-
}
-
});
mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {
@Override
public void onSuccess() {
Log.e(TAG, “移除组群成功”);
Toast.makeText(ReceiveFileActivity.this, “移除组群成功”, Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int reason) {
Log.e(TAG, “移除组群失败”);
Toast.makeText(ReceiveFileActivity.this, “移除组群失败,请创建组群重试”, Toast.LENGTH_SHORT).show();
}
});
3、监听客户端发送过来的文件信息
作为服务端要不断地监听客户端socket的端口来获取客户端的IO信息, 所以需要开启一个服务在后台监听客户端socket,因此创建一个Wifip2pService继承自IntentService,在onHandleIntent中创建ServerSocket,当ReceiveFileActivity启动的时候开启服务,代码如下:
[java] view plain copy
-
public class Wifip2pService extends IntentService {
-
private static final String TAG = “Wifip2pService”;
-
private ReceiveSocket mReceiveSocket;
-
public Wifip2pService() {
-
super(“Wifip2pService”);
-
}
-
@Nullable
-
@Override
-
public IBinder onBind(Intent intent) {
-
return new MyBinder();
-
}
-
public class MyBinder extends Binder {
-
public MyBinder() {
-
super();
-
}
-
public void initListener(ReceiveSocket.ProgressReceiveListener listener){
-
mReceiveSocket.setOnProgressReceiveListener(listener);
-
}
-
}
-
@Override
-
public void onCreate() {
-
super.onCreate();
-
Log.e(TAG, ”服务启动了”);
-
}
-
@Override
-
protected void onHandleIntent(Intent intent) {
-
mReceiveSocket = new ReceiveSocket();
-
mReceiveSocket.createServerSocket();
-
Log.e(TAG, ”传输完毕”);
-
}
-
@Override
-
public void onDestroy() {
-
super.onDestroy();
-
mReceiveSocket.clean();
-
}
-
}
public class Wifip2pService extends IntentService {
private static final String TAG = “Wifip2pService”;
private ReceiveSocket mReceiveSocket;
public Wifip2pService() {
super(“Wifip2pService”);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public class MyBinder extends Binder {
public MyBinder() {
super();
}
public void initListener(ReceiveSocket.ProgressReceiveListener listener){
mReceiveSocket.setOnProgressReceiveListener(listener);
}
}
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, “服务启动了”);
}
@Override
protected void onHandleIntent(Intent intent) {
mReceiveSocket = new ReceiveSocket();
mReceiveSocket.createServerSocket();
Log.e(TAG, “传输完毕”);
}
@Override
public void onDestroy() {
super.onDestroy();
mReceiveSocket.clean();
}
}
ReceiveSocket是一个ServerSocket的封装类,类似于客户端socket的封装,为了监听接收进度,同样需要创建监听接口对信息的写入进度等信息进行监听。Wifip2pService服务中的方法是对listener的一个初始化设置:
[java] view plain copy
-
private ProgressReceiveListener mListener;
-
public void setOnProgressReceiveListener(ProgressReceiveListener listener) {
-
mListener = listener;
-
}
-
public interface ProgressReceiveListener {
-
//开始传输
-
void onSatrt();
-
//当传输进度发生变化时
-
void onProgressChanged(File file, int progress);
-
//当传输结束时
-
void onFinished(File file);
-
//传输失败回调
-
void onFaliure(File file);
-
}
private ProgressReceiveListener mListener;
public void setOnProgressReceiveListener(ProgressReceiveListener listener) {
mListener = listener;
}
public interface ProgressReceiveListener {
//开始传输
void onSatrt();
//当传输进度发生变化时
void onProgressChanged(File file, int progress);
//当传输结束时
void onFinished(File file);
//传输失败回调
void onFaliure(File file);
}
在ReceiveSocket中监听进度等信息,设置ProgressReceiveListener的各个监听接口信息。代码如下:
[java] view plain copy
-
public class ReceiveSocket {
-
public static final String TAG = “ReceiveSocket”;
-
public static final int PORT = 10000;
-
private ServerSocket mServerSocket;
-
private Socket mSocket;
-
private InputStream mInputStream;
-
private ObjectInputStream mObjectInputStream;
-
private FileOutputStream mFileOutputStream;
-
private File mFile;
-
private Handler mHandler = new Handler(Looper.getMainLooper()) {
-
@Override
-
public void handleMessage(Message msg) {
-
super.ha
ndleMessage(msg); -
switch (msg.what) {
-
case 40:
-
if (mListener != null) {
-
mListener.onSatrt();
-
}
-
break;
-
case 50:
-
int progress = (int) msg.obj;
-
if (mListener != null) {
-
mListener.onProgressChanged(mFile, progress);
-
}
-
break;
-
case 60:
-
if (mListener != null) {
-
mListener.onFinished(mFile);
-
}
-
break;
-
case 70:
-
if (mListener != null) {
-
mListener.onFaliure(mFile);
-
}
-
break;
-
}
-
}
-
};
-
public void createServerSocket() {
-
try {
-
mServerSocket = new ServerSocket();
-
mServerSocket.setReuseAddress(true);
-
mServerSocket.bind(new InetSocketAddress(PORT));
-
mSocket = mServerSocket.accept();
-
Log.e(TAG, ”客户端IP地址 : ” + mSocket.getRemoteSocketAddress());
-
mInputStream = mSocket.getInputStream();
-
mObjectInputStream = new ObjectInputStream(mInputStream);
-
FileBean fileBean = (FileBean) mObjectInputStream.readObject();
-
String name = new File(fileBean.filePath).getName();
-
Log.e(TAG, ”客户端传递的文件名称 : ” + name);
-
Log.e(TAG, ”客户端传递的MD5 : ” + fileBean.md5);
-
mFile = new File(FileUtils.SdCardPath(name));
-
mFileOutputStream = new FileOutputStream(mFile);
-
//开始接收文件
-
mHandler.sendEmptyMessage(40);
-
byte bytes[] = new byte[1024];
-
int len;
-
long total = 0;
-
int progress;
-
while ((len = mInputStream.read(bytes)) != -1) {
-
mFileOutputStream.write(bytes, 0, len);
-
total += len;
-
progress = (int) ((total * 100) / fileBean.fileLength);
-
Log.e(TAG, ”文件接收进度: ” + progress);
-
Message message = Message.obtain();
-
message.what = 50;
-
message.obj = progress;
-
mHandler.sendMessage(message);
-
}
-
//新写入文件的MD5
-
String md5New = Md5Util.getMd5(mFile);
-
//发送过来的MD5
-
String md5Old = fileBean.md5;
-
if (md5New != null || md5Old != null) {
-
if (md5New.equals(md5Old)) {
-
mHandler.sendEmptyMessage(60);
-
Log.e(TAG, ”文件接收成功”);
-
}
-
} else {
-
mHandler.sendEmptyMessage(70);
-
}
-
mServerSocket.close();
-
mInputStream.close();
-
mObjectInputStream.close();
-
mFileOutputStream.close();
-
} catch (Exception e) {
-
mHandler.sendEmptyMessage(70);
-
Log.e(TAG, ”文件接收异常”);
-
}
-
}
-
public void clean() {
-
if (mServerSocket != null) {
-
try {
-
mServerSocket.close();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
if (mInputStream != null) {
-
try {
-
mInputStream.close();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
if (mObjectInputStream != null) {
-
try {
-
mObjectInputStream.close();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
if (mFileOutputStream != null) {
-
try {
-
mFileOutputStream.close();
-
} catch (IOException e) {
-
e.printStackTrace();
-
}
-
}
-
}
-
}
public class ReceiveSocket {
public static final String TAG = “ReceiveSocket”;
public static final int PORT = 10000;
private ServerSocket mServerSocket;
private Socket mSocket;
private InputStream mInputStream;
private ObjectInputStream mObjectInputStream;
private FileOutputStream mFileOutputStream;
private File mFile;
private Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 40:
if (mListener != null) {
mListener.onSatrt();
}
break;
case 50:
int progress = (int) msg.obj;
if (mListener != null) {
mListener.onProgressChanged(mFile, progress);
}
break;
case 60:
if (mListener != null) {
mListener.onFinished(mFile);
}
break;
case 70:
if (mListener != null) {
mListener.onFaliure(mFile);
}
break;
}
}
};
public void createServerSocket() {
try {
mServerSocket = new ServerSocket();
mServerSocket.setReuseAddress(true);
mServerSocket.bind(new InetSocketAddress(PORT));
mSocket = mServerSocket.accept();
Log.e(TAG, "客户端IP地址 : " + mSocket.getRemoteSocketAddress());
mInputStream = mSocket.getInputStream();
mObjectInputStream = new ObjectInputStream(mInputStream);
FileBean fileBean = (FileBean) mObjectInputStream.readObject();
String name = new File(fileBean.filePath).getName();
Log.e(TAG, "客户端传递的文件名称 : " + name);
Log.e(TAG, "客户端传递的MD5 : " + fileBean.md5);
mFile = new File(FileUtils.SdCardPath(name));
mFileOutputStream = new FileOutputStream(mFile);
//开始接收文件
mHandler.sendEmptyMessage(40);
byte bytes[] = new byte[1024];
int len;
long total = 0;
int progress;
while ((len = mInputStream.read(bytes)) != -1) {
mFileOutputStream.write(bytes, 0, len);
total += len;
progress = (int) ((total * 100) / fileBean.fileLength);
Log.e(TAG, "文件接收进度: " + progress);
Message message = Message.obtain();
message.what = 50;
message.obj = progress;
mHandler.sendMessage(message);
}
//新写入文件的MD5
String md5New = Md5Util.getMd5(mFile);
//发送过来的MD5
String md5Old = fileBean.md5;
if (md5New != null || md5Old != null) {
if (md5New.equals(md5Old)) {
mHandler.sendEmptyMessage(60);
Log.e(TAG, “文件接收成功”);
}
} else {
mHandler.sendEmptyMessage(70);
}
mServerSocket.close();
mInputStream.close();
mObjectInputStream.close();
mFileOutputStream.close();
} catch (Exception e) {
mHandler.sendEmptyMessage(70);
Log.e(TAG, “文件接收异常”);
}
}
public void clean() {
if (mServerSocket != null) {
try {
mServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (mInputStream != null) {
try {
mInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (mObjectInputStream != null) {
try {
mObjectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (mFileOutputStream != null) {
try {
mFileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
让服务端的ReceiveFileActivity实现ProgressReceiveListener接口,为了初始化ProgressReceiveListener需要在开启服务之后绑定服务,监听文件的接收情况,从而更新接受进度,核心代码如下:
[java] view plain copy
-
private ServiceConnection serviceConnection = new ServiceConnection() {
-
@Override
-
public void onServiceConnected(ComponentName name, IBinder service) {
-
//调用服务里面的方法进行绑定
-
mBinder = (Wifip2pService.MyBinder) service;
-
mBinder.initListener(ReceiveFileActivity.this);
-
}
-
@Override
-
public void onServiceDisconnected(ComponentName name) {
-
//服务断开重新绑定
-
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
-
}
-
};
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//调用服务里面的方法进行绑定
mBinder = (Wifip2pService.MyBinder) service;
mBinder.initListener(ReceiveFileActivity.this);
}
@Override
public void onServiceDisconnected(ComponentName name) {
//服务断开重新绑定
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
};
[java] view plain copy
-
Intent intent = new Intent(ReceiveFileActivity.this, Wifip2pService.class);
-
startService(intent);
-
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
Intent intent = new Intent(ReceiveFileActivity.this, Wifip2pService.class);
startService(intent);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
在每次接收完毕文件的时候需要释放Socket资源重新准备接收下次文件,因此需要在onFinished回调中重启一次服务,为下次的接收做好准备:
[java] view plain copy
-
@Override
-
public void onFinished(File file) {
-
Log.e(TAG, ”接收完成”);
-
Toast.makeText(this, file.getName() + “接收完毕!”, Toast.LENGTH_SHORT).show();
-
//接收完毕后再次启动服务等待下载一次连接
-
clear();
-
startService(mIntent);
-
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
-
}
@Override
public void onFinished(File file) {
Log.e(TAG, “接收完成”);
Toast.makeText(this, file.getName() + “接收完毕!”, Toast.LENGTH_SHORT).show();
//接收完毕后再次启动服务等待下载一次连接
clear();
startService(mIntent);
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
最后别忘记了当Activity关闭的时候释放资源,解绑服务:
[java] view plain copy
-
@Override
-
protected void onDestroy() {
-
super.onDestroy();
-
clear();
-
}
@Override
protected void onDestroy() {
super.onDestroy();
clear();
}
[java] view plain copy
-
private void clear() {
-
if (serviceConnection != null) {
-
unbindService(serviceConnection);
-
}
-
if (mIntent != null) {
-
stopService(mIntent);
-
}
-
}
private void clear() {
if (serviceConnection != null) {
unbindService(serviceConnection);
}
if (mIntent != null) {
stopService(mIntent);
}
}
以上,就是WIFIP2P服务端的代码详解。至此关于WIFIP2P的应用已经介绍完毕,如果有什么问题欢迎大家提出。最后总结一下WIFIP2P的整体流程:
1、声明权限。
2、清单文件注册权限。
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-lf5DZG8F-1718992092013)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取
回调中重启一次服务,为下次的接收做好准备:
[java] view plain copy
-
@Override
-
public void onFinished(File file) {
-
Log.e(TAG, ”接收完成”);
-
Toast.makeText(this, file.getName() + “接收完毕!”, Toast.LENGTH_SHORT).show();
-
//接收完毕后再次启动服务等待下载一次连接
-
clear();
-
startService(mIntent);
-
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
-
}
@Override
public void onFinished(File file) {
Log.e(TAG, “接收完成”);
Toast.makeText(this, file.getName() + “接收完毕!”, Toast.LENGTH_SHORT).show();
//接收完毕后再次启动服务等待下载一次连接
clear();
startService(mIntent);
bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);
}
最后别忘记了当Activity关闭的时候释放资源,解绑服务:
[java] view plain copy
-
@Override
-
protected void onDestroy() {
-
super.onDestroy();
-
clear();
-
}
@Override
protected void onDestroy() {
super.onDestroy();
clear();
}
[java] view plain copy
-
private void clear() {
-
if (serviceConnection != null) {
-
unbindService(serviceConnection);
-
}
-
if (mIntent != null) {
-
stopService(mIntent);
-
}
-
}
private void clear() {
if (serviceConnection != null) {
unbindService(serviceConnection);
}
if (mIntent != null) {
stopService(mIntent);
}
}
以上,就是WIFIP2P服务端的代码详解。至此关于WIFIP2P的应用已经介绍完毕,如果有什么问题欢迎大家提出。最后总结一下WIFIP2P的整体流程:
1、声明权限。
2、清单文件注册权限。
最后
小编这些年深知大多数初中级Android工程师,想要提升自己,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
[外链图片转存中…(img-lf5DZG8F-1718992092013)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人
都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
资料⬅专栏获取