Android多媒体---Camera(调用系统Camera,非自定义)

时间:2022-10-19 20:34:06

调用系统Camera App实现拍照和摄像功能
不是专门的Camera应用,一般用到Camera的需求就是获取照片或者视 频,比如微博分享、随手记等,对于在Symbian系统上通过简单地调用系统自带的Camera APP来实现该功能是做不到的,但是Android系统强大的组件特性,使得应用开发者只需通过Intent就可以方便的打开系统自带的Camera APP,并通过MediaStroe方便地获取照片和视频的文件路径。具体我们还是用代码来说话吧:
21版本之后改成了camera2,需要相机权限和写权限(如果是调用的系统Camera程序不需要权限)。

<!--相机调用权限-->
<uses-permission android:name="android.permission.CAMERA"></uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

实例: 实现拍照
在菜单或按钮的选择操作中调用如下代码,开启系统自带Camera APP,并传递一个拍照存储的路径给系统应用程序,具体如下:

mBtn_startcamera.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
            Intent intent=new Intent();
            intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);//隐式启动相机
file=new File(Environment.getExternalStorageDirectory(),"20150915.jpg");//确定文件路径
try {
file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));//告诉相机照片保存路径
startActivityForResult(intent, REQUESTCODE);//requestCode设置为0,
}
    });
}

上 面我们使用的是startActivityForResult,所以最好需要重载void onActivityResult(int requestCode, int resultCode, Intent data)函数:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode==REQUESTCODE){ Toast.makeText(getApplication(),""+Uri.fromFile(file),Toast.LENGTH_SHORT).show(); if (resultCode==RESULT_OK) { mImageview.setImageURI(Uri.fromFile(file)); Toast.makeText(getApplication(),""+Uri.fromFile(file),Toast.LENGTH_SHORT).show(); }
    }
}

不过因为当传入文件路径的的情况下,data返回参数是null值,只要resultCode为RESULT_OK,则上述代码中 20150915.jpg的图片文件就是最新的照片文件。所以我们在这里只需给出如下简单的代码,将其显示到ImageView中

if (resultCode==RESULT_OK) {
mImageview.setImageURI(Uri.fromFile(file));
        }

假设不传参数MediaStore.EXTRA_OUTPUT的情况下,onActivityResult函数在resultCode为RESULT_OK的情况下,data返回的参数是经过实际拍摄照片经过缩放的图像数据,可以通过类似如下方法来打印缩放图像的尺寸

if (resultCode == RESULT_OK)
{
Bitmap bmp = (Bitmap)data.getExtras().get("data");
Log.d("Test", "bmp width:" + bmp.getWidth() + ", height:" + bmp.getHeight());
}

另外假如仅仅是调用系统照相机拍照,不关心拍照结果,则可以简单使用如下代码

Intent intent = new Intent(); //调用照相机
intent.setAction("android.media.action.STILL_IMAGE_CAMERA");
startActivity(intent);

备 注:上面设置MediaStore.EXTRA_OUTPUT的方法,经过手机实测除了设定的路径下有照片外,在手机存储卡上也会保存一份照片,默认 目录为sdcard/dcim/camera下面,我曾经尝试着想如果每次返回可以取得sdcard/dcim/camera下面的路径就好了,但是目前 看来没办法直接获得,可以借助MediaStroe每次去查询最后一条照片记录,应该也是可行的。
启动相册:
在按钮操作中添加如下代码

mBtn_select.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent=new Intent(Intent.ACTION_GET_CONTENT);//隐式启动相册
        intent.setType("image/*");//设置类型为图片
        startActivityForResult(intent,REQUESTCODESELECT);
    }
});

在复写的onActivityResult中判断requestcode,用data参数得到这张照片的Uri

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode==RESULT_OK){
      switch (requestCode){
          case REQUESTCODE://添加压缩后的调用Camera
              zipImage(file.getAbsolutePath());
              mImageview.setImageURI(Uri.fromFile(file));
              break;
          case REQUESTCODESELECT:
              Uri uri=data.getData();
              mImageview.setImageURI(uri);
              break;
      }
    }
}

压缩方法代码块,压缩后覆盖原文件:
private void zipImage(String savePath) {//传入路径file。getabsolutepath();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(savePath, options);
options.inSampleSize = computeInitialSampleSize(options, 480, 480 * 960);
options.inJustDecodeBounds = false;
Bitmap bitmap = BitmapFactory.decodeFile(savePath, options);
try {
FileOutputStream fos = new FileOutputStream(savePath);
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fos);
fos.flush();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
bitmap.recycle();
bitmap = null;
System.gc();
}
public int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);
int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}

private int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}