Android笔记(十七):PendingIntent简介

news2024/11/29 0:54:19

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","歌曲")
        }
        //定义启动服务的意图
        val intent = Intent(this,SongActivity::class.java)
        //定义跳转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?) {
            playMusic()
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            stopMusic()
        }

    }
    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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【每日一题】—— D. Jumping Through Segments(Codeforces Round 913 (Div. 3))(二分)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;每日一题 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日反刍 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0c;缓称…

配置端口安全示例

组网需求 如图1所示&#xff0c;用户PC1、PC2、PC3通过接入设备连接公司网络。为了提高用户接入的安全性&#xff0c;将接入设备Switch的接口使能端口安全功能&#xff0c;并且设置接口学习MAC地址数的上限为接入用户数&#xff0c;这样其他外来人员使用自己带来的PC无法访问公…

【MATLAB源码-第96期】基于simulink的光伏逆变器仿真,光伏,boost,逆变器(IGBT)。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 光伏单元&#xff08;PV Cell&#xff09; 工作原理&#xff1a;光伏单元通过光电效应将太阳光转换为直流电。它们的输出取决于光照强度、单元温度和负载条件。Simulink建模&#xff1a;在Simulink中&#xff0c;光伏单元…

mysql的组合查询

mysql的组合查询 1、mysql的内连接查询 在 MySQL 中&#xff0c;内连接&#xff08;INNER JOIN&#xff09;是一种根据两个或多个表之间的匹配条件&#xff0c;将多个表中的数据进行联接的操作。内连接只返回符合联接条件的行&#xff0c;而不会返回未匹配的行。 内连接的语…

QT5.4.1无法打开文件

问题描述&#xff1a;起初是在QT代码中运行打开文件代码&#xff1a; QString gFilename QFileDialog::getOpenFileName(this,"open File",path,"*", nullptr,QFileDialog::DontUseNativeDialog);时&#xff0c;出现了堵塞情况&#xff0c;经过多次实验一…

ElasticSearch篇---第五篇

系列文章目录 文章目录 系列文章目录前言一、什么是ElasticSearch?二、ElasticSearch中的集群、节点、索引、文档、类型是什么?三、ElasticSearch中的分片是什么?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,…

nodejs微信小程序+python+PHP新闻发布系统的设计与实现-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

Stable Diffusion AI绘画系列【18】:东方巨龙,威武霸气

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

深圳冬季穿搭造型

深圳冬季穿搭造型 今天是2023年11月17日&#xff0c;北方在11月初就降下了大雪&#xff0c;那是我的老家&#xff0c;无比怀念。 而在深圳&#xff0c;冬天是体会不到那份冷冽的寒冷的&#xff0c;所以在深圳&#xff0c;每天的晚上&#xff0c;我都会出去散步&#xff0c;昨…

走迷宫(详细分析)

目录 一、课题描述 输入样例&#xff1a; 输出样例&#xff1a; 二、需求分析 输入的形式和输入值的范围&#xff1a; 输出的形式&#xff1a; 程序所能达到的功能&#xff1a; 三、概要设计 四、流程图 五 、代码详细注释 六、测试数据和结果 一、课题描述 以一个…

win10编译golang程序报病毒错误

错误为command-line-arguments: open C:\Users\ADMINI~1\AppData\Local\Temp\go-build435947867\b001\exe\a.out.exe: Operation did not complete successfully because the file contains a virus or potentially unwanted software. 解决办法&#xff0c;将Local/Temp目录添…

流量分析1--菜刀666

1&#xff1a;菜刀666&#xff1a; 题目描述 分析流量包&#xff0c;过滤http数据流 追踪TCP数据流 对比第5个流和第7个流发现&#xff0c;同样的目录下 多出了6666.jpg。猜测是由攻击者上传&#xff0c;直接在请求包里搜索FFD8--FFD9 保存为1.jpg 利用foremost工具对1.jpg进…

【Axure高保真原型】个性化自定义图片显示列表

今天和大家分享个性化自定义图片显示列表的原型模板&#xff0c;鼠标点击多选按钮&#xff0c;可以切换按钮选中或者取消选中&#xff0c;按钮选中时&#xff0c;对应图片会在列表中显示&#xff0c;按钮取消后&#xff0c;对应图片会自动隐藏。那这个模板是用中继器制作的&…

三数之和(LeetCode 15)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路方法一&#xff1a;暴力法方法二&#xff1a;排序双指针 5.实现示例参考文献 1.问题描述 给你一个整数数组 nums&#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时…

Qt开发学习笔记01

设置窗口背景图 在 .h 文件中添加引用和方法 #include <QPainter> #include <QPixmap> void paintEvent(QPaintEvent *);.cpp 文件中实现 paintEvent void sur_dev::paintEvent(QPaintEvent *ev) {QPainter painter(this);QPixmap pix;pix.load(":/image/bj01…

金融行业文件摆渡,如何兼顾安全和效率?

金融行业是数据密集型产业&#xff0c;每时每刻都会产生海量的数据&#xff0c;业务开展时&#xff0c;数据在金融机构内部和内外部快速流转&#xff0c;进入生产的各个环节。 为了保障基础的数据安全和网络安全&#xff0c;金融机构采用网络隔离的方式来隔绝外部网络的有害攻击…

vue v-for获取子组件$ref总是拿到最后一个元素

页面循环列表&#xff0c;把子组件放在循环里面&#xff0c;此处获取this.$refs返回的应该是个数组&#xff0c;但是不知道为什么&#xff0c;一直返回的是循环的最后一个的子组件实列&#xff0c;官网上已经说明v-for返回的就是数组&#xff0c;所以一直很困惑 代码如下&#…

02 CSS基础入门

文章目录 一、CSS介绍1. 简介2. 相关网站3. HTML引入方式 二、选择器1. 标签选择器2. 类选择器3. ID选择器4. 群组选择器 四、样式1. 字体样式2. 文本样式3. 边框样式4. 表格样式 五、模型和布局1. 盒子模型2. 网页布局 一、CSS介绍 1. 简介 CSS主要用于控制网页的外观&#…

编程实战:类C语法的编译型脚本解释器(十)编译表达式

系列入口&#xff1a;编程实战&#xff1a;类C语法的编译型脚本解释器&#xff08;九&#xff09;编译语句 本文介绍表达式的编译。 一、代码概览 表达式的编译就是不断获取下一个标识符&#xff0c;直到遇到不属于表达式的东西。 完整代码如下&#xff1a; Expression* GetExp…