引言:为什么要从其他应用调用 Activity?
\n\n想象一下,您正在创建一个笔记应用,并希望让用户能够直接从您的界面拍照。或者,假设您的即时通讯应用需要打开通讯录中的联系人。在这两种情况下,您都需要在 Android 中从其他应用启动 Activity。
\n\n这个任务是 Stack Overflow 上最热门的问题之一(数千次浏览和数百次点赞)。这并非没有原因:如果操作不当,应用可能会因 ActivityNotFoundException 而崩溃,或者更糟的是,造成安全威胁。在本教程中,我们将使用 Kotlin 语言详细解析所有细节,让您能够自信地将外部界面集成到自己的项目中。
顺便提一下,您正在访问 PythonLib 网站,我们经常在这里讨论 Python,但今天是个特例。使用 Kotlin 进行 Android 开发是一项强大的技能,与 Python 后端完美结合。我们开始吧!
\n\n什么是 Intent,为什么它是解决问题的关键?
\n\n在 Android 中,Intent 是一条消息,它告诉系统:“嘿,我需要用某个动作做某事”。对于从其他应用启动 Activity,有两种方法:
\n\n- \n
- 显式 Intent — 您确切知道要启动哪个组件(例如
com.example.target.MainActivity)。仅当您有权访问该应用的代码时才有效。 \n - 隐式 Intent — 您描述想要做什么(例如“根据坐标打开地图”),系统会自动找到合适的应用。这是调用外部 Activity 更灵活、更安全的方式。 \n
我们将重点放在隐式 Intent 上,因为它们最常用于Android 进程间通信。
\n\n基本示例:根据坐标打开地图
\n\n从一个简单的示例开始,演示如何从其他应用启动 Activity 来显示地图。
\n\n// Kotlin\nval gmmIntentUri = Uri.parse("geo:55.7558,37.6173?z=15")\nval mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)\nmapIntent.setPackage("com.google.android.apps.maps")\n\n// 检查是否有应用可以处理此 Intent\nif (mapIntent.resolveActivity(packageManager) != null) {\n startActivity(mapIntent)\n} else {\n // 向用户显示错误消息\n Toast.makeText(this, "Google 地图未安装", Toast.LENGTH_SHORT).show()\n}\n\n这里发生了什么?我们创建了一个带有 ACTION_VIEW 动作和包含坐标的 URI 的 Intent。然后使用 setPackage 明确指定要使用 Google 地图(尽管这不是必需的——系统可能会提供选择)。最重要的是通过 resolveActivity 进行检查。这可以防止在设备上缺少所需应用时崩溃。
场景:调用相机并获取结果
\n\n现在,我们转向更复杂的用例——从其他应用启动 Activity 并等待结果。经典示例:拍照并在自己的应用中获取照片。
\n\n// Kotlin\nprivate const val REQUEST_IMAGE_CAPTURE = 1\n\nprivate fun dispatchTakePictureIntent() {\n val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)\n // 检查相机是否可用\n if (takePictureIntent.resolveActivity(packageManager) != null) {\n startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)\n } else {\n // 错误处理:未找到相机\n }\n}\n\noverride fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {\n super.onActivityResult(requestCode, resultCode, data)\n if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {\n val imageBitmap = data?