Android无网络传输文件之WifiP2P

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端口,获取信息流,写入文件,这就是整个传输信息中客户端和服务端的交互过程。按照这样的步骤,客户端需要实现以下几点:

  1. 搜索设备信息

  2. 选择设备连接服务端组群信息

  3. 选择要传输的文件路径

  4. 把该文件通过socket发送到服务端

我们就按照这四点一步步实现:

1、搜索设备信息

通过mWifiP2pManager的discoverPeers方法进行搜索,有搜索成功和搜索失败的回调,搜索到设备时候会触发WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION 广播,此时就可以调用 requestPeers 方法获取设备列表信息,在回调方法onPeersInfo中可以得到设备信息。

[java] view plain copy

print ?

  1. mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {

  2. @Override

  3. public void onSuccess() {

  4. Log.e(TAG, ”搜索设备成功”);

  5. }

  6. @Override

  7. public void onFailure(int reasonCode) {

  8. Log.e(TAG, ”搜索设备失败”);

  9. }

  10. });

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

print ?

  1. WifiP2pConfig config = new WifiP2pConfig();

  2. if (wifiP2pDevice != null) {

  3. //需要将address,WpsInfo.PBC信息包装成WifiP2pConfig

  4. config.deviceAddress = wifiP2pDevice.deviceAddress;

  5. config.wps.setup = WpsInfo.PBC;

  6. mWifiP2pManager.connect(mChannel, config, new WifiP2pManager.ActionListener() {

  7. @Override

  8. public void onSuccess() {

  9. Log.e(TAG, ”连接成功”);

  10. Toast.makeText(SendFileActivity.this, “连接成功”, Toast.LENGTH_SHORT).show();

  11. }

  12. @Override

  13. public void onFailure(int reason) {

  14. Log.e(TAG, ”连接失败”);

  15. Toast.makeText(SendFileActivity.this, “连接失败”, Toast.LENGTH_SHORT).show();

  16. }

  17. });

  18. }

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

