This commit is contained in:
Yutousama 2022-08-24 21:12:13 +08:00
parent 887c7681dc
commit 54eb1365c6
5 changed files with 347 additions and 44 deletions

20
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,20 @@
{
"MicroPython.executeButton": [
{
"text": "▶",
"tooltip": "运行",
"alignment": "left",
"command": "extension.executeFile",
"priority": 3.5
}
],
"MicroPython.syncButton": [
{
"text": "$(sync)",
"tooltip": "同步",
"alignment": "left",
"command": "extension.execute",
"priority": 4
}
]
}

View File

@ -18,8 +18,8 @@
</select> </select>
<input id="btn" name="btn" type="button" value="执行" class="layui-btn layui-btn-normal" /> <input id="btn" name="btn" type="button" value="执行" class="layui-btn layui-btn-normal" />
<button type="button" class="layui-btn" id="upload"> <button type="button" class="layui-btn" id="setSignFile">
<i class="layui-icon">&#xe67c;</i>上传APK <i class="layui-icon">&#xe67c;</i>设置签名
</button> </button>
<input id="flush" name="flush" type="button" value="刷新设备列表" class="layui-btn" /> <input id="flush" name="flush" type="button" value="刷新设备列表" class="layui-btn" />
<input id="showPack" name="showPack" type="button" value="已安装列表" class="layui-btn" /> <input id="showPack" name="showPack" type="button" value="已安装列表" class="layui-btn" />
@ -36,6 +36,28 @@
</body> </body>
<script> <script>
function showWindows() {
utools.showMainWindow()
}
function uploadSign(alias, aliasPassword, password, sign) {
utools.db.put({
_id: "alias",
data: alias
})
utools.db.put({
_id: "aliasPassword",
data: aliasPassword
})
utools.db.put({
_id: "password",
data: password
})
utools.db.put({
_id: "sign",
data: sign
})
}
function log(data) { function log(data) {
console.log("日志输出:" + data) console.log("日志输出:" + data)
$('#log').val($('#log').val() + "\n" + data) $('#log').val($('#log').val() + "\n" + data)
@ -84,6 +106,9 @@
$('#flush').click(function () { $('#flush').click(function () {
reload() reload()
}) })
$('#setSignFile').click(function () {
setSign()
})
reload() reload()
utools.onPluginEnter(({ utools.onPluginEnter(({
@ -91,14 +116,56 @@
type, type,
payload payload
}) => { }) => {
if (type == 'files') { console.log(code)
if (type != 'window')
path = payload[0].path; path = payload[0].path;
if (code == 'install') {
console.log("检测到文件:" + path) console.log("检测到文件:" + path)
log("准备安装:" + path) log("准备安装:" + path)
} } else if (code == 'unapk') {
reload() log("准备反编译:" + path)
window.unapk(payload[0].path, (stdout, error) => {
log(stdout)
utools.shellBeep()
}) })
} else if (code == 'apkinfo') {
window.apkinfo(path, (stdout, error) => {
log(stdout)
})
} else if (code == 'packapk') {
utools.readCurrentFolderPath().then((dir) => {
log("正在回编译")
window.packapk(dir, (stdout, error) => {
log(stdout)
})
})
} else if (code == 'signapk') {
let isUseSign = utools.db.get('sign')
if (isUseSign == null) {
setSign()
} else {
log("正在签名:" + path)
window.signapk(payload[0].path, (stdout, error) => {
log(stdout)
utools.shellBeep()
log('签名完成')
})
}
}
})
function setSign() {
layer.open({
type: 2,
title: '设置签名'
, area: ['350px', '300px']
, content: ['sign_dialog.html', 'no']
, cancel: function (index, layero) {
layer.close(index)
return false;
}
});
}
function reload() { function reload() {
chinese = []; chinese = [];
@ -149,9 +216,11 @@
log("没有连接设备"); log("没有连接设备");
} }
}) })
} }
$('#showPack').click(function () { $('#showPack').click(function () {
window.adb("adb shell pm list package", (stdout,error) => { var dv = devices[0].split(/\s+/);
window.adb("adb -s "+dv[0]+" shell pm list package", (stdout, error) => {
if (error == true) { if (error == true) {
log(stdout) log(stdout)
return; return;
@ -173,7 +242,8 @@
}) })
}) })
$('#showTopActivity').click(function () { $('#showTopActivity').click(function () {
window.adb("adb shell dumpsys window | findstr mCurrentFocus",(data,error)=>{ var dv = devices[0].split(/\s+/);
window.adb("adb -s "+dv[0]+" shell dumpsys window | findstr mCurrentFocus", (data, error) => {
log(data) log(data)
}) })
}) })

View File

@ -11,15 +11,73 @@
}, },
"features": [ "features": [
{ {
"code": "adb", "code":"text",
"cmds":["adb",{ "cmds": [ "adb", "android" ]
"label":"adb install apk", },
{
"code": "install",
"cmds": [
{
"label": "安装apk到手机",
"type": "files", "type": "files",
"fileType": "file", "fileType": "file",
"match":"/.*?\\.apk$/i",
"minNum": 1,
"maxNum": 1
}
]
},
{
"code": "unapk",
"cmds": [
{
"label": "反编译",
"type": "files",
"fileType": "file",
"match":"/.*?\\.apk$/i",
"minNum": 1,
"maxNum": 1
}
]
},
{
"code": "packapk",
"cmds": [
{
"label": "回编apk",
"type": "window",
"match":{
"title":"*"
}
}
]
},
{
"code": "signapk",
"cmds": [
{
"label": "签名apk",
"type": "files",
"fileType": "file",
"match":"/.*?\\.apk$/i",
"minNum": 1, "minNum": 1,
"maxNum": 1 "maxNum": 1
}]
} }
]
}
,
{
"code": "apkinfo",
"cmds": [
{
"label": "查看apk信息",
"type": "files",
"fileType": "file",
"match":"/.*?\\.apk$/i",
"minNum": 1,
"maxNum": 1
}
]
}
] ]
} }

