前情提要
在上一篇文章写到可以提前选好票档,等待到开售时间直接提交进入订单确认页面.
然而这仅仅是"快人一步",在非常热门的演出情况下,一次提交购票成功的几率还是很低的.
在订单确认页面第一次提交往往会弹出"前方拥挤"的提示,这情况下点击确认有可能会被返回上一页.
现在就想办法在可以重复提交的情况下,停留在订单确认页面,直接提交.
分析
这个动作非常影响捡漏速度,有无办法可以去掉呢?
从整个行为过程分析:
调用接口---->返回数据---->弹出窗口---->点击按钮---->关闭页面/返回上一页
所以如果我们可以找到弹出窗口,然后hook按钮点击事件,应该就可以不返回上一页
动手
根据上面的过程分析,首先需要找到"提交订单"调用接口的地方(UltronPresenter
):
其中的onSuccess
和onError
就是调用接口成功和失败的回调函数.
DmUltronRequestErrorUtils.getInstance()
猜测应该是错误弹出窗口的单例.进去看看~
枚举的名字:
多个点击事件
的设置:
都证明这里应该就是错误弹窗点击按钮设置回调的地方.到这个就可以开始暴力hook了
注入
DmUltronRequestErrorUtils
中有三个OnClickListener
:
DialogInterface$OnClickListenerC4733a
DialogInterface$OnClickListenerC4734b
DialogInterface$OnClickListenerC4735c
暴力hook的方法就是把这三个OnClickListener
的onClick
事件替换:
let DialogInterface$OnClickListenerC4733a = Java.use(
"cn.damai.ultron.utils.DmUltronRequestErrorUtils$a"
);
DialogInterface$OnClickListenerC4733a["onClick"].implementation = function (
dialogInterface,
i
) {
console.log(
`DialogInterface$OnClickListenerC4733a.onClick is called: dialogInterface=${dialogInterface}, i=${i}`
);
// this["onClick"](dialogInterface, i);
};
let DialogInterface$OnClickListenerC4734b = Java.use(
"cn.damai.ultron.utils.DmUltronRequestErrorUtils$b"
);
DialogInterface$OnClickListenerC4734b["onClick"].implementation = function (
dialogInterface,
i
) {
console.log(
`DialogInterface$OnClickListenerC4734b.onClick is called: dialogInterface=${dialogInterface}, i=${i}`
);
// this["onClick"](dialogInterface, i);
};
let DialogInterface$OnClickListenerC4735c = Java.use(
"cn.damai.ultron.utils.DmUltronRequestErrorUtils$c"
);
DialogInterface$OnClickListenerC4735c["onClick"].implementation = function (
dialogInterface,
i
) {
console.log(
`DialogInterface$OnClickListenerC4735c.onClick is called: dialogInterface=${dialogInterface}, i=${i}`
);
// this["onClick"](dialogInterface, i);
};
这样就能做到无视重试返回上一页:
继续进阶
在阅读源码过程中发现了错误处理的工厂函数:
发现其中有TOAST
的errorType
,TOAST
在android中是一个自动消失的提示消失,所以在想如果hook这个函数,是否可以做到连dialog
都不用弹窗了,就可以疯狂按提交了,于是hook:
let DmUltronRequestErrorUtils = Java.use(
"cn.damai.ultron.utils.DmUltronRequestErrorUtils"
);
DmUltronRequestErrorUtils["b"].overload(
"cn.damai.ultron.view.activity.DmOrderActivity",
"cn.damai.ultron.utils.DmUltronRequestErrorUtils$ErrorType",
"java.lang.String",
"java.lang.String",
"java.lang.String"
).implementation = function (dmOrderActivity, errorType, str, str2, str3) {
console.log(
`DmUltronRequestErrorUtils.MMdmOrderActivityApiErrorHandle is called: dmOrderActivity=${dmOrderActivity}, errorType=${errorType}, str=${str}, str2=${str2}, str3=${str3}`
);
let ErrorType = Java.use(
"cn.damai.ultron.utils.DmUltronRequestErrorUtils$ErrorType"
);
let TOAST = ErrorType.TOAST;
console.log(this._a.value);
this["b"](dmOrderActivity, TOAST.value, str, str2, str3);
if (this._a.value != "CREATE") {
// console.log("build/adjust api , finish");
dmOrderActivity.finish();
} else {
console.log("CREATE api , toast");
}
// dmOrderActivity.finish();
};
这里做到的操作效果是,如果是create
接口的话,就用toast
的形式提示,如果不是的话,就直接返回上一页.当然这里还可以做更多的细化判断.但是我这里就没有继续研究了.