設備要求
已root的Android手機。
背景
這個方法是意外發現的,最初同事有一台測試機插上usb能充電但不能識別,他讓我幫他看看怎么回事,於是我就按照常規套路,開發者模式、usb調試、MTP什么的一通操作,插上電腦一看,還是沒有反應,於是只有尷尬的給他說,估計是usb接口壞了
,
本來以為這就完事了,事實證明,出來混都是要還的
,過了幾天,是因為筆記本電腦的usb接口不夠用,想通過無線網絡連接手機進行調試,於是百度一下,找了篇教程【使用WIFI連接ADB、再也不用USB啦~~~~】就開始操作,成功連接,想着從此擺脫接口限制,心里美滋滋
,然后因為當時測試一個東西需要好幾台手機,在附近搜刮了一波,沒想到那個破手機又到我手上來了
,想着我也就看看日志不干其他的事,於是就連接WiFi,准備照着前面的教程再來一遍,然后就開啟了一段懷疑人生之旅,
操作過程
先來一個正常的手機
電腦和手機在同一個局域網:


直接adb連接,會被拒絕

打開終端模擬器進入shell,設置端口

adb通過ip連接手機,查看設備,可以看到已經連接上了

再看一個坑爹手機
首先,還是電腦和手機在同一局域網


同樣,直接adb連接,會被拒絕

進入終端模擬器設置端口,也沒有什么異常

接下來,adb通過ip連接手機,杯具了,還是連接不上

開始還以為是我那里弄錯了,又重復弄了幾遍,還是不行,開始懷疑人生了
,
然后我就懷疑是adbd有問題,於是用ps查看進程,發現根本沒有adbd的進程,

於是手動啟動adbd的進程試下

再次用adb通過ip連接手機,已經能連接上了

意外收獲
adb連接上后突然想到,因為adbd進程沒有啟動導致通過WiFi連接不上,那么usb連接不上是不是也是這個原因呢,於是馬上插上數據線驗證一下,發現已經能連接到該設備了

