Android用SurfaceView播放本地视屏(音频)文件

2024-04-23 01:48

本文主要是介绍Android用SurfaceView播放本地视屏(音频)文件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

    我们知道Android中可以使用VideoView播放视频,而且操作简单、方便。除此之外,我们还可以利用MediaPlayer用来播放视频,不过MediaPlayer主要用于播放音频,没有提供输出图像的输出界面,就是只能听到声音,看不到画面,这时就想到到了SurfaceView控件,将它与MediaPlayer结合起来,就能达到了视屏播放效果了,今天就做一个简单的视屏播放功能,把准备好的视屏文件test.3gp放在手机SD卡中,然后用SurfaceView来播放:

先看布局activity_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/LinearLayout1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:weightSum="1"
    android:orientation="vertical" >
    <SurfaceView
        android:id="@+id/surfaceVIew"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="0.15"
        tools:context=".MainActivity" />
    <LinearLayout 
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="0.85">
        <Button 
            android:id="@+id/btn_play"
            android:text="开始"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button 
           android:id="@+id/btn_pause"
            android:text="暂停"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button 
          android:id="@+id/btn_stop"
            android:text="停止"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button 
           android:id="@+id/btn_low"
            android:text="调低音量"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
        <Button 
           android:id="@+id/btn_hight"
            android:text="调高音量"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</LinearLayout>

接着就是Activity:

public class MainActivity extends Activity implements OnClickListener {

         /* 功能按钮 */
private Button btn_play, btn_pause, btn_stop, btn_low, btn_height;

       /* SurfaceView */
private SurfaceView mSurfaceView;
/* 播放视频对象 */
private MediaPlayer mediaPlayer;
/* 系统声音 */
private AudioManager audioManager;
/* 记录播放位置 */
private int position;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

               /*设置窗口无title*/
requestWindowFeature(Window.FEATURE_NO_TITLE);

                 /*全屏显示*/
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
findViews();
setListeners();
mediaPlayer = new MediaPlayer();
setSurfaceView();
}


// 横竖屏切换时的处理
@Override
protected void onSaveInstanceState(Bundle outState) {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {// 如果在播放的时候切换屏幕则保存当前观看的位置
outState.putInt("position", mediaPlayer.getCurrentPosition());
}
super.onSaveInstanceState(outState);
}


// 横竖屏切换后的处理
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.containsKey("position")) {
position = savedInstanceState.getInt("position");// 取得切换屏幕时保存的位置
}
super.onRestoreInstanceState(savedInstanceState);
}


/* 实例化UI */
private void findViews() {
btn_play = (Button) findViewById(R.id.btn_play);
btn_pause = (Button) findViewById(R.id.btn_pause);
btn_stop = (Button) findViewById(R.id.btn_stop);
btn_low = (Button) findViewById(R.id.btn_low);
btn_height = (Button) findViewById(R.id.btn_hight);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceVIew);
audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
}


/* 为5个按钮设置监听 */
private void setListeners() {
btn_play.setOnClickListener(this);
btn_pause.setOnClickListener(this);
btn_stop.setOnClickListener(this);
btn_low.setOnClickListener(this);
btn_height.setOnClickListener(this);
}


/* 播放视频 */
private void playMedia() {
/* 初始化状态 */
mediaPlayer.reset();
/* 设置声音流类型 */
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
/* 设置mp3\mp4加载路径 */
File file = new File(Environment.getExternalStorageDirectory(), "test.3gp");
try {
mediaPlayer.setDataSource(file.getAbsolutePath());
// 缓冲
mediaPlayer.prepare();
// 开始播放
mediaPlayer.start();
// 具体位置
Log.i("position", position + "------");
mediaPlayer.seekTo(position);
// 视频输出到View
mediaPlayer.setDisplay(mSurfaceView.getHolder());
// 重置位置为0
position = 0;
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/* 设置surfaceView视图 */
private void setSurfaceView() {
// creates a "push" surface
mSurfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// 设置事件,回调函数
mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
/* SurfaceView创建时 */
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (position > 0) {
playMedia();
position = 0;
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
/* SurfaceView销毁视图 */
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
}
/* Activity销毁时停止播放,释放资源。不做这个操作,即使退出,还是能听到视频的声音 */
mediaPlayer.release();
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_play:// 播放
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
return;
} else {
playMedia();
}
break;
case R.id.btn_pause:// 暂停
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
position = mediaPlayer.getCurrentPosition();
mediaPlayer.pause();
} else {
return;
}
break;
case R.id.btn_stop:// 停止
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
position = 0;
} else {
return;
}
break;
case R.id.btn_low:// 调小音量
// 获取当前的音乐音量
int volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
Log.v("Volume", "volume" + volume);
// 音量>0
if (volume > 0) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_LOWER, 0);
} else {
return;
}
break;
case R.id.btn_hight:// 调大音量
volume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
// 音量<100
if (volume < audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) {
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC, AudioManager.ADJUST_RAISE, 0);
} else {
return;
}
break;
}
}
}

ok,就不贴图了。

这篇关于Android用SurfaceView播放本地视屏(音频)文件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/927454

相关文章

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

JAVA集成本地部署的DeepSeek的图文教程

《JAVA集成本地部署的DeepSeek的图文教程》本文主要介绍了JAVA集成本地部署的DeepSeek的图文教程,包含配置环境变量及下载DeepSeek-R1模型并启动,具有一定的参考价值,感兴趣的... 目录一、下载部署DeepSeek1.下载ollama2.下载DeepSeek-R1模型并启动 二、J

Android开发中gradle下载缓慢的问题级解决方法

《Android开发中gradle下载缓慢的问题级解决方法》本文介绍了解决Android开发中Gradle下载缓慢问题的几种方法,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧... 目录一、网络环境优化二、Gradle版本与配置优化三、其他优化措施针对android开发中Gradle下载缓慢的问

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

一文教你使用Python实现本地分页

《一文教你使用Python实现本地分页》这篇文章主要为大家详细介绍了Python如何实现本地分页的算法,主要针对二级数据结构,文中的示例代码简洁易懂,有需要的小伙伴可以了解下... 在项目开发的过程中,遇到分页的第一页就展示大量的数据,导致前端列表加载展示的速度慢,所以需要在本地加入分页处理,把所有数据先放

本地搭建DeepSeek-R1、WebUI的完整过程及访问

《本地搭建DeepSeek-R1、WebUI的完整过程及访问》:本文主要介绍本地搭建DeepSeek-R1、WebUI的完整过程及访问的相关资料,DeepSeek-R1是一个开源的人工智能平台,主... 目录背景       搭建准备基础概念搭建过程访问对话测试总结背景       最近几年,人工智能技术

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

Python实现多路视频多窗口播放功能

《Python实现多路视频多窗口播放功能》这篇文章主要为大家详细介绍了Python实现多路视频多窗口播放功能的相关知识,文中的示例代码讲解详细,有需要的小伙伴可以跟随小编一起学习一下... 目录一、python实现多路视频播放功能二、代码实现三、打包代码实现总结一、python实现多路视频播放功能服务端开