当前位置: 首页 > article >正文

GDPU Android移动应用 使用多媒体

制作一个播放器,触发通知。

音视频播放器

1.新建一个项目MultimediaPlayer,

2.创建一个Activity,利用MediaPlayer实现一个简单的音频播放器,功能包括:

a)支持播放一个固定的音频文件

b)包含三个按钮,分别实现播放、暂停和停止

c)在音频播放结束时,触发一个通知,提醒音频播放结束

3.创建另一个Activity,实现视频的播放。

a)支持播放一个固定的视频文件

b)包含三个按钮,分别实现播放、暂停和重新播放

c)在视频播放结束时,触发一个通知,提醒视频播放结束(跟音频播放结束的通知要有所区别)。

新建项目,名称为MultimediaPlayer,不会新建项目的可以翻看以前的文章。然后一个活动用来做音频播放器,一个活动用来做视频播放器,此外可以再建一个活动用来做通知,再分别编写对应的xml即可。由于一个app进去的就是主活动,所以在主活动页面再写一个intent跳转到另一个活动页面。

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.media.MediaPlayer
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import android.widget.SeekBar
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat

class MainActivity : AppCompatActivity() {

    private var mediaPlayer: MediaPlayer? = null
    private lateinit var btnPlay: Button
    private lateinit var btnPause: Button
    private lateinit var btnStop: Button
    private lateinit var seekBar: SeekBar
    private lateinit var songNameTextView: TextView
    private lateinit var handler: Handler

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // 初始化视图
        btnPlay = findViewById(R.id.btnPlay)
        btnPause = findViewById(R.id.btnPause)
        btnStop = findViewById(R.id.btnStop)
        seekBar = findViewById(R.id.seekBar)
        songNameTextView = findViewById(R.id.songNameTextView)


    // 添加一个按钮来启动视频播放器
    val btnOpenVideoPlayer: Button = findViewById(R.id.btnOpenVideoPlayer)
    btnOpenVideoPlayer.setOnClickListener {
        val intent = Intent(this, VideoPlayer::class.java)
        startActivity(intent)
    }

        handler = Handler(Looper.getMainLooper()) // 初始化 handler

        mediaPlayer = MediaPlayer()
        // 初始化 MediaPlayer
        initMediaPlayer()
        // 播放音频
        btnPlay.setOnClickListener {
            mediaPlayer?.let {
                if (!it.isPlaying) {
                    it.start()
                    updateSeekBar()
                }
            }
        }
        // 暂停音频
        btnPause.setOnClickListener {
            mediaPlayer?.let {
                if (it.isPlaying) {
                    it.pause()
                    handler.removeCallbacks(updateSeekBarTask)
                }
            }
        }
        // 停止音频
        btnStop.setOnClickListener {
            mediaPlayer?.let {
                if (it.isPlaying) {
                    it.stop()
                    it.prepareAsync()
                    handler.removeCallbacks(updateSeekBarTask)
                }
            }
        }

        // 创建通知渠道
        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val channel = NotificationChannel(
                "normal", "Normal", NotificationManager.IMPORTANCE_DEFAULT
            )
            manager.createNotificationChannel(channel)
            // 设置音频播放完成的监听器,播放结束时发送通知
            mediaPlayer?.setOnCompletionListener {
                val notification = NotificationCompat.Builder(this, "normal")
                    .setContentTitle("音频播放结束")
                    .setContentText("你的音乐播放完啦~")
                    .setSmallIcon(R.drawable.notice_icon)
                    .setLargeIcon(
                        BitmapFactory.decodeResource(
                            resources,
                            R.drawable.large_icon
                        )
                    )
                    .setAutoCancel(true)// 点击后自动取消通知
                    .build()

                manager.notify(1, notification)// 发送通知
            }
        }

        // 为 SeekBar 设置监听器
        seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                // 如果是用户拖动导致的进度条变化,则更新音频播放位置
                if (fromUser) {
                    mediaPlayer?.seekTo(progress)
                }
            }
            override fun onStartTrackingTouch(seekBar: SeekBar?) {}
            override fun onStopTrackingTouch(seekBar: SeekBar?) {}
        })
    }

    // 音频初始化
    private fun initMediaPlayer() {
        mediaPlayer?.setDataSource(assets.openFd("等你下课-周杰伦.mp3"))
        mediaPlayer?.prepare()
        songNameTextView.text = "等你下课-周杰伦"// 显示歌曲名称
        seekBar.max = mediaPlayer?.duration ?: 0
    }

    // 更新进度条
    private fun updateSeekBar() {
        mediaPlayer?.let {
            seekBar.progress = it.currentPosition
            handler.postDelayed(updateSeekBarTask, 1000)
        }
    }

    private val updateSeekBarTask = Runnable { updateSeekBar() }

    override fun onDestroy() {
        super.onDestroy()
        mediaPlayer?.release()
        handler.removeCallbacks(updateSeekBarTask)
    }
}
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.widget.Button
import android.widget.SeekBar
import android.widget.VideoView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat

