adb查看手机设备型号、品牌、机型等信息,利用socket直接与adb的pc service通讯

  • Post author:
  • Post category:其他


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命令即可。



版权声明:本文为qq_21743659原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。