ReceiveFilesActivity.java 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. package com.example.socketdemo.activity;
  2. import android.content.DialogInterface;
  3. import android.content.IntentFilter;
  4. import android.net.wifi.ScanResult;
  5. import android.net.wifi.WifiManager;
  6. import android.os.Handler;
  7. import android.os.Message;
  8. import android.support.v7.app.AlertDialog;
  9. import android.support.v7.widget.DividerItemDecoration;
  10. import android.support.v7.widget.LinearLayoutManager;
  11. import android.support.v7.widget.RecyclerView;
  12. import android.view.LayoutInflater;
  13. import android.view.View;
  14. import android.widget.Button;
  15. import android.widget.CheckBox;
  16. import android.widget.CompoundButton;
  17. import android.widget.EditText;
  18. import android.widget.ProgressBar;
  19. import android.widget.TextView;
  20. import com.example.socketdemo.R;
  21. import com.example.socketdemo.base.AppContext;
  22. import com.example.socketdemo.base.BaseActivity;
  23. import com.example.socketdemo.base.BaseTransfer;
  24. import com.example.socketdemo.bean.FileInfo;
  25. import com.example.socketdemo.common.Consts;
  26. import com.example.socketdemo.common.FileReceiver;
  27. import com.example.socketdemo.common.SpaceItemDecoration;
  28. import com.example.socketdemo.receiver.WifiBroadcaseReceiver;
  29. import com.example.socketdemo.utils.FileUtils;
  30. import com.example.socketdemo.utils.LogUtils;
  31. import com.example.socketdemo.utils.NetUtils;
  32. import com.example.socketdemo.wifitools.WifiMgr;
  33. import com.zhy.adapter.recyclerview.CommonAdapter;
  34. import com.zhy.adapter.recyclerview.MultiItemTypeAdapter;
  35. import com.zhy.adapter.recyclerview.base.ViewHolder;
  36. import java.io.IOException;
  37. import java.net.DatagramPacket;
  38. import java.net.DatagramSocket;
  39. import java.net.InetAddress;
  40. import java.net.InetSocketAddress;
  41. import java.net.Socket;
  42. import java.util.ArrayList;
  43. import java.util.Collections;
  44. import java.util.List;
  45. import java.util.Map;
  46. import butterknife.BindView;
  47. import butterknife.OnClick;
  48. /**
  49. * Created by AA on 2017/3/28.
  50. */
  51. public class ReceiveFilesActivity extends BaseActivity implements MultiItemTypeAdapter.OnItemClickListener {
  52. /**
  53. * 接收端初始化完毕
  54. */
  55. public static final int MSG_FILE_RECEIVER_INIT_SUCCESS = 0x661;
  56. /**
  57. * 更新适配器
  58. */
  59. public static final int MSG_UPDATE_ADAPTER = 0x662;
  60. /**
  61. * 发送选中要接收的文件列表
  62. */
  63. public static final int MSG_SEND_RECEIVE_FILE_LIST = 0x663;
  64. /**
  65. * 添加接收文件
  66. */
  67. public static final int MSG_ADD_FILEINFO = 0x664;
  68. /**
  69. * 更新进度条
  70. */
  71. public static final int MSG_UPDATE_PROGRESS = 0x665;
  72. /**
  73. * 设置当前状态
  74. */
  75. public static final int MSG_SET_STATUS = 0x666;
  76. @BindView(R.id.tv_receive_files_status)
  77. TextView tvStatus;
  78. @BindView(R.id.btn_receive_files)
  79. Button btnSendFileList;
  80. @BindView(R.id.rv_receive_files_choose_hotspot)
  81. RecyclerView mChooseHotspotRecyclerView;
  82. private CommonAdapter<ScanResult> mChooseHotspotAdapter;
  83. @BindView(R.id.rv_receive_files)
  84. RecyclerView mReceiveFilesRecyclerView;
  85. private CommonAdapter<Map.Entry<String, FileInfo>> mReceiveFilesAdapter;
  86. /**
  87. * 选中待发送的文件列表
  88. */
  89. private List<FileInfo> mSendFileInfos = new ArrayList<>();
  90. /**
  91. * 接收文件线程列表数据
  92. */
  93. private List<FileReceiver> mFileReceiverList = new ArrayList<>();
  94. /**
  95. * WiFi工具类
  96. */
  97. private WifiMgr mWifiMgr;
  98. /**
  99. * 扫描到的可用WiFi列表
  100. */
  101. private List<ScanResult> mScanResults = new ArrayList<>();
  102. /**
  103. * 用来接收文件的Socket
  104. */
  105. private Socket mClientSocket;
  106. /**
  107. * UDP Socket
  108. */
  109. private DatagramSocket mDatagramSocket;
  110. /**
  111. * 接收文件线程
  112. */
  113. private ReceiveServerRunnable mReceiveServerRunnable;
  114. /**
  115. * 是否已发送初始化指令
  116. */
  117. private boolean mIsSendInitOrder;
  118. /**
  119. * 获取权限是否成功
  120. */
  121. private boolean mIsPermissionGranted;
  122. /**
  123. * 当前所选WiFi的SSID
  124. */
  125. private String mSelectedSSID;
  126. private Handler mHandler = new Handler() {
  127. @Override
  128. public void handleMessage(Message msg) {
  129. super.handleMessage(msg);
  130. if (msg.what == MSG_FILE_RECEIVER_INIT_SUCCESS) {
  131. //告知发送端,接收端初始化完毕
  132. sendInitSuccessToFileSender();
  133. } else if (msg.what == MSG_UPDATE_ADAPTER) {
  134. //更新适配器
  135. setupReceiveFilesAdapter();
  136. } else if (msg.what == MSG_SEND_RECEIVE_FILE_LIST) {
  137. //发送选中要接收的文件列表
  138. sendFileListToFileSender();
  139. } else if (msg.what == MSG_ADD_FILEINFO) {
  140. //添加接收文件
  141. mReceiveFilesAdapter.notifyDataSetChanged();
  142. } else if (msg.what == MSG_UPDATE_PROGRESS) {
  143. //更新进度条
  144. int position = msg.arg1;
  145. int progress = msg.arg2;
  146. if (position >= 0 && position < mReceiveFilesAdapter.getItemCount()) {
  147. updateProgress(position, progress);
  148. }
  149. } else if (msg.what == MSG_SET_STATUS) {
  150. //设置当前状态
  151. setStatus(msg.obj.toString());
  152. }
  153. }
  154. };
  155. @Override
  156. protected int getLayoutId() {
  157. return R.layout.activity_receive_files;
  158. }
  159. @Override
  160. protected String getTitleText() {
  161. return "接收文件";
  162. }
  163. @Override
  164. protected void initData() {
  165. //请求权限
  166. requestPermission(PERMISSION_CONNECT_WIFI, PERMISSION_REQ_CONNECT_WIFI);
  167. }
  168. @Override
  169. protected void onResume() {
  170. super.onResume();
  171. if(mIsPermissionGranted && mWifiBroadcaseReceiver == null) {
  172. registerWifiReceiver();
  173. }
  174. }
  175. @Override
  176. protected void onPause() {
  177. super.onPause();
  178. if(mWifiBroadcaseReceiver != null) {
  179. unregisterWifiReceiver();
  180. }
  181. }
  182. @Override
  183. public void onBackPressed() {
  184. if(hasFileReceiving()) {
  185. showTipsDialog("文件正在接收,是否退出?", "是", new DialogInterface.OnClickListener() {
  186. @Override
  187. public void onClick(DialogInterface dialog, int which) {
  188. finishActivity();
  189. }
  190. }, "否", null);
  191. } else {
  192. finishActivity();
  193. }
  194. }
  195. @Override
  196. protected void permissionSuccess(int requestCode) {
  197. super.permissionSuccess(requestCode);
  198. if(requestCode == PERMISSION_REQ_CONNECT_WIFI) {
  199. //权限请求成功
  200. mIsPermissionGranted = true;
  201. //开启WiFi,监听WiFi广播
  202. registerWifiReceiver();
  203. mWifiMgr = new WifiMgr(getContext());
  204. if(mWifiMgr.isWifiEnabled()) {
  205. setStatus("正在扫描可用WiFi...");
  206. mWifiMgr.startScan();
  207. } else {
  208. mWifiMgr.openWifi();
  209. }
  210. }
  211. }
  212. @Override
  213. protected void permissionFail(int requestCode) {
  214. super.permissionFail(requestCode);
  215. if(requestCode == PERMISSION_REQ_CONNECT_WIFI) {
  216. //权限请求失败
  217. mIsPermissionGranted = false;
  218. showTipsDialog("WiFi权限获取失败", new DialogInterface.OnClickListener() {
  219. @Override
  220. public void onClick(DialogInterface dialog, int which) {
  221. onBackPressed();
  222. }
  223. });
  224. }
  225. }
  226. /**
  227. * 注册监听WiFi操作的系统广播
  228. */
  229. private void registerWifiReceiver() {
  230. IntentFilter filter = new IntentFilter();
  231. filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
  232. filter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
  233. filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
  234. registerReceiver(mWifiBroadcaseReceiver, filter);
  235. }
  236. /**
  237. * 反注册WiFi相关的系统广播
  238. */
  239. private void unregisterWifiReceiver() {
  240. if (mWifiBroadcaseReceiver != null) {
  241. unregisterReceiver(mWifiBroadcaseReceiver);
  242. mWifiBroadcaseReceiver = null;
  243. }
  244. }
  245. /**
  246. * 开启文件接收服务
  247. */
  248. private void initReceiverServer() {
  249. mReceiveServerRunnable = new ReceiveServerRunnable();
  250. new Thread(mReceiveServerRunnable).start();
  251. }
  252. /**
  253. * 告知发送端初始化完毕
  254. */
  255. private void sendInitSuccessToFileSender() {
  256. new Thread() {
  257. @Override
  258. public void run() {
  259. try {
  260. //确保WiFi连接后获取正确IP地址
  261. int tryCount = 0;
  262. String serverIp = mWifiMgr.getIpAddressFromHotspot();
  263. while (serverIp.equals(Consts.DEFAULT_UNKNOW_IP) && tryCount < Consts.DEFAULT_TRY_COUNT) {
  264. Thread.sleep(1000);
  265. serverIp = mWifiMgr.getIpAddressFromHotspot();
  266. tryCount ++;
  267. }
  268. //是否可以ping通指定IP地址
  269. tryCount = 0;
  270. while (!NetUtils.pingIpAddress(serverIp) && tryCount < Consts.DEFAULT_TRY_COUNT) {
  271. Thread.sleep(500);
  272. LogUtils.i("Try to ping ------" + serverIp + " - " + tryCount);
  273. tryCount ++;
  274. }
  275. //创建UDP通信
  276. if(mDatagramSocket == null) {
  277. //解决:java.net.BindException: bind failed: EADDRINUSE (Address already in use)
  278. mDatagramSocket = new DatagramSocket(null);
  279. mDatagramSocket.setReuseAddress(true);
  280. mDatagramSocket.bind(new InetSocketAddress(Consts.DEFAULT_SERVER_UDP_PORT));
  281. }
  282. //发送初始化完毕指令
  283. InetAddress ipAddress = InetAddress.getByName(serverIp);
  284. byte[] sendData = Consts.MSG_FILE_RECEIVER_INIT_SUCCESS.getBytes(BaseTransfer.UTF_8);
  285. DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, ipAddress, Consts.DEFAULT_SERVER_UDP_PORT);
  286. mDatagramSocket.send(sendPacket);
  287. LogUtils.i("发送消息 ------->>>" + Consts.MSG_FILE_RECEIVER_INIT_SUCCESS);
  288. //接收文件列表
  289. while (true) {
  290. byte[] receiveData = new byte[1024];
  291. DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
  292. mDatagramSocket.receive(receivePacket);
  293. String response = new String(receivePacket.getData()).trim();
  294. if(isNotEmptyString(response)) {
  295. //发送端发来的文件列表
  296. LogUtils.e("接收到的消息 -------->>>" + response);
  297. parseFileInfoList(response);
  298. }
  299. }
  300. } catch (Exception e) {
  301. e.printStackTrace();
  302. }
  303. }
  304. }.start();
  305. }
  306. /**
  307. * 设置WiFi列表适配器
  308. */
  309. private void setupWifiAdapter() {
  310. if(mChooseHotspotAdapter == null) {
  311. mChooseHotspotAdapter = new CommonAdapter<ScanResult>(getContext(), R.layout.item_choose_hotspot, mScanResults) {
  312. @Override
  313. protected void convert(ViewHolder holder, ScanResult scanResult, int position) {
  314. holder.setText(R.id.tv_item_choose_hotspot_ssid, scanResult.SSID);
  315. holder.setText(R.id.tv_item_choose_hotspot_level, String.format(getString(R.string.item_level), scanResult.level));
  316. }
  317. };
  318. //设置点击事件
  319. mChooseHotspotAdapter.setOnItemClickListener(this);
  320. //设置适配器
  321. mChooseHotspotRecyclerView.setAdapter(mChooseHotspotAdapter);
  322. //设置间隔
  323. mChooseHotspotRecyclerView.addItemDecoration(new SpaceItemDecoration(10));
  324. mChooseHotspotRecyclerView.setVisibility(View.VISIBLE);
  325. } else {
  326. mChooseHotspotAdapter.notifyDataSetChanged();
  327. }
  328. }
  329. /**
  330. * 设置接收文件列表适配器
  331. */
  332. private void setupReceiveFilesAdapter() {
  333. List<Map.Entry<String, FileInfo>> fileInfos = AppContext.getAppContext().getReceiverFileInfoMap();
  334. Collections.sort(fileInfos, Consts.DEFAULT_COMPARATOR);
  335. //设置适配器
  336. mReceiveFilesAdapter = new CommonAdapter<Map.Entry<String, FileInfo>>(getContext(), R.layout.item_files_selector, fileInfos) {
  337. @Override
  338. protected void convert(ViewHolder holder, Map.Entry<String, FileInfo> fileInfoMap, int position) {
  339. final FileInfo fileInfo = fileInfoMap.getValue();
  340. //文件路径
  341. holder.setText(R.id.tv_item_files_selector_file_path, fileInfo.getFilePath());
  342. //文件大小
  343. holder.setText(R.id.tv_item_files_selector_size, FileUtils.FormetFileSize(fileInfo.getSize()));
  344. //文件接收状态
  345. if(fileInfo.getProgress() >= 100) {
  346. holder.setText(R.id.tv_item_files_selector_status, "接收完毕");
  347. } else if(fileInfo.getProgress() == 0) {
  348. holder.setText(R.id.tv_item_files_selector_status, "准备接收");
  349. } else if(fileInfo.getProgress() < 100) {
  350. holder.setText(R.id.tv_item_files_selector_status, "正在接收");
  351. } else {
  352. holder.setText(R.id.tv_item_files_selector_status, "接收失败");
  353. }
  354. //文件接收进度
  355. ProgressBar progressBar = holder.getView(R.id.pb_item_files_selector);
  356. progressBar.setProgress(fileInfo.getProgress());
  357. //选中文件
  358. CheckBox checkBox = holder.getView(R.id.cb_item_files_selector);
  359. checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
  360. @Override
  361. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  362. if(isChecked) {
  363. mSendFileInfos.add(fileInfo);
  364. } else {
  365. mSendFileInfos.remove(fileInfo);
  366. }
  367. //选中的文件个数大于零才可点击底部按钮
  368. btnSendFileList.setEnabled(mSendFileInfos.size() > 0);
  369. }
  370. });
  371. }
  372. };
  373. mReceiveFilesRecyclerView.setAdapter(mReceiveFilesAdapter);
  374. //设置ListView样式
  375. mReceiveFilesRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
  376. //分割线
  377. mReceiveFilesRecyclerView.addItemDecoration(new DividerItemDecoration(getContext(), DividerItemDecoration.VERTICAL));
  378. }
  379. /**
  380. * 更新文件接收进度
  381. * @param position 文件索引
  382. * @param progress 接收进度
  383. */
  384. private void updateProgress(int position, int progress) {
  385. FileInfo fileInfo = mReceiveFilesAdapter.getDatas().get(position).getValue();
  386. fileInfo.setProgress(progress);
  387. mReceiveFilesAdapter.notifyItemChanged(position);
  388. if(position == AppContext.getAppContext().getReceiverFileInfoMap().size() - 1 && progress == 100) {
  389. toast("所有文件接收完毕");
  390. LogUtils.e("所有文件接收完毕");
  391. }
  392. }
  393. /**
  394. * 将字符串解析成FileInfo列表
  395. * @param jsonStr
  396. */
  397. private void parseFileInfoList(String jsonStr) {
  398. if(isNotEmptyString(jsonStr)) {
  399. List<FileInfo> fileInfos = FileInfo.toObjectList(jsonStr);
  400. if(!isEmptyList(fileInfos)) {
  401. for(FileInfo fileInfo : fileInfos) {
  402. if(fileInfo != null && isNotEmptyString(fileInfo.getFilePath())) {
  403. AppContext.getAppContext().addReceiverFileInfo(fileInfo);
  404. }
  405. }
  406. //更新适配器
  407. mHandler.sendEmptyMessage(MSG_UPDATE_ADAPTER);
  408. }
  409. }
  410. }
  411. /**
  412. * 发送选中的文件列表给发送端
  413. */
  414. private void sendFileListToFileSender() {
  415. new Thread() {
  416. @Override
  417. public void run() {
  418. try {
  419. //确保WiFi连接后获取正确IP地址
  420. String serverIp = mWifiMgr.getIpAddressFromHotspot();
  421. if(mDatagramSocket == null) {
  422. //解决:java.net.BindException: bind failed: EADDRINUSE (Address already in use)
  423. mDatagramSocket = new DatagramSocket(null);
  424. mDatagramSocket.setReuseAddress(true);
  425. mDatagramSocket.bind(new InetSocketAddress(Consts.DEFAULT_SERVER_UDP_PORT));
  426. }
  427. //发送选中的文件列表
  428. InetAddress ipAddress = InetAddress.getByName(serverIp);
  429. String jsonStr = FileInfo.toJsonStr(mSendFileInfos);
  430. DatagramPacket sendPacket = new DatagramPacket(jsonStr.getBytes(), jsonStr.getBytes().length, ipAddress, Consts.DEFAULT_SERVER_UDP_PORT);
  431. mDatagramSocket.send(sendPacket);
  432. LogUtils.i("Send Msg To FileSender ------->>>" + jsonStr);
  433. //发送开始发送文件指令
  434. byte[] sendData = Consts.MSG_START_SEND.getBytes(BaseTransfer.UTF_8);
  435. DatagramPacket sendPacket2 = new DatagramPacket(sendData, sendData.length, ipAddress, Consts.DEFAULT_SERVER_UDP_PORT);
  436. mDatagramSocket.send(sendPacket2);
  437. LogUtils.i("Send Msg To FileSender ------->>>" + sendData);
  438. } catch (Exception e) {
  439. e.printStackTrace();
  440. }
  441. }
  442. }.start();
  443. }
  444. /**
  445. * 显示WiFi密码输入框
  446. * @param title
  447. * @param listener
  448. */
  449. protected void showDialogWithEditText(String title, final OnWifiPasswordConfirmListener listener) {
  450. View dialogView = LayoutInflater.from(this).inflate(R.layout.layout_dialog_with_edittext, null);
  451. final EditText etPassword = (EditText) dialogView.findViewById(R.id.et_dialog_with_edittext);
  452. AlertDialog.Builder builder = new AlertDialog.Builder(this);
  453. builder.setTitle(title);
  454. builder.setView(dialogView);
  455. builder.setPositiveButton(getString(R.string.confirm), new DialogInterface.OnClickListener() {
  456. @Override
  457. public void onClick(DialogInterface dialog, int which) {
  458. if (listener != null) {
  459. listener.onConfirm(etPassword.getText().toString().trim());
  460. }
  461. }
  462. });
  463. builder.setNegativeButton(getString(R.string.cancel), null);
  464. builder.create().show();
  465. }
  466. /**
  467. * 设置状态
  468. * @param status
  469. */
  470. private void setStatus(String status) {
  471. tvStatus.setText(status);
  472. LogUtils.e(status);
  473. }
  474. /**
  475. * 是否还有文件在接收
  476. * @return
  477. */
  478. private boolean hasFileReceiving() {
  479. for(FileReceiver fileReceiver : mFileReceiverList) {
  480. if(fileReceiver != null && fileReceiver.isRunning()) {
  481. return true;
  482. }
  483. }
  484. return false;
  485. }
  486. /**
  487. * 停止所有文件发送任务
  488. */
  489. private void stopAllFileReceivingTask() {
  490. for(FileReceiver fileReceiver : mFileReceiverList) {
  491. if(fileReceiver != null) {
  492. fileReceiver.stop();
  493. }
  494. }
  495. }
  496. /**
  497. * 关闭此Activity
  498. */
  499. private void finishActivity() {
  500. //断开UDP Socket
  501. closeUdpSocket();
  502. //停止所有文件接收任务
  503. stopAllFileReceivingTask();
  504. //断开接收文件的Socket
  505. closeClientSocket();
  506. //清除WiFi网络
  507. mWifiMgr.clearWifiConfig();
  508. //清空接收文件列表
  509. AppContext.getAppContext().clearReceiverFileInfoMap();
  510. finish();
  511. }
  512. /**
  513. * 断开接收文件的Socket
  514. */
  515. private void closeClientSocket() {
  516. if(mClientSocket != null) {
  517. try {
  518. mClientSocket.close();
  519. mClientSocket = null;
  520. } catch (IOException e) {
  521. e.printStackTrace();
  522. }
  523. }
  524. }
  525. /**
  526. * 关闭UDP Socket
  527. */
  528. private void closeUdpSocket() {
  529. if(mDatagramSocket != null) {
  530. mDatagramSocket.disconnect();
  531. mDatagramSocket.close();
  532. mDatagramSocket = null;
  533. }
  534. }
  535. @OnClick(R.id.btn_receive_files)
  536. public void sendReceiveFileListToFileSender() {
  537. //将选择的文件列表发给发送端,开始接收文件
  538. AppContext.getAppContext().clearReceiverFileInfoMap();
  539. for(FileInfo fileInfo : mSendFileInfos) {
  540. fileInfo.setPosition(mSendFileInfos.indexOf(fileInfo));
  541. AppContext.getAppContext().addReceiverFileInfo(fileInfo);
  542. }
  543. setupReceiveFilesAdapter();
  544. initReceiverServer();
  545. }
  546. @Override
  547. public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) {
  548. if(position < mChooseHotspotAdapter.getItemCount() && position >= 0) {
  549. //获取当前点击WiFi的SSID
  550. ScanResult scanResult = mChooseHotspotAdapter.getDatas().get(position);
  551. mSelectedSSID = scanResult.SSID;
  552. if((scanResult.capabilities != null && !scanResult.capabilities.equals(WifiMgr.NO_PASSWORD)) || (scanResult.capabilities != null && !scanResult.capabilities.equals(WifiMgr.NO_PASSWORD_WPS))){
  553. //弹出密码输入框
  554. showDialogWithEditText(mSelectedSSID, new OnWifiPasswordConfirmListener() {
  555. @Override
  556. public void onConfirm(String password) {
  557. //使用密码连接WiFi
  558. if(isNotEmptyString(password)) {
  559. try {
  560. setStatus("正在连接Wifi...");
  561. mWifiMgr.connectWifi(mSelectedSSID, password, mScanResults);
  562. } catch (InterruptedException e) {
  563. e.printStackTrace();
  564. }
  565. } else {
  566. toast("密码不能为空");
  567. }
  568. }
  569. });
  570. } else {
  571. //连接免密码WiFi
  572. try {
  573. setStatus("正在连接Wifi...");
  574. mWifiMgr.connectWifi(mSelectedSSID, "", mScanResults);
  575. } catch (InterruptedException e) {
  576. e.printStackTrace();
  577. }
  578. }
  579. }
  580. }
  581. @Override
  582. public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) {
  583. return false;
  584. }
  585. /**
  586. * WiFi广播接收器
  587. */
  588. private WifiBroadcaseReceiver mWifiBroadcaseReceiver = new WifiBroadcaseReceiver() {
  589. @Override
  590. public void onWifiEnabled() {
  591. //WiFi已开启,开始扫描可用WiFi
  592. setStatus("正在扫描可用WiFi...");
  593. mWifiMgr.startScan();
  594. }
  595. @Override
  596. public void onWifiDisabled() {
  597. //WiFi已关闭,清除可用WiFi列表
  598. mSelectedSSID = "";
  599. mScanResults.clear();
  600. setupWifiAdapter();
  601. }
  602. @Override
  603. public void onScanResultsAvailable(List<ScanResult> scanResults) {
  604. //扫描周围可用WiFi成功,设置可用WiFi列表
  605. mScanResults.clear();
  606. mScanResults.addAll(scanResults);
  607. setupWifiAdapter();
  608. }
  609. @Override
  610. public void onWifiConnected(String connectedSSID) {
  611. //判断指定WiFi是否连接成功
  612. if (connectedSSID.equals(mSelectedSSID) && !mIsSendInitOrder) {
  613. //连接成功
  614. setStatus("Wifi连接成功...");
  615. //显示发送列表,隐藏WiFi选择列表
  616. mChooseHotspotRecyclerView.setVisibility(View.GONE);
  617. mReceiveFilesRecyclerView.setVisibility(View.VISIBLE);
  618. //告知发送端,接收端初始化完毕
  619. mHandler.sendEmptyMessage(MSG_FILE_RECEIVER_INIT_SUCCESS);
  620. mIsSendInitOrder = true;
  621. } else {
  622. // //连接成功的不是设备WiFi,清除该WiFi,重新扫描周围WiFi
  623. // LogUtils.e("连接到错误WiFi,正在断开重连...");
  624. // mWifiMgr.disconnectWifi(connectedSSID);
  625. // mWifiMgr.startScan();
  626. }
  627. }
  628. @Override
  629. public void onWifiDisconnected() {
  630. }
  631. };
  632. /**
  633. * ServerSocket启动线程
  634. */
  635. private class ReceiveServerRunnable implements Runnable {
  636. @Override
  637. public void run() {
  638. try {
  639. //发送选择接收的文件
  640. mHandler.sendEmptyMessage(MSG_SEND_RECEIVE_FILE_LIST);
  641. Thread.sleep(3000);
  642. //开始接收文件
  643. String serverIp = mWifiMgr.getIpAddressFromHotspot();
  644. List<Map.Entry<String, FileInfo>> fileInfoList = AppContext.getAppContext().getReceiverFileInfoMap();
  645. Collections.sort(fileInfoList, Consts.DEFAULT_COMPARATOR);
  646. for(final Map.Entry<String, FileInfo> fileInfoMap : fileInfoList) {
  647. //连接发送端,逐个文件进行接收
  648. final int position = fileInfoList.indexOf(fileInfoMap);
  649. mClientSocket = new Socket(serverIp, Consts.DEFAULT_FILE_RECEIVE_SERVER_PORT);
  650. FileReceiver fileReceiver = new FileReceiver(mClientSocket, fileInfoMap.getValue());
  651. fileReceiver.setOnReceiveListener(new FileReceiver.OnReceiveListener() {
  652. @Override
  653. public void onStart() {
  654. mHandler.obtainMessage(MSG_SET_STATUS, "开始接收"+ FileUtils.getFileName(fileInfoMap.getValue().getFilePath())).sendToTarget();
  655. }
  656. @Override
  657. public void onProgress(FileInfo fileInfo, long progress, long total) {
  658. //更新接收进度视图
  659. int i_progress = (int) (progress * 100 / total);
  660. LogUtils.e("正在接收:" + fileInfo.getFilePath() + "\n当前进度:" + i_progress);
  661. Message msg = new Message();
  662. msg.what = MSG_UPDATE_PROGRESS;
  663. msg.arg1 = position;
  664. msg.arg2 = i_progress;
  665. mHandler.sendMessage(msg);
  666. }
  667. @Override
  668. public void onSuccess(FileInfo fileInfo) {
  669. //接收成功
  670. mHandler.obtainMessage(MSG_SET_STATUS, "文件:" + FileUtils.getFileName(fileInfo.getFilePath()) + "接收成功").sendToTarget();
  671. fileInfo.setResult(FileInfo.FLAG_SUCCESS);
  672. AppContext.getAppContext().updateReceiverFileInfo(fileInfo);
  673. Message msg = new Message();
  674. msg.what = MSG_UPDATE_PROGRESS;
  675. msg.arg1 = position;
  676. msg.arg2 = 100;
  677. mHandler.sendMessage(msg);
  678. }
  679. @Override
  680. public void onFailure(Throwable throwable, FileInfo fileInfo) {
  681. if(fileInfo != null) {
  682. //接收失败
  683. mHandler.obtainMessage(MSG_SET_STATUS, "文件:" + FileUtils.getFileName(fileInfo.getFilePath()) + "接收失败").sendToTarget();
  684. fileInfo.setResult(FileInfo.FLAG_FAILURE);
  685. AppContext.getAppContext().updateReceiverFileInfo(fileInfo);
  686. Message msg = new Message();
  687. msg.what = MSG_UPDATE_PROGRESS;
  688. msg.arg1 = position;
  689. msg.arg2 = -1;
  690. mHandler.sendMessage(msg);
  691. }
  692. }
  693. });
  694. //加入线程池执行
  695. mFileReceiverList.add(fileReceiver);
  696. AppContext.getAppContext().MAIN_EXECUTOR.execute(fileReceiver);
  697. }
  698. } catch (Exception e) {
  699. e.printStackTrace();
  700. }
  701. }
  702. }
  703. private interface OnWifiPasswordConfirmListener {
  704. void onConfirm(String password);
  705. }
  706. }