class VideoPlayer : AppCompatActivity() {

    private lateinit var videoView: VideoView
    private lateinit var btnPlay: Button
    private lateinit var btnPause: Button
    private lateinit var btnReplay: Button
    private lateinit var videoSeekBar: SeekBar

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_video_player)

        // 初始化控件
        btnPlay = findViewById(R.id.btnPlay)
        btnPause = findViewById(R.id.btnPause)
        btnReplay = findViewById(R.id.btnReplay)
        videoSeekBar = findViewById(R.id.videoSeekBar)
        videoView = findViewById(R.id.videoView)

        // 设置视频文件
        val videoUri = Uri.parse("android.resource://${packageName}/${R.raw.t11}")
        videoView.setVideoURI(videoUri)

        // 播放按钮点击事件
        btnPlay.setOnClickListener {
            if (!videoView.isPlaying) {
                videoView.start()
            }
        }
        // 暂停按钮点击事件
        btnPause.setOnClickListener {
            if (videoView.isPlaying) {
                videoView.pause()
            }
        }
        // 重播按钮点击事件
        btnReplay.setOnClickListener {
            if (!videoView.isPlaying) {
                videoView.resume()
            }
        }

        // 设置视频准备完成后的回调
        videoView.setOnPreparedListener { mediaPlayer ->
            // 设置进度条的最大值为视频的总时长
            videoSeekBar.max = mediaPlayer.duration
        }


            val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channel2 = NotificationChannel(
                    "important", "Important", NotificationManager.IMPORTANCE_HIGH
                )
                manager.createNotificationChannel(channel2)


                videoView.setOnCompletionListener {
                    // 构建通知
                    val intent = Intent(this, Notification::class.java)
                    val pendingIntent = PendingIntent.getActivity(
                        this, 0, intent, PendingIntent.FLAG_IMMUTABLE
                    )

                    val notification = NotificationCompat.Builder(this, "important")
                        .setContentTitle("视频播放结束")
                        .setContentText("你的视频播放完啦…")
                        .setSmallIcon(R.drawable.notice_icon)
                        .setLargeIcon(BitmapFactory.decodeResource(resources, R.drawable.large_icon))
                        .setContentIntent(pendingIntent)
                        .build()

                    manager.notify(1, notification)
                }
            }
        // 设置视频进度条监听器
        videoSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                if (fromUser) {
                    videoView.seekTo(progress)
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {}
            override fun onStopTrackingTouch(seekBar: SeekBar?) {}
        })

        updateSeekBar()
    }

    // 更新视频进度条
    private fun updateSeekBar() {
        val handler = android.os.Handler()
        handler.postDelayed(object : Runnable {
            override fun run() {
                videoSeekBar.progress = videoView.currentPosition
                handler.postDelayed(this, 1000)
            }
        }, 0)
    }

    override fun onDestroy() {
        super.onDestroy()
        videoView.stopPlayback()
    }
}
import android.app.NotificationManager
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class Notification : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_notification)

        val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        // 取消通知
        manager.cancel(1)
    }
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <!-- SeekBar -->
    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="28dp"
        android:max="100"
        android:progress="0" />

    <!-- Song Name TextView -->
    <TextView
        android:id="@+id/songNameTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/seekBar"
        android:layout_marginTop="20dp"
        android:gravity="center"
        android:textSize="18sp"
        android:textStyle="bold" />

    <!-- Buttons Layout -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/songNameTextView"
        android:layout_marginTop="20dp"
        android:gravity="center_horizontal">

        <!-- Play Button -->
        <Button
            android:id="@+id/btnPlay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="播放" />

        <!-- Pause Button -->
        <Button
            android:id="@+id/btnPause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            android:text="暂停" />

        <!-- Stop Button -->
        <Button
            android:id="@+id/btnStop"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="停止" />
    </LinearLayout>

    <!-- New Video Player Button in a new LinearLayout -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="200dp"
        android:gravity="center_horizontal">

        <Button
            android:id="@+id/btnOpenVideoPlayer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            android:text="打开视频播放器" />
    </LinearLayout>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- VideoView -->
    <VideoView
        android:id="@+id/videoView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- SeekBar -->
    <SeekBar
        android:id="@+id/videoSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/videoView"
        android:max="100"
        android:progress="0" />

    <!-- Buttons Layout -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/videoSeekBar"
        android:gravity="center"
        android:orientation="horizontal">

        <!-- Play Button -->
        <Button
            android:id="@+id/btnPlay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="播放" />

        <!-- Pause Button -->
        <Button
            android:id="@+id/btnPause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="20dp"
            android:layout_marginEnd="20dp"
            android:text="暂停" />

        <!-- Replay Button -->
        <Button
            android:id="@+id/btnReplay"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="重新播放" />

    </LinearLayout>

