运用手机多媒体

运用手机多媒体

运用手机多媒体

2021.2.24

Gary哥哥的哥哥

运用手机多媒体丰富你的程序

Android提供了一系列的相关API,使得我们在程序当中可以调用很多手机的多媒体资源,从而编写出更加丰富的应用

程序运行在Android手机上

在正式讲解之前,我们先来了解一下,如何将程序运行在Android手机上

这个很简单啦,USB连电脑,手机开发者选项开启调试,然后运行Android Studio的项目代码即可安装到手机上了

下面我们对几个常用的多媒体进行一一讲解

使用通知

这是一个很有特色的功能,连iOS5.0页引入了类似的功能

即便当应用程序不在前台运行的时候,借助通知来发送提示用户

通知渠道

Android 8.0开始,每一个通知都要属于一个相应的渠道,每个应用程序都可以自由地创建当前应用拥有哪些通知渠道,但这些渠道的掌控权在用户的手上。用户可以自由地选择这些通知渠道的重要程度,是否响铃,是否震动或者是否要关闭这个渠道

为此,我们不用再担心一些垃圾通知的骚扰了

下面我们来看看创建自己的通知渠道的详细步骤吧

首先需要一个NotificationManager对通知进行管理,可以调用Contenx的getSystemService()方法来获取

getSystemService()

p:接收一个字符串参数用于确定获取系统的哪个服务,这里我们传入Context.NOTIFICATION_SERVICE即可

写法如下

val manager=getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

接下来需要使用NotificationCannel类构件一个通知渠道,并调用NotificationManager的createNotificationChannel()方法完成构建

由于这些方法都是Android8.0新增的API,我们调用的时候还需要进行版本的判断

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){

val channel = NotificationChannel(channelId, channelName, importance)

manager. createNotificationChannel(channel)

}

我这里重点提醒提醒,VERSION_CODES.O(是O不是0)

创建一个通知渠道至少需要知道渠道的ID,渠道名称和重要性三个删除

渠道的ID可以随便定义,只要保证全局唯一性即可渠道名称是个用户看的,需要可以清楚地表达这个渠道的用途通知重要性等级从高到低:IMPORTANCE_HIGH / DEFAULT / LOW / MIN

用户可以随意更改通知的重要性等级,开发者是无法干预的

通知的基本用法

通知的使用方法还是比较灵活的,可以创建在Activity,BroadcastReceiver 和Service当中(Service后面会学习到)。一般创建场景在后面两个常见,Activity里创建通知还是比较少的,因为一般只有当程序进入后台的时候才需要使用通知

我们先来学习一下创建通知的一般步骤

首先需要一个Builder构造器来创建Notification对象,AndroidX库提供了一些兼容之前版本的API

AndroidX提供了一个NotificationCompat类,使用这个类来构建Notification对象就不存在兼容性的问题了

val notification = NotificationCompat.Builder(context, channelId).build()

NotificationCompat.Builder的构造函数中,p1是一个context;p2是渠道的ID

需要我们在创建通知渠道时指定的渠道ID相匹配才行

上述代码只是创建了一个空的Notification对象,并没有什么实际的作用, 我们可以在最终的build()方法中连缀人一多的设置方法来创建一个丰富的Notification对象,先来看看一些基本的操作:

val notification=NotificationCompat.Builder(context,channelId)

.setContentTitle("This is content title")

.setContentText("This is content text").setSmallIcon(R.drawable.ic_launcher_background)

.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background))

.build()

这里一共调用了四个设置方法:

设置Title设置正文内容(下拉状态栏也可以看到这部分的内容)设置通知的小图标

注意:这里使用纯alpha图层的图片进行设置,小图标会显示在状态栏上方出现

设置大图标,下拉状态栏可以看到大图标

以上工作全部完成过后,只需要调用NotificationManager的notify()方法就可以放通知显示出来

notify()方法接受两个参数:

p1:id,保证为每个通知指定的id都是不相同的

p2:Notification对象,这里我们将我们刚刚创建的Notification对象传入即可,因此显示一个通知就写成:

manager.notify(1, notification)

