天天看點

Pro Android學習筆記(一三四):Media Frameworks(9):MediaStore

文章轉載隻能用于非商業性質,且不能帶有虛拟貨币、積分、注冊等附加條件。轉載須注明出處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開發相關文章