基于Android的文件传输零碎
开发步骤
- 在 AndroidManifest 中申明相干权限(网络和文件读写权限)
- 获取 WifiP2pManager ,注册相干播送监听Wifi直连的状态变动
- 指定某一台设施为服务器(用来接管文件),创立群组并作为群主存在,在指定端口监听客户端的连贯申请,期待客户端发动连贯申请以及文件传输申请
客户端(用来发送文件)被动搜寻左近的设施,退出到服务器创立的群组,获取服务器的 IP 地址,向其发动文件传输申请
- 校验文件完整性
设置Android权限
Wifi P2P 技术并不会拜访网络,但因为会应用到 Java Socket,所以须要申请网络权限。此外,因为是要实现文件互传,所以也须要申请SD卡读写权限。
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
注册播送
与 Wifi P2P 相干的播送有以下几个:
- WIFI_P2P_STATE_CHANGED_ACTION( 用于批示 Wifi P2P 是否可用 )
- WIFI_P2P_PEERS_CHANGED_ACTION( 对等节点列表产生了变动 )
- WIFI_P2P_CONNECTION_CHANGED_ACTION( Wifi P2P 的连贯状态产生了扭转 )
- WIFI_P2P_THIS_DEVICE_CHANGED_ACTION( 本设施的设施信息产生了变动 )
当接管到这几个播送时,咱们都须要到 WifiP2pManager (对等网络管理器)来进行相应的信息申请,此外还须要用到 Channel 对象作为申请参数
mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);mChannel = mWifiP2pManager.initialize(this, getMainLooper(), this);
当收到 WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION 播送时,能够判断以后 Wifi P2P是否可用
int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1);if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) { mDirectActionListener.wifiP2pEnabled(true);} else { mDirectActionListener.wifiP2pEnabled(false); }
当收到 WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION 播送时,象征设施四周的可用设施列表产生了变动,能够通过 requestPeers 办法失去可用的设施列表,之后就能够抉择当中的某一个设施进行连贯操作
mWifiP2pManager.requestPeers(mChannel, new WifiP2pManager.PeerListListener() { @Override public void onPeersAvailable(WifiP2pDeviceList peers) { mDirectActionListener.onPeersAvailable(peers.getDeviceList()); }});
当收到 WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION 播送时,意味着 Wifi P2P 的连贯状态产生了变动,可能是连贯到了某设施,或者是与某设施断开了连贯
NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);if (networkInfo.isConnected()) { mWifiP2pManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() { @Override public void onConnectionInfoAvailable(WifiP2pInfo info) { mDirectActionListener.onConnectionInfoAvailable(info); } }); Log.e(TAG, "已连贯p2p设施");} else { mDirectActionListener.onDisconnection(); Log.e(TAG, "与p2p设施已断开连接");}
如果是与某设施连贯上了,则能够通过 requestConnectionInfo 办法获取到连贯信息
当收到 WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION 播送时,则能够获取到本设施变动后的设施信息
(WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE)
能够看出 Wifi P2P 的接口高度异步化,到当初曾经用到了三个零碎的回调函数,一个用于 WifiP2pManager 的初始化,两个用于在播送中异步申请数据,为了简化操作,此处对立应用一个自定义的回调函数,办法含意与零碎的回调函数统一
public interface DirectActionListener extends WifiP2pManager.ChannelListener { void wifiP2pEnabled(boolean enabled); void onConnectionInfoAvailable(WifiP2pInfo wifiP2pInfo); void onDisconnection(); void onSelfDeviceAvailable(WifiP2pDevice wifiP2pDevice); void onPeersAvailable(Collection<WifiP2pDevice> wifiP2pDeviceList);}//所以,整个播送接收器应用到的所有代码是:public class DirectBroadcastReceiver extends BroadcastReceiver { private static final String TAG = "DirectBroadcastReceiver"; private WifiP2pManager mWifiP2pManager; private WifiP2pManager.Channel mChannel; private DirectActionListener mDirectActionListener; public DirectBroadcastReceiver(WifiP2pManager wifiP2pManager, WifiP2pManager.Channel channel, DirectActionListener directActionListener) { mWifiP2pManager = wifiP2pManager; mChannel = channel; mDirectActionListener = directActionListener; } public static IntentFilter getIntentFilter() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); return intentFilter; } @Override public void onReceive(Context context, Intent intent) { Log.e(TAG, "接管到播送: " + intent.getAction()); if (!TextUtils.isEmpty(intent.getAction())) { switch (intent.getAction()) { // 用于批示 Wifi P2P 是否可用 case WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION: { int state = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, -1); if (state == WifiP2pManager.WIFI_P2P_STATE_ENABLED) { mDirectActionListener.wifiP2pEnabled(true); } else { mDirectActionListener.wifiP2pEnabled(false); List<WifiP2pDevice> wifiP2pDeviceList = new ArrayList<>(); mDirectActionListener.onPeersAvailable(wifiP2pDeviceList); } break; } // 对等节点列表产生了变动 case WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION: { mWifiP2pManager.requestPeers(mChannel, new WifiP2pManager.PeerListListener() { @Override public void onPeersAvailable(WifiP2pDeviceList peers) { mDirectActionListener.onPeersAvailable(peers.getDeviceList()); } }); break; } // Wifi P2P 的连贯状态产生了扭转 case WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION: { NetworkInfo networkInfo = intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO); if (networkInfo.isConnected()) { mWifiP2pManager.requestConnectionInfo(mChannel, new WifiP2pManager.ConnectionInfoListener() { @Override public void onConnectionInfoAvailable(WifiP2pInfo info) { mDirectActionListener.onConnectionInfoAvailable(info); } }); Log.e(TAG, "已连贯p2p设施"); } else { mDirectActionListener.onDisconnection(); Log.e(TAG, "与p2p设施已断开连接"); } break; } //本设施的设施信息产生了变动 case WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION: { mDirectActionListener.onSelfDeviceAvailable((WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE)); break; } } } }}
未完待续.....................................
成果展现
[图片上传失败...(image-89ef4a-1604286797706)]
[图片上传失败...(image-d1227e-1604286797706)]