Android-实现拍照并显示(7.0及以上版本)

7.0以上版本(包括7.0)实现拍照功能有两个需要注意的地方

  • 拍照权限的动态获取
  • 内容提供器的使用

注意⚠️:如果是调用系统相机,是不用动态申请相机权限的!但是如果AndroidManifest.xml里面写了相机权限声明,那么就需要动态申请权限了

动态权限获取

在6.0系统之前,需要指定的权限可以在AndroidManifest.xml文件中进行权限声明
例如:

<user-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

但是这样会涉及到一个安全性问题,在6.0系统之前通过此方法声明的权限会在安装app的时候告诉用户该app需要的所有权限,一旦安装就表示授权,用户没有选择的余地。因此6.0后android将权限分级,不重要的权限可以在AndroidManifest.xml文件中
声明,等级较高(比如涉及到相机,电话等权限)权限则需要动态授权,并且用户可以随时在设置中取消授权。

重要权限可以查阅相关文档
官方说明

获取权限

调用ActivityComapt的requestPermissions的方法

public static void requestPermissions(@NonNull final Activity activity, @NonNull final String[] permissions, @IntRange(from = 0L) final int requestCode)

实例

ActivityCompat.requestPermissions(MainActivity.this,new String [] {permission},1);

调用这个方法获取权限后,将会回调MainActivity中的onRequestPermissionsResult()方法,在此方法中可以通过requestCode来判断是否获得到了权限进而进行下一步操作。

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
   swich(requestCode){
      case 1:
         if(grantResults.length > 0 && grantResults[0]==PackageManager.PERMISSION_GRANTED){
           // to do
         }else{
           Toast.makeText(this,"You denied the permission",Toast.LENGTH_SHORT).show();
         }
         break;
      default:
   }
     
}

检测系统版本

在实际开发中,为了程序能适应多个版本的系统,需要对系统版本进行检测,从而来执行不同的操作

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
       // 7.0 以上    
}else {
      // 7.0 以下
}

检测是否某拥有权限

if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.CAMERA)!=PackageManager.PERMISSION_GRANTED){  
    //to do
   }

PackageManager.PERMISSION_DENIED 表示没有权限
PackageManager.PERMISSION_GRANTED 有权限

通过内容提供器显示图片

详细参考内容提供器 content provider

获取权限

  1. 在androidManifest.XML 文件申请相关权限
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA"/>
  1. 动态获取权限

    if (ContextCompat.checkSelfPermission(this,Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
        ActivityCompat.requestPermissions(this,new String [] {Manifest.permission.CAMERA},1);
    }

修改AndroidManifest.XML 文件

在application标签中添加

 <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.baiduocr.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
 provider>

创建xml文件

在res下创建一个xml文件夹再创建一个file_paths.XML 文件
Android-实现拍照并显示(7.0及以上版本)_第1张图片
file_paths.XML文件内容

<Paths xmlns:android="http://schemas.android.com/apk/res/android">
  <external-path name="camera_photos" path=""/>
Paths>

完整代码

Android-实现拍照并显示(7.0及以上版本)_第2张图片
Ui层是由一个ImageView和一个button构成


public class MainActivity extends AppCompatActivity {
    private ImageView imageView=null;
    private Uri imageUri;
    private Button button=null;
    private static final int TAKE_PHOTO = 1;
    private File outputFile;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
        setListener();
    }
    
    /**
    * 如果用户拒绝相机权限就再次获取
    **/
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                } else {
                    requestPermission(Manifest.permission.CAMERA);
                }

    }

    protected void init(){
        button=(Button)findViewById(R.id.button);
        imageView=(ImageView)findViewById(R.id.imageView);
        requestPermission(Manifest.permission.CAMERA);
    }

    private void setListener(){
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                takePhoto();
            }
        });
    }


    public void takePhoto(){
        outputFile = new File(MainActivity.this.getExternalCacheDir(),"output.jpg");
        try{
            if (outputFile.exists()){
                outputFile.delete();
            }
            outputFile.createNewFile();
        }catch (Exception e){

        }
        if (Build.VERSION.SDK_INT>=24){
            imageUri=FileProvider.getUriForFile(MainActivity.this,"com.example.baiduocr.fileprovider",outputFile);
        }else{
            imageUri=Uri.fromFile(outputFile);
        }
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT,imageUri);
        startActivityForResult(intent,TAKE_PHOTO);
    }

    public void requestPermission(String permission){
        if (ContextCompat.checkSelfPermission(this,permission)!= PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String [] {permission},1);
        }
    }


    public void startPhotoZoom(Uri uri) {
        Log.e("uri=====", "" + uri);
        //com.android.camera.action.CROP,这个action是调用系统自带的图片裁切功能
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");//裁剪的图片uri和图片类型
        intent.putExtra("crop", "true");//设置允许裁剪,如果不设置,就会跳过裁剪的过程,还可以设置putExtra("crop", "circle")
        intent.putExtra("aspectX", 4);//裁剪框的 X 方向的比例,需要为整数
        intent.putExtra("aspectY", 1);//裁剪框的 Y 方向的比例,需要为整数
        intent.putExtra("outputX", 100*4);//返回数据的时候的X像素大小。
        intent.putExtra("outputY", 100);//返回数据的时候的Y像素大小。
        //uritempFile为Uri类变量,实例化uritempFile
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            if (TAKE_PHOTO == 1) {//如果是7.0的拍照
                //开启临时访问的读和写权限
                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
                //针对7.0以上的操作
                intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, uri));
                imageUri = uri;
            } else {//如果是7.0的相册
                //设置裁剪的图片地址Uri
                imageUri = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "clip.jpg");
            }

        } else {
            imageUri = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "clip.jpg");
            Toast.makeText(this,imageUri.toString(),Toast.LENGTH_SHORT).show();
        }
        Log.e("uriClipUri=====", "" + imageUri);
        //Android 对Intent中所包含数据的大小是有限制的,一般不能超过 1M,否则会使用缩略图 ,所以我们要指定输出裁剪的图片路径
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
        intent.putExtra("return-data", false);//是否将数据保留在Bitmap中返回
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//输出格式,一般设为Bitmap格式及图片类型
        startActivityForResult(intent, PHOTO_PHOTOCLIP);//裁剪完成的标识

    }

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

            switch (requestCode){
                case TAKE_PHOTO:
                    //to do
                    break;
            }
        }catch (FileNotFoundException e){
        }
    }
}

你可能感兴趣的:(android开发)