安卓逆向之Android-Intent介绍
Intent是各个组件之间交互的一种重要方式,它不仅可以指明当前组件想要执行的动作,而且还能在各组件之间传递数据。Intent一般可用于启动Activity、启动Service、发送广播等场景。Intent有多个构造函数的重载。
显式intent
显式 Intent 明确指定要启动的目标组件的类名。通过显式 Intent,开发者可以直接调用应用程序内的特定 Activity 或服务。主要用于应用程序内部组件之间的调用。比如在一个 Activity 中启动另一个 Activity。
Intent intent = new Intent(MainActivity.class,SecondActivity.class);
intent.putExtra("et1",et1Str);
startActivity(intent);
Intent intent = new Intent(...)
:这行代码创建了一个新的 Intent 对象。Intent 是 Android 中用于不同组件(如 Activity、服务等)之间进行通信的基础类。new Intent(MainActivity.class, SecondActivity.class)
:这个构造函数的两个参数分别是起始 Activity和目标 Activity。在这个例子中,从MainActivity
目标是SecondActivity
。这意味着当 Intent 被启动时,应用程序会在SecondActivity
中打开界面。intent.putExtra("et1", et1Str)
:这行代码用于将额外的数据放入 Intent 中。在这里,"et1"
是键(key),而et1Str
是与之关联的值。这种方式允许我们在启动的SecondActivity
中接收et1Str
的值,便于在新的界面上使用或显示该数据。startActivity(intent)
:这行代码调用startActivity
方法,使用先前创建的 Intent 启动SecondActivity
。执行这一行后,应用程序将离开MainActivity
,并加载SecondActivity
的界面。
隐式intent
隐式 Intent 不直接指定目标组件,而是通过指定一个动作(Action)和/或数据(Data)来指示系统执行某种操作。系统会根据 Intent 的信息查找可以处理该 Intent 的合适组件。
隐式 Intent 允许多个应用程序响应同一个 Intent。只要有一个组件注册了与 Intent 的动作、类别和数据匹配的 intent-filter,就可以接收到这个 Intent。
java部分
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://www.baidu.com"));
startActivity(intent);
Intent intent = new Intent(Intent.ACTION_VIEW);
:这行代码创建了一个新的 Intent 对象,指定了动作为ACTION_VIEW
intent.setData(Uri.parse("https://www.baidu.com"));
:这行代码将 Intent 的数据设置为一个 URI(统一资源标识符),在这个例子中是百度的网页地址"https://www.baidu.com"
。使用Uri.parse()
方法将字符串转换为 URI 格式,这允许系统知道需要打开什么资源。startActivity(intent);
:这行代码使用先前创建的 Intent 启动一个新的 Activity。在这里,它通常会打开一个浏览器或系统的 Web 视图,展示所指定的 URL。
AndroidManifest.xml部分
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="com.example.test.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http">
</intent-filter>
</activity>
<activity android:name=".SecondActivity">
:这行代码在 AndroidManifest.xml 文件中声明了一个 Activity,名为SecondActivity
。<intent-filter>
:这个标签用于定义这个 Activity 能够响应的 intent<action android:name="com.example.test.action.VIEW" />
:这行代码定义了一个自定义的动作,com.example.test.action.VIEW
,意味着这个 Activity 可以处理带有这个动作的 Intent。<category android:name="android.intent.category.DEFAULT" />
:这行代码将意图分类为默认类别,表示这个 Activity 可以处理一些常见的意图。<data android:scheme="http" />
:这行代码指定了这个 Activity 处理的数据类型,主要是以http
开头的 URI。在这里,它明确表示这个 Activity 可以接收以http
或https
开头的网址。
对比
特点 | 显式 Intent | 隐式 Intent |
目标指定法 | 直接指定目标组件(类名) | 不指定目标组件,通过 Action、Data 让系统解析 |
适用场景 | 应用内组件间的通信 | 向系统或其他应用发送请求 |
安全性 | 相对更安全,明确调用 | 相对不安全,需要意图过滤器匹配 |
注册需求 | 无需在 Manifest 中注册 | 需要在 Manifest 中使用 intent-filter 注册 |
使用示例 |
|
|
intent接收字符串
Intent intent = getIntent();
String data = intent.getStringExtra("et1");
接收名为et1的参数值
第二个组件返回数据
有两种方式一种式通过startActivityForResult,一种是通过back键
第一种 不按back键
// 在第一个 Activity 中
Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent, 1); // 1为请求码,用于标识该请求
使用 startActivityForResult()
方法启动第二个组件(Activity)。这允许第一个组件在第二个组件结束时接收结果。
// 在第二个 Activity 中
EditText editText = findViewById(R.id.editText);
String resultData = editText.getText().toString();
// 处理用户点击的按钮
Button button = findViewById(R.id.button);
button.setOnClickListener(v -> {
Intent resultIntent = new Intent();
resultIntent.putExtra("returnData", resultData); // 返回数据
setResult(RESULT_OK, resultIntent); // 设置结果为 OK,并传递数据
finish(); // 结束该 Activity
});
在第二个组件(Activity)中,获取用户输入的数据,并在用户完成操作后使用 setResult()
方法将数据返回给第一个组件,然后调用 finish()
结束该 Activity。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) { // 检查请求码
if (resultCode == RESULT_OK) { // 检查结果是否 OK
String returnData = data.getStringExtra("returnData");
// 处理返回的数据
Toast.makeText(this, "Received: " + returnData, Toast.LENGTH_SHORT).show();
}
}
}
在第一个组件中,重写 onActivityResult()
方法,以接收来自第二个组件的结果。可以通过请求码来识别该结果是来自哪个 Activity。
第二种 按back键
如果用户通过点击 Back 键返回到第一个 Activity,在正常情况下,Back 键会关闭第二个 Activity,而不会返回任何结果。在这种情况下,onActivityResult()
方法将不会被调用,因为没有通过 setResult()
返回结果。如果你希望在用户按 Back 键时处理结果,可以在第二个 Activity 中重写 onBackPressed()
方法,并使用 setResult()
返回数据。
@Override
public void onBackPressed() {
Intent resultIntent = new Intent();
resultIntent.putExtra("returnData", "User cancelled"); // 设置返回数据
setResult(RESULT_CANCELED, resultIntent); // 设置结果为 CANCELLED
super.onBackPressed(); // 调用父类方法,结束该 Activity
}
那么第一个组件种也要重写onActivityResult来接收传递的值
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1) { // 检查请求码
if (resultCode == RESULT_OK) { // 检查结果是否 OK
String returnData = data.getStringExtra("returnData");
// 处理返回的数据
Toast.makeText(this, "Received: " + returnData, Toast.LENGTH_SHORT).show();
}
}
}
仔细观察会发现他们第二个组件都是差不多的,都有以下相同的代码逻辑
Intent resultIntent = new Intent();
resultIntent.putExtra("returnData", "User cancelled"); // 设置返回数据
setResult(RESULT_CANCELED, resultIntent); // 设置结果为 CANCELLED
super.onBackPressed(); // 调用父类方法,结束该 Activity
但是如果通过按back键来返回的话就多了一个 重写onBackPressed的过程,他是针对用户需要进行back键来返回的逻辑处理,通俗来讲也就是针对用户按下back键这一操作的逻辑处理。
不同场景 使用不同的方式 例如:
- 如果用户必须完成某项操作后才能返回数据,那么使用 不按back的方式 是更合适的选择。
- 如果你希望记录用户退出的状态,或者允许用户在不完成输入的情况下返回数据,重写
onBackPressed()
来返回一些适合的默认值是一个很好的选择。