python3:多程序複製檔案至手機
阿新 • • 發佈:2019-02-03
在最近的工作中又再次用到這個py指令碼,但由於機器太多,有更多的需求,故多了一些其它的需求:
1. 要求能自動檢測usb的連線情況
2. 多程序copy.
3. 在copy之前要先刪除一些檔案
4. copy完後要自動打檔案管理器進行升級,這個動作有好幾個點:
a. 在有些操作後手機usb會自動斷開,故要求檢測usb是否斷開並自動重連後再繼續操作
b. 判斷手動是否在亮屏狀態。
5. 只要有手機正在升級時,PC端自動響‘嘟嘟’聲.
主要涉及的點就是以下幾點,不再單獨作說明,直接上code吧:
#!/user/bin/python # -*- coding:utf-8 -*- import os from multiprocessing import Pool from time import sleep import winsound # 重連動作 def reconnectAction(deviceid): devlist = getdevlist() print(f'裝置{deviceid}正在嘗試重連.') id = 1 while deviceid not in devlist: print(f'第{id}次 ', end = ' ') devlist = getdevlist() id = id + 1 print(f'\n裝置{deviceid}重新建立連線成功.') sleep(1) # 執行普通的cmd命令 def exeCmd(cmdInfo, deviceid): cmd = 'adb -s ' + deviceid + ' shell ' + cmdInfo[0] print(f'裝置{deviceid}:exeCmd():{cmdInfo[1]}.') if os.system(cmd) != 0: return False else: return True # 按鍵動作 def pressKeyevent(keycodeInfo, deviceid = ''): cmd = 'adb -s ' + deviceid + ' shell input keyevent ' + keycodeInfo[0] print(f'裝置{deviceid}:pressKeyevent():{keycodeInfo[1]}.') if os.system(cmd) != 0: return False else: return True # 點選螢幕的動作 def clickScreen(positionInfo, deviceid = ''): cmd = 'adb -s ' + deviceid + ' shell input tap ' + positionInfo[0] print(f'裝置{deviceid}:clickScreen():{positionInfo[1]}.') if os.system(cmd) != 0: return False else: return True # 滑動螢幕的動作 def swipeScreen(positionInfo, deviceid = ''): cmd = 'adb -s ' + deviceid + ' shell input swipe ' + positionInfo[0] print(f'裝置{deviceid}:swipeScreen():{positionInfo[1]}.') if os.system(cmd) != 0: return False else: return True # 執行app def launchApp(appactivityInfo, deviceid = ''): cmd = 'adb -s ' + deviceid + ' shell am start ' + appactivityInfo[0] print(f'裝置{deviceid}:launchApp():{appactivityInfo[1]}.') if os.system(cmd) != 0: return False else: return True # 獲取username, 如chinaren def getusername(): namelist = os.popen('echo %username%').readlines() username = namelist[0].replace("\n", "") # 獲取當前的username return username # 獲取裝置id列表 def getdevlist(): devlist = [] connectfile = os.popen('adb devices') list = connectfile.readlines() # print(list) for i in range(len(list)): if list[i].find('\tdevice') != -1: temp = list[i].split('\t') devlist.append(temp[0]) return devlist # 返回指定txt檔案的第一行內容,主要是為了獲取待Copy的檔名 def getspecifytxtfilefirstline(txtfilename): ''' 返回指定txt檔案的第一行內容 txt檔要求與py檔在同一目錄 ''' currunningpyfilepath = os.path.split(os.path.realpath(__file__))[0] copyfile2phoneTXT = currunningpyfilepath + '\\' + txtfilename while True: if os.path.exists(copyfile2phoneTXT) == True: with open(copyfile2phoneTXT, 'r') as f: filename = f.readline() if filename == '': print('txt檔為空,輸入重新寫入待copy檔名.') with open(copyfile2phoneTXT, 'w') as f: fileStr = input('請輸入你要copy檔案的完整檔名\n(建議直接拖入檔案至這裡,會自動獲取寫入txt檔):') filenamelist = fileStr.split('\\') filename = filenamelist[len(filenamelist) - 1] f.write(filename) print('輸入的檔名已寫入.') return filename else: return filename else: print('copyfile2phone.txt檔案不存在,將在當前目錄新建一個此txt檔案!') with open(copyfile2phoneTXT, 'w') as f: print('copyfile2phone.txt檔案新建成功!') fileStr = input('請輸入你要copy檔案的完整檔名\n(建議直接拖入檔案至這裡,會自動獲取寫入txt檔):') filenamelist = fileStr.split('\\') filename = filenamelist[len(filenamelist) - 1] f.write(filename) print('輸入的檔名已寫入.') return filename # 測試Adb連線性 def checkAdbConnectability(flag=0): ''' flag =0時,當連線正常時返回True(default) flag!=0時,直接打印出結果 ''' connectstring = '''ADB連線失敗, 請check以下項: 1. 是否有連線上手機?請連線上手機選並重新check連線性! 2. 是否有開啟"開發者選項\\USB除錯模式"?\n''' connectinfolist = getdevlist() if len(connectinfolist) == 0: return False if len(connectinfolist) == 1: if flag != 0: print('連線正常') print(f'裝置SN: {connectinfolist[0]}') else: return True if len(connectinfolist) >= 2: print('連線正常,當前有連線多臺裝置. ') for i in range(len(connectinfolist)): print(f'裝置{i + 1} SN: {connectinfolist[i]}') return True def isAwaked(deviceid = ''): ''' 判斷的依據是' mAwake=false\n' ''' if deviceid == '': cmd = 'adb shell dumpsys window policy' else: cmd = 'adb -s ' + deviceid + ' shell dumpsys window policy' screenAwakevalue = ' mAwake=true\n' allList = os.popen(cmd).readlines() if screenAwakevalue in allList: return True else: return False # Copy檔案操作 def copyfile_task(deviceid, filename): # 刪除BxxTest資料夾和*.zip檔案 delBxxTestcmd = ('rm -r /sdcard/BxxTest', '刪除BxxTest資料夾') delXXXreportscmd = ('rm -r /sdcard/XXXreports', '刪除1report資料夾') delzipcmd = ('rm -r /sdcard/*.*', '刪除根目錄下的舊版本檔案') print(f'裝置:{deviceid}正在執行刪除BSTTest、XXXreports資料夾動作... ...') exeCmd(delBxxTestcmd, deviceid) exeCmd(delXXXreportscmd, deviceid) exeCmd(delzipcmd, deviceid) copyfilepath = 'C:\\Users\\' + getusername() + '\\Desktop\\' + filename print(f'裝置:{deviceid}準備執行copy操作!') cmd = 'adb -s ' + deviceid + ' push ' + copyfilepath + ' /sdcard/' if os.system(cmd) == 0: print(f'裝置:{deviceid} 檔案copy成功!\n') else: winsound.Beep(800, 10000) # 開啟filemanager application print('正在開啟filemanager應用... ...') isexistCmd = ('ps | findstr filemanager', '檢視filemanager app是否已開啟') closeappCmd = ('am force-stop com.android.filemanager', '關閉filemanager app') runappCmd = ('am start com.android.filemanager/.FileManagerListActivity', '開啟filemanager app') if exeCmd(isexistCmd, deviceid) == True: print(f'裝置{deviceid}的filemanager app之前已開啟.將關閉再開啟') exeCmd(closeappCmd, deviceid) # exeCmd(runappCmd, deviceid) if exeCmd(runappCmd, deviceid) == False: reconnectAction(deviceid) exeCmd(runappCmd, deviceid) else: print('filemanager app已開啟.') if exeCmd(runappCmd, deviceid) == False: reconnectAction(deviceid) exeCmd(runappCmd, deviceid) # 點亮手機螢幕開始升級 lightCmd = ('26', '點亮螢幕') unlockscreenCmd = ('380 1300 380 300', '螢幕解鎖') swipescreen = ('380 1300 380 300', '上滑螢幕') clickload = ('400 1300', '在檔案列表中點選load') clickupdata = ('509 1330', '點選升級按鍵') if isAwaked(deviceid) == False: pressKeyevent(lightCmd, deviceid) swipeScreen(unlockscreenCmd, deviceid) sleep(0.5) # 因為在解鎖後設備會大概率的斷開一下,故如果斷線則需要等待重連 if swipeScreen(swipescreen, deviceid) == False: reconnectAction(deviceid) swipeScreen(swipescreen, deviceid) swipeScreen(swipescreen, deviceid) sleep(0.5) if clickScreen(clickload, deviceid) == False: reconnectAction(deviceid) clickScreen(clickload, deviceid) sleep(0.5) if clickScreen(clickupdata, deviceid) == False: reconnectAction(deviceid) clickScreen(clickupdata, deviceid) # 當所有操作完成時,手機會不斷的閃屏+PC會不斷的'嘟嘟'提醒,直到裝置斷開 print(f'\n當前裝置{deviceid} copy動作已完成... 請撥線... ') temp = getdevlist() while deviceid in temp: # os.popen('adb -s ' + deviceid + ' shell input keyevent 26') winsound.Beep(500, 500) temp = getdevlist() def main(): print('---------重要提示---------') print('請將待Copy檔案放置在桌面再進行操作\n\n') connectdevice = input('請輸入每次要同時下載的裝置數(注意:如果要改變裝置同時下載的裝置數,則需要關閉指令碼重新run):') number = int(connectdevice.strip()) while True: lists = getdevlist() devnum = len(lists) id = 1 tempdevlist = getdevlist() if devnum < number: print(f'\n裝置未全部識別,應識別{number}臺裝置!\n當前已識別{devnum}臺裝置,請連線裝置並等待識別:\n\n') for i in range(devnum): print(f'裝置{id}: {lists[i]}') id = id + 1 while devnum < number: lists = getdevlist() curnum = len(lists) if curnum > devnum: for i in range(len(lists)): if lists[i] not in tempdevlist: print(f'裝置{id}: {lists[i]}') id = id + 1 tempdevlist = getdevlist() devnum = curnum print(f'\n所有裝置已全部識別!當前有連線{len(getdevlist())}臺裝置.\n\n') while True: copyfilename = getspecifytxtfilefirstline('copyfile2phone.txt') if checkAdbConnectability() == True: copyfilepath = 'C:\\Users\\' + getusername() + '\\Desktop\\' + copyfilename if os.path.isfile(copyfilepath) == True: devicelist = getdevlist() print(f'要copy的檔名:{copyfilename}') print('COPY檔案準備中,請稍候... ...\n') p = Pool(4) for i in range(len(devicelist)): p.apply_async(copyfile_task, args=(devicelist[i], copyfilename)) p.close() p.join() # 等待的裝置斷開 devnum = len(getdevlist()) while devnum != 0: devnum = len(getdevlist()) print('\n所有裝置已斷開!\n\n\n請連線其它手機進行下一輪Copy... ...') else: print('TXT檔中指定的檔名不存在TXT檔將被刪除並新建,需要重新輸入檔名:') # 刪除檔案 curfilepath = os.path.split(os.path.realpath(__file__))[0] TXTfilepath = curfilepath + '\\' + 'copyfile2phone.txt' os.remove(TXTfilepath) print('TXT檔被刪除成功') else: break # 主程式 if __name__ == '__main__': main()