Snake's Home

libimobiledevice

Android 及 iOS 常用操作命令

最近做 iOS 相关的事情比较多,发现其实 iOS 下还是有很多和 android 可以对应的操作,所以在此记录一下。

备注: iOS 用到的ideviceinstaller,idevicesyslog 等命令安装命令为:brew install libimobiledevice

应用相关

1、 安装应用(真机)

1
2
3
4
5
6
Android

adb install xxx.apk
iOS

ideviceinstaller -i xxx.ipa

2、 卸载应用(真机)

1
2
3
4
5
6
Android

adb uninstall <packageName>
iOS

ideviceinstaller -U <bundleId>

3、 获取应用唯一标识

其实也不算唯一标识了,只是大部分操作会用到。

Android: packageName
获取方式很多,只举其中一个比较容易的:

1
2
3
4
5
6
7
8
9
10
$ apktool d xxx.apk -o xxx
$ cd xxx
$ cat AndroidManifest.xml | grep -o "package=\".*\"" | sed "s/package=\"//g" | sed "s/\"//g"
com.test
iOS:bundleId

$ unzip xxx.ipa
$ cd Payload/xxx.app
$ defaults read `pwd`/Info CFBundleIdentifier
com.test

4、从源码构建应用安装包

这里只举 debug 包

android(现在 android studio 项目已经很流行了,所以就不说 ant 了)

1
$ cd /source-folder/

注意:没翻墙情况下貌似不能自动下载 gradle ,那么可以自行下载 gradle 后用 gradle 的 bin 文件代替此处的 gradlew 。

1
$ ./gradlew build

build 完的 apk 包放在 Application/build/outputs/apk 中
iOS 真机

1
2
3
4
$ cd /source-folder/
$ PROJECT=<your-project-name>
$ xcodebuild clean -project $PROJECT.xcodeproj -configuration Debug -alltargets
$ xcodebuild archive -project $PROJECT.xcodeproj -scheme $PROJECT -archivePath $PROJECT.xcarchive

注意,末尾的 exportProvisioningProfile 参数值是在 Xcode 的 Performance->Accounts->Apple ID->View Details 窗口的下半部分看到的名称。如 iOS Team Provisioning Profile: chj.ToDoList

1
2
3
4
$ xcodebuild -exportArchive -archivePath 

$PROJECT.xcarchive -exportPath $PROJECT -exportFormat ipa -exportProvisioningProfile "your provision profile"
# build 完的 ipa 包直接就放在当前目录

设备相关

1、查看设备中的应用列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Android

$ adb shell pm list packages
package:com.miui.gallery
package:com.xiaomi.tv.gallerylockscreen
...
如果有 drozer 的话能显示得更清晰

dz> run app.package.list
com.miui.gallery (图库)
com.xiaomi.tv.gallerylockscreen (锁屏画报)
...
iOS

$ ideviceinstaller [-u <device-udid>] -l
Total: 46 apps
com.xiaojukeji.didi - 滴滴出行 4.1.5.0
com.tencent.mqq - QQ 6.0.0.424
...

2、获取真机实时日志

1
2
3
4
5
6
Android

adb [-s <device-name>] logcat
iOS

idevicesyslog [-u <device-udid>]

3、获取当前连接的设备列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Android

$ adb devices
iOS

注意:这里列出的设备包括模拟器及 mac 电脑本身
$ instruments -s devices
补充:
mac安装以下内容:

brew install usbmuxd
brew install ideviceinstaller
可以获取ios手机的udid

idevice_id -l
对于脚本中要使用默认设备的场景很方便。

ideviceinfo 获取ios手机信息
ideviceinfo -x 获取ios手机信息,并以xml形式显示

ideviceinfo -k ProductType 获取手机型号
ideviceinfo -k ProductVersion 获取系统版本
ideviceinfo -k DeviceName 获取手机名称

Android

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import os
import re
import shutil
import subprocess
import time



englishtown_url = "http://10.128.42.155:8080/view/Engage/job/engage-android-release/{0}/artifact/engage/build/outputs/apk/engage-englishtown-live-release.apk"
corporate_url = "http://10.128.42.155:8080/view/Engage/job/engage-android-release/{0}/artifact/engage/build/outputs/apk/engage-corporate-live-release.apk"

current_dir = os.path.split(os.path.realpath(__file__))[0]
report_path = current_dir + "/apk/"
old_path = current_dir + "/old/"
new_path = current_dir + "/new/"


def exec_command(cmd):
result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
(stdoutdata, stderrdata) = result.communicate()
if (re.search("error", str(stdoutdata))):
print "error occur!"
else:
return stdoutdata

def check_folder(name):
if os.path.exists(name):
# os.removedirs(report_path)
shutil.rmtree(name)

else:
pass
os.makedirs(name)


def get_url(url,folder_name):
cmd = 'curl -O {0}'.format(url)
os.chdir(folder_name)
exec_command(cmd)
os.chdir(current_dir)


def check_md5(file):
cmd = 'md5 {0}'.format(file)
md5_id = exec_command(cmd)
print "{0} md5 value is {1}".format(file, md5_id)


def find_devices():
rst = os.popen('adb devices').read()
devices = re.findall(r'(.*?)\s+device',rst)
if len(devices) > 1:
Ids = devices[1:]
else:
Ids = []
return Ids

def find_apks():
apks = []
for c in os.listdir(os.getcwd()):
if os.path.isfile(c) and c.endswith('.apk'):
apks.append(c)
return apks

