Android笔记(十七):PendingIntent简介

PendingIntent翻译成中文为“待定意图”,这个翻译很好地表示了它的涵义。PendingIntent描述了封装Intent意图以及该意图要执行的目标操作。PendingIntent封装Intent的目标行为的执行是必须满足一定条件,只有条件满足,才会触发意图的目标操作。

一.获取PendingIntent对象

获取PendingIntent对象有以下几种方式:

  • PendingIntent.getActivity(Context, int, Intent, int):启动活动
  • PendingIntent.getActivities(Context, int, Intent[], int):启动多个活动,意图中为数组
  • PendingIntent.getBroadcast(Context, int, Intent, int):启动广播
  • PendingIntent.getService(Context, int, Intent, int):启动服务

参数说明:

  • Context:context上下文,PendingIntent启动活动的上下文
  • int:requestCode请求码 ,发送者发送的请求码
  • Intent:intent意图:要加载活动的意图
  • int:flags 标记

对于其中的标记可以定义为下列形式

  • FLAG_ONE_SHOT:PendingIntent对象仅使用一次;
  • FLAG_NO_CREATE:如果PendingIntent对象不存在则返回null
  • FLAG_CANCEL_CURRENT:如果PendingIntent对象已存在,则取消原有的对象,创建新的PendingIntent对象
  • FLAG_UPDATE_CURRENT:如果PendingIntent对象已存在,则保留原有的对象,修改原有对象的属性数据
  • FLAG_IMMUTABLE:PendingIntent对象是不可变的
  • FLAG_MUTABLE:PendingIntent对象是可变的
  • 另外其他Intent中支持的标记都可以在标记参数中使用。

二、应用实例

例如:在MainActivity启动前台服务播放音乐,利用前台服务的通知提供的内容跳转到其他活动例如SongActivity介绍歌曲。界面如下所示。
在这里插入图片描述
点击第一张图的播放,会播放音频,同时发布通知如第二张图所示。在第二张图的红色箭头区域点击,可以屏幕会跳转到第三张图。在第三张图中点击“返回”,则返回主活动。

1. AndroidManifest.xml清单配置权限

  <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
  <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
  <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

2. 定义MusicService

class MusicService : Service() {
    lateinit var mediaPlayer: MediaPlayer
    override fun onCreate() {
        super.onCreate()
        mediaPlayer = MediaPlayer.create(this,R.raw.song3)
    }

    override fun onBind(intent: Intent): IBinder? {
        postNotification()
        playMusic()
        return null
    }

    override fun onUnbind(intent: Intent?): Boolean {
        stopMusic()
        return super.onUnbind(intent)
    }

    /**
     * 播放音乐
     */
    private fun playMusic(){
        mediaPlayer.setOnPreparedListener {
            mediaPlayer.start()
        }
        mediaPlayer.setOnCompletionListener {
            mediaPlayer.release()
        }
    }

    /**
     * 停止播放
     */
    private fun stopMusic(){
        if(mediaPlayer.isPlaying){
            mediaPlayer.stop()
            mediaPlayer.release()
        }
    }
    /**
     * 创建通知渠道
     * @param id String
     * @param name String
     */
    private fun createNotificationChannel(id:String,name:String){
        //创建通知管理器
        val notificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        //定义通知渠道
        val channel = NotificationChannel(id,name,NotificationManager.IMPORTANCE_DEFAULT)
        //创建通知渠道
        notificationManager.createNotificationChannel(channel)
    }