下面我们就以一个完整的例子NotificationTest项目来看看通知到底是长什么样的

activity_main.xml文件:

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity"

android:orientation="vertical">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Send Notice"

android:textAllCaps="false"

android:id="@+id/sendNotice"/>

MainActivity中:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.0){

val channel = NotificationChannel("normal","Normal",NotificationManager.IMPORTANCE_DEFAULT)

manager.createNotificationChannel(channel)

}

sendNotice.setOnClickListener {

val notification = NotificationCompat.Builder(this,"normal")

.setContentTitle("This is content title")

.setContentText("This is content text")

.setSmallIcon(R.drawable.ic_launcher_background)

.setLargeIcon(BitmapFactory.decodeResource(resources,R.drawable.ic_launcher_background))

.build()

manager.notify(1,notification)

}

}

}

下面我们要使点击这条通知之后有效果,这里涉及新的概念PendingIntent

和Intent有些类似

PendingIntent用法

它主要提供几个静态方法用于获取PendingIntent的实例

getActivity()getBroadcast()getService

他们的参数都是:

p1:Context一般不用到,传入0即可p3:是一个Intent对象,通过这个对象构建出PendingIntent的意图p4:用于确定PendingIntent的行为,有FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT,通常情况下传入0即可(至于上面这几个需要自行查阅文档)

下面来优化我们的NotificationTest项目

activity_notification.xml和NotificationActivity

android:layout_width="match_parent" android:layout_height="match_parent">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:textSize="24sp"

android:text="This is notification layout"/>

MainActivity中:

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

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)

}

sendNotice.setOnClickListener {

//构建意图

val intent=Intent(this,NotificationActivity::class.java)

val pi = PendingIntent.getActivity(this,0,intent,0)

//注意下面setContentIntent(pi)

//setAutoCancel(true) 点击之后自动消失

val notification = NotificationCompat.Builder(this,"normal")

.setContentTitle("This is content title")

.setContentText("This is content text")

.setSmallIcon(R.drawable.ic_launcher_background)

.setLargeIcon(BitmapFactory.decodeResource(resources,R.drawable.ic_launcher_background))

.setContentIntent(pi)

.setAutoCancel(true)

.build()

manager.notify(1,notification)

}

}

}

关于点击后自动消失,也可以在NotificationActivity中实现

class NotificationActivity : 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)//这里的1就是那个通知设定的id

}

}

进阶技巧

实际上NotificationCompat.Builder中还提到了非常丰富的API,以便我们创建出更加多样的通知效果

但我们只讲解一些比较常用的API,其他API可以在大家实践的时候自行查阅资料

setStyle()方法

这个方法允许我们构建富文本的通知内容。也就是说,通知不光可以有文字和图标,还可以包含更多的内容

p:NotificationCompat.Style参数,这个参数就是用来构建具体的富文本信息,如长文字和图片等

ex:如果按我们之前讲的那样子写,如果通知的内容文字太多,他就只会缩略尾部的方式进行显示,而这里可以做到将全部东西显示出来