def upgrade_englishtown(old_folder,new_folder):
old_version = raw_input("please input the old build number")
new_version = raw_input("please input the new build number")
old_apk_name = englishtown_url.format(old_version).split("/")[-1]
get_url(englishtown_url.format(old_version),old_folder)
new_apk_name = englishtown_url.format(new_version).split("/")[-1]
get_url(englishtown_url.format(new_version),new_folder)
return old_apk_name, new_apk_name

def upgrade_corporate(old_folder,new_folder):
old_version = raw_input("please input the old build number")
new_version = raw_input("please input the new build number")
old_apk_name = corporate_url.format(old_version).split("/")[-1]
get_url(corporate_url.format(old_version),old_folder)
new_apk_name = corporate_url.format(new_version).split("/")[-1]
get_url(corporate_url.format(new_version),new_folder)
return old_apk_name, new_apk_name

def install_apks(apk_name):
cmd = 'adb install {0}'.format(apk_name)
print cmd
result = exec_command(cmd)
print result
if (re.search("success", result)):
print "install success!"
else:
print "install fail!"



def main():

choose = raw_input("please select the type you want: 1:md5,2:upgrade_englishtown,3:upgrade_corporate")
if choose == '1':
build_id = raw_input("please input the build number")
check_folder(report_path)
get_url(englishtown_url.format(build_id),report_path)
get_url(corporate_url.format(build_id),report_path)
if os.path.exists(report_path):
for file in os.listdir(report_path):
check_md5(report_path + file)
else:
"please check your network!"
elif choose == '2':
check_folder(old_path)
check_folder(new_path)
(old_apk,new_apk) =upgrade_englishtown(old_path,new_path)
print "old apk is : %s" % old_apk
install_apks(old_path + old_apk)
print "new apk is : %s" % new_apk
install_apks(new_path+new_apk)


elif choose == '3':
check_folder(old_path)
check_folder(new_path)
(old_apk, new_apk) = upgrade_corporate(old_path,new_path)
print "old apk is : %s" % old_apk
install_apks(old_path + old_apk)
print "new apk is : %s" % new_apk
install_apks(new_path+new_apk)

else:
print "please select again"




if __name__ == '__main__':
main()

IOS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import os
import re
import subprocess
import time

current_time = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time()))


class iosinformation():
def exec_command(self, cmd):
result = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
(stdoutdata, stderrdata) = result.communicate()
# print("Result is:%s") % stdoutdata
if (re.search("No device found", str(stdoutdata)) or re.search("Could not connect", str(stdoutdata))):
print "Please connet it agian, or add permission like: brew install libimobiledevice --HEAD,sudo chmod -R 777 /var/db/lockdown/"
else:
return stdoutdata

def Get_UUID(self):
cmd = 'idevice_id -l'
uuid = self.exec_command(cmd)
return uuid

def Get_Device_Name(self):
cmd = 'ideviceinfo -k DeviceName'
device_name = self.exec_command(cmd)
return device_name

def Get_Device_information(self):
cmd = 'ideviceinfo -k ProductVersion'
device_information = self.exec_command(cmd)
return device_information

def Get_Device_Product_type(self):
cmd = 'ideviceinfo -k ProductType'
product_type = self.exec_command(cmd)
return product_type

def List_All_Pakages(self, uuid):
cmd = 'ideviceinstaller -u {0}'.format(uuid)

print cmd
all_pakages = self.exec_command(cmd)

return all_pakages

def List_All_Logs(self, uuid):
all_logs = "idevicesyslog -u {0}".format(uuid)
return all_logs

def Take_Screenshot(self):
current_dir = os.path.split(os.path.realpath(__file__))[0]
cmd1 = "idevicescreenshot {0} + '/' + screenshot-DATE.tiff".format(current_dir)
cmd2 = "sips - s format png {0}.tiff - -out {1}.png".format(current_time, current_time)
self.exec_command(cmd1)
print "ok"
# self.exec_command(cmd2)

def Install_Ipa(self, ipa):
cmd = 'ideviceinstaller -i {0}'.format(ipa)
result = self.exec_command(cmd)
return result

def Uninstall_Ipa(self, appid):
cmd1 = 'ideviceinstaller -l'
cmd2 = 'ideviceinstaller -U {0}'.format(appid)
result = self.exec_command(cmd1)
appids=[]
for id in result.split('\n'):
if re.search('-',id):
str = id[0:id.find("-")].strip()
appids.append(str)

else:
pass
print appids
if appid in appids:
result = self.exec_command(cmd2)
else:
print "The appid dosen't exit in the devices"



# cmd2 = 'ideviceinstaller -u appid'.format(appid)
# result = self.exec_command(cmd)
# return result


def main():
ios = iosinformation()

uuid = ios.Get_UUID()
print " uuid is {0}".format(uuid)
device = ios.Get_Device_Name()
print " device is {0}".format(device)
device_info = ios.Get_Device_information()
print " device_info is {0}".format(device_info)
product_type = ios.Get_Device_Product_type()
print " product_type is {0}".format(product_type)
# all_pakagas = ios.List_All_Pakages(uuid)
# print " all_pakagas is {0}".format(all_pakagas)
ios.Take_Screenshot()
ios.Install_Ipa('/Users/anderson/testcode/python/flask/uploads/englishtown_corporate_daily-190-2016.07.15.ipa')
#ios.Uninstall_Ipa("com.ef.engage.englishtown.uat.dailydebug")



if __name__ == '__main__':
main()