Android:在应用程序中连接时,应用程序无法在 wifi 网络上 ping 设备
Android: app cant ping device on wifi network when connecting in the app
我已经使用 Socket.io 和 android 网络发现构建了一个应用程序。当服务器启动并且 android 设备解析服务时,我尝试创建一个套接字,但它在第一次尝试时从未工作过。我必须终止该应用程序并重新启动它,然后它才能正常工作。
服务器 运行ning 在接入点上。网络连接正常,但我无法 ping 服务器。但如前所述,如果我终止应用程序并再次 运行 它工作正常。
第 2 天
进一步调试后,我将崩溃范围缩小到我的应用程序设置 wifi 连接的任何时间。 ssid 和密码是从二维码获取的,应用程序设置 wifi 连接。
读取二维码数据
@Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barCodes = detections.getDetectedItems();
if (!receivedDetection) {
if (barCodes.size() != 0) {
Log.i(TAG, "received a Barcode");
receivedDetection = true;
Gson g = new Gson();
try {
barCodeData = g.fromJson(barCodes.valueAt(0).rawValue, AccessPointCredentials.class);
} catch (Exception e) {
barCodeData = new AccessPointCredentials();
barCodeData.setSsid(barCodes.valueAt(0).rawValue);
barCodeData.setPass(null);
e.printStackTrace();
}
connectToWifi(barCodeData);
}
}
}
connectToWifi()
private void connectToWifi(final AccessPointCredentials credentials) {
new AsyncTask<Object, Object, Object>() {
@Override
protected Object doInBackground(Object... objects) {
WifiManager wifiManager = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(true);
int netId;
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
for (WifiConfiguration tmp : wifiManager.getConfiguredNetworks()) {
if (tmp.SSID.equals("\"" + credentials.getSsid() + "\"")) {
netId = tmp.networkId;
boolean enabled = wifiManager.enableNetwork(netId, true);
Log.i(TAG, "doInBackground: Enabled? " + enabled);
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.onBackPressed();
}
});
return null;
}
}
final String[] apSettings = {credentials.getSsid(), credentials.getPass()};
final WifiConnect WifiTask = new WifiConnect(mActivity);
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
WifiTask.execute(apSettings);
}
});
this.cancel(true);
return null;
}
@TargetApi(23)
@Override
protected void onPostExecute(Object aVoid) {
super.onPostExecute(aVoid);
if (Build.VERSION.RELEASE.equalsIgnoreCase("6.0")) {
if (!Settings.System.canWrite(mActivity)) {
Intent goToSettings = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
goToSettings.setData(Uri.parse("package:" + mActivity.getPackageName()));
mActivity.startActivity(goToSettings);
} else {
bindToNetwork();
}
} else {
bindToNetwork();
}
}
}.execute();
}
bindToNetwork()
private void bindToNetwork() {
final ConnectivityManager connectivityManager = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new NetworkRequest.Builder();
//set the transport type do WIFI
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.bindProcessToNetwork(network);
} else {
//This method was deprecated in API level 23
ConnectivityManager.setProcessDefaultNetwork(network);
}
try {
//do a callback or something else to alert your code that it's ok to send the message through socket now
} catch (Exception e) {
e.printStackTrace();
}
connectivityManager.unregisterNetworkCallback(this);
}
});
}
}
编辑
布尔方法 isServerReachable() 抛出异常
java.net.SocketException: socket failed: ENONET (Machine is not on the network)
public boolean isServerReachable(){
boolean isReachable;
try {
isReachable = InetAddress.getByName(mService.getHost().getHostAddress()).isReachable(5000);
} catch (Exception e) {
e.printStackTrace();
isReachable = false;
}
Log.i(TAG, "onServiceResolved: Server reachable? " + String.valueOf(isReachable));
Log.i(TAG, "onServiceResolved: Is Network online? " + String.valueOf(isNetworkOnline()));
if (isReachable){
return true;
} else {
return false;
}
}
从症状来看,您似乎希望 wifiManager.enableNetwork() 调用被阻塞,但实际上并非如此。所以你在网络实际连接之前调用 isServerReachable() 。
您可以在 this topic(第一个答案)中找到关于该做什么的详细描述。
我解决了它,但我不相信它是最好的解决方案,如果添加,我会接受更好的解决方案。
我修改了 connectToWifi()
方法中的 for 循环,在 wifiManager.enableNetwork()
之后添加了一个 Thread.sleep(500);
调用,它现在可以工作了。
for (WifiConfiguration tmp : wifiManager.getConfiguredNetworks()) {
if (tmp.SSID.equals("\"" + credentials.getSsid() + "\"")) {
netId = tmp.networkId;
boolean enabled = wifiManager.enableNetwork(netId, true);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.onBackPressed();
}
});
return null;
}
}
我已经使用 Socket.io 和 android 网络发现构建了一个应用程序。当服务器启动并且 android 设备解析服务时,我尝试创建一个套接字,但它在第一次尝试时从未工作过。我必须终止该应用程序并重新启动它,然后它才能正常工作。 服务器 运行ning 在接入点上。网络连接正常,但我无法 ping 服务器。但如前所述,如果我终止应用程序并再次 运行 它工作正常。
第 2 天
进一步调试后,我将崩溃范围缩小到我的应用程序设置 wifi 连接的任何时间。 ssid 和密码是从二维码获取的,应用程序设置 wifi 连接。
读取二维码数据
@Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
final SparseArray<Barcode> barCodes = detections.getDetectedItems();
if (!receivedDetection) {
if (barCodes.size() != 0) {
Log.i(TAG, "received a Barcode");
receivedDetection = true;
Gson g = new Gson();
try {
barCodeData = g.fromJson(barCodes.valueAt(0).rawValue, AccessPointCredentials.class);
} catch (Exception e) {
barCodeData = new AccessPointCredentials();
barCodeData.setSsid(barCodes.valueAt(0).rawValue);
barCodeData.setPass(null);
e.printStackTrace();
}
connectToWifi(barCodeData);
}
}
}
connectToWifi()
private void connectToWifi(final AccessPointCredentials credentials) {
new AsyncTask<Object, Object, Object>() {
@Override
protected Object doInBackground(Object... objects) {
WifiManager wifiManager = (WifiManager) mActivity.getSystemService(Context.WIFI_SERVICE);
wifiManager.setWifiEnabled(true);
int netId;
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
for (WifiConfiguration tmp : wifiManager.getConfiguredNetworks()) {
if (tmp.SSID.equals("\"" + credentials.getSsid() + "\"")) {
netId = tmp.networkId;
boolean enabled = wifiManager.enableNetwork(netId, true);
Log.i(TAG, "doInBackground: Enabled? " + enabled);
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.onBackPressed();
}
});
return null;
}
}
final String[] apSettings = {credentials.getSsid(), credentials.getPass()};
final WifiConnect WifiTask = new WifiConnect(mActivity);
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
WifiTask.execute(apSettings);
}
});
this.cancel(true);
return null;
}
@TargetApi(23)
@Override
protected void onPostExecute(Object aVoid) {
super.onPostExecute(aVoid);
if (Build.VERSION.RELEASE.equalsIgnoreCase("6.0")) {
if (!Settings.System.canWrite(mActivity)) {
Intent goToSettings = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS);
goToSettings.setData(Uri.parse("package:" + mActivity.getPackageName()));
mActivity.startActivity(goToSettings);
} else {
bindToNetwork();
}
} else {
bindToNetwork();
}
}
}.execute();
}
bindToNetwork()
private void bindToNetwork() {
final ConnectivityManager connectivityManager = (ConnectivityManager) mActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder = new NetworkRequest.Builder();
//set the transport type do WIFI
builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
connectivityManager.bindProcessToNetwork(network);
} else {
//This method was deprecated in API level 23
ConnectivityManager.setProcessDefaultNetwork(network);
}
try {
//do a callback or something else to alert your code that it's ok to send the message through socket now
} catch (Exception e) {
e.printStackTrace();
}
connectivityManager.unregisterNetworkCallback(this);
}
});
}
}
编辑
布尔方法 isServerReachable() 抛出异常
java.net.SocketException: socket failed: ENONET (Machine is not on the network)
public boolean isServerReachable(){
boolean isReachable;
try {
isReachable = InetAddress.getByName(mService.getHost().getHostAddress()).isReachable(5000);
} catch (Exception e) {
e.printStackTrace();
isReachable = false;
}
Log.i(TAG, "onServiceResolved: Server reachable? " + String.valueOf(isReachable));
Log.i(TAG, "onServiceResolved: Is Network online? " + String.valueOf(isNetworkOnline()));
if (isReachable){
return true;
} else {
return false;
}
}
从症状来看,您似乎希望 wifiManager.enableNetwork() 调用被阻塞,但实际上并非如此。所以你在网络实际连接之前调用 isServerReachable() 。
您可以在 this topic(第一个答案)中找到关于该做什么的详细描述。
我解决了它,但我不相信它是最好的解决方案,如果添加,我会接受更好的解决方案。
我修改了 connectToWifi()
方法中的 for 循环,在 wifiManager.enableNetwork()
之后添加了一个 Thread.sleep(500);
调用,它现在可以工作了。
for (WifiConfiguration tmp : wifiManager.getConfiguredNetworks()) {
if (tmp.SSID.equals("\"" + credentials.getSsid() + "\"")) {
netId = tmp.networkId;
boolean enabled = wifiManager.enableNetwork(netId, true);
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
mActivity.runOnUiThread(new Runnable() {
@Override
public void run() {
mActivity.onBackPressed();
}
});
return null;
}
}