Moto G5 Plus无法通过Socket连接到本地服务器
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Moto G5 Plus无法通过Socket连接到本地服务器相关的知识,希望对你有一定的参考价值。
我有一个应用程序,智能手机必须通过SSLSocket连接到本地服务器。我在5款不同的智能手机上测试了我的应用程序:Moto G2(6.0),Redmi 3S(6.0.1),LG K5(6.0),Moto G5 Plus(7.1.1)和OnePlus 5(8.0)。 Moto G5 Plus是唯一一个能够解决这个问题的人。
这是导致问题行为的线。所有测试都在同一网络上完成。
socket = (SSLSocket) sslContext.getSocketFactory().createSocket(serverAddress, serverPort);
对于这种行为,Moto G5 Plus或android 7+是否存在任何已知问题?
编辑:一些更多的测试导致Android系统的想法试图强迫Socket通过移动网络连接时识别WiFi接口已连接,但没有互联网。有没有办法强制Socket使用WiFi而不是移动网络?
免责声明:我没有测试这个,所以我真的不确定它是否有效。
Network
类有一个bind(Socket)
方法,也许你可以找到wifi网络然后绑定到你的套接字。从文档看来,这似乎是你需要的,它说:
/**
* Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket
* will be sent on this {@code Network}, irrespective of any process-wide network binding set by
* {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected.
*/
在绑定到网络之前,不应该连接Socket
,因此我认为您应该使用socketFactory.createSocket()
创建它并仅在绑定后连接它。
所以,你应该首先找到你的Network
(Kotlin):
val connectivityManager = getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val wifiNetwork = connectivityManager.allNetworks.firstOrNull {
val info = connectivityManager.getNetworkInfo(it)
info.type == ConnectivityManager.TYPE_WIFI
}
或(Java)
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
Network wifiNetwork = null;
for(Network network : connectivityManager.getAllNetworks()){
NetworkInfo networkInfo = connectivityManager.getNetworkInfo(network);
if(networkInfo.getType() == ConnectivityManager.TYPE_WIFI){
wifiNetwork = network;
break;
}
}
然后将它绑定到Socket
并最终连接(Kotlin):
wifiNetwork?.bindSocket(socket)
val socketAddress = InetSocketAddress(hostname, port)
socket.connect(socketAddress)
或(Java)
if(wifiNetwork != null){
wifiNetwork.bindSocket(socket);
}
InetSocketAddress socketAddress = InetSocketAddress(hostName, port);
socket.connect(socketAddress);
注意,它需要ACCESS_NETWORK_STATE
权限
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
我希望它可以帮助你,我刚刚在github上找到了你的解决方案。有关更多详细信息和官方链接,请check this out,我认为这对您有所帮助。如果不是答案,请忽略这个答案。
我们正在使用AsyncTask来避免网络访问的StrictMode致命错误(查看引用)。 StrictMode策略只是禁止我们影响UI线程。
/* AsyncTask class which manages connection with server app and is sending shutdown command.
*/
public class ShutdownAsyncTask extends AsyncTask<String, String, TCPClient> {
private static final String COMMAND = "shutdown -s" ;
private TCPClient tcpClient ;
private Handler mHandler ;
private static final String TAG = "ShutdownAsyncTask";
/**
* ShutdownAsyncTask constructor with handler passed as argument. The UI is updated via handler.
* In doInBackground(...) method, the handler is passed to TCPClient object.
* @param mHandler Handler object that is retrieved from MainActivity class and passed to TCPClient
* class for sending messages and updating UI.
*/
public ShutdownAsyncTask(Handler mHandler){
this.mHandler = mHandler;
}
/**
* Overriden method from AsyncTask class. There the TCPClient object is created.
* @param params From MainActivity class empty string is passed.
* @return TCPClient object for closing it in onPostExecute method.
*/
@Override
protected TCPClient doInBackground(String... params) {
Log.d(TAG, "In do in background");
try{
tcpClient = new TCPClient(mHandler,
COMMAND,
"192.168.1.1",
new TCPClient.MessageCallback() {
@Override
public void callbackMessageReceiver(String message) {
publishProgress(message);
}
});
}catch (NullPointerException e){
Log.d(TAG, "Caught null pointer exception");
e.printStackTrace();
}
tcpClient.run();
return null;
}
在这个AsyncTask中,我们创建了TCPClient对象(如下所述)。在TCPClient构造函数中,我们传递Handler对象以更改UI,COMMAND - 带有“shutdown -s”命令的String用于关闭计算机,IP号码 - 服务器ip号;回调对象 - 当我们得到服务器响应时,回调方法'messageCallbackReceiver'正在启动'publishProgress'方法,即将进度发布到'onProgressUpdate'AsyncTask的方法。
/**
* Overriden method from AsyncTask class. Here we're checking if server answered properly.
* @param values If "restart" message came, the client is stopped and computer should be restarted.
* Otherwise "wrong" message is sent and 'Error' message is shown in UI.
*/
@Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
Log.d(TAG, "In progress update, values: " + values.toString());
if(values[0].equals("shutdown")){
tcpClient.sendMessage(COMMAND);
tcpClient.stopClient();
mHandler.sendEmptyMessageDelayed(MainActivity.SHUTDOWN, 2000);
}else{
tcpClient.sendMessage("wrong");
mHandler.sendEmptyMessageDelayed(MainActivity.ERROR, 2000);
tcpClient.stopClient();
}
}
收到正确的消息后,我们发送命令,或者如果收到错误的消息,我们发送消息“错误”并停止客户端。在此之后,我们将被转移到'onPostExecute'方法:
@Override
protected void onPostExecute(TCPClient result){
super.onPostExecute(result);
Log.d(TAG, "In on post execute");
if(result != null && result.isRunning()){
result.stopClient();
}
mHandler.sendEmptyMessageDelayed(MainActivity.SENT, 4000);
}
}
所以一步一步:
- > AsyncTask正在创建TCPClient对象。
- >在TCPClient构造函数中,我们传递Handler,Command,IP Number和Callback对象。
- >当TCPClient开始连接时,它会向服务器发送消息“shutdown”。
- >当我们从服务器接收消息时,回调将它传递给'onProgressUpdate'。
- >如果收到的消息(来自服务器的响应)等于“shutdown”,我们正在向服务器发送COMMAND。
- >发送后我们停止客户端,将我们转移到'onPostExecute'方法。
- >同时,处理程序正在接收带有MainActivity中定义的'msg.what'整数的空消息,它们负责更新GUI。
窗口小部件UI如何更新的示例:
mHandler = new Handler(){
public void handleMessage(Message msg) {
switch(msg.what){
case SHUTDOWN:
Log.d(mTag, "In Handler's shutdown");
views = new RemoteViews(context.getPackageName(), R.layout.activity_main);
widget = new ComponentName(context, MainActivity.class);
awManager = AppWidgetManager.getInstance(context);
views.setTextViewText(R.id.state, "Shutting PC...");
awManager.updateAppWidget(widget,views);
break;
TCPClient
该类负责维护连接。我会一步一步解释:
在第一步中,我们可以看到从ShutdownAsyncTask和其他人传递的对象。另外,我们可以看到sendMessage和stopClient方法。
public class TCPClient {
private static final String TAG = "TCPClient" ;
private final Handler mHandler ;
private String ipNumber, incomingMessage, command;
BufferedReader in ;
PrintWriter out ;
private MessageCallback listener = null ;
private boolean mRun = false ;
/**
* TCPClient class constructor, which is created in AsyncTasks after the button click.
* @param mHandler Handler passed as an argument for updating the UI with sent messages
* @param command Command passed as an argument, e.g. "shutdown -r" fo以上是关于Moto G5 Plus无法通过Socket连接到本地服务器的主要内容,如果未能解决你的问题,请参考以下文章
带docker的Mysql:无法通过socket连接到本地MySQL服务器
无法通过 php 脚本连接到 xdebug(在 xampp for mac 上运行)