前言
关于开启热点,手机间通信,网上有很多相关的例子,但几乎所有的例子只在开启热点和进行socket连接部分有比较详细的描叙,实际上,这其中还有很多重要的细节,例如热点的IP如何获得, socket连接如何保证连接上等?
正文
两个Android手机要想相互间通信,可以通过蓝牙,也可以通过WIFI,相对而已WIFI的速度更快,但两个手机必须连接同一WIFI源才行。如果没有WIF源呢?Android 9提供了一个叫LocalOnlyHotspot的东西,其中一个手机开启热点,另一手机连接此热点,然后就可以通过socket通信。
实际上,这整个过程可以划分为三个独立部分开启热点、启动ServerSocket、连接热点并连接socket。但下面我是按相关技术的要点进行分段描叙的。
- 开启热点,获得热点名称,密码
这部分在网上有很多介绍,我就直接贴代码了:
private void startHotApp(final Intent intent) {
final WifiManager manager = (WifiManager) getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (manager!= null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
manager.startLocalOnlyHotspot(new WifiManager.LocalOnlyHotspotCallback() {
@Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
sReservation = reservation;
PendingIntent pendingIntent = intent.getParcelableExtra("pendingIntent");
Intent data = new Intent();
data.putExtra(Constants.KEY_SSID, reservation.getWifiConfiguration().SSID);
data.putExtra(Constants.KEY_PRESHARE, reservation.getWifiConfiguration().preSharedKey);
final String ipAddress = getLocalIpAddress();
data.putExtra(Constants.KEY_IP, ipAddress);
try {
DebugLog.info("pendingIntent.send:" + ipAddress);
if(pendingIntent != null) {
pendingIntent.send(HotService.this, 200, data);
}
} catch (PendingIntent.CanceledException e) {
e.printStackTrace();
}
}
@Override
public void onStopped() {
super.onStopped();
}
@Override
public void onFailed(int reason) {
super.onFailed(reason);
}
}, null);
}
}
- 获得热点的IP
这部分我要重点说说,网上很多通过WifiManager或者读取本地文件等方式来获取手机IP,其实都是不对的,我们手机连接别人的热点,才能通过这种方式获得IP,而我们手机自己开启的热点,这种方式要么获得的一直是0,要么就不对,可能是以前手机连接他人的热点形成的ip。
首先,我们来看看热点IP是如何生成的:
源代码网址:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java
198 // TODO: Refactor this in terms of calls to InterfaceController.
199 private boolean configureIPv4(boolean enabled) {
200 if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")");
201
202 // TODO: Replace this hard-coded information with dynamically selected
203 // config passed down to us by a higher layer IP-coordinating element.
204 String ipAsString = null;
205 int prefixLen = 0;
206 if (mInterfaceType == ConnectivityManager.TETHERING_USB) {
207 ipAsString = USB_NEAR_IFACE_ADDR;
208 prefixLen = USB_PREFIX_LENGTH