中秋假期轉眼已經過去兩天了,我們的學習也在不斷向前,經過前面三篇文章的學習,我們已經可以做出來一個簡單的反編譯apk的工具了。
為了更友善的使用我們自己編寫的工具,是以我們對于第三篇文章中的search_file button來進行處理,我們使用拖拽檔案到QLineEdit控件上面來顯示檔案路徑,而不用打開window來選擇了,這樣對我們的操作來說更加友善一點。
0x1:拖拽事件的處理
拖拽事件,經過一晚上的查詢以及翻看Java已經寫好的工具,終于找到dragEnterEvent和dropEvent兩個事件。關于這兩個事件的詳細介紹,自行google搜尋一下即可。
要想使用這個事件,我們需要重寫一下QLineEdit控件,并且在其init方法裡面設定setAcceptDrops為True來接收拖拽事件。
是以現在的問題就是我們如何來擷取得到拖入檔案的路徑呢?
經過查詢mimeData有一些方法可以參考,經過測試,urls()屬性還是比較貼近我們所需的,但是還需要對其進行處理得到檔案路徑。
詳細代碼如下:
def dropEvent(self, event):
###擷取拖放過來的檔案的路徑
st=str(event.mimeData().urls())
print(st)
###這裡沒發現好的api,是以用mimeData()的urls屬性了,text()不好用,是以下面就是字元串截取,來還原路徑
a='///'
b=')]'
num2=st.index(b)-1
num=st.index(a)+3
st=st[num:num2]
##這裡定義全局變量,拖入檔案或者檔案夾的路徑
global APK_STR
APK_STR=st
self.setText(st)
0x2:重新做一下布局檔案
詳細代碼如下,有詳細注釋,這裡不再多說:
QWidget.__init__(self, parent)
self.setWindowTitle('Android_APK')
###第一行
self.apk_decode=QPushButton("Apk_Decode")
self.apk_path_edit = MyEditText(self)
###第二行,三個按鈕,這裡第三個按鈕的點選事件還沒寫
self.apk_build=QPushButton("Apk_Build")
self.apk_build_edit = MyEditText()
###第三行
self.sign = QPushButton("Apk_Sign")
self.apk_sign_edit = MyEditText()
##第四行
self.shootcut=QPushButton("Shoot_Cut")
self.shootcut_text=QLabel("please keep moile with usb")
###布局檔案的編寫,四行兩列
grid = QGridLayout()
grid.setSpacing(10)
grid.addWidget(self.apk_decode, 1, 0)
grid.addWidget(self.apk_path_edit, 1, 1)
grid.addWidget(self.apk_build, 2, 0)
grid.addWidget(self.apk_build_edit, 2, 1)
grid.addWidget(self.sign,3,0)
grid.addWidget(self.apk_sign_edit, 3,1)
grid.addWidget(self.shootcut,4,0)
grid.addWidget(self.shootcut_text, 4,1)
###設定視窗的高寬,将gridview放入大布局中
self.setLayout(grid)
self.resize(450, 300)
效果圖如下:
0x3:整合相關按鈕的點選事件
前面一篇文章已經将反編譯的按鈕事件做好,是以這裡我們照着寫一下回編譯和簽名以及最後的截屏事件即可。
def apkD(self):
###上面openFIle方法中定義的全局變量,列印一下路徑,看看是否正确#####
print(APK_STR)
###apktool的指令使用#####
apkToD='java -jar apktool.jar d '+APK_STR
###調用os的system指令來執行cmd的相關指令###
os.system(apkToD)
def apkB(self):
###上面openFIle方法中定義的全局變量,列印一下路徑,看看是否正确#####
print(APK_STR)
###apktool的指令使用#####
apkToD='java -jar apktool.jar b '+APK_STR
###調用os的system指令來執行cmd的相關指令###
os.system(apkToD)
def apkS(self):
apkSign='java -jar signapk.jar testkey.x509.pem testkey.pk8 '+APK_STR+' Signed_apk.apk'
print apkSign
###調用os的system指令來執行cmd的相關指令###
os.system(apkSign)
def shootCut(self):
pre_com='adb wait-for-device'
os.system(pre_com)
###将截圖儲存到local下
fir_com='adb shell screencap -p /data/local/tmp/tmp.png'
print (fir_com)
os.system(fir_com)
###目前時間,精确到秒,來儲存圖檔命名
timestamp = time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time()))
path=os.getcwd()
###将其導出來
sec_com='adb pull /data/local/tmp/tmp.png '+path+'\\'+timestamp+'.png'
print(sec_com)
os.system(sec_com)
thi_com='adb shell rm /data/local/tmp/tmp.png'
os.system(thi_com)
0x4:完整的代碼
下面附上完整的代碼,有興趣的朋友,直接測試即可。記得先配置好pyqt相關開發環境。
# -*- coding: utf-8 -*-
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
import os
import time
class MainLayout(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setWindowTitle('Android_APK')
###第一行
self.apk_decode=QPushButton("Apk_Decode")
self.apk_path_edit = MyEditText(self)
###第二行,三個按鈕,這裡第三個按鈕的點選事件還沒寫
self.apk_build=QPushButton("Apk_Build")
self.apk_build_edit = MyEditText()
###第三行
self.sign = QPushButton("Apk_Sign")
self.apk_sign_edit = MyEditText()
##第四行
self.shootcut=QPushButton("Shoot_Cut")
self.shootcut_text=QLabel("please keep moile with usb")
###反編譯按鈕的點選事件
self.connect(self.apk_decode,SIGNAL('clicked()'),self.apkD)
###回編譯按鈕的點選事件
self.connect(self.apk_build,SIGNAL('clicked()'),self.apkB)
###簽名按鈕的點選事件
self.connect(self.sign,SIGNAL('clicked()'),self.apkS)
###截屏按鈕的點選事件
self.connect(self.shootcut,SIGNAL('clicked()'),self.shootCut)
###布局檔案的編寫,四行兩列
grid = QGridLayout()
grid.setSpacing(10)
grid.addWidget(self.apk_decode, 1, 0)
grid.addWidget(self.apk_path_edit, 1, 1)
grid.addWidget(self.apk_build, 2, 0)
grid.addWidget(self.apk_build_edit, 2, 1)
grid.addWidget(self.sign,3,0)
grid.addWidget(self.apk_sign_edit, 3,1)
grid.addWidget(self.shootcut,4,0)
grid.addWidget(self.shootcut_text, 4,1)
###設定視窗的高寬,将gridview放入大布局中
self.setLayout(grid)
self.resize(450, 300)
''''def openFile(self):
##調用QfileDialog的相關方法來打開檔案選擇框
s=QFileDialog.getOpenFileName(self,"Open file dialog","/","Apk files(*.apk)")
##定義全局變量,用于接收需要反編譯的apk的路徑
global APK_STR
APK_STR=str(s)
self.apk_path_edit.setText(APK_STR)'''
def apkD(self):
###上面openFIle方法中定義的全局變量,列印一下路徑,看看是否正确#####
print(APK_STR)
###apktool的指令使用#####
apkToD='java -jar apktool.jar d '+APK_STR
###調用os的system指令來執行cmd的相關指令###
os.system(apkToD)
def apkB(self):
###上面openFIle方法中定義的全局變量,列印一下路徑,看看是否正确#####
print(APK_STR)
###apktool的指令使用#####
apkToD='java -jar apktool.jar b '+APK_STR
###調用os的system指令來執行cmd的相關指令###
os.system(apkToD)
def apkS(self):
apkSign='java -jar signapk.jar testkey.x509.pem testkey.pk8 '+APK_STR+' Signed_apk.apk'
print apkSign
###調用os的system指令來執行cmd的相關指令###
os.system(apkSign)
def shootCut(self):
pre_com='adb wait-for-device'
os.system(pre_com)
###将截圖儲存到local下
fir_com='adb shell screencap -p /data/local/tmp/tmp.png'
print (fir_com)
os.system(fir_com)
###目前時間,精确到秒,來儲存圖檔命名
timestamp = time.strftime('%Y-%m-%d-%H-%M-%S',time.localtime(time.time()))
path=os.getcwd()
###将其導出來
sec_com='adb pull /data/local/tmp/tmp.png '+path+'\\'+timestamp+'.png'
print(sec_com)
os.system(sec_com)
thi_com='adb shell rm /data/local/tmp/tmp.png'
os.system(thi_com)
class MyEditText(QLineEdit):
def __init__(self,parent=None):
super(MyEditText,self).__init__(parent)
#這裡在init初始化,接受拖入事件
self.setAcceptDrops(True)
###重寫兩個拖入檔案的操作方法
def dragEnterEvent(self,event):
event.accept()
def dropEvent(self, event):
###擷取拖放過來的檔案的路徑
st=str(event.mimeData().urls())
print(st)
###這裡沒發現好的api,是以用mimeData()的urls屬性了,text()不好用,是以下面就是字元串截取,來還原路徑
a='///'
b=')]'
num2=st.index(b)-1
num=st.index(a)+3
st=st[num:num2]
##這裡定義全局變量,拖入檔案或者檔案夾的路徑
global APK_STR
APK_STR=st
self.setText(st)
###程式的主入口
if __name__ == "__main__":
app = QApplication(sys.argv)
qb = MainLayout()
qb.show()
sys.exit(app.exec_())
效果圖,前面幾篇基本都有了,這裡不再貼出了。
注意:
1.反編譯采用的是apktool.jar的指令,是以得将其放到.py檔案對應目錄
2.簽名采用google的公鑰來過的,是以其檔案也必須在同目錄下
3.截屏動作,得保證手機正常連接配接usb,adb程序不被占用,是以如果讀者有自己編譯的adb是最好的,若此功能不好用,直接做個cmd腳本将上述方法中的指令放入即可
4.這四篇文章,僅記錄一下PyQt的相關學習過程,讀者可以随意對其進行擴充開發,做一個IDE工具集合搜尋,修改,儲存以及一些自動化工具
結束語:
雖然中秋幾天假期沒有出去玩,不過從頭開始學習PyQt還是有一些進步的。代碼方面編寫肯定是有很多疏漏,其對應功能方面也可以做更多優化,有興趣的朋友,請繼續加油。
僅以一句話勉勵自己:
勤能補拙是良訓,一分辛苦一分才。
相關附件之類的,我就上傳到百度網盤了:
http://pan.baidu.com/s/1o6sONoQ