设备要求
已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;
}
}
}