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

相关文章

Nginx搭建前端本地预览环境的完整步骤教学

《Nginx搭建前端本地预览环境的完整步骤教学》这篇文章主要为大家详细介绍了Nginx搭建前端本地预览环境的完整步骤教学,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录项目目录结构核心配置文件:nginx.conf脚本化操作:nginx.shnpm 脚本集成总结:对前端的意义很多

Vue3视频播放组件 vue3-video-play使用方式

《Vue3视频播放组件vue3-video-play使用方式》vue3-video-play是Vue3的视频播放组件,基于原生video标签开发,支持MP4和HLS流,提供全局/局部引入方式,可监听... 目录一、安装二、全局引入三、局部引入四、基本使用五、事件监听六、播放 HLS 流七、更多功能总结在 v

Git打标签从本地创建到远端推送的详细流程

《Git打标签从本地创建到远端推送的详细流程》在软件开发中,Git标签(Tag)是为发布版本、标记里程碑量身定制的“快照锚点”,它能永久记录项目历史中的关键节点,然而,仅创建本地标签往往不够,如何将其... 目录一、标签的两种“形态”二、本地创建与查看1. 打附注标http://www.chinasem.cn

Android实现图片浏览功能的示例详解(附带源码)

《Android实现图片浏览功能的示例详解(附带源码)》在许多应用中,都需要展示图片并支持用户进行浏览,本文主要为大家介绍了如何通过Android实现图片浏览功能,感兴趣的小伙伴可以跟随小编一起学习一... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

在Android中使用WebView在线查看PDF文件的方法示例

《在Android中使用WebView在线查看PDF文件的方法示例》在Android应用开发中,有时我们需要在客户端展示PDF文件,以便用户可以阅读或交互,:本文主要介绍在Android中使用We... 目录简介:1. WebView组件介绍2. 在androidManifest.XML中添加Interne

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手

使用Spring Cache本地缓存示例代码

《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac... 目录一、Spring Cache简介核心特点:二、基础配置1. 添加依赖2. 启用缓存3. 缓存配置方案方案

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

Java实现本地缓存的四种方法实现与对比

《Java实现本地缓存的四种方法实现与对比》本地缓存的优点就是速度非常快,没有网络消耗,本地缓存比如caffine,guavacache这些都是比较常用的,下面我们来看看这四种缓存的具体实现吧... 目录1、HashMap2、Guava Cache3、Caffeine4、Encache本地缓存比如 caff

Android 缓存日志Logcat导出与分析最佳实践

《Android缓存日志Logcat导出与分析最佳实践》本文全面介绍AndroidLogcat缓存日志的导出与分析方法,涵盖按进程、缓冲区类型及日志级别过滤,自动化工具使用,常见问题解决方案和最佳实... 目录android 缓存日志(Logcat)导出与分析全攻略为什么要导出缓存日志?按需过滤导出1. 按