sendNotice.setOnClickListener {

//构建意图

val intent=Intent(this,NotificationActivity::class.java)

val pi = PendingIntent.getActivity(this,0,intent,0)

//注意下面setContentIntent(pi)

//setAutoCancel(true) 点击之后自动消失

val notification = NotificationCompat.Builder(this,"normal")

.setContentTitle("This is content title")

// .setContentText(" 全国脱贫攻坚总结表彰大会开始,中共中央政治局常委、全国政协主席汪洋同志宣读《中共中央 国务院关于授予全国脱贫攻坚楷模荣誉称号的决定》。\n" +

// "\n" +

// " 为隆重表彰激励先进,大力弘扬民族精神、时代精神和脱贫攻坚精神,充分激发全党全国各族人民干事创业的责任感、使命感、荣誉感,汇聚更强大的力量推进全面建设社会主义现代化国家,党中央、国务院决定,授予毛相林等10名同志,河北省塞罕坝机械林场等10个集体“全国脱贫攻坚楷模”荣誉称号。")

.setStyle(NotificationCompat.BigTextStyle().bigText(" 全国脱贫攻坚总结表彰大会开始,中共中央政治局常委、全国政协主席汪洋同志宣读《中共中央 国务院关于授予全国脱贫攻坚楷模荣誉称号的决定》。\n" +

"\n" +

" 为隆重表彰激励先进,大力弘扬民族精神、时代精神和脱贫攻坚精神,充分激发全党全国各族人民干事创业的责任感、使命感、荣誉感,汇聚更强大的力量推进全面建设社会主义现代化国家,党中央、国务院决定,授予毛相林等10名同志,河北省塞罕坝机械林场等10个集体“全国脱贫攻坚楷模”荣誉称号。"))

.setSmallIcon(R.drawable.ic_launcher_background)

.setLargeIcon(BitmapFactory.decodeResource(resources,R.drawable.ic_launcher_background))

.setContentIntent(pi)

// .setAutoCancel(true)

.build()

manager.notify(1,notification)

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Qu7DDJ9R-1614257888277)(E:\kotlin-study\Studying-Kotlin\Multimedia\setStyle()].png)

除此之外还可以做到完整的显示一张图片

sendNotice.setOnClickListener {

//构建意图

val intent=Intent(this,NotificationActivity::class.java)

val pi = PendingIntent.getActivity(this,0,intent,0)

//注意下面setContentIntent(pi)

//setAutoCancel(true) 点击之后自动消失

val notification = NotificationCompat.Builder(this,"normal")

.setContentTitle("This is content title")

// .setContentText(" 全国脱贫攻坚总结表彰大会开始,中共中央政治局常委、全国政协主席汪洋同志宣读《中共中央 国务院关于授予全国脱贫攻坚楷模荣誉称号的决定》。\n" +

// "\n" +

// " 为隆重表彰激励先进,大力弘扬民族精神、时代精神和脱贫攻坚精神,充分激发全党全国各族人民干事创业的责任感、使命感、荣誉感,汇聚更强大的力量推进全面建设社会主义现代化国家,党中央、国务院决定,授予毛相林等10名同志,河北省塞罕坝机械林场等10个集体“全国脱贫攻坚楷模”荣誉称号。")

// .setStyle(NotificationCompat.BigTextStyle().bigText(" 全国脱贫攻坚总结表彰大会开始,中共中央政治局常委、全国政协主席汪洋同志宣读《中共中央 国务院关于授予全国脱贫攻坚楷模荣誉称号的决定》。\n" +

// "\n" +

// " 为隆重表彰激励先进,大力弘扬民族精神、时代精神和脱贫攻坚精神,充分激发全党全国各族人民干事创业的责任感、使命感、荣誉感,汇聚更强大的力量推进全面建设社会主义现代化国家,党中央、国务院决定,授予毛相林等10名同志,河北省塞罕坝机械林场等10个集体“全国脱贫攻坚楷模”荣誉称号。"))

.setContentText("Look, what a beautiful picture")

.setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources,R.drawable.ic_launcher_background)))

.setSmallIcon(R.drawable.ic_launcher_background)

.setLargeIcon(BitmapFactory.decodeResource(resources,R.drawable.ic_launcher_background))

.setContentIntent(pi)

// .setAutoCancel(true)

.build()

manager.notify(1,notification)

}

需要注意的是,开发者只能再创建通知渠道的时候为他制定初始的重要等级,用户不认可,用户可以自行修改,因为通知渠道一旦创建就不能通过代码修改,我们再创建一条通知渠道来测试:

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){

val channel = NotificationChannel("normal","Normal",NotificationManager.IMPORTANCE_DEFAULT)

manager.createNotificationChannel(channel)

val channel2=NotificationChannel("important","Important",NotificationManager.IMPORTANCE_HIGH)

manager.createNotificationChannel(channel2)

}

sendNotice.setOnClickListener {

//构建意图

val intent=Intent(this,NotificationActivity::class.java)

val pi = PendingIntent.getActivity(this,0,intent,0)

//注意下面setContentIntent(pi)

//setAutoCancel(true) 点击之后自动消失

val notification = NotificationCompat.Builder(this,"important")

.setContentTitle("This is content title")

...

}

