Files
fuzhu/doc/技术文档

395 lines
19 KiB
Plaintext
Raw Permalink Normal View History

2026-01-06 10:32:14 +08:00
一、三种常用的定时器
1.Handler类的postDelayed方法:
final Handler mHandler = new Handler();
Runnable r = new Runnable() {
@Override
public void run() {
//do something
//每隔1s循环执行run方法
mHandler.postDelayed(this, 1000);
}
};
//主线程中调用:
mHandler.postDelayed(r, 100);//延时100毫秒
2.用handler+timer+timeTask方法:
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
//do something
}
super.handleMessage(msg);
}
};
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
Message message = new Message();
message.what = 1;
handler.sendMessage(message);
}
};
//主线程中调用:
timer.schedule(timerTask, 1000, 500);//延时1s,每隔500毫秒执行一次run方法
3.Thread+handler方法:
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
//do something
}
super.handleMessage(msg);
}
};
class MyThread extends Thread {//这里也可用Runnable接口实现
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);//每隔1s执行一次
Message msg = new Message();
msg.what = 1;
handler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//主线程中调用:
new Thread(new MyThread()).start();
4.ScheduledThreadPoolExecutor方法:
private ScheduledThreadPoolExecutor mThreadPoolExecutor;
if (mThreadPoolExecutor != null) {
mThreadPoolExecutor.shutdownNow();
}
mThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
mThreadPoolExecutor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
}
}, 0, 500, TimeUnit.MILLISECONDS);
二、三种延时的快捷方法:
1.Handler的postDelayed方法:
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//do something
}
}, 1000); //延时1s执行
2.timer + TimerTask方法:
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
//do something
}
},1000);//延时1s执行
3.Thread方法:
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);//延时1s
//do something
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
自带定时器 CountDownTimer
利用 CountDownTimer 实现一个时长为 5 秒的 View 倒计时显示,要求从 5s 开始每隔 1 秒倒计时显示到 1s
CountDownTimer countDownTimer = new CountDownTimer(totalTime, 2000) {
@Override
public void onTick(long millisUntilFinished) {
updateFileData(fileId); //执行任务
}
@Override
public void onFinish() {
if (User.getInstance().isLoginIng()) {
if (countDownTimer != null) {
countDownTimer.start();
}
}
}
};
countDownTimer.start();
三、定时轮询
为什么使用Service
普通的线程也可以达到在后台做事情的功能,那么为什么使用 Service呢?是因为 Service是系统的组件,它的优先级比普通的线程要高,
不容易被系统回收。而且 线程不好控制,Service相对好控制一些。运行在前台的Activity是不会被系统回收 的,而Service如果不想被
系统回收,就需要在Service中设置一下
startForeground(int,Notification)
具体的使用场景有:
a、拥有长连接QQ
b、定时轮询
c、服务里面注册广播接收者。有些广播接收者只能通过代码注册,比如屏幕锁屏、 屏幕解锁、电量发生变化等。
e、IntentService
Android RxJava 实际应用讲解:(无条件)网络请求轮询
https://www.jianshu.com/p/11b3ec672812
四、沉浸式框架implementation 'com.hannesdorfmann.mosby3:mvp:3.0.0-alpha4'
五、获取结点元素 方式一:
// 遍历root下的子节点有哪些
for (int i = 0; i < root.getChildCount(); i++) {
AccessibilityNodeInfo child = root.getChild(i);
Log.e("TIAOSHI###", "----oneNode:" + child.getClassName() + ":" + child.getText() + ":" + child.getContentDescription());
if ("dmt.viewpager.DmtViewPager$d".equals(child.getClassName())) {
Log.e("TIAOSHI###ViewPager", "----twoNode:" + child.getChildCount());
for (int y = 0; y < child.getChildCount(); y++) {
AccessibilityNodeInfo child1 = child.getChild(y);
Log.e("TIAOSHI###", "----twoNode:" + child1.getClassName() + ":" + child1.getText() + ":" + child1.getContentDescription());
if ("android.widget.TabHost".equals(child1.getClassName())) {
for (int j = 0; j < child1.getChildCount(); j++) {
AccessibilityNodeInfo child2 = child1.getChild(j);
Log.e("TIAOSHI###", "----threeNode:" + child2.getClassName() + ":" + child2.getText());
}
}
}
}
}
六、横向滑动
AblViewUtil.scrollHorizontal(10,600,100,600, new GestureCallBack() {
@Override
public void succ(GestureDescription gestureDescription) {
}
@Override
public void fail(GestureDescription gestureDescription) {
}
});
七、停止服务
AblStepHandler.getInstance().setStop(true);
八、定时器
private void daojishizreo(int a) {
//启动计时器
//从0开始发射11个数字为:0-10依次输出,延时0s执行,每1s发射一次。
mdDisposable = Flowable.intervalRange(0, a + 1, 0, 1, TimeUnit.SECONDS)
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(new Consumer<Long>() {
@Override
public void accept(Long aLong) throws Exception {
long b = a - aLong;
}
})
.doOnComplete(new Action() {
@Override
public void run() throws Exception {
AblStepHandler.getInstance().setStop(true);
Log.e("TIAOSHI###", "停止了");
}
})
.subscribe();
}
九、for循环找控件
/**
* 寻找留下你的精彩评论
*/
private AccessibilityNodeInfo findcoment() {
AccessibilityNodeInfo infooos=null;
AccessibilityNodeInfo rootttt = AblService.getInstance().getRootInActiveWindow();
for (int j = 0; j < rootttt.getChildCount(); j++) {
AccessibilityNodeInfo child = rootttt.getChild(j);
Log.e("TIAOSHI###", "----1Node:" + child.getClassName() + ":" + child.getText());
if (!"dmt.viewpager.DmtViewPager$d".equals(child.getClassName())) {
// Log.e("TIAOSHI###ViewPager", "----2Node:" + child.getChildCount());
for (int y = 0; y < child.getChildCount(); y++) {
AccessibilityNodeInfo child1 = child.getChild(y);
Log.e("TIAOSHI###", "----2Node:" + child1.getClassName() + ":" + child1.getText());
// if ("android.widget.LinearLayout".equals(child1.getClassName())) {
for (int x = 0; x < child1.getChildCount(); x++) {
AccessibilityNodeInfo child6 = child1.getChild(x);
Log.e("TIAOSHI###", "----3Node:" + child6.getClassName() + ":" + child6.getText());
for (int z = 0; z < child6.getChildCount(); z++) {
AccessibilityNodeInfo child7 = child6.getChild(z);
// Log.e("TIAOSHI###", "----4Node:" + child7.getClassName() + ":" + child7.getText());
// if ("android.widget.LinearLayout".equals(child7.getClassName())) {
for (int r = 0; r < child7.getChildCount(); r++) {
AccessibilityNodeInfo child2 = child7.getChild(r);
// Log.e("TIAOSHI###", "----5Node:" + child2.getClassName() + ":" + child2.getText());
for (int m = 0; m < child2.getChildCount(); m++) {
AccessibilityNodeInfo child3 = child2.getChild(m);
// Log.e("TIAOSHI###", "----6Node:" + child3.getClassName() + ":" + child3.getText());
for (int n = 0; n < child3.getChildCount(); n++) {
AccessibilityNodeInfo child4 = child3.getChild(n);
// Log.e("TIAOSHI###", "----7Node:" + child4.getClassName() + ":" + child4.getText());
for (int k = 0; k < child4.getChildCount(); k++) {
AccessibilityNodeInfo child5 = child4.getChild(k);
// Log.e("TIAOSHI###", "----8Node:" + child5.getClassName() + ":" + child5.getText());
for (int p = 0; p < child5.getChildCount(); p++) {
AccessibilityNodeInfo child8 = child5.getChild(p);
// Log.e("TIAOSHI###", "----9Node:" + child8.getClassName() + ":" + child8.getText());
}
}
}
}
}
// }
//
}
}
}
}
// }
}
return infooos;
}
十、超级大坑 目前无解
在做验证码登录的是时候,getRootInActiveWindow()方法的返回值为null,getWindow()方法也为null,网上查遍资料也没有
印象笔记搜索:getRootInActiveWindow()方法的返回值为null
解决办法是让,也没先返回home,然后再打开就可以了。
十一、导入手机联系人
遇到的两个问题:1是内容提供者的配置
2是权限的问题
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
int hasWriteContactsPermission = checkSelfPermission(Manifest.permission.READ_CONTACTS);
if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.WRITE_CONTACTS},REQUEST_CODE_ASK_PERMISSIONS);
// return;
}
}
加入这段代码就好了。
十二、绑定服务 https://blog.csdn.net/imxiangzi/article/details/76039978?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromBaidu-1.control
十三、WindowManager.LayoutParams详解 https://blog.csdn.net/weixin_34055787/article/details/92576555
十四、在Android中用广播监听AccessibilityService的开启状态并更新UI界面https://blog.csdn.net/huang826336127/article/details/80139543
十五、Android RxJava/RxAndroid:takeWhile,直test测试条件通过才执行链式操作TestAblStep12
https://blog.csdn.net/zhangphil/article/details/79882700
十六、关机重启
AblStepHandler.getInstance().setStop(false);
AblStepHandler.sendMsg(AblSteps.STEP_25);
十七、退出抖音
AblStepHandler.getInstance().setStop(false);
AblStepHandler.sendMsg(AblSteps.STEP_192);//检测我的页面弹出了好友推荐对话框,并关闭
十八、捕捉弹框(获取事件)
// TODO Auto-generated method stub
// System.out.println("Enter->onAccessibilityEvent");
//判断是否是通知事件typeAnnouncement
if(event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){
List<CharSequence> text = event.getText();
if(text.size()>0) {
CharSequence charSequence = text.get(0);
String s = charSequence.toString();
Log.e("TIAOSHI", "有弹出");
Log.e("TIAOSHI", "有弹出==" + s);
//获取消息来源
String sourcePackageName = (String) event.getPackageName();
//获取事件具体信息
Parcelable parcelable = event.getParcelableData();
//如果是下拉通知栏消息
if (parcelable instanceof Notification) {
} else {
//其它通知信息,包括Toast
String toastMsg = (String) event.getText().get(0);
Log.e("TIAOSHI", "有弹出" + toastMsg);
Log.e("Latest Toast Message:", "" + toastMsg + " [Source: " + sourcePackageName + "]");
EventBus.getDefault().post(new SixEvent("success", toastMsg));
}
}
}
private void getdouyin() {
int num = 0;
accessibilityNodeInfos = new ArrayList<>();
AccessibilityNodeInfo root = AblService.getInstance().getRootInActiveWindow();
for (int i = 0; i < root.getChildCount(); i++) {
AccessibilityNodeInfo child = root.getChild(i);
Log.e("TIAOSHI###", "----oneNode:" + child.getClassName() + ":" + child.getText() + ":" + child.getContentDescription());
// if ("androidx.viewpager.widget.ViewPager".equals(child.getClassName())) {
for (int y = 0; y < child.getChildCount(); y++) {
AccessibilityNodeInfo child1 = child.getChild(y);
Log.e("TIAOSHI###", "----twoNode:" + child1.getClassName() + ":" + child1.getText() + ":" + child1.getContentDescription());
// if ("androidx.recyclerview.widget.RecyclerView".equals(child1.getClassName())) {
for (int j = 0; j < child1.getChildCount(); j++) {
AccessibilityNodeInfo child2 = child1.getChild(j);
Log.e("TIAOSHI###", "----threeNode:" + child2.getClassName() + ":" + child2.getText() + ":" + child1.getContentDescription());
for (int x = 0; x < child2.getChildCount(); x++) {
AccessibilityNodeInfo child3 = child2.getChild(x);
Log.e("TIAOSHI###", "----fourNode:" + child3.getClassName() + ":" + child3.getText() + ":" + child1.getContentDescription());
for (int r = 0; r < child3.getChildCount(); r++) {
AccessibilityNodeInfo child4 = child3.getChild(r);
Log.e("TIAOSHI###", "----5Node:" + child4.getClassName() + ":" + child4.getText()+ ":" + child4.getContentDescription());
for (int m = 0; m < child4.getChildCount(); m++) {
AccessibilityNodeInfo child5 = child4.getChild(m);
Log.e("TIAOSHI###", "----6Node:" + child5.getClassName() + ":" + child5.getText()+ ":" + child5.getContentDescription());
for (int p = 0; p < child5.getChildCount();p++) {
AccessibilityNodeInfo child6 = child5.getChild(p);
Log.e("TIAOSHI###", "----7Node:" + child6.getClassName() + ":" + child6.getText()+ ":" + child6.getContentDescription());
for (int t = 0; t < child6.getChildCount();t++) {
AccessibilityNodeInfo child7 = child6.getChild(t);
Log.e("TIAOSHI###", "----8Node:" + child7.getClassName() + ":" + child7.getText()+ ":" + child7.getContentDescription());
}
}
}
}
}
}
}
// }
// }
}
}
Rect rect = new Rect();
child7.getBoundsInScreen(rect);
Log.e("TIAOSHI###", "----8Node:" + "(" + rect.left + "," + rect.top + ")" + "," + "(" + rect.right + "," + rect.bottom + ")");
数据更新进度条:http://www.zyiz.net/tech/detail-56306.html
抢红包的demo: http://www.voidcn.com/article/p-cujkxxnt-bpb.html