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