搞个high给他,发现这里已经变成一个弹出式的通知了

调用摄像头和相册

调用摄像头拍照

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="take Photo"

android:id="@+id/takePhotoBtn"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:id="@+id/imageView"/>

MainActivity中:

下面代码确实比较长,详细的解析请见书本p369页

class MainActivity : AppCompatActivity() {

val takePhoto = 1

lateinit var imageUri :Uri

lateinit var outputImage: File

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

takePhotoBtn.setOnClickListener {

//创建File对象,用于存储拍照后的图片

outputImage = File(externalCacheDir,"output_image.jpg")//采用应用管理目录来缓存(避免读写SD卡的危险权限)

if(outputImage.exists()){

outputImage.delete()

}

outputImage.createNewFile()

imageUri = if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N){

//将File对象转化成一个封装过的Uri对象(FileProvider对数据进行了保护)

FileProvider.getUriForFile(this,"com.workaholiclab.cameraalbumtest.fileprovider",outputImage)

}else{

Uri.fromFile(outputImage) //该设备低于android7就调用Uri的fromFile方法将File转话为Uri对象

//这个Uri对象包含了这张图片的真实存在的路径

}

//启动相机程序

val intent =Intent("android.media.action.IMAGE_CAPTURE")

intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)//指定图片的输入地址,这里为刚刚的Uri对象

startActivityForResult(intent,takePhoto)

}

}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

super.onActivityResult(requestCode, resultCode, data)

when(requestCode){

takePhoto->{

if (resultCode ==Activity.RESULT_OK){

//将拍摄的照片显示出来

val bitmap= BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))//将这张图片解析称为Bitmap对象

imageView.setImageBitmap(rotateIfRequired(bitmap))//变成ImageView,需要注意一些手机上拍照转化会发生一些旋转,需要处理一下

}

}

}

}

//照片旋转处理

private fun rotateIfRequired(bitmap: Bitmap): Bitmap {

val exif = ExifInterface(outputImage.path)

val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)

return when(orientation){

ExifInterface.ORIENTATION_ROTATE_90->rotateBitmap(bitmap,90)

ExifInterface.ORIENTATION_ROTATE_180->rotateBitmap(bitmap,180)

ExifInterface.ORIENTATION_ROTATE_270->rotateBitmap(bitmap,270)

else-> bitmap

}

}

private fun rotateBitmap(bitmap: Bitmap, degree: Int): Bitmap {

val matrix =Matrix()

matrix.postRotate(degree.toFloat())

val rotateBitmap = Bitmap.createBitmap(bitmap,0,0,bitmap.width,bitmap.height,matrix,true)

bitmap.recycle()//将不再需要的Bitmap对象回收

return rotateBitmap

}

}

下面不要忘记注册我们Provider了,FileProvider是一种特殊的Provider

package="com.workaholiclab.cameraalbumtest">

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/AppTheme">

android:authorities="com.workaholiclab.cameraalbumtest.fileprovider"

android:name="androidx.core.content.FileProvider"

android:exported="false"

android:grantUriPermissions="true">

android:name="android.support.FILE_PROVIDER_PATHS"

android:resource="@xml/file_paths"/>

name属性是固定的

authorities属性的值必须和刚才getUriForFile()方法的第二个参数一致

指定Uri的分享路径,冰鞋引用了一个@xml/file_paths资源

file_paths.xml

name="my_images"

path="/"/>

name属性随便写

path属性值表示共享的具体路径,一个/表示将整个SD卡进行分享,当然你也可以这分享存放上面图片的路径

从相册中选取照片

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity"

android:orientation="vertical">

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="take Photo"

android:id="@+id/takePhotoBtn"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="From Album"

android:id="@+id/fromAlbumBtn"/>

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_gravity="center_horizontal"

android:id="@+id/imageView"/>

