Android笔记(十七):PendingIntent简介

2023-12-13 05:20:40

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

文章来源:https://blog.csdn.net/userhu2012/article/details/134831961
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。