</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textSize="24sp" />

</RelativeLayout>

注意音视频文件资源引入,可以放在src的main目录下的assets文件(没有就新建),也可以放在main目录下的res文件下的raw文件(没有就新建),再找两个图标文件用于通知显示,放在res下的drawable文件下。

还要在AndroidManifest.xml声明几个权限。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.t11">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.T11">
        <activity
            android:name=".Notification"
            android:exported="false" />
        <activity
            android:name=".VideoPlayer"
            android:exported="false" />
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

播放完后拉一下通知栏。

跳到视频播放器。

没有收到应该是还没有开权限,点开设置,找到通知里的app notifications,点进去切换all apps找到你的当前项目,把它开启。

实验心得

有时候,生活平静也是一种奢求。 

 


http://www.kler.cn/a/420966.html

相关文章:

  • 实例分割模型的数据集格式转换
  • 【案例教程】python生物信息多组学大数据深度挖掘与论文整理技巧实践技术应用
  • 三维测量与建模笔记 - 5.3 光束法平差(Bundle Adjustment)
  • .NET 9 中 LINQ 新增功能实现过程
  • 002-日志增强版
  • THENA大涨将对整个DeFi市场产生怎样的影响?
  • 使用 Vite 快速搭建 Vue 2开发环境
  • 001-SpringBoot整合日志
  • 神经网络入门实战:(十一)池化层搭建,以及填充层的说明
  • 解读 77页2024 集团企业IT技术架构规划方案
  • k8s使用的nfs作为sc。
  • 传统客服中心和呼叫中心客服系统的区别
  • 时间序列模型在LSTM中的特征输入
  • AlmaLinux8.10安装samba实现与Windows文件共享
  • 获取联通光猫的管理员密码
  • 【AI日记】24.12.03 kaggle 比赛 Titanic-6
  • SVN客户端及语言包免费下载 无需积分
  • 计算机网络八股整理(四)
  • 【SpringBoot】SpringBoot优雅停机机制
  • Springboot(五十)SpringBoot3集成sentinel并连接sentinel-dashboard
  • 【大数据学习 | 面经】Spark3.x对比2.x有哪些优点
  • 通过搭建安消一体化管理体系,高校实现应急中心数字化转型升级新动能
  • 树和二叉树(概念 结构)
  • 手机租赁系统开发全攻略 创新服务助力企业智能转型
  • 库存管理如何做到“先进先出”?
  • delphi 12 idhttpsever(S)+idhttp(C) 实现简单的JSON API服务