class MainActivity : AppCompatActivity() {

val takePhoto = 1

lateinit var imageUri :Uri

lateinit var outputImage: File

val fromAlbum = 2

override fun onCreate(savedInstanceState: Bundle?) {

super.onCreate(savedInstanceState)

setContentView(R.layout.activity_main)

takePhotoBtn.setOnClickListener {

//创建File对象,用于存储拍照后的图片

outputImage = File(externalCacheDir,"output_image.jpg")//采用应用管理目录来缓存(避免读写SD卡的危险权限)

if(outputImage.exists()){

outputImage.delete()

}

outputImage.createNewFile()

imageUri = if(Build.VERSION.SDK_INT>= Build.VERSION_CODES.N){

//将File对象转化成一个封装过的Uri对象(FileProvider对数据进行了保护)

FileProvider.getUriForFile(this,"com.workaholiclab.cameraalbumtest.fileprovider",outputImage)

}else{

Uri.fromFile(outputImage) //该设备低于android7就调用Uri的fromFile方法将File转话为Uri对象

//这个Uri对象包含了这张图片的真实存在的路径

}

//启动相机程序

val intent =Intent("android.media.action.IMAGE_CAPTURE")

intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri)//指定图片的输入地址,这里为刚刚的Uri对象

startActivityForResult(intent,takePhoto)

}

//选取相册

fromAlbumBtn.setOnClickListener {

//打开文件选择器

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)

intent.addCategory(Intent.CATEGORY_OPENABLE)

//指定只显示图片

intent.type ="image/*"

startActivityForResult(intent,fromAlbum)

}

}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {

super.onActivityResult(requestCode, resultCode, data)

when(requestCode){

takePhoto->{

if (resultCode ==Activity.RESULT_OK){

//将拍摄的照片显示出来

val bitmap= BitmapFactory.decodeStream(contentResolver.openInputStream(imageUri))//将这张图片解析称为Bitmap对象

imageView.setImageBitmap(rotateIfRequired(bitmap))//变成ImageView,需要注意一些手机上拍照转化会发生一些旋转,需要处理一下

}

}

fromAlbum->{

if(resultCode == Activity.RESULT_OK && data != null){

data.data?.let {

uri ->

//将选择的图片显示

val bitmap=getBitmapFromUri(uri)

imageView.setImageBitmap(bitmap)

}

}

}

}

}

private fun getBitmapFromUri(uri: Uri) = contentResolver

.openFileDescriptor(uri,"r")?.use {

BitmapFactory.decodeFileDescriptor(it.fileDescriptor)

}

//照片旋转处理

private fun rotateIfRequired(bitmap: Bitmap): Bitmap {

val exif = ExifInterface(outputImage.path)

val orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,ExifInterface.ORIENTATION_NORMAL)

return when(orientation){

ExifInterface.ORIENTATION_ROTATE_90->rotateBitmap(bitmap,90)

ExifInterface.ORIENTATION_ROTATE_180->rotateBitmap(bitmap,180)

ExifInterface.ORIENTATION_ROTATE_270->rotateBitmap(bitmap,270)

else-> bitmap

}

}

private fun rotateBitmap(bitmap: Bitmap, degree: Int): Bitmap {

val matrix =Matrix()

matrix.postRotate(degree.toFloat())

val rotateBitmap = Bitmap.createBitmap(bitmap,0,0,bitmap.width,bitmap.height,matrix,true)

bitmap.recycle()//将不再需要的Bitmap对象回收

return rotateBitmap

}

}

需要注意的是,一般的程序对加载的图片压缩,这样子是为了避免直接加载到内存崩溃,好的做法是先压缩,这里大家可以自行查阅相关资料了

播放多媒体文件

Android MediaPlayer 常用方法介绍

方法:create(Context context, Uri uri)

解释:静态方法,通过Uri创建一个多媒体播放器。

方法:create(Context context, int resid)

解释:静态方法,通过资源ID创建一个多媒体播放器

方法:create(Context context, Uri uri, SurfaceHolder holder)

解释:静态方法,通过Uri和指定 SurfaceHolder 【抽象类】 创建一个多媒体播放器

方法: getCurrentPosition()

解释:返回 Int, 得到当前播放位置

