adb查看手机设备型号、品牌、机型等信息
以下操作均基于ADB模式。
1、查看机型时,可以使用以下命令:
$ adb shell getprop ro.product.model
1
输出结果如下:
2、如果我们忘记具体系统属性的名字,我们可以使用grep进行过滤,比如:
$ adb shell getprop | grep product
1
输出结果如下:
我们过滤product关键字,可以看到很多关于产品的系统属性(品牌、型号、厂商等)。
也可以使用如下方式,直接查找/system/build.prop文件中属性值:
$ adb shell cat /system/build.prop | grep product
1
输出结果如下图所示:
3、我们还可以通过 adb devices 命令来查看设备信息:
以下命令查看设备ID:
$ adb devices
1
查看型号等详细信息使用以下命令:
$ adb devices -l
1
输出结果如下图所示:
本文就是在我们自己的代码里面直接利用socket与adb service通讯,绕过执行cmd和利用管道获取数据,这种方式在速度上面会快很多,基本原理就是参考adb的源码 把socket与adb service相关的代码移植到自己的工程里面,下面就是一个demo代码,真正移植到项目还需要修改。
(由于在公司有加密软件的原因,源代码只能以文本方式一部分一部分拷贝到博客,所有下面的布局会不清晰)
AdbSocketHelper.h
#pragma once
#include <Winsock2.h>//这个需要放在 windows.h前面
#include <string>
#include <vector>
using std::string;
using std::wstring;
class AdbSocketHelper
{
public:
AdbSocketHelper(void);
~AdbSocketHelper(void);
string getDevices();
string getAdbVersion();
string adbShell(const string shellCmd,const string deviceSN);
void setAdbPathAndPort(wstring wcspath,int server_port);
private:
string executeAdb(const string cmd);
string executeDeviceAdb(const string cmd,const string deviceSN);
bool createAdbSocket(SOCKET &Socket,string &strError);
int launch_server();
SOCKET socketClient();
bool executeSocket(const SOCKET Socket,const string cmd,bool recvLoop,string &strdata);
bool sendSocketData(const SOCKET Socket,const string strdata);
bool recvSocketDataOnce(const SOCKET Socket,string &strdata);
bool recvSocketDataLoop(const SOCKET Socket,string &strdata);
int m_serverport;
wstring m_wcspath;
static bool iniSocketLib;
};
下面是AdbSocketHelper.cpp文件
#include “AdbSocketHelper.h”
#pragma comment(lib,”ws2_32.lib”)
bool AdbSocketHelper::iniSocketLib = false;
#define MAX_BUF 1024*4+1
AdbSocketHelper::AdbSocketHelper(void)
{
//test 的默认值设置
m_serverport = 6037;
m_wcspath = L”E:\\work\\adb\\LibAdb\\Debug\\LibAdb.exe”;
}
AdbSocketHelper::~AdbSocketHelper(void)
{
}
void AdbSocketHelper::setAdbPathAndPort(wstring wcspath,int server_port)
{
m_wcspath = wcspath;
m_serverport = server_port;
}
string AdbSocketHelper::getAdbVersion()
{
string retStr = executeAdb(“host:version”);
return retStr;
}
string AdbSocketHelper::getDevices()
{
string retStr = executeAdb(“host:devices”);
return retStr;
}
string AdbSocketHelper::adbShell(string shellCmd,string deviceSN)
{
string retStr;
string realCmd = “shell:”;
realCmd+=shellCmd;
string realdeviceSN = deviceSN;
if (realdeviceSN.empty())
{//0012host:transport-any
realdeviceSN = “-any”;
}
else
{
realdeviceSN = “:”+realdeviceSN;
}
retStr = executeDeviceAdb(realCmd,realdeviceSN);
return retStr;
}
string AdbSocketHelper::executeAdb(const string cmd)
{
string retStr;
retStr.clear();
SOCKET clientSocket = INVALID_SOCKET;
if (createAdbSocket(clientSocket,retStr))
{
executeSocket(clientSocket,cmd,true,retStr);
// 服务端会关闭,所以客户端每次都创建新的socket,用完就关闭
closesocket(clientSocket);
}
return retStr;
}
string AdbSocketHelper::executeDeviceAdb(const string cmd,const string deviceSN)
{
string retStr;
retStr.clear();
SOCKET clientSocket = INVALID_SOCKET;
if (createAdbSocket(clientSocket,retStr))
{
//因为指定了 设备序列号,所以需要先host:transport
string transportCmd = “host:transport”;
transportCmd += deviceSN;
executeSocket(clientSocket,transportCmd,false,retStr);
//需要执行两次
executeSocket(clientSocket,cmd,true,retStr);
// 服务端会关闭,所以客户端每次都创建新的socket,用完就关闭
closesocket(clientSocket);
}
return retStr;
}
bool AdbSocketHelper::createAdbSocket(SOCKET &Socket,string &strError)
{
bool bRet = true;
Socket = socketClient();
if (INVALID_SOCKET == Socket)
{
//socket 连接不上就 认为服务没有启动
if (0==launch_server())
{//启动服务 成功
}
else
{
strError = “Error:launch server fail.”;
bRet = false;
}
}
return bRet;
}
bool AdbSocketHelper::executeSocket(const SOCKET Socket,const string cmd,bool recvLoop,string &strdata)
{
bool bRet = true;
if ((sendSocketData(Socket,cmd)))
{
if (recvLoop)
{
bRet = recvSocketDataLoop(Socket,strdata);
}
else
{
bRet = recvSocketDataOnce(Socket,strdata);
}
}
else
{
bRet = false;
}
return bRet;
}
bool AdbSocketHelper::sendSocketData(const SOCKET Socket,const string strdata)
{
//发送的数据前面需要添加 4位的 数据长度,这个是从adb源码获取的
char tmpCharLen[5] = {0};
_snprintf_s(tmpCharLen, sizeof tmpCharLen,4 ,”%04x”,strdata.length());
string realData(tmpCharLen);
realData += strdata;
int retVal = send(Socket,realData.c_str(),realData.length(),0);
if (SOCKET_ERROR == retVal)
{
printf(“sendSocketData %s error = %d\n”,strdata.c_str(),WSAGetLastError());
return false;
}
return true;
}
bool AdbSocketHelper::recvSocketDataOnce(const SOCKET Socket,string &strdata)
{
bool bRet = true;
char *buf = new char[MAX_BUF+1];
ZeroMemory(buf, MAX_BUF+1);
int retVal=recv(Socket,buf,MAX_BUF,0);
if (SOCKET_ERROR == retVal )
{
//接收出错了
printf(“recvSocketData recv error %d\n”,WSAGetLastError());
bRet = false;
}
else
{
if(0 == memcmp(buf, “OKAY”, 4))
{
}
else
{
strdata.append(buf);
bRet = false; //状态错误
}
}
return bRet;
}
bool AdbSocketHelper::recvSocketDataLoop(const SOCKET Socket,string &strdata)
{
bool bRet = true;
strdata.clear();
char *buf = new char[MAX_BUF+1];
bool isFist = true;
int DataLen;
while(1)
{
ZeroMemory(buf, MAX_BUF+1);
int retVal=recv(Socket,buf,MAX_BUF,0);
if (SOCKET_ERROR == retVal )
{
//接收出错了
printf(“recvSocketData recv error %d\n”,WSAGetLastError());
bRet = false;
break;
}
else if (0 == retVal)
{
//数据接收完成了
break;
}
else
{
if (isFist)
{
isFist = false;
if(0 == memcmp(buf, “OKAY”, 4))
{//应该接收到的数据长度
char tmp[5] = {0};
memcpy(tmp,buf+4,4);
DataLen = strtol(tmp, NULL, 16);
}
else
{
bRet = false; //状态错误
}
}
else
{
strdata.append(buf);
}
}
}
delete [] buf;
if (DataLen != strdata.length())
{
printf(“recvSocketData data length is error \n”);
}
return bRet;
}
SOCKET AdbSocketHelper::socketClient()
{
SOCKET clientSocket = INVALID_SOCKET;
if (!iniSocketLib)
{
//加载socket库函数
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2,2);
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
printf(“WSAStartup fail … %d \n”,WSAGetLastError());
return clientSocket;
}
else
{
iniSocketLib = true;
}
}
// 创建套接字
if ((clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
{
printf(“socket() failed with error %d\n”, WSAGetLastError());
}
else
{
SOCKADDR_IN InternetAddr;
memset(&InternetAddr, 0, sizeof(InternetAddr));
InternetAddr.sin_family = AF_INET;
InternetAddr.sin_port = htons(m_serverport);
InternetAddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
int retVal;
//连接服务器
retVal = connect(clientSocket, (LPSOCKADDR)&InternetAddr, sizeof(InternetAddr));
if (SOCKET_ERROR == retVal)
{
printf(“connect() socket failed with error %d\n”, WSAGetLastError());
closesocket(clientSocket);
clientSocket = INVALID_SOCKET;
}
}
return clientSocket;
}
//启动服务 这个是从adb源码里面获取出来的,修改了部分
int AdbSocketHelper::launch_server()
{
HANDLE pipe_read, pipe_write;
HANDLE stdout_handle, stderr_handle;
SECURITY_ATTRIBUTES sa;
PROCESS_INFORMATION pinfo;
int ret;
STARTUPINFOW startup;
wchar_t program_path_unicode[MAX_PATH] = {0};
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
/* create pipe, and ensure its read handle isn’t inheritable */
ret = CreatePipe( &pipe_read, &pipe_write, &sa, 0 );
if (!ret) {
fprintf(stderr, “CreatePipe() failure, error %ld\n”, GetLastError() );
return -1;
}
SetHandleInformation( pipe_read, HANDLE_FLAG_INHERIT, 0 );
ZeroMemory( &pinfo, sizeof(pinfo) );
ret = CreateProcessW(m_wcspath.c_str(),L”adb fork-server server”,NULL,NULL,TRUE,DETACHED_PROCESS,NULL,NULL,&startup,&pinfo);
CloseHandle( pipe_write );
if (!ret) {
fprintf(stderr, “CreateProcess failure, error %ld\n”, GetLastError() );
CloseHandle( pipe_read );
return -1;
}
CloseHandle( pinfo.hProcess );
CloseHandle( pinfo.hThread );
/* wait for the “OK\n” message */
{
char temp[3];
DWORD count;
ret = ReadFile( pipe_read, temp, 3, &count, NULL );
CloseHandle( pipe_read );
if ( !ret ) {
fprintf(stderr, “could not read ok from ADB Server, error = %ld\n”, GetLastError() );
return -1;
}
if (count != 3 || temp[0] != ‘O’ || temp[1] != ‘K’ || temp[2] != ‘\n’) {
fprintf(stderr, “ADB server didn’t ACK\n” );
return -1;
}
}
return 0;
}
下面是测试代码,测试代码只是测试了两个命令,测试代码很简单
AdbSocketHelper adbHelper;
adbHelper.setAdbPathAndPort(L”E:\\work\\adb\\LibAdb\\Debug\\Adb.exe”,5037);
string strRet;
strRet = adbHelper.getAdbVersion();
printf(“%s\n”,strRet.c_str());
strRet = adbHelper.getDevices();
printf(“%s\n”,strRet.c_str());
strRet = adbHelper.adbShell(“dumpsys iphonesubinfo”,””);
printf(“%s\n”,strRet.c_str());
简单的把手机连接到电脑,安装好驱动,就能获取到adb的版本信息和当前的设备列表。
其他的adb命令可以参考adb的源码来完善,这里只是给出一个demo,需要在项目中使用的时候,直接把上面的类添加到工程,补充其他的adb命令即可。