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 注册 |
使用示例 |
new Intent(this, SecondActivity.class) |
new Intent(Intent.ACTION_VIEW) |
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() 来返回一些适合的默认值是一个很好的选择。
原文始发于微信公众号(Ting丶的安全笔记):安卓逆向之Android-Intent介绍
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论