天天看點

跟着鬼哥學PyQtPart.4

中秋假期轉眼已經過去兩天了,我們的學習也在不斷向前,經過前面三篇文章的學習,我們已經可以做出來一個簡單的反編譯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)
           

效果圖如下:

跟着鬼哥學PyQtPart.4

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