Pro Android学习笔记(一三四):Media Frameworks(9):MediaStore

时间:2022-03-25 16:23:58

文章转载只能用于非商业性质,且不能带有虚拟货币、积分、注册等附加条件。转载须注明出处http://blog.csdn.net/flowingflying/以及作者@恺风Wei

MediaStore类提供了媒体接口,可以搜索特定类型的媒体,通过intent调用其它应用进行录音录像,建立playlist等等。和之前学习不同,MediaStore不能对编码、帧率、输入源和输出格式进行设定,如果我们不需要这些,使用MediaStore可能会更简单,MediaStore不需要permission,因为通过intent调起的activity已经具备这些权限。

录音小例子

Pro Android学习笔记(一三四):Media Frameworks(9):MediaStore

相关代码如下:

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();
        }
    }    
}

拍照小例子

Pro Android学习笔记(一三四):Media Frameworks(9):MediaStore

相关的代码片段如下:

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显示图片的方式,会出现异常,报告:

Pro Android学习笔记(一三四):Media Frameworks(9):MediaStore

当然,我们可以用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);               
}

通过MediaScan将媒体加入到MediaStore

通过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开发相关文章