    /**
     * 发布通知
     */
    private fun postNotification(){
        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {
            createNotificationChannel("music_service","歌曲")
        }
      
        //定义跳转SongActivity的PendingIntent
        val descPendingIntent = getSongPendingIntent()
        //定义启动控制音乐播放广播接受器的PendingIntent
        val playPendingIntent = getPlayPendingIntent()
        //定义启动控制音乐停止播放广播接受器的PendingIntent
        val stopPendingIntent = getStopPendingIntent()
        //定义动作
        val playAction = NotificationCompat.Action(android.R.drawable.ic_media_play,"播放",playPendingIntent)
        val stopAction = NotificationCompat.Action(android.R.drawable.ic_media_pause,"停止",stopPendingIntent)
        //创建通知
        val notification = NotificationCompat.Builder(this,"music_service").apply{
            setOngoing(true)
            setOnlyAlertOnce(true)
            setContentTitle("播放音乐")
            setContentText("正在播放歌曲...")
            setSmallIcon(R.mipmap.ic_launcher)
            setColorized(true)
            color = resources.getColor(R.color.teal_200,null)

            setContentIntent(descPendingIntent)

//            addAction(android.R.drawable.ic_media_play,"播放",playPendingIntent) //android23开始不支持
//            addAction(android.R.drawable.ic_media_pause,"停止",stopPendingIntent)//android23开始不支持
            addAction(playAction)
            addAction(stopAction)

        }.build()

        startForeground(1,notification)
    }

    /**
     * 跳转到歌曲介绍的界面
     * @return PendingIntent
     */
    private fun getSongPendingIntent():PendingIntent{
        //定义启动服务的意图
        val intent = Intent(this,SongActivity::class.java)
        //定义PendingIntent
        return PendingIntent.getActivity(this,1,
                intent,PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE)
    }

    private fun getPlayPendingIntent(): PendingIntent {
        //创建意图过滤器
        val intentFilter = IntentFilter()
        //增加动作
        intentFilter.addAction("PLAY_ACTION")
        //创建音乐播放广播接受器
        val playReceiver = object: BroadcastReceiver(){
            override fun onReceive(context: Context?, intent: Intent?) {
                playMusic()
            }
        }
        //注册播放音乐广播器
        registerReceiver(playReceiver,intentFilter)
        //创建播放意图
        val intent = Intent("PLAY_ACTION")
        return PendingIntent.getBroadcast(this,
            2,intent,PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
    }

    private fun getStopPendingIntent():PendingIntent{
        //创建意图过滤器
        val intentFilter = IntentFilter()
        //增加动作
        intentFilter.addAction("STOP_ACTION")
        //创建停止播放广播接受器
        val stopReceiver = object: BroadcastReceiver(){
            override fun onReceive(context: Context?, intent: Intent?) {
                stopMusic()
            }
        }
        //注册广播接收器
        registerReceiver(stopReceiver,intentFilter)
        //创建意图
        val intent = Intent("STOP_ACTION")
        return PendingIntent.getBroadcast(this,
            3,intent,
            PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT)
    }
}

3.定义主活动MainActivity

class MainActivity : ComponentActivity() {
    lateinit var intent1:Intent
    val conn = object:ServiceConnection{
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
        }

        override fun onServiceDisconnected(name: ComponentName?) {
        }

    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        intent1 = Intent(this,MusicService::class.java)

        requestNotificationPermission()
        setContent {
            Lab03Theme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    MainScreen(playAction=::playMusic,stopAction=::stopMusic)
                }
            }
        }
    }

    /**
     * 请求通知权限
     */
    private fun requestNotificationPermission(){
        if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.TIRAMISU) {
            ActivityCompat.requestPermissions(
                this,
                arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
                0
            )
        }
    }

    /**
     * 绑定播放音频的服务
     */
    private fun playMusic(){
        bindService(intent1,conn, Context.BIND_AUTO_CREATE)
    }

    /**
     * 解除绑定
     */
    private fun stopMusic(){
        unbindService(conn)
    }
}

@Composable
fun MainScreen(playAction:()->Unit,stopAction:()->Unit) {
    Column(horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center){
        Row{
          TextButton(onClick = {
              playAction.invoke()
          }){
              Row{
                  Icon(imageVector = Icons.Filled.PlayArrow,contentDescription = "play")
                  Text("播放")
              }
          }
          TextButton(onClick = {
              stopAction.invoke()
          }){
                Row{
                    Icon(imageVector = Icons.Filled.Stop,contentDescription = "play")
                    Text("停止")
                }
          }
        }
    }
}

4.定义显示歌曲介绍的SongActivity

class SongActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent{
            Column{
                Text("正在播放歌曲,歌曲介绍内容描述暂时没有定义")
                TextButton(onClick = {
                    //结束当前活动
                    finish()
                }){
                    Text("返回")
                }
            }
        }
    }
}

参考文献

1.PendingIntent
https://developer.android.google.cn/reference/android/app/PendingIntent

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/233195.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HCIP —— BGP 基础 (上)

BGP --- 边界网关协议 &#xff08;路径矢量协议&#xff09; IGP --- 内部网关协议 --- OSPF RIP ISIS EGP --- 外部网关协议 --- EGP BGP AS --- 自治系统 由单一的组织或者机构独立维护的网络设备以及网络资源的集合。 因 网络范围太大 需 自治 。 为区分不同的AS&#…

C#,图算法——以邻接节点表示的图最短路径的迪杰斯特拉(Dijkstra)算法C#程序

1 文本格式 using System; using System.Text; using System.Linq; using System.Collections; using System.Collections.Generic; namespace Legalsoft.Truffer.Algorithm { public class Node // : IComparable<Node> { private int vertex, weigh…

CNN发展史脉络 概述图整理

CNN发展史脉络概述图整理&#xff0c;学习心得&#xff0c;供参考&#xff0c;错误请批评指正。 相关论文&#xff1a; LeNet&#xff1a;Handwritten Digit Recognition with a Back-Propagation Network&#xff1b; Gradient-Based Learning Applied to Document Recogniti…

【工具使用-JFlash】如何使用Jflash擦除和读取MCU内部指定扇区的数据

一&#xff0c;简介 在调试的过程中&#xff0c;特别是在调试向MCU内部flash写数据的时候&#xff0c;我们常常要擦除数据区的内容&#xff0c;而不想擦除程序取。那这种情况就需要擦除指定的扇区数据即可。本文介绍一种方法&#xff0c;可以擦除MCU内部Flash中指定扇区的数据…

【小沐学Python】Python实现TTS文本转语音(speech、pyttsx3、百度AI)

文章目录 1、简介2、Windows语音2.1 简介2.2 安装2.3 代码 3、pyttsx33.1 简介3.2 安装3.3 代码 4、ggts4.1 简介4.2 安装4.3 代码 5、pywin326、百度AI7、百度飞桨结语 1、简介 TTS(Text To Speech) 译为从文本到语音&#xff0c;TTS是人工智能AI的一个模组&#xff0c;是人机…

【linux】yum安装时: Couldn‘t resolve host name for XXXXX

yum 安装 sysstat 报错了&#xff1a; Kylin Linux Advanced Server 10 - Os 0.0 B/s | 0 B 00:00 Errors during downloading metadata for repository ks10-adv-os:- Curl error (6): Couldnt resolve host nam…

【摸鱼向】利用Arduino实现自动化切屏

曾几何时&#xff0c;每次背着老妈打游戏的时候都要紧张兮兮地听着爸妈是不是会破门而入&#xff0c;这严重影响了游戏体验&#xff0c;因此&#xff0c;最近想到了用Arduino加上红外传感器来实现自动监测的功能&#xff0c;当有人靠近门口的时候&#xff0c;电脑可以自动执行预…

【文件上传系列】No.2 秒传(原生前端 + Node 后端)

上一篇文章 【文件上传系列】No.1 大文件分片、进度图展示&#xff08;原生前端 Node 后端 & Koa&#xff09; 秒传效果展示 秒传思路 整理的思路是&#xff1a;根据文件的二进制内容生成 Hash 值&#xff0c;然后去服务器里找&#xff0c;如果找到了&#xff0c;说明已经…

pytorch:YOLOV1的pytorch实现

pytorch&#xff1a;YOLOV1的pytorch实现 注&#xff1a;本篇仅为学习记录、学习笔记&#xff0c;请谨慎参考&#xff0c;如果有错误请评论指出。 参考&#xff1a; 动手学习深度学习pytorch版——从零开始实现YOLOv1 目标检测模型YOLO-V1损失函数详解 3.1 YOLO系列理论合集(Y…

【IDEA】解决mac版IDEA,进行单元测试时控制台不能输入问题

我的IDEA版本 编辑VM配置 //增加如下配置&#xff0c;重启IDEA -Deditable.java.test.consoletrue测试效果

风力发电对讲 IP语音对讲终端IP安防一键呼叫对讲 医院对讲终端SV-6005网络音频终端

风力发电对讲 IP语音对讲终端IP安防一键呼叫对讲 医院对讲终端SV-6005网络音频终端 目 录 1、产品规格 2、接口使用 2.1、侧面接口功能 2.2、背面接口功能 2.3、面板接口功能 3、功能使用 1、产品规格 输入电源&#xff1a; 12V&#xff5e;24V的直流电源 网络接口&am…

初级数据结构(二)——链表

文中代码源文件已上传&#xff1a;数据结构源码 <-上一篇 初级数据结构&#xff08;一&#xff09;——顺序表 | NULL 下一篇-> 1、链表特征 与顺序表数据连续存放不同&#xff0c;链表中每个数据是分开存放的&#xff0c;而且存放的位置尤其零散&#…

C# WPF上位机开发(会员管理软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 好多同学都认为上位机只是纯软件开发&#xff0c;不涉及到硬件设备&#xff0c;比如听听音乐、看看电影、写写小的应用等等。如果是消费电子&#…

人工智能从 DeepMind 到 ChatGPT ,从 2012 - 2024

本心、输入输出、结果 文章目录 人工智能从 DeepMind 到 ChatGPT &#xff0c;从 2012 - 2024前言2010年&#xff1a;DeepMind诞生2012&#xff5e;2013年&#xff1a;谷歌重视AI发展&#xff0c;“拿下”Hinton2013&#xff5e;2014年&#xff1a;谷歌收购DeepMind2013年&…

调用别人提供的接口无法通过try catch捕获异常(C#),见鬼了

前几天做CA签名这个需求时发现一个很诡异的事情&#xff0c;CA签名调用的接口是由另外一个开发部门的同事(比较难沟通的那种人)封装并提供到我们这边的。我们这边只需要把数据准备好&#xff0c;然后调他封装的接口即可完成签名操作。但在测试过程中&#xff0c;发现他提供的接…

2024年网络安全竞赛-数字取证调查attack817

​ 数字取证调查 (一)拓扑图 服务器场景:FTPServer20221010(关闭链接) 服务器场景操作系统:未知 FTP用户名:attack817密码:attack817 分析attack.pcapng数据包文件,通过分析数据包attack.pcapng找出恶意用户第一次访问HTTP服务的数据包是第几号,将该号数作为Flag值…

力扣刷题总结 字符串(2)【KMP】

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 28.找出字符串中第一个匹配项的下标mid经典KMP4593重复的子字符串mid可以使用滑动窗口或者KMP KMP章节难度较大&#xff0c;需要深入理解其中…

Uncaught SyntaxError: Unexpected end of input (at manage.html:1:21) 的一个解

关于Uncaught SyntaxError: Unexpected end of input (at manage.html:1:21)的一个解 问题复现 <button onclick"deleteItem(${order.id},hire,"Orders")" >delete</button>报错 原因 函数参数的双引号和外面的双引号混淆了&#xff0c;改成…

数据可视化|jupyter notebook运行pyecharts,无法正常显示“可视化图形”,怎么解决?

前言 本文是该专栏的第39篇,后面会持续分享python数据分析的干货知识,记得关注。 相信有些同学在本地使用jupyter notebook运行pyecharts的时候,在代码没有任何异常的情况下,无论是html还是notebook区域,都无法显示“可视化图形”,界面区域只有空白一片。遇到这种情况,…

精选Axure原型设计模板,RP原型组件库(PC端移动端元件库及Axure函数及运算符说明)

好的原型组件会大大的提高产品经理的工作效率&#xff0c;小7在陆续整理、精选Axure 8的原型设计模板&#xff0c;包含了原型设计的常用元素和AxureRP 8函数及运算符的说明文档&#xff0c;及各种设备模板框架。 本文也是基于小7另一篇文章的补充&#xff0c;更多更详细的资料…