共计 5555 个字符,预计需要花费 14 分钟才能阅读完成。
基于 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)]
最初