调用多媒体功能

    Android系统的多媒体功能使用的是MediaStore类,这个类是Android多媒体数据库的封装类。无论我们是调用多媒体功能发送的intent,data,extra等,还是从多媒体数据库存取数据,都要通过这个类。

    比如,我们要调用拍照功能,需要发送如下intent:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);				
startActivityForResult(intent, IMAGE_REQUEST_CODE);

    其中,MediaStore.ACTION_IMAGE_CAPTURE是调用拍照功能的action,startActivityForResult是启动相机拍照并获取结果。

    使用相机拍照后,获取结果的处理如下:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	super.onActivityResult(requestCode, resultCode, data);

	if (resultCode == Activity.RESULT_OK) {
		switch (requestCode) {
		case IMAGE_REQUEST_CODE:
			Uri uri = data.getData();							
			if (null == uri) {
				Bundle bundle = data.getExtras();
				if (null != bundle) {
					Bitmap bitmap = (Bitmap) bundle.get("data");
					//	MediaStore.Images.Media.insertImage(getContentResolver(),
					//		bitmap, "title", "description");
					mImage.setImageBitmap(bitmap);
				}
			} else {
				Log.d(TAG, "uri:" + uri.toString());
			}
			break;
		}
	}
}

    不同手机中的相机处理照片的获取方式是不同的。方式有两种:

1、有的能够取到照片的Uri,然后我们可以直接用Uri获取到照片;

2、有的不能取到Uri,即此时的Uri为null,这时我们可以通过extra中的bundle,通过bundle.get("data"),将图片内容取出来。这时先将相机返回的数据转换成Bitmap图片格式,然后存储到多媒体数据库表中,并通过mImage.setImageBitmap(bitmap)方法显示到界面上,其中mImage是一个ImageView。

    以上的方法是先调用拍照,然后通过相机程序拍照后返回的缩略图来显示。缺点是有时可能得不到原图的uri路径。因为不同手机的相机功能实现可能各异,导致支持的结果也不一样。就拿android Camera源码来看,采用以上方法就获取不到图片的Uri。

    android Camera源码中执行处理拍照并返回的类是Camera.java。里面有这样一段代码,用来处理拍照后,并确认后所执行的内容:

  private void doAttach() {
        if (mPausing) {
            return;
        }

        byte[] data = mJpegImageData;

        if (mCropValue == null) {
            // First handle the no crop case -- just return the value.  If the
            // caller specifies a "save uri" then write the data to it's
            // stream. Otherwise, pass back a scaled down version of the bitmap
            // directly in the extras.
            if (mSaveUri != null) {
                OutputStream outputStream = null;
                try {
                    outputStream = mContentResolver.openOutputStream(mSaveUri);
                    outputStream.write(data);
                    outputStream.close();

                    setResultEx(RESULT_OK);
                    finish();
                } catch (IOException ex) {
                    // ignore exception
                } finally {
                    Util.closeSilently(outputStream);
                }
            } else {
                int orientation = Exif.getOrientation(data);
                Bitmap bitmap = Util.makeBitmap(data, 50 * 1024);
                bitmap = Util.rotate(bitmap, orientation);
                setResultEx(RESULT_OK,
                        new Intent("inline-data").putExtra("data", bitmap));
                finish();
            }
        } else {
            // Save the image to a temp file and invoke the cropper
            Uri tempUri = null;
            FileOutputStream tempStream = null;
            try {
                File path = getFileStreamPath(sTempCropFilename);
                path.delete();
                tempStream = openFileOutput(sTempCropFilename, 0);
                tempStream.write(data);
                tempStream.close();
                tempUri = Uri.fromFile(path);
            } catch (FileNotFoundException ex) {
                setResultEx(Activity.RESULT_CANCELED);
                finish();
                return;
            } catch (IOException ex) {
                setResultEx(Activity.RESULT_CANCELED);
                finish();
                return;
            } finally {
                Util.closeSilently(tempStream);
            }

            Bundle newExtras = new Bundle();
            if (mCropValue.equals("circle")) {
                newExtras.putString("circleCrop", "true");
            }
            if (mSaveUri != null) {
                newExtras.putParcelable(MediaStore.EXTRA_OUTPUT, mSaveUri);
            } else {
                newExtras.putBoolean("return-data", true);
            }

            Intent cropIntent = new Intent("com.android.camera.action.CROP");

            cropIntent.setData(tempUri);
            cropIntent.putExtras(newExtras);

            startActivityForResult(cropIntent, CROP_MSG);
        }
    }

其中,mSaveUri就是前一个Activity发来的intent中的key为MediaStore.EXTRA_OUTPUT的extra值。mSaveUri获取代码如下:

   private void setupCaptureParams() {
        Bundle myExtras = getIntent().getExtras();
        if (myExtras != null) {
            mSaveUri = (Uri) myExtras.getParcelable(MediaStore.EXTRA_OUTPUT);
            mCropValue = myExtras.getString("crop");
        }
    }

从上面的两段代码可以看出,当mSaveUri不为null时,即前一个应用程序传的intent包含key为MediaStore.EXTRA_OUTPUT的extra值时,相机程序会将拍出的照片保存本地存储,然后返回的值不包括intent;当mSaveUri为null时,相机程序会将拍出的照片转成bitmap通过intent返回给前一个调用的Activity。

    我们的需求是既要保存到本地存储,又要获取到bitmap用以展示。因此,我采用了以下做法。

	private final static int IMAGE_REQUEST_CODE = 1;
	
	private Uri mPhotoUri;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
		
		ContentValues values = new ContentValues();
		mPhotoUri = getContentResolver().insert(
				MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

		intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri);
		
		startActivityForResult(intent, IMAGE_REQUEST_CODE);
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		if (resultCode == Activity.RESULT_OK) {
			switch (requestCode) {
			case IMAGE_REQUEST_CODE:
				Bitmap bitmap = getBitmapFromUri();
				//show bitmap
			}
		}
	}
	
	private Bitmap getBitmapFromUri() {
		try {
			Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), mPhotoUri);
			return bitmap;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return null;
	}

    这种做法是:

1、获取到图片的uri;

2、将该uri通过intent的extra传递给相机程序,以便保存照片到本地;

3、在onActivityResult回调中,获取到resultCode为Activity.RESULT_OK时,采用之前获得的uri来取出相应照片的缩略图bitmap以共展示。

    其中需要注意,一般照片都是存储在sdcard/DCIM目录下,也就是外部存储。所以需要以下权限:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />





你可能感兴趣的:(调用多媒体功能)