View File

@ -1,10 +1,36 @@
const exec = require('child_process'); const exec = require('child_process');
const path = require('path')
const fs = require('fs')
const { POINT_CONVERSION_HYBRID } = require('constants');
const iconv = require('iconv-lite') const iconv = require('iconv-lite')
var encoding = 'GBK'; var encoding = 'GBK';
var binaryEncoding = 'binary'; var binaryEncoding = 'binary';
window.adb = function (ext,fun) { window.exec_ = function (ext, fun) {
exec.exec(ext, { encoding: 'binary' }, (err, stdout, stderr) => { exec.exec(ext, { encoding: 'binary' }, (err, stdout, stderr) => {
if (stderr != '') {
fun(iconv.decode(new Buffer(stderr, binaryEncoding), encoding), true)
} else if (stdout != '') {
fun(iconv.decode(new Buffer(stdout, binaryEncoding), encoding), false)
} else if (err != '') {
try {
fun(iconv.decode(new Buffer(err, binaryEncoding), encoding), true)
} catch (error) {
fun(err)
}
} else {
fun("异常错误")
}
})
}
window.adb = function (ext, fun) {
let adb = getAdb()
let _exec = ext.replace('adb', adb)
//ext="dir"
console.log(_exec)
exec.exec(_exec, { encoding: 'binary' }, (err, stdout, stderr) => {
if (stderr != '') { if (stderr != '') {
fun(iconv.decode(new Buffer(stderr, binaryEncoding), encoding), true) fun(iconv.decode(new Buffer(stderr, binaryEncoding), encoding), true)
} else if (stdout != '') { } else if (stdout != '') {
@ -14,6 +40,59 @@ window.adb = function (ext,fun) {
} else { } else {
fun("异常错误") fun("异常错误")
} }
}) })
} }
window.unapk = function (file, fun) {
let apktool = getApkTools();
let _exec = getJavaRuntimer()+"java -jar \"" + apktool + "\" d -f \"" + file + "\" --only-main-classes -out=\"" + getFilePath(file) + path.sep + getFileNotExtName(file) + "\""
exec_(_exec, fun)
}
window.apkinfo = function (file, fun) {
let aapt = getAapt()
let _exec = aapt + " dump badging " + file
exec_(_exec, fun)
}
window.packapk = function (dir, fun) {
let apktool = getApkTools();
let _exec = getJavaRuntimer()+"java -jar " + apktool + " -r b -f " + dir + " -o " + dir + path.sep + "game.apk"
exec_(_exec, fun)
}
window.signapk = function (file, fun) {
let sign = getSign()
let _exec =getJavaRuntimer()+ sign + " -verbose -keystore " + utools.db.get('sign').data + ' -keypass ' + utools.db.get('password').data
+ ' -storepass ' + utools.db.get('aliasPassword').data + ' -signedjar \"' + file + '_sign.apk\" \"'
+ file + '\" ' + utools.db.get('alias').data
console.log(_exec)
exec_(_exec, fun)
}
window.readSignDialog = function (fun) {
console.log('read file')
let data = fs.readFileSync('sign_dialog.txt');
console.log(data)
fun(data)
}
function getApkTools() {
return utools.getPath('documents') + path.sep + 'utools_adb_libs' + path.sep + 'apktool.jar'
}
function getAdb() {
return utools.getPath('documents') + path.sep + 'utools_adb_libs' + path.sep + 'adb.exe';
}
function getAapt() {
return utools.getPath('documents') + path.sep + 'utools_adb_libs' + path.sep + 'aapt.exe';
}
function getSign() {
return 'jarsigner.exe';
}
function getSignTools() {
return utools.getPath('documents') + path.sep + 'utools_adb_libs' + path.sep + 'sign'+path.sep+'bin';
}
function getJavaRuntimer(){
return "path="+getSignTools()+"&"
}
function getFilePath(file) {
return path.dirname(file)
}
function getFileNotExtName(file) {
return path.basename(file, path.extname(file))
}

76
sign_dialog.html Normal file
View File

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<script src="js/jquery-3.2.1.js"></script>
<script src="layui/layui.all.js"></script>
<link rel="stylesheet" href="layui/css/layui.css">
<link rel="stylesheet" href="layui/css/modules/layer/default/layer.css">
<link rel="stylesheet" href="layui/css/layui.css" media="all">
</head>
<body>
<form class="layui-form" style="height: 300px;width: 330px;">
<div class="layui-form-item">
<label class="layui-form-label">别名</label>
<div class="layui-input-block">
<input type="text" id="alias" required lay-verify="required" placeholder="请输入别名(Alias)" autocomplete="off"
class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">别名密码</label>
<div class="layui-input-block">
<input type="text" id="aliasPassword" required lay-verify="required" placeholder="请输入别名密码(AliasPassword)"
autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">签名密码</label>
<div class="layui-input-block">
<input type="text" id="password" required lay-verify="required" placeholder="请输入签名密码(Password)"
autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item" style="margin-left: 10px;">
<button id="select" type="button" class="layui-btn">选择签名</button>
<button id="sub" type="button" class="layui-btn">保存</button>
</div>
</form>
</body>
<script>
layui.use('upload', function () {
let upload = layui.upload;
let signFile
let uploadInst = upload.render({
elem: '#select' //绑定元素
, url: '/' //上传接口
, accept: 'file'
, auto: false
, choose: function (res) {
//上传完毕回调
let files = res.pushFile();
res.preview(function (index, file, result) {
path = file.path;
signFile=path
window.parent.showWindows()
});
}
, error: function () {
//请求异常回调
}
});
$('#sub').click(function(){
let alias=$('#alias').val()
let aliasPassword=$('#aliasPassword').val()
let password=$('#password').val()
window.parent.uploadSign(alias,aliasPassword,password,signFile)
layer.msg('保存成功,正常关闭对话框即可')
})
})
</script>
</html>