文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei。
MediaStore类提供了媒体接口,可以搜索特定类型的媒体,通过intent调用其它应用进行录音录像,建立playlist等等。和之前学习不同,MediaStore不能对编码、帧率、输入源和输出格式进行设定,如果我们不需要这些,使用MediaStore可能会更简单,MediaStore不需要permission,因为通过intent调起的activity已经具备这些权限。
相关代码如下:
private static final int REQUESTCODE_RECORD_AUDIO = 1000;
public void startRecord(){
Intent intent = new Intent("android.provider.MediaStore.RECORD_SOUND");
startActivityForResult(intent, REQUESTCODE_RECORD_AUDIO);
}
@Override //获取录音文件的URI
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUESTCODE_RECORD_AUDIO){
if(resultCode == RESULT_OK){
Uri uri = data.getData();
Toast.makeText(this, "Uri is " + uri.toString(), Toast.LENGTH_LONG).show();
}
}
}
相关的代码片段如下:
private static final int REQUESTCODE_CAPTURE_PICTURE = 1001;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUESTCODE_CAPTURE_PICTURE){
if(resultCode == RESULT_OK){
findViewById(R.id.mediaStore_pictureShowButton).setEnabled(true); //本例简单将button设为enable,经检查data=null
}
}
}
private Uri myPicUri = null;
private void capturePicture(){
// 预先设定图像的URI,并设定TITLE和Description的内容,可设置的参数参见MediaStore.Images.ImageColumns
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "Wei Test");
values.put(MediaStore.Images.Media.DESCRIPTION, "Capture by camera via an intent");
myPicUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
debug(myPicUri.toString());
// 打开照相应用
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, myPicUri);
startActivityForResult(intent, REQUESTCODE_CAPTURE_PICTURE);
}
//调用查看图片的应用
private void showPicture(){
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(myPicUri);
startActivity(i);
}
我们也可以制定图片的存贮文件,但是这样,我们就不能指定相关TITLE,DESCRIPTION。相关代码如下:
myPicUri = Uri.fromFile(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/100ANDRO/test002.jpg"));
这种方式能将照相图片存放在制定的文件,但是如果我们仍使用之前通过content URI显示图片的方式,会出现异常,报告:
当然,我们可以用ImageView来打开指定的图片,也可以通过后面介绍的MediaScan方式获得其Content URI。
在指定URI的情况下,onActivityResult()中的Intent data为null,如果我们不指定URI,即注释掉intent.putExtra(MediaStore.EXTRA_OUTPUT, myPicUri);,图片信息付在Intent data中,获取的方式如下:
Bitmap myBitmap = (Bitmap) data.getExtras().get("data");
由于Intent携带信息不能太多,限制在50k,因此我们不会获得一个很大的图片,而是个小图。
视频录像和照相很形似,如下:
private void captureVideo(){
ContentValues values = new ContentValues();
myPicUri = getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, values);
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, myPicUri);
startActivityForResult(intent, 0);
}
在视频录像中,和音频录音相似,在onActivityResult中会返回Uri的。通常无需在一开始设定Uri,如下:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == REQUESTCODE_CAPTURE_VIDEO){
if(resultCode == RESULT_OK){
myMediaUri = data.getData();
}
}
}
private void captureVideo(){
Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
startActivityForResult(intent, REQUESTCODE_CAPTURE_VIDEO);
}
通过Intent进行照相,如果我们指定文件名字。我们在文件夹中可以找到该文件,然后点击用图库打开,我们发现有些不一样,无法读取该图片的详细信息(菜单中无详细信息一栏)。因为这种方式,我们并没有将之加入MediaStore。加入MediaStore后,可以获得其Content URI。方式如下:
public class RecordAudioByMediaStore extends Activity implements MediaScannerConnectionClient{
……
private String fileName = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM) + "/100ANDRO/wei0001.jpg";
private void capturePicture(){
File myImageFile = new File(fileName);
myImageFile.delete();
myMediaUri = Uri.fromFile(myImageFile);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, myMediaUri);
startActivityForResult(intent, REQUESTCODE_CAPTURE_PICTURE);
}
private MediaScannerConnection conn = null;
public void scanMedia(){
if(conn != null)
conn.disconnect();
File fileCheck = new File(fileName);
if(fileCheck.isFile()){
conn = new MediaScannerConnection(this, this);
conn.connect();
}else{
Log.d("WEI","That file does not exitst!");
}
}
@Override
public void onMediaScannerConnected() {
Log.d("WEI","onMediaScannerConnected()");
conn.scanFile(fileName, null); //扫描该文件,可以在第二个参数中指定MIME类型,MediaScaner将检查是哪类型的文件,以及相关的详细信息。onMediaScannerConnected()是在main中线程中运行,但是scanFile()将可能持续较长时间,将启动后台线程进行。
}
@Override // 扫描完成,如果能获知文件类型是媒体,在媒体provider database中加入entry,即有了content URI。我们在/data/data/com.android.providers.media/databases中可以看到数据库,如internal.db、external.db。相关的数据查询方式可以参见:Pro Android学习笔记(五):了解Content Provider(上) 。加入了MediaStore后,如果是图片,我们将在图库(Gallery)应用中可以看到它,如果是音乐,可以在音乐应用中看到它。此外注意,onScanCompleted运行在线程Binder_1中,而非UI线程,所以不要在此进行UI处理。
public void onScanCompleted(String path, Uri uri) {
try{
Log.d("WEI","onScanCompleted(): path=" + path + " uri=" + uri);
if(uri != null){ //如果成功扫描并加入,查看之
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(uri);
startActivity(i);
}else{
Log.d("WEI","That file is no good.");
}
}finally{
conn.disconnect();
conn = null;
}
}
}
在4.4版本之前,我们可以发送广播,要求对某个文件或者文件夹进行扫描,同样也能将之加入到相应的媒体库中,代码如下:
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
或者
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(file:///mnt/sdcard1/DCIM/100ANDRO/)));
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse(file:///mnt/sdcard1/DCIM/100ANDRO/wei0001.jpg)));
根据网上资料,在Android4.4版本,限制了非系统应用通过广播要求扫描。
小例子代码在:Pro Android学习:media framworks小例子
相关链接:我的Android开发相关文章