由此想到,手機啟動的時候,由於某些原因,adbd啟動失敗,導致usb連接不上手機,
解決方法
既然知道了連接不上手機是adbd沒有啟動導致的,那么每次手機重啟動后手動把adbd啟動即可,
但是想着在手機上去輸命令行有點麻煩,於是動手寫了個app,每次啟動后點一下這個app就好了
,
代碼如下,一條命令搞定,
package com.example.startadbd;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ShellUtils.execCommand("/sbin/adbd &",true);
}
}
其中用到的執行shell命令的工具類ShellUtils是以前在網上找的,具體網址忘了收藏了,代碼直接貼下面吧,
public class ShellUtils
{
public static final String COMMAND_SU = "su";
public static final String COMMAND_SH = "sh";
public static final String COMMAND_EXIT = "exit\n";
public static final String COMMAND_LINE_END = "\n";
private ShellUtils()
{
throw new AssertionError();
}
/**
* 查看是否有了root權限
*
* @return
*/
public static boolean checkRootPermission()
{
return execCommand("echo root", true, false).result == 0;
}
/**
* 執行shell命令,默認返回結果
*
* @param command command
* @param isRoot 運行是否需要root權限
* @return
* @see ShellUtils#execCommand(String[], boolean, boolean)
*/
public static CommandResult execCommand(String command, boolean isRoot)
{
return execCommand(new String[]{command}, isRoot, true);
}
/**
* 執行shell命令,默認返回結果
*
* @param commands command list
* @param isRoot 運行是否需要root權限
* @return
* @see ShellUtils#execCommand(String[], boolean, boolean)
*/
public static CommandResult execCommand(List<String> commands,
boolean isRoot)
{
return execCommand(
commands == null ? null : commands.toArray(new String[]{}),
isRoot, true);
}
/**
* 執行shell命令,默認返回結果
*
* @param commands command array
* @param isRoot 運行是否需要root權限
* @return
* @see ShellUtils#execCommand(String[], boolean, boolean)
*/
public static CommandResult execCommand(String[] commands, boolean isRoot)
{
return execCommand(commands, isRoot, true);
}
/**
* execute shell command
*
* @param command command
* @param isRoot 運行是否需要root權限
* @param isNeedResultMsg whether need result msg
* @return
* @see ShellUtils#execCommand(String[], boolean, boolean)
*/
public static CommandResult execCommand(String command, boolean isRoot,
boolean isNeedResultMsg)
{
return execCommand(new String[]{command}, isRoot, isNeedResultMsg);
}
/**
* execute shell commands
*
* @param commands command list
* @param isRoot 運行是否需要root權限
* @param isNeedResultMsg 是否需要返回運行結果
* @return
* @see ShellUtils#execCommand(String[], boolean, boolean)
*/
public static CommandResult execCommand(List<String> commands,
boolean isRoot, boolean isNeedResultMsg)
{
return execCommand(
commands == null ? null : commands.toArray(new String[]{}),
isRoot, isNeedResultMsg);
}
/**
* execute shell commands
*
* @param commands command array
* @param isRoot 運行是否需要root權限
* @param isNeedResultMsg 是否需要返回運行結果
* @return <ul>
* <li>if isNeedResultMsg is false, {@link CommandResult#successMsg}
* is null and {@link CommandResult#errorMsg} is null.</li>
* <li>if {@link CommandResult#result} is -1, there maybe some
* excepiton.</li>
* </ul>
*/
public static CommandResult execCommand(String[] commands, boolean isRoot,
boolean isNeedResultMsg)
{
int result = -1;
if (commands == null || commands.length == 0)
{
return new CommandResult(result, null, null);
}
Process process = null;
BufferedReader successResult = null;
BufferedReader errorResult = null;
StringBuilder successMsg = null;
StringBuilder errorMsg = null;
DataOutputStream os = null;
try
{
process = Runtime.getRuntime().exec(
isRoot ? COMMAND_SU : COMMAND_SH);
os = new DataOutputStream(process.getOutputStream());
for (String command : commands)
{
if (command == null)
{
continue;
}
// donnot use os.writeBytes(commmand), avoid chinese charset
// error
os.write(command.getBytes());
os.writeBytes(COMMAND_LINE_END);
os.flush();
}
os.writeBytes(COMMAND_EXIT);
os.flush();
result = process.waitFor();
// get command result
if (isNeedResultMsg)
{
successMsg = new StringBuilder();
errorMsg = new StringBuilder();
successResult = new BufferedReader(new InputStreamReader(
process.getInputStream()));
errorResult = new BufferedReader(new InputStreamReader(
process.getErrorStream()));
String s;
while ((s = successResult.readLine()) != null)
{
successMsg.append(s);
}
while ((s = errorResult.readLine()) != null)
{
errorMsg.append(s);
}
}
} catch (IOException e)
{
e.printStackTrace();
} catch (Exception e)
{
e.printStackTrace();
} finally
{
try
{
if (os != null)
{
os.close();
}
if (successResult != null)
{
successResult.close();
}
if (errorResult != null)
{
errorResult.close();
}
} catch (IOException e)
{
e.printStackTrace();
}
if (process != null)
{
process.destroy();
}
}
return new CommandResult(result, successMsg == null ? null
: successMsg.toString(), errorMsg == null ? null
: errorMsg.toString());
}
/**
* 運行結果
* <ul>
* <li>{@link CommandResult#result} means result of command, 0 means normal,
* else means error, same to excute in linux shell</li>
* <li>{@link CommandResult#successMsg} means success message of command
* result</li>
* <li>{@link CommandResult#errorMsg} means error message of command result</li>
* </ul>
*
* @author <a href="http://www.trinea.cn" target="_blank">Trinea</a>
* 2013-5-16
*/
public static class CommandResult
{
/**
* 運行結果
**/
public int result;
/**
* 運行成功結果
**/
public String successMsg;
/**
* 運行失敗結果
**/
public String errorMsg;
public CommandResult(int result)
{
this.result = result;
}
public CommandResult(int result, String successMsg, String errorMsg)
{
this.result = result;
this.successMsg = successMsg;
this.errorMsg = errorMsg;
}
}
}
再附一個編譯好的安裝包,不想自己編譯的可以直接【下載】安裝,
