Android学习羁绊之多媒体开发
Posted 姓chen的大键哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android学习羁绊之多媒体开发相关的知识,希望对你有一定的参考价值。
文章目录
手机在我们的生活中正扮演着越来越重要的角色,各种娱乐方式都可以在手机上进行。众多的娱乐方式少不了强大的多媒体功能的支持,而android在这方面也做得非常出色。它提供了一系列的API,使得我们可以在程序中调用很多手机的多媒体资源,从而编写出更加丰富多彩的应用程序。
调用摄像头和相册
调用摄像头拍照
现在很多的应用都会要求用户上传一张图片来作为头像,这时打开摄像头拍张照是最简单快捷的。
启动摄像头
应用程序要启动手机的相机程序需要通过以下代码来实现:
// 启动相机程序
Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, 1);
- 使用Intent对象启动相机程序,Intent的action指定为android.media.action.IMAGE_CAPTURE;
- 调用Intent对象的putExtra() 方法将图片的输出地址的Uri对象作为值传入,以MediaStore.EXTRA_OUTPUT 作为键(与多媒体相关的可以从MediaStore这个类中得到)
指定照片存放路径
拍照需要指定图片存储路径,在上述代码中将Uri对象作为图片输出路径,通过以下代码来构建这个Uri对象:
private Uri imageUri;
// 创建File对象,用于存储拍照后的图片
File outputImage = new File(getExternalCacheDir(), "output_image.jpg");
try
if (outputImage.exists())
outputImage.delete();
outputImage.createNewFile();
catch (IOException e)
e.printStackTrace();
if (Build.VERSION.SDK_INT >= 24)
imageUri = FileProvider.getUriForFile(MainActivity.this, "cn.chenjianlink.cameraalbumtest.fileprovider", outputImage);
else
imageUri = Uri.fromFile(outputImage);
-
照片属于文件,用File类临时保存。
-
getExternalCacheDir() 方法用于获取应用程序关联目录,具体的路径是:/sdcard/Android/data/<package name>/cache(这个目录是SD卡中专门用于存放当前应用缓存数据的位置,由于从Android 6.0系统开始,读写SD卡被列为了危险权限,如果将图片存放在SD卡的任何其他目录,都要进行运行时权限处理才行,而使用应用关联目录则可以跳过这一步)
-
Build.VERSION.SDK_INT用于获取当前系统的SDK版本
-
如果运行设备的系统版本低于Android 7.0,就调用Uri的fromFile() 方法将File对象转换成Uri对象,这个Uri对象标识着output_image.jpg这张图片的本地真实路径。
-
从Android 7.0系统开始,直接使用本地真实路径的Uri被认为是不安全的,会抛出一个FileUriExposedException异常。而FileProvider则是一种特殊的内容提供器,它使用了和内容提供器类似的机制来对数据进行保护,可以选择性地将封装过的Uri共享给外部,从而提高了应用的安全性。
在系统版本高于Android 7.0的设备上,调用FileProvider的getUriForFile() 方法将File 对象转换成一个封装过的Uri对象,这个方法有三个参数:
public static Uri getUriForFile(@NonNull Context context, @NonNull String authority, @NonNull File file)
- Context context:Context对象,一般传入调用的程序当前Activity
- String authority:任意唯一的字符串,作为唯一标识
- File file:将要转换的文件的file对象传入
- 使用FileProvider,需要在AndroidManifest.xml中对这个内容提供器进行注册
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="cn.chenjianlink.cameraalbumtest">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
...
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="cn.chenjianlink.cameraalbumtest.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>
- 访问SD卡需要声明权限(Android 4.4系统以前)
- android:authorities属性的值必须要和FileProvider.getUriForFile() 方法中的第二个参数一致
- <provider>标签中使用<meta-data>来指定Uri的共享路径,引用@xml/file_paths 资源,这个文件内容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="my_images" path="" />
</paths>
external-path用来指定Uri共享,name属性的值可以随便填,path属性的值表示共享的具体路径(设置为空值表示将整个SD卡共享)
照片显示
拍完照之后,一般需要回到应用程序中,则需要重写Activity类中的onActivityResult() 方法,在这个方法中执行相关逻辑。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
//自定义逻辑
如果需要将拍摄好的照片在应用程序中显示,则需要使用调用BitmapFactory的
decodeStream() 方法将照片解析成Bitmap 对象,然后把它设置到ImageView中显示出来:
// 将拍摄的照片显示出来
private ImageView picture = (ImageView) findViewById(R.id.picture);
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
picture.setImageBitmap(bitmap);
还需要在布局文件中引入ImageView这个控件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >
···
<ImageView
android:id="@+id/picture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
···
</LinearLayout>
从相册中选取照片
应用程序调用照片还可从手机相册里
打开相册
用Intent对象打开相册,相关代码如下:
Intent intent = new Intent("android.intent.action.GET_CONTENT");
intent.setType("image/*");
startActivityForResult(intent, 1); // 打开相册
打开相册需要动态申请WRITE_EXTERNAL_STORAGE 这个危险权限,相册中的照片都是存储在SD卡上的,要从SD卡中读取照片就需要申请这个权限。WRITE_EXTERNAL_STORAGE 表示同时授予程序对SD卡读和写的能力。
相册图片显示
Android系统从4.4版本开始,选取相册中的图片不再返回图片真实的Uri了,而是一个封装过的Uri,因此如果是4.4版本以上的手机就需要对这个Uri进行解析才能获取照片的真实路径。
在Android 4.4以下系统获取图片真实路径:
private void handleImageBeforeKitKat(Intent data)
Uri uri = data.getData();
String imagePath = getImagePath(uri, null);
displayImage(imagePath);
private String getImagePath(Uri uri, String selection)
String path = null;
// 通过Uri和selection来获取真实的图片路径
Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
if (cursor != null)
if (cursor.moveToFirst())
path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
cursor.close();
return path;
private void displayImage(String imagePath)
if (imagePath != null)
Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
picture.setImageBitmap(bitmap);
else
//···
在Android 4.4以上系统获取图片真实路径:
@TargetApi(19)
private void handleImageOnKitKat(Intent data)
String imagePath = null;
Uri uri = data.getData();
if (DocumentsContract.isDocumentUri(this, uri))
// 如果是document类型的Uri,则通过document id处理
String docId = DocumentsContract.getDocumentId(uri);
if("com.android.providers.media.documents".equals(uri.getAuthority()))
String id = docId.split(":")[1]; // 解析出数字格式的id
String selection = MediaStore.Images.Media._ID + "=" + id;
imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);
else if ("com.android.providers.downloads.documents".equals(uri.getAuthority()))
Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
imagePath = getImagePath(contentUri, null);
else if ("content".equalsIgnoreCase(uri.getScheme()))
// 如果是content类型的Uri,则使用普通方式处理
imagePath = getImagePath(uri, null);
else if ("file".equalsIgnoreCase(uri.getScheme()))
// 如果是file类型的Uri,直接获取图片路径即可
imagePath = uri.getPath();
displayImage(imagePath); // 根据图片路径显示图片
- 如果返回的Uri是document类型的话,那就取出document id 进行处理,如果不是的话,那就使用普通的方式处理。
- 如果Uri的authority是media格式的话,document id还需要再进行一次解析,要通过字符串分割的方式取出后半部分才能得到真正的数字id。
播放多媒体文件
手机上最常见的休闲方式毫无疑问就是听音乐和看电影了,Android在播放音频和视频方面也是做了相当不错的支持,它提供了一套较为完整的API,使得开发者可以很轻松地编写出一个简易的音频或视频播放器。
播放音频
在Android中播放音频文件一般都是使用MediaPlayer 类来实现的,它对多种格式的音频文件提供了非常全面的控制方法,从而使得播放音乐的工作变得十分简单。
MediaPlayer常用方法如下:
MediaPlayer的工作流程如下:
- 创建出一个MediaPlayer对象
- 调用 setDataSource() 方法来设置音频文件的路径
- 调用prepare() 方法使MediaPlayer进入到准备状态
- 调用start() 方法开始b播放
- 播放音频,调用pause() 方法就会暂停播放,调用reset() 方法就会停止播放
在不再使用MediaPlayer时,分别调用stop() 方法和release() 方法,将与MediaPlayer相关的资源释放掉
播放视频
播放视频文件使用VideoView类来实现,这个类将视频的显示和控制集于一身。
VideoView的用法和MediaPlayer也比较类似,主要有以下常用方法:
VideoView的工作流程如下:
- 创建出一个VideoView对象
- 调用setVideoPath() 方法来设置音频文件的路径
- 调用start() 方法开始播放
- 播放视频,调用pause() 方法就会暂停播放
要在程序中显示播放的视频,需要在布局文件中添加VideoView这个控件。
以上是关于Android学习羁绊之多媒体开发的主要内容,如果未能解决你的问题,请参考以下文章