方法: getDuration()

解释:返回 Int,得到文件的时间

方法:getVideoHeight()

解释:返回 Int ,得到视频的高度

方法:getVideoWidth()

解释:返回 Int,得到视频的宽度

方法:isLooping()

解释:返回 boolean ,是否循环播放

方法:isPlaying()

解释:返回 boolean,是否正在播放

方法:pause()

解释:无返回值 ,暂停

方法:prepare()

解释:无返回值,准备同步

方法:prepareAsync()

解释:无返回值,准备异步

方法:release()

解释:无返回值,释放 MediaPlayer 对象

方法:reset()

解释:无返回值,重置 MediaPlayer 对象

方法:seekTo(int msec)

解释:无返回值,指定播放的位置(以毫秒为单位的时间)

方法:setAudioStreamType(int streamtype)

解释:无返回值,指定流媒体的类型

方法:setDataSource(String path)

解释:无返回值,设置多媒体数据来源【根据 路径】

方法:setDataSource(FileDescriptor fd, long offset, long length)

解释:无返回值,设置多媒体数据来源【根据 FileDescriptor】

方法:setDataSource(FileDescriptor fd)

解释:无返回值,设置多媒体数据来源【根据 FileDescriptor】

方法:setDataSource(Context context, Uri uri)

解释:无返回值,设置多媒体数据来源【根据 Uri】

方法:setDisplay(SurfaceHolder sh)

解释:无返回值,设置用 SurfaceHolder 来显示多媒体

方法:setLooping(boolean looping)

解释:无返回值,设置是否循环播放

事件:setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener listener)

解释:监听事件,网络流媒体的缓冲监听

事件:setOnCompletionListener(MediaPlayer.OnCompletionListener listener)

解释:监听事件,网络流媒体播放结束监听

事件:setOnErrorListener(MediaPlayer.OnErrorListener listener)

解释:监听事件,设置错误信息监听

事件:setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener listener)

解释:监听事件,视频尺寸监听

方法:setScreenOnWhilePlaying(boolean screenOn)

解释:无返回值,设置是否使用 SurfaceHolder 显示

方法:setVolume(float leftVolume, float rightVolume)

解释:无返回值,设置音量

方法:start()

解释:无返回值,开始播放

方法:stop()

解释:无返回值,停止播放

我们先来梳理一下MediaPlayer的工作流程

创建MediaPlayer对象调用setDataSource()方法设置音频文件的路径再调用prepare()方法进入准备状态start(),pause(),reset()方法

我们来看一个很简单的例子吧

这部分比较简单不再展开来说了,有兴趣自己看一下书p374页即可

播放视频

VedioView和MediaPlayer很类似,其主要方法如下:

setVideoPath:设置要播放的视频文件的位置start:开始或继续播放视频pause:暂停播放视频resume:将视频从头开始播放seekTo:从指定的位置开始播放视频isPlaying:判断当前是否正在播放视频getCurrentPosition:获取当前播放的位置getDuration:获取载入的视频文件的时长setVideoPath(String path):以文件路径的方式设置VideoView播放的视频源setVideoURI(Uri uri):以Uri的方式设置视频源,可以是网络Uri或本地UrisetMediaController(MediaController controller):设置MediaController控制器setOnCompletionListener(MediaPlayer.onCompletionListener l):监听播放完成的事件setOnErrorListener(MediaPlayer.OnErrorListener l):监听播放发生错误时候的事件setOnPreparedListener(MediaPlayer.OnPreparedListener l):监听视频装载完成的事件

同样,这一部分比较简单详见书本p378页即可

多媒体部分完更

相关推荐

怎么穿高跟鞋自然又优雅?这招学会了没!
365bet大陆网站

怎么穿高跟鞋自然又优雅?这招学会了没!

08-26 👁️ 9383
汉密尔顿手表和天梭手表哪个好
365bet大陆网站

汉密尔顿手表和天梭手表哪个好

08-13 👁️ 8039
微博删除后怎么恢复
365bet大陆网站

微博删除后怎么恢复

07-11 👁️ 9417