B13_通知图片相机与影音 Android 基础补强 B13通知、图片、相机与影音先分清资源从哪里来发布摘要围绕一张文章附件理解通知渠道与权限、系统照片选择器、拍照输出 URI以及播放器的资源寿命。标签通知、Photo Picker、相机、Media3。《第一行代码》第 9 章把通知、拍照、选图和播放音视频放在多媒体主题下但实际开发时它们不是“一套权限加几个按钮”。通知由系统展示图片可能来自另一个内容提供者拍照可以委托相机应用播放器则持有解码与输出资源。先回答由谁执行、内容在哪里、谁负责释放API 才不会混成一团。本篇是第 9 章基础补强适合放在 D19 后的选修时段。练习场景是给本地文章笔记选择附件并用一条调试通知提示“附件已准备好”。下列代码尚未在用户工程编译运行通知和媒体入口分别验证后再合并。一、通知渠道与通知权限是两道条件Android 8.0API 26引入通知渠道面向该版本及以上的应用发送通知需要指定渠道。用户可以在系统设置中修改渠道行为应用重复创建同一个渠道不会把用户设置随意重置。通知渠道Android 13API 33及以上非豁免通知还涉及 POST_NOTIFICATIONS 运行时权限。目标 SDK 33 及以上的应用能选择合适的申请时机旧目标版本的弹窗时机由系统规则决定不能直接套用同一流程。通知运行时权限下面函数假设 compileSdk 至少 33、minSdk 至少 23已声明通知权限申请流程在宿主完成。依赖 AndroidX Core导入需要 Android 的 Context、NotificationChannel、NotificationManager、Build、Manifest、PackageManager和 AndroidX 的 ContextCompat、NotificationCompat、NotificationManagerCompat。funpostAttachmentNotice(context:Context):Boolean{valchannelIdattachment_resultsvalmanagercontext.getSystemService(NotificationManager::class.java)if(Build.VERSION.SDK_INTBuild.VERSION_CODES.O){manager.createNotificationChannel(NotificationChannel(channelId,附件处理结果,NotificationManager.IMPORTANCE_DEFAULT))}if(Build.VERSION.SDK_INT33ContextCompat.checkSelfPermission(context,Manifest.permission.POST_NOTIFICATIONS)!PackageManager.PERMISSION_GRANTED)returnfalsevalcompatNotificationManagerCompat.from(context)if(!compat.areNotificationsEnabled())returnfalsevalnoticeNotificationCompat.Builder(context,channelId).setSmallIcon(android.R.drawable.ic_dialog_info).setContentTitle(附件已准备好).setContentText(可以返回文章笔记查看).setAutoCancel(true).build()compat.notify(1001,notice)returntrue}true 表示代码走到了提交通知不保证用户实际看见渠道可能被单独关闭设备也可能采用不同展示策略。示例用系统图标方便实验正式应用应提供符合通知要求的自身小图标。若需要点击进入笔记再加入显式目标 PendingIntent并正确指定可变性上面的最小通知没有实现点击跳转。二、选一张图片不等于读取整个图库Photo Picker 让用户选定图片或视频应用取得所选内容访问权。AndroidX Activity 的 PickVisualMedia 合约提供设备适配与回退支持应使用工程配套的稳定版本不根据某个 Android 版本号自行假设所有设备都安装相同选择器。Photo Picker实现步骤是注册选择合约、点击时 launch、处理非空 URI、用图片加载器解码显示。结果为 null 代表没有选中内容是正常取消不能在回调里自动再次打开选择器。显示缩略图应让成熟图片加载库按目标尺寸加载不把原图全部解码到一个随意大小的 Bitmap。如果附件需要长期保留先决定保留原文档授权还是复制到应用自己的存储。前者受提供者和授权寿命影响后者需要管理容量、重复文件和删除时机。复制完成后才把附件元数据写入数据库避免列表记录存在但实际文件尚未准备好。三、拍照先准备输出不能只等一个 Bitmap使用系统相机时完整照片应写到启动前准备好的 URI。ActivityResultContracts.TakePicture 接受这个输出 URI返回是否成功应用仍要保存待处理 URI以便宿主重建后知道照片应该在哪里。仅使用相机返回的小缩略图无法代表已经保存高清原图。本课可以复用 FileProvider 的专用照片目录授予相机应用必要的写入访问。若仅委托外部相机拍摄且应用没有自行声明使用 CAMERA 的需求通常无需自己请求相机权限直接使用 CameraX 或 Camera2 则属于应用使用相机需要相应权限与生命周期管理。不要把两种方式混在同一权限结论里。相机委托拍照用户取消拍照时清理本次创建的无效临时文件成功后检查可读取性并生成展示缩略图。若写入的是公开媒体库还需使用对应版本的 MediaStore 规则本练习限定为应用控制的附件目录避免把旧版外部存储路径写法照搬到现代系统。四、播放器必须有明确的所有者书中的 MediaPlayer 有自己的状态机创建、准备、播放、暂停和释放不是任意顺序都合法。现代新功能可使用 Media3 ExoPlayer但“换库”也不能省掉生命周期。阅读页内短视频由阅读页相关宿主管理退出后释放真正需要后台持续播放则应设计 MediaSession 与服务不把页面播放器偷偷留在内存里。创建播放器、设置 MediaItem、prepare、连接播放器视图和 release 应成对设计。重组时不能无条件重新创建播放器释放后不能继续播放前后台切换策略也要根据是否允许持续播放明确实现。Media3 播放器入门五、故障实验与预期关闭通知渠道后发送预期不能仅凭 notify 调用成功判断可见拒绝通知权限后附件处理本身仍应成功。选图后取消预期保留原附件选择大图预期按显示尺寸加载而不是造成明显内存压力。拍照期间重建宿主检查待处理 URI 是否保留取消拍照检查临时文件清理。播放期间退出页面再进入新页面预期旧播放器不会继续占用当前页面的音视频输出。每种现象都需设备验证本文不把预期写成既有测试记录。六、原创面试问答与追问本篇可联系题库权限申请和Activity 生命周期。下面问答为自拟。问通知权限允许就一定出现通知吗答渠道、全局设置和系统展示行为仍会影响结果。追问如何定位分别检查权限、渠道、构建字段和实际系统状态。问选一张图为什么通常不用申请整个媒体库权限答系统选择器提供针对选中内容的访问。追问URI 能一直用吗要考虑授权持久化、内容删除和复制策略。问播放器藏到单例就能避免重建吗答可能延长资源寿命并持有错误宿主不是通用答案。追问怎样决定归属由页面播放或后台播放需求决定生命周期所有者。七、练习与验收建议分两次完成第一次九十分钟做通知与选图第二次九十分钟做拍照输出和短视频释放。每次只增加一个功能故障注入后再整合。交付包含版本条件表、附件 URI 流程图和四类取消或失败记录。主线只需要系统分享时可以把本篇标为基础选修不能为了覆盖书籍目录就宣称全部多媒体功能已经进入 DevCommunity。