Android — AsyncTask 异步加载

前言

我们知道,当Android程序启动的时候,会同时启动一个对应的主线程 (Main Thread),这个线程主要负责处理与UI相关的事件,我们也叫它UI线程。而Android UI操作并不是线程安全的并且这些操作都要在UI线程中执行。还有就是像一些耗时操作如网络操作不能在主线程中进行,一旦时间超过五秒,就会报ANR(应用程序无响应)异常。那么问题来了,如果我们要在非UI线程中操作UI该怎么做呢?这里就需要引入异步任务了,当然实现异步任务也不只是可以使用AsyncTask,这里我们先讲讲AsyncTask这个官方给我们封装好的轻量级异步类。

基本结构

AsyncTask是一个抽象类,一般我们会定义一个类继承至AsyncTask,然后重写相关的方法。

AsyncTask 包含三个泛型参数:(不需要返回类型写 Void 即可)

Params : 启动任务时输入的参数类型。

Progress : 后台任务执行返回进度值得类型。

Result : 后台任务执行完成后返回结果的类型。

more >>


Android — Activity详解

前言

Activity作为四大组件之一,简单来说就是用来处理与用户交互的。本节我们简单讲解一下Activity的生命周期、任务栈以及数据传递,刚刚接触安卓,大佬轻拍。

Activity生命周期

onCreat() —> onStart() —> onResume() —> onPause() —> onStop() —> onDestroy() 完整的生命周期。

onResume()会使当前Activity获得焦点,当调用onPause()时,当前还是可见的,但失去焦点了,在调用onStop()后,该Activity已经变得不可见了。这时候可以调用onRestart()重新回到前台。

Activity任务栈

一个APP都是由多个Activity构成的,而在Android中给我提供了一个Task (任务)的概念,而在Android中实现了Task的数据结构就是Bask Stack (回退堆栈),也就是后进先出。官方文档给出的流程图:

总结:

Task是Activity的集合,是一个概念,实际上是使用Back Stack来存储Activity,可以有多个Task,但是同一时刻只有一个栈在最前面,其他的都在后台。那么栈是如何产生的呢?

答:当我们新打开一个APP,此时会创建一个的Task。举个例子:我们通过点击通信录APP的图标打开APP,这个时候会新建一个栈1,然后开始把新产生的Activity添加进来,可能我们在通讯录的APP中打开了短信APP的页面,但是此时不会新建一个栈,而是继续添加到栈1中,这是 Android推崇一种用户体验方式,即不同应用程序之间的切换能使用户感觉就像是同一个应用程序, 很连贯的用户体验,官方称其为seamless (无缝衔接)! ——————这个时候假如我们点击Home键,回到主屏幕,此时栈1进入后台,我们可能有下述两种操作:
1)点击菜单键(正方形那个按钮),点击打开刚刚的程序,然后栈1又回到前台了! 又或者我们点击主屏幕上通信录的图标,打开APP,此时也不会创建新的栈,栈1回到前台!
2)如果此时我们点击另一个图标打开一个新的APP,那么此时则会创建一个新的栈2,栈2就会到前台, 而栈1继续呆在后台;
3) 后面也是这样…以此类推!

Activity数据传递

  1. 简单的数据传递(单个数据和多个数据的传递)

保存数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
String text = mEditText1.getText().toString().trim();
String sex="";
// //单个数据传递
// if (mRadioButton1.isChecked()) {
// sex = mRadioButton1.getText().toString();
// }
// Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
// Log.i("2333", text);
// intent.putExtra("key", text);
// intent.putExtra("sex", sex);
// startActivity(intent);
//多个数据传递
for (int i = 0; i < mRadioGroup1.getChildCount(); i++) {
RadioButton rb = (RadioButton) mRadioGroup1.getChildAt(i);
if (rb.isChecked()) {
sex = rb.getText().toString();
break;
}
}
Bundle bundle = new Bundle();
bundle.putString("username", text);
bundle.putInt("age", 18);
bundle.putString("sex", sex);
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtras(bundle);
startActivity(intent);

获取数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
mTextView1 = findViewById(R.id.textView2);
//获取单个数据
// Intent intent = getIntent();
// String username = intent.getStringExtra("key").toString();
// String sex = intent.getStringExtra("sex").toString();
// mTextView1.setText(username+sex);
//获取数据集
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
String username = bundle.getString("username").toString();
String sex = bundle.getString("sex").toString();
int age = bundle.getInt("age");
mTextView1.setText(username+sex+age);
  1. 多个Activity之间的数据传递(后一个Activity回传给前一个Activity)

在第一个Activity中启动第二个Activity的时候不用startActivity()方法了,改用startActivityForResult()方法。然后在第一个Activity中重写回调方法onActivityResult。然后在第二个Activity中存数据传入到第一个Activity。

第一个Activity :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
mButton1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
requestCode = 1;
Intent intent = new Intent(MainActivity.this, TestActivity.class);
startActivityForResult(intent,requestCode);
}
});
}
//回调方法
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == 1) {
Bundle bd = data.getExtras();
String text1 = bd.getString("text1");
mTextView1.setText(text1);
Log.i("2333", text1);
}
}

第二个Activity :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.testactivity);
mButton3 = findViewById(R.id.button3);
requestCode = 1;
Intent intent = getIntent();
Bundle bundle = new Bundle();
bundle.putString("text1","辣鸡1");
bundle.putString("text2", "辣鸡2");
intent.putExtras(bundle);
this.setResult(requestCode, intent);
mButton3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
TestActivity.this.finish();
}
});
}

Android — 有道翻译

前言

利用有道提供的API,写一个自动识别语言的翻译软件。支持汉译英,英译汉,小语种,短语句子等。实现也很简单,简单来说就是拼接URL然后请求网络返回接收数据后解析到UI中。

效果预览

more >>


长密码拒绝服务攻击

0X01

今天在用AWVS扫一个站点时,发现一个Long password denial of service高危漏洞。通常情况下,我们都强调用复杂的密码来防止被爆破,然而过长的密码也可能被Hacker用来发起DOS攻击。Hacker故意反复发送长度较长,让服务器进行复杂的计算,可能导致服务器不响应或者资源耗尽。

0X02

这里假设在一个网站上注册一个用户,用户名会被明文存储,而密码一般都用 MD5 加密存储,如果密码设置的过长,服务器就要进行大量的计算出该密码对对应的 MD5 值,这个过程可能会使服务器宕机,所以一般网站都会对密码的长度进行限制,不只是最短长度。

测试执行(以我扫的那个站为例):

  • password of 1000000 characters => 30.015 s
  • password of 100 characters => 0.047 s
  • password of 100000 characters => 30.03 s
  • password of 1100000 characters => 29.999 s
  • password of 500 characters => 0.078 s

这里,为极简图床默哀一秒。


敏感信息泄露

0X00

本文简述几个不是很常见的敏感信息泄露的途径,敏感信息的泄露可以帮助攻击者为高级的攻击做准备,而防护办法只有一个:删,删,删。

more >>

我们一直都向往,面朝大海,春暖花开。 但是几人能做到,心中有爱,四季不败?