作者:韩亚飞_yue31313_韩梦飞沙 QQ:313134555
day08 多媒体
Ø 多媒体
一、多媒体相关权限
Manifest声明
开始开发摄像头 API的应用之前,应该确保已经在manifest中正确声明了对摄像头的使用及其它相关的feature。
· Camera权限——应用程序必须对请求摄像头的使用权限。
<uses-permission android:name="android.permission.CAMERA" />
注意:如果是通过意图来使用摄像头的,应用程序就不必请求本权限。
· Camera Feature——应用程序必须同时声明对camera feature的使用,例如:
<uses-feature android:name="android.hardware.camera" />
关于摄像头feature的清单,参阅manifest Feature参考。
在manifest中加入camera feature,将会使得Android Market在没有摄像头或不支持指定feature的设备上禁止安装该应用程序。关于Android Market基于feature过滤的使用详情,请参阅Android Market和基于Feature的过滤。
如果应用程序可能用到摄像头或摄像头feature,但却不是必需的,则应在manifest中指定包含android:required属性的feature,并将该属性设为false:
<uses-feature android:name="android.hardware.camera" android:required="false"/>
· 存储权限——如果应用程序要把图像或视频保存到设备的外部存储上(SD卡),则还必须在manifest中指定如下权限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
· 录音权限——要用音频捕获来录音,应用程序必须请求音频捕获权限。
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
二、音频播放:MediaPlayer
(一)界面相关:
<SeekBar---进度条
android:id="@+id/audioSB"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_weight="5" />
<ImageButton---图片按钮
android:onClick="onClick"
android:id="@+id/ppIB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:drawable/ic_media_play" />
(二)定义三个监听器
1. 定义音频准备完成监听器--缓冲完后的动作
privateOnPreparedListener onPreparedListener =
new OnPreparedListener() {
public void onPrepared(MediaPlayer mp){
dialog.dismiss(); // 取消对话框
mediaPlayer.start(); // 开始播放(新线程中执行)
handleSeekBar(); // 处理进度条
// 处理ImageButton图标的变化
ppIB.setImageResource(mediaPlayer.isPlaying()
? android.R.drawable.ic_media_pause
: android.R.drawable.ic_media_play);
}
2. 定义进度条改变监听器--让进度条拖动快进
privateOnSeekBarChangeListener onSeekBarChangeListener = new OnSeekBarChangeListener() {
public voidonStopTrackingTouch(SeekBar seekBar) {
// 当进度条停止时,让歌曲播放到这个位置
if (mediaPlayer != null)
// 设置播放器的进度为进度条的当前进度
mediaPlayer.seekTo(audioSB.getProgress());
}
public voidonStartTrackingTouch(SeekBar seekBar) {}
public void onProgressChanged(SeekBarseekBar, int progress,
boolean fromUser) {}
};
3. 定义播放完成监听
privateOnCompletionListener onCompletionListener = new OnCompletionListener() {
public void onCompletion(MediaPlayermp) {
//如果设了单曲循环则让其重新播放
if (mediaPlayer.isLooping()){
try {
mediaPlayer.setDataSource(filePath);
mediaPlayer.prepareAsync(); // 异步加载
showDialog();// 显示对话框
mediaPlayer.start();
} catch (Exception e) {
e.printStackTrace();
}
//否则:停止播放,释放资源,
} else {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
audioSB.setProgress(0);//让进度条回归开始位置
//让图标改成停止播放
ppIB.setImageResource(android.R.drawable.ic_media_play);
}
}
};
(三)定义ImageButton播放按钮事件-播放音乐
public void onClick(View view) throws Exception {
if (filePath == null)
filePath = fileList.get(0).getAbsolutePath();
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer(); // 创建媒体播放器
// 设置音频流类型
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
// 设置播放完成监听器
mediaPlayer.setOnCompletionListener(onCompletionListener);
// 添加准备完成监听器
mediaPlayer.setOnPreparedListener(onPreparedListener); mediaPlayer.setDataSource(filePath);// 设置音频源
mediaPlayer.prepareAsync();// 异步加载
showDialog(); // 显示对话框
} else if (mediaPlayer.isPlaying()){
mediaPlayer.pause(); // 暂停
} else {
mediaPlayer.start(); // 继续播放
}
// 给播放按钮实现图标切换
ppIB.setImageResource(mediaPlayer.isPlaying()? android.R.drawable.ic_media_pause
:android.R.drawable.ic_media_play);
}
(四)定义进度条动作方法
private void handleSeekBar() {
audioSB.setOnSeekBarChangeListener(onSeekBarChangeListener);
// 设置进度条的最近进度为播放器文件的时长
audioSB.setMax(mediaPlayer.getDuration());
new Thread() {
public void run() {
while (mediaPlayer != null) {
if (mediaPlayer.isPlaying()&& !audioSB.isPressed())
// 设置进度条当前进度为播放器当前进度
audioSB.setProgress(mediaPlayer.getCurrentPosition()); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
};
(五)设制Activity销毁时清空资源占用
重定onDestroy方法
protected void onDestroy() {
super.onDestroy();
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
(六)MediaPlayer常用方法
mediaPlayer.start(); // 开始播放(新线程中执行)
mediaPlayer.isPlaying();是否在播放返回一个boolean
mediaPlayer.seekTo(int);跳到指定位置播放int一般与进度条相关getProgress()
mediaPlayer.getDuration();获取当前播放的文件总长度,返回一个int
mediaPlayer.getCurrentPosition()获取当前播放到的长度,返回一个int
mediaPlayer.isLooping();判断是否单曲循环
mediaPlayer.setDataSource(filePath);设置视频资源的路径
mediaPlayer.prepareAsync();// 异步加载(开新线程去加载)
mediaPlayer.prepare();同步加载
mediaPlayer.start();开始播放
mediaPlayer.stop();暂停播放
mediaPlayer.release();清空缓存
(七)音频池的用法:SoundPool类
用于存放一些常用的,比较小的音频,比如游戏中,
把所有音频先加载好,要哪个就用哪个,用完再放回去这样就比较省内存
用一个raw资源文件夹
使用步骤:
创建对象:
public class SoundPoolActivity extends Activity {
private SoundPool pool;
private int id;
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
sondPool类构造方法有三个参数
(最大个数,音频类型,音频质量(2.3不支持只能用0))
pool = new SoundPool(10,AudioManager.STREAM_MUSIC, 0);
加载:异步加载,不能放在事件方法里
load方法(this,音频资源,1(兼容性,现在只能用1));返回一个intid用于play和卸载
id = pool.load(this, R.raw.d, 1);
}
定义播放事件
public void poolClick(View view) {
播放:每次自动用新线程运行
(id,左声道大小,右声道大小,优先级0最低,要不要循环(0不循环),播放的数据(1普通速度,越小越慢))
pool.play(id, 1, 1, 0, 0, 1);
}
三、视频播放--关键控件SurfaceView(画面)
(一)界面相关:帧式布局嵌套上用线性布局进度条
<?xml version="1.0"encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<SurfaceView
android:id="@+id/videoSV"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<LinearLayout
android:layout_gravity="bottom"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp" >
<SeekBar
android:id="@+id/videoSB"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1" />
<ImageButton
android:id="@+id/ppIB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onClick"
android:src="@android:drawable/ic_media_play" />
</LinearLayout>
</FrameLayout>
(二)manifest.xml配置
<activity
android:configChanges="orientation"--横坚屏切换画面不销毁
android:screenOrientation="sensorLandscape"--保证横屏
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"--全屏
(三)实现原理
在播放时需要一个画面,这个时候在MediaPlayer上添加surfaceView,然后给surfaceView设置数据类型,其内部是通过,MediaPlayer的双缓冲机制,把数据给SurfaceView,然而如果切换到后台的话,系统会自动清理掉surfaceView以节省内存,但再开的时候,再创建,但MediaPlayer却里添加的却是之前的,所以,可以给SurfaceView添加一个回调,让其可以在重新创建时,把surfaceView添加入MediaPlayer
(四)核心代码:
在播放音频的基础上添加surfaceView
先有surfaceView对象
videoSV = (SurfaceView) findViewById(R.id.videoSV);
// 指定SurfaceView的数据类型
videoSV.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//那个参数表示获取数据的方式是:由 mediaPlayer提供来的
videoSV.getHolder().addCallback(callback);给SurfaceView添加回调, 监听其创建和摧毁
让surface销毁时记住播放位置,创建新的surfaceView后添加给mediaplayer,让mediaPlayer.seekTo(int)到指定位置播放.
private Callback callback = new Callback() {
//创建SurfaceView时创建播放,且判断播放点是否存在,存在就seek到那个位置播放
public voidsurfaceCreated(SurfaceHolder holder) {
if (position != 0)
mediaPlayer = new MediaPlayer(); // 创建媒体播放器
mediaPlayer.setDisplay(videoSV.getHolder());// 设置视频显示位置,让其显示在画面上
mediaPlayer.setDataSource("/mnt/sdcard/1.mp4");// 设置数据源
mediaPlayer.setOnCompletionListener(onCompletionListener);设置播放完成监听器
添加准备完成监听器
mediaPlayer.setOnPreparedListener(onPreparedListener);
mediaPlayer.prepareAsync(); // 异步加载
}
public voidsurfaceDestroyed(SurfaceHolder holder) {
// 如果surfaceView销毁就记录播放位置,然后销毁对象创建资源
if (mediaPlayer != null) {
position = mediaPlayer.getCurrentPosition();
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
}
public voidsurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
};
public void onClick(View view) throws Exception {
if (mediaPlayer == null) {
mediaPlayer = new MediaPlayer(); // 创建媒体播放器
mediaPlayer.setDisplay(videoSV.getHolder());// 设置视频显示位置
mediaPlayer.setDataSource("/mnt/sdcard/1.mp4");// 设置数据源
mediaPlayer.setOnCompletionListener(onCompletionListener);设置播放完成监听器
添加准备完成监听器
mediaPlayer.setOnPreparedListener(onPreparedListener);
mediaPlayer.prepareAsync(); // 异步加载
} else if (mediaPlayer.isPlaying()){
mediaPlayer.pause(); // 暂停
} else {
mediaPlayer.start(); //继续播放
}
ppIB.setImageResource(mediaPlayer.isPlaying()? android.R.drawable.ic_media_pause :android.R.drawable.ic_media_play);
}
四、拍照
(一)原理
开启摄像头,并给其一个显示数据的位置,这里就是手机屏幕显示画面,然后定义其参数,及其拍照按钮事件.
总的来说:获取对象--设置参数---获取资源--然后定义各种事件或回调函数--启动,这是多媒体通用模式,
(二)步骤:
1. 获取SurfaceView对象并设置sv对象的数据来源
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
previewSV= (SurfaceView) findViewById(R.id.previewSV);
previewSV.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
2. 定义SurfaceView回调函数
在其创建要执行的方法中让其一创建则开启摄像头并开始预览,
在其销毁要执行的方法中画面一关闭,则关闭摄像头并释放资源
private Callbackcallback = new Callback() {
public voidsurfaceDestroyed(SurfaceHolder holder) {
if (camera != null) {
camera.stopPreview(); // 停止预览
camera.release(); // 释放摄像头, 其他程序可以使用摄像头
camera = null; // 垃圾回收
}
}
public voidsurfaceCreated(SurfaceHolder holder) {
try {
camera =Camera.open(); //打开摄像头
Parameters params =camera.getParameters(); //获取摄像头的默认参数
System.out.println(params.flatten()); // 打印默认参数
params.setPictureSize(800,480); // 设置图片尺寸
params.setPreviewSize(800,480); // 设置预览尺寸
params.setJpegQuality(50); // 设置图片质量
camera.setParameters(params); // 改变摄像头的默认参数
camera.setPreviewDisplay(previewSV.getHolder()); // 给摄像头设置预览显示位置
camera.startPreview(); //开始预览
} catch (IOException e) {
e.printStackTrace();
}
}
public voidsurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
};
3. 给SurfaceView添加回调函数,
previewSV.getHolder().addCallback(callback);
4. 定义按快门按钮事件
当按下快门时先自动对焦,
public voidtake(View view) {
camera.autoFocus(newMyAutoFocusCallback()); // 按钮按下后, 自动对焦
}
5. 定义对焦的回调函数
当对焦完成时拍照
//对焦完成后回调函数
privateclass MyAutoFocusCallback implements AutoFocusCallback {
publicvoid onAutoFocus(boolean success, Camera camera) { // 对焦完成后执行
camera.takePicture(null,null, new MyPictureCallback()); // 拍照, 当数据生成完毕后执行回调函数
}
}
6. 定义拍照的回调函数
当拍照完成时,是直接保存,还是提示后再保存怎么的
注:拍照完成后,会停止预览,在这里要让其回复预览
//拍照完成后的回调函数
privateclass MyPictureCallback implements PictureCallback {
publicvoid onPictureTaken(byte[] data, Camera camera) { // 拍照完成后
try{
FileOutputStreamfos = new FileOutputStream("/mnt/sdcard/" +System.currentTimeMillis() + ".jpg");
fos.write(data);
fos.close();
camera.startPreview(); // 拍照之后, 预览会停止, 继续显示预览
}catch (IOException e) {
e.printStackTrace();
}
}
}
(三)常用的方法:
// 打开摄像头:camera = Camera.open();
// 获取摄像头的默认参数:Parameters params =camera.getParameters();
// 设置图片尺寸:params.setPictureSize(800,480);
// 设置预览尺寸:params.setPreviewSize(800,480);
// 设置图片质量:params.setJpegQuality(50);
// 改变摄像头的默认参数camera.setParameters(params);
// 给摄像头设置预览显示位置camera.setPreviewDisplay(previewSV.getHolder());
// 开始预览camera.startPreview();
//显示预览:camera.startPreview(); //拍照之后, 预览会停止, 继续显示预览
camera.stopPreview(); // 停止预览
camera.release(); // 释放摄像头, 其他程序可以使用摄像头
camera.autoFocus(newMyAutoFocusCallback()); // 按钮按下后, 自动对焦
camera.takePicture(null, null, newMyPictureCallback()); // 拍照, 当数据生成完毕后执行回调函数
五、录像
(一)步骤:
1. 获取SurfaceView对象设置获取资源方式及添加回调
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
previewSV = (SurfaceView) findViewById(R.id.previewSV);
previewSV.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//定义..
previewSV.getHolder().addCallback(callback);//
}
2. 定义SurfaceView的回调方法--要在SurfaceView添加之前定义
当SurfaceView创建时,开启预览
当Surface销毁时,停止预览释放资源
//定义画面回调函数
private Callback callback = new Callback() {
//当画面结束时
publicvoid surfaceDestroyed(SurfaceHolder holder) {
if(camera != null) {
camera.stopPreview(); // 停止预览
camera.release(); // 释放摄像头, 其他程序可以使用摄像头
camera= null; // 垃圾回收
}
}
//当画面启动时
publicvoid surfaceCreated(SurfaceHolder holder) {
try{
camera= Camera.open(); // 打开摄像头
camera.setPreviewDisplay(previewSV.getHolder()); // 给摄像头设置预览显示位置
camera.startPreview(); //开始预览
}catch (IOException e) {
e.printStackTrace();
}
}
publicvoid surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
};
3. 定义录像按钮的事件
按下按钮录像并同时保存
再按下按钮停止录像释放资源
//定义按钮
public void take(View view) throws IOException {
Button button = (Button) view;
if ("录像".equals(button.getText())) {
camera.unlock(); // 解锁摄像头
recorder= new MediaRecorder(); // 创建媒体记录器
recorder.setCamera(camera); // 设置摄像头
recorder.setAudioSource(AudioSource.MIC); // 设置音频源
recorder.setVideoSource(VideoSource.CAMERA); // 设置视频源
//设置输出格式
recorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_LOW));
//设置输出文件路径
recorder.setOutputFile("/mnt/sdcard/"+ System.currentTimeMillis() + ".mp4");
recorder.setPreviewDisplay(previewSV.getHolder().getSurface());
recorder.prepare(); // 准备
recorder.start(); // 开始录制
button.setText("停止");
} else {
recorder.stop(); // 停止录制
recorder.release(); // 释放资源
recorder= null; // 垃圾回收
camera.lock(); // 锁定摄像头
button.setText("录像");
}
}
六、调用手机自带的多媒体App
(一)调用系统自带摄像头app的步骤::
1.构建一个摄像头 Intent 用以下意图类型之一,创建一个请求图像或视频的Intent :
o MediaStore.ACTION_IMAGE_CAPTURE ——向内置摄像头程序请求图像的意图活动类型。
o MediaStore.ACTION_VIDEO_CAPTURE ——向内置摄像头程序请求视频的意图活动类型。
2. 启动摄像头 Intent ——用startActivityForResult()方法执行摄像头 intent。
启动完毕后摄像头应用的用户界面就会显示在屏幕上,用户就可以拍照或摄像了。
3. 接收Intent结果 —— 在应用程序中设置onActivityResult()方法,用于接收从摄像头 intent返回的数据。当用户拍摄完毕后(或者取消操作),系统会调用此方法。
(二)调用自带Camera捕获图像
如果希望程序以最少的代码实现拍照功能,利用摄像头intent捕获图像是一条捷径。图像捕捉intent还可以包含以下附加信息:
· MediaStore.EXTRA_OUTPUT ——本设置需要一个Uri对象,用于指定存放图片的路径和文件名。本设置是可选项,但强烈建议使用。如果未指定本设置值,那么摄像应用将会把所请求的图片以默认文件名和路径进行保存,并将数据置入intent的Intent.getData()部分返回。
以下例子演示了如何构建并执行一个图像捕获intent。此例中的getOutputMediaFileUri()方法引自保存媒体文件中的例程代码。.
private static final intCAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private Uri fileUri;
@Override
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建拍照Intent并将控制权返回给调用的程序
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
fileUri =getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
// 创建保存图片的文件
intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri);
// 设置图片文件名
// 启动图像捕获Intent
startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
startActivityForResult() 方法执行完毕后,用户将看到内置摄像头应用程序的界面。用户拍照完毕(或取消操作)后,用户界面返回应用程序,这时必须截获onActivityResult()方法来接收intent的返回结果并执行后续操作。关于如何接收完整的intent,请参阅接收摄像头Intent的结果。
(三)调用系统Camera捕获视频
如果希望程序以最少的代码实现摄像功能,利用摄像头 intent捕获视频是一条捷径。视频捕捉intent可以包含以下附带信息:
· MediaStore.EXTRA_OUTPUT —— 本设置需要一个Uri,用于指定保存视频的路径和文件名。本设置是可选项,但强烈建议使用。如果未指定本设置值,那么摄像应用将会把所请求的视频以默认文件名和路径进行保存,并将数据置入intent的Intent.getData()部分返回。
· MediaStore.EXTRA_VIDEO_QUALITY ——本值用0表示最低品质及最小的文件尺寸,用1表示最高品质和较大的文件尺寸。
· MediaStore.EXTRA_DURATION_LIMIT ——本值用于限制所捕获视频的长度,以秒为单位。
· MediaStore.EXTRA_SIZE_LIMIT —— 本值用于限制所捕获视频的文件尺寸,以字节为单位。
以下例子演示了如何构建并执行一个视频捕获intent。本例中的getOutputMediaFileUri()方法引自保存媒体文件中的例程代码。
private static final intCAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
private Uri fileUri;
public void onCreate(BundlesavedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建新的Intent
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
fileUri =getOutputMediaFileUri(MEDIA_TYPE_VIDEO);
// 创建保存视频的文件
intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri);
// 设置视频文件名
intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY,1); // 设置视频的品质为高
// 启动视频捕获Intent
startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
}
startActivityForResult() 方法执行完毕后,用户将看到一个改动过的摄像程序界面。用户摄像完毕(或取消操作)后,用户界面返回应用程序,这时必须监听onActivityResult()方法来接收intent的返回结果并执行后续操作。关于如何接收完整的intent,请参阅下一节。
(四)接收摄像头 intent的结果(相片及录像)
一旦已构建并运行了图像或视频的摄像头intent,应用程序就必须进行设置,以接收intent返回的结果。本节展示了如何监听摄像头intent的回调方法,以便应用程序对捕获到的图片及视频进行进一步的处理。
要接收intent的返回结果,必须覆盖启动intent的activity中的onActivityResult()方法。以下例子演示了如何覆盖onActivityResult()来获取上述章节例程中的图像捕获intent或视频捕获intent的结果。
private static final intCAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
private static final intCAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
protected void onActivityResult(intrequestCode, int resultCode, Intent data) {
1. 图像的保存
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// 捕获的图像保存到Intent指定的fileUri
Toast.makeText(this, "Image saved to:\n" +
data.getData(),Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// 用户取消了图像捕获
} else {
// 图像捕获失败,提示用户
}
}
2. 录像的保存
if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// 捕获的视频保存到Intent指定的fileUri
Toast.makeText(this, "Video saved to:\n" +
data.getData(),Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// 用户取消了视频捕获
} else {
// 视频捕获失败,提示用户
}
}
}
一旦activity接收到成功的结果,就说明捕获到的图像或视频已保存到指定位置了,应用程序就可对其进行访问。