print ?

  1. Intent intent = new Intent(Intent.ACTION_GET_CONTENT);

  2. intent.setType(”*/*”);

  3. intent.addCategory(Intent.CATEGORY_OPENABLE);

  4. 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

print ?

  1. public class FileBean implements Serializable{

  2. public static final String serialVersionUID = “6321689524634663223356”;

  3. public String filePath;

  4. public long fileLength;

  5. //MD5码:保证文件的完整性

  6. public String md5;

  7. public FileBean(String filePath, long fileLength, String md5) {

  8. this.filePath = filePath;

  9. this.fileLength = fileLength;

  10. this.md5 = md5;

  11. }

  12. }

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

print ?

  1. @Override

  2. protected void onActivityResult(int requestCode, int resultCode, Intent data) {

  3. super.onActivityResult(requestCode, resultCode, data);

  4. if (requestCode == 10) {

  5. if (resultCode == RESULT_OK) {

  6. Uri uri = data.getData();

  7. if (uri != null) {

  8. String path = FileUtils.getAbsolutePath(this, uri);

  9. if (path != null) {

  10. final File file = new File(path);

  11. if (!file.exists() || mWifiP2pInfo == null) {

  12. Toast.makeText(SendFileActivity.this,“文件路径找不到”,Toast.LENGTH_SHORT).show();

  13. return;

  14. }

  15. String md5 = Md5Util.getMd5(file);

  16. FileBean fileBean = new FileBean(file.getPath(), file.length(), md5);

  17. String hostAddress = mWifiP2pInfo.groupOwnerAddress.getHostAddress();

  18. new SendTask(SendFileActivity.this, fileBean).execute(hostAddress);

  19. }

  20. }

  21. }

  22. }

  23. }

@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

print ?

  1. public interface ProgressSendListener {

  2. //当传输进度发生变化时

  3. void onProgressChanged(File file, int progress);

  4. //当传输结束时

  5. void onFinished(File file);

  6. //传输失败时

  7. void onFaliure(File file);

  8. }

public interface ProgressSendListener {

//当传输进度发生变化时

void onProgressChanged(File file, int progress);

//当传输结束时

void onFinished(File file);

//传输失败时

void onFaliure(File file);

}

回调接口在socket的操作中进行设置回调数据,关于socket的完整代码如下:

[java] view plain copy

print ?

  1. public class SendSocket {

  2. public static final String TAG = “SendSocket”;

  3. public static final int PORT = 10000;

  4. private FileBean mFileBean;

  5. private String mAddress;

  6. private File mFile;

  7. private ProgressSendListener mlistener;

  8. private Handler mHandler = new Handler(Looper.getMainLooper()) {

  9. @Override

  10. public void handleMessage(Message msg) {

  11. super.handleMessage(msg);

  12. switch (msg.what) {

  13. case 10:

  14. int progress = (int) msg.obj;

  15. if (mlistener != null) {

  16. mlistener.onProgressChanged(mFile, progress);

  17. }

  18. break;

  19. case 20:

  20. if (mlistener != null) {

  21. mlistener.onFinished(mFile);

  22. }

  23. break;

  24. case 30:

  25. if (mlistener != null) {

  26. mlistener.onFaliure(mFile);

  27. }

  28. break;

  29. }

  30. }

  31. };

  32. public SendSocket(FileBean fileBean, String address, ProgressSendListener listener) {

  33. mFileBean = fileBean;

  34. mAddress = address;

  35. mlistener = listener;

  36. }

  37. public void createSendSocket() {

  38. try {

  39. Socket socket = new Socket();

  40. InetSocketAddress inetSocketAddress = new InetSocketAddress(mAddress, PORT);

  41. socket.connect(inetSocketAddress);

  42. OutputStream outputStream = socket.getOutputStream();

  43. ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);

  44. objectOutputStream.writeObject(mFileBean);

  45. mFile = new File(mFileBean.filePath);

  46. FileInputStream inputStream = new FileInputStream(mFile);

  47. long size = mFileBean.fileLength;

  48. long total = 0;

  49. byte bytes[] = new byte[1024];

  50. int len;

  51. while ((len = inputStream.read(bytes)) != -1) {

  52. outputStream.write(bytes, 0, len);

  53. total += len;

  54. int progress = (int) ((total * 100) / size);

  55. Log.e(TAG, ”文件发送进度:” + progress);

  56. Message message = Message.obtain();

  57. message.what = 10;

  58. message.obj = progress;

  59. mHandler.sendMessage(message);

  60. }

  61. outputStream.close();

  62. objectOutputStream.close();

  63. inputStream.close();

  64. socket.close();

  65. mHandler.sendEmptyMessage(20);

  66. Log.e(TAG, ”文件发送成功”);

  67. } catch (Exception e) {

  68. mHandler.sendEmptyMessage(30);

  69. Log.e(TAG, ”文件发送异常”);

  70. }

  71. }

  72. }

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

print ?

  1. @Override

  2. protected Void doInBackground(String… strings) {

  3. mSendSocket = new SendSocket(mFileBean, strings[0], this);

  4. mSendSocket.createSendSocket();

  5. return null;

  6. }

@Override

protected Void doInBackground(String… strings) {

mSendSocket = new SendSocket(mFileBean, strings[0], this);

mSendSocket.createSendSocket();

return null;

}

就这样客户端的功能完成。

五、服务端创建


服务端创主要用监听客户端发送过来的文件,接收传送过来的文件。建一个服务端的ReceiveFileActivity继承自BaseActivity,作为服务端的界面,需要实现以下功能:

  1. 创建组群信息,供客户端连接

  2. 移除组群信息

  3. 监听客户端发送过来的文件信息

接下来分别实现以上三个功能。

1、创建组群信息,供客户端连接

使用WifiP2pManager的createGroup方法进行设置,有设置成功和失败的回调。

[java] view plain copy

print ?

  1. mWifiP2pManager.createGroup(mChannel, new WifiP2pManager.ActionListener() {

  2. @Override

  3. public void onSuccess() {

  4. Log.e(TAG, ”创建群组成功”);

  5. Toast.makeText(ReceiveFileActivity.this, “创建群组成功”, Toast.LENGTH_SHORT).show();

  6. }

  7. @Override

  8. public void onFailure(int reason) {

  9. Log.e(TAG, ”创建群组失败: ” + reason);

  10. Toast.makeText(ReceiveFileActivity.this, “创建群组失败,请移除已有的组群或者连接同一WIFI重试”, Toast.LENGTH_SHORT).show();

  11. }

  12. });

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

print ?

  1. mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {

  2. @Override

  3. public void onSuccess() {

  4. Log.e(TAG, ”移除组群成功”);

  5. Toast.makeText(ReceiveFileActivity.this, “移除组群成功”, Toast.LENGTH_SHORT).show();

  6. }

  7. @Override

  8. public void onFailure(int reason) {

  9. Log.e(TAG, ”移除组群失败”);

  10. Toast.makeText(ReceiveFileActivity.this, “移除组群失败,请创建组群重试”, Toast.LENGTH_SHORT).show();

  11. }

  12. });

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

print ?

  1. public class Wifip2pService extends IntentService {

  2. private static final String TAG = “Wifip2pService”;

  3. private ReceiveSocket mReceiveSocket;

  4. public Wifip2pService() {

  5. super(“Wifip2pService”);

  6. }

  7. @Nullable

  8. @Override

  9. public IBinder onBind(Intent intent) {

  10. return new MyBinder();

  11. }

  12. public class MyBinder extends Binder {

  13. public MyBinder() {

  14. super();

  15. }

  16. public void initListener(ReceiveSocket.ProgressReceiveListener listener){

  17. mReceiveSocket.setOnProgressReceiveListener(listener);

  18. }

  19. }

  20. @Override

  21. public void onCreate() {

  22. super.onCreate();

  23. Log.e(TAG, ”服务启动了”);

  24. }

  25. @Override

  26. protected void onHandleIntent(Intent intent) {

  27. mReceiveSocket = new ReceiveSocket();

  28. mReceiveSocket.createServerSocket();

  29. Log.e(TAG, ”传输完毕”);

  30. }

  31. @Override

  32. public void onDestroy() {

  33. super.onDestroy();

  34. mReceiveSocket.clean();

  35. }

  36. }

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

print ?

  1. private ProgressReceiveListener mListener;

  2. public void setOnProgressReceiveListener(ProgressReceiveListener listener) {

  3. mListener = listener;

  4. }

  5. public interface ProgressReceiveListener {

  6. //开始传输

  7. void onSatrt();

  8. //当传输进度发生变化时

  9. void onProgressChanged(File file, int progress);

  10. //当传输结束时

  11. void onFinished(File file);

  12. //传输失败回调

  13. void onFaliure(File file);

  14. }

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

print ?

  1. public class ReceiveSocket {

  2. public static final String TAG = “ReceiveSocket”;

  3. public static final int PORT = 10000;

  4. private ServerSocket mServerSocket;

  5. private Socket mSocket;

  6. private InputStream mInputStream;

  7. private ObjectInputStream mObjectInputStream;

  8. private FileOutputStream mFileOutputStream;

  9. private File mFile;

  10. private Handler mHandler = new Handler(Looper.getMainLooper()) {

  11. @Override

  12. public void handleMessage(Message msg) {

  13. super.ha
    ndleMessage(msg);

  14. switch (msg.what) {

  15. case 40:

  16. if (mListener != null) {

  17. mListener.onSatrt();

  18. }

  19. break;

  20. case 50:

  21. int progress = (int) msg.obj;

  22. if (mListener != null) {

  23. mListener.onProgressChanged(mFile, progress);

  24. }

  25. break;

  26. case 60:

  27. if (mListener != null) {

  28. mListener.onFinished(mFile);

  29. }

  30. break;

  31. case 70:

  32. if (mListener != null) {

  33. mListener.onFaliure(mFile);

  34. }

  35. break;

  36. }

  37. }

  38. };

  39. public void createServerSocket() {

  40. try {

  41. mServerSocket = new ServerSocket();

  42. mServerSocket.setReuseAddress(true);

  43. mServerSocket.bind(new InetSocketAddress(PORT));

  44. mSocket = mServerSocket.accept();

  45. Log.e(TAG, ”客户端IP地址 : ” + mSocket.getRemoteSocketAddress());

  46. mInputStream = mSocket.getInputStream();

  47. mObjectInputStream = new ObjectInputStream(mInputStream);

  48. FileBean fileBean = (FileBean) mObjectInputStream.readObject();

  49. String name = new File(fileBean.filePath).getName();

  50. Log.e(TAG, ”客户端传递的文件名称 : ” + name);

  51. Log.e(TAG, ”客户端传递的MD5 : ” + fileBean.md5);

  52. mFile = new File(FileUtils.SdCardPath(name));

  53. mFileOutputStream = new FileOutputStream(mFile);

  54. //开始接收文件

  55. mHandler.sendEmptyMessage(40);

  56. byte bytes[] = new byte[1024];

  57. int len;

  58. long total = 0;

  59. int progress;

  60. while ((len = mInputStream.read(bytes)) != -1) {

  61. mFileOutputStream.write(bytes, 0, len);

  62. total += len;

  63. progress = (int) ((total * 100) / fileBean.fileLength);

  64. Log.e(TAG, ”文件接收进度: ” + progress);

  65. Message message = Message.obtain();

  66. message.what = 50;

  67. message.obj = progress;

  68. mHandler.sendMessage(message);

  69. }

  70. //新写入文件的MD5

  71. String md5New = Md5Util.getMd5(mFile);

  72. //发送过来的MD5

  73. String md5Old = fileBean.md5;

  74. if (md5New != null || md5Old != null) {

  75. if (md5New.equals(md5Old)) {

  76. mHandler.sendEmptyMessage(60);

  77. Log.e(TAG, ”文件接收成功”);

  78. }

  79. } else {

  80. mHandler.sendEmptyMessage(70);

  81. }

  82. mServerSocket.close();

  83. mInputStream.close();

  84. mObjectInputStream.close();

  85. mFileOutputStream.close();

  86. } catch (Exception e) {

  87. mHandler.sendEmptyMessage(70);

  88. Log.e(TAG, ”文件接收异常”);

  89. }

  90. }

  91. public void clean() {

  92. if (mServerSocket != null) {

  93. try {

  94. mServerSocket.close();

  95. } catch (IOException e) {

  96. e.printStackTrace();

  97. }

  98. }

  99. if (mInputStream != null) {

  100. try {

  101. mInputStream.close();

  102. } catch (IOException e) {

  103. e.printStackTrace();

  104. }

  105. }

  106. if (mObjectInputStream != null) {

  107. try {

  108. mObjectInputStream.close();

  109. } catch (IOException e) {

  110. e.printStackTrace();

  111. }

  112. }

  113. if (mFileOutputStream != null) {

  114. try {

  115. mFileOutputStream.close();

  116. } catch (IOException e) {

  117. e.printStackTrace();

  118. }

  119. }

  120. }

  121. }

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

print ?

  1. private ServiceConnection serviceConnection = new ServiceConnection() {

  2. @Override

  3. public void onServiceConnected(ComponentName name, IBinder service) {

  4. //调用服务里面的方法进行绑定

  5. mBinder = (Wifip2pService.MyBinder) service;

  6. mBinder.initListener(ReceiveFileActivity.this);

  7. }

  8. @Override

  9. public void onServiceDisconnected(ComponentName name) {

  10. //服务断开重新绑定

  11. bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);

  12. }

  13. };

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

print ?

  1. Intent   intent = new Intent(ReceiveFileActivity.this, Wifip2pService.class);

  2. startService(intent);

  3. 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

print ?

  1. @Override

  2. public void onFinished(File file) {

  3. Log.e(TAG, ”接收完成”);

  4. Toast.makeText(this, file.getName() + “接收完毕!”, Toast.LENGTH_SHORT).show();

  5. //接收完毕后再次启动服务等待下载一次连接

  6. clear();

  7. startService(mIntent);

  8. bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);

  9. }

@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

print ?

  1. @Override

  2. protected void onDestroy() {

  3. super.onDestroy();

  4. clear();

  5. }

@Override

protected void onDestroy() {

super.onDestroy();

clear();

}

[java] view plain copy

print ?

  1. private void clear() {

  2. if (serviceConnection != null) {

  3. unbindService(serviceConnection);

  4. }

  5. if (mIntent != null) {

  6. stopService(mIntent);

  7. }

  8. }

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

print ?

  1. @Override

  2. public void onFinished(File file) {

  3. Log.e(TAG, ”接收完成”);

  4. Toast.makeText(this, file.getName() + “接收完毕!”, Toast.LENGTH_SHORT).show();

  5. //接收完毕后再次启动服务等待下载一次连接

  6. clear();

  7. startService(mIntent);

  8. bindService(mIntent, serviceConnection, Context.BIND_AUTO_CREATE);

  9. }

@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

print ?

  1. @Override

  2. protected void onDestroy() {

  3. super.onDestroy();

  4. clear();

  5. }

@Override

protected void onDestroy() {

super.onDestroy();

clear();

}

[java] view plain copy

print ?

  1. private void clear() {

  2. if (serviceConnection != null) {

  3. unbindService(serviceConnection);

  4. }

  5. if (mIntent != null) {

  6. stopService(mIntent);

  7. }

  8. }

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行业感兴趣的新人

都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

资料⬅专栏获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值