中秋假期转眼已经过去两天了,我们的学习也在不断向前,经过前面三篇文章的学习,我们已经可以做出来一个简单的反编译apk的工具了。
为了更方便的使用我们自己编写的工具,所以我们对于第三篇文章中的search_file button来进行处理,我们使用拖拽文件到QLineEdit控件上面来显示文件路径,而不用打开window来选择了,这样对我们的操作来说更加方便一点。
拖拽事件,经过一晚上的查询以及翻看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)
详细代码如下,有详细注释,这里不再多说:
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)
效果图如下:
前面一篇文章已经将反编译的按钮事件做好,所以这里我们照着写一下回编译和签名以及最后的截屏事件即可。
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)
下面附上完整的代码,有兴趣的朋友,直接测试即可。记得先配置好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