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

相关文章

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

Android ClassLoader加载机制详解

《AndroidClassLoader加载机制详解》Android的ClassLoader负责加载.dex文件,基于双亲委派模型,支持热修复和插件化,需注意类冲突、内存泄漏和兼容性问题,本文给大家介... 目录一、ClassLoader概述1.1 类加载的基本概念1.2 android与Java Class

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

SQLite3 在嵌入式C环境中存储音频/视频文件的最优方案

《SQLite3在嵌入式C环境中存储音频/视频文件的最优方案》本文探讨了SQLite3在嵌入式C环境中存储音视频文件的优化方案,推荐采用文件路径存储结合元数据管理,兼顾效率与资源限制,小文件可使用B... 目录SQLite3 在嵌入式C环境中存储音频/视频文件的专业方案一、存储策略选择1. 直接存储 vs

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

Python如何将OpenCV摄像头视频流通过浏览器播放

《Python如何将OpenCV摄像头视频流通过浏览器播放》:本文主要介绍Python如何将OpenCV摄像头视频流通过浏览器播放的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完... 目录方法1:使用Flask + MJPEG流实现代码使用方法优点缺点方法2:使用WebSocket传输视

Android DataBinding 与 MVVM使用详解

《AndroidDataBinding与MVVM使用详解》本文介绍AndroidDataBinding库,其通过绑定UI组件与数据源实现自动更新,支持双向绑定和逻辑运算,减少模板代码,结合MV... 目录一、DataBinding 核心概念二、配置与基础使用1. 启用 DataBinding 2. 基础布局

Android ViewBinding使用流程

《AndroidViewBinding使用流程》AndroidViewBinding是Jetpack组件,替代findViewById,提供类型安全、空安全和编译时检查,代码简洁且性能优化,相比Da... 目录一、核心概念二、ViewBinding优点三、使用流程1. 启用 ViewBinding (模块级

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.

Android学习总结之Java和kotlin区别超详细分析

《Android学习总结之Java和kotlin区别超详细分析》Java和Kotlin都是用于Android开发的编程语言,它们各自具有独特的特点和优势,:本文主要介绍Android学习总结之Ja... 目录一、空安全机制真题 1:Kotlin 如何解决 Java 的 NullPointerExceptio