0
点赞
收藏
分享

微信扫一扫

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

自信的姐姐 2023-04-10 阅读 36


作者@恺风Wei。

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

录音小例子

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

相关代码如下:

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_ide_02

相关的代码片段如下:

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_UI_03

当然,我们可以用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小例子


举报

相关推荐

0 条评论