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找到你的当前项目,把它开启。

实验心得

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值