中秋假期转眼已经过去两天了,我们的学习也在不断向前,经过前面三篇文章的学习,我们已经可以做出来一个简单的反编译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