美文网首页
【Android】调用系统相机和相册

【Android】调用系统相机和相册

作者: 感同身受_ | 来源:发表于2020-02-18 16:33 被阅读0次

今天在写一个Demo的时候,需要调用系统相机和相册,虽然之前写过类似的代码,但是还是无从下手,所以准备用这篇博客记录一下如何调用,以后再遇到这个功能的实现,就直接过来调用就行

这里的代码基本时模板代码,直接使用就行,细节地方根据自己的需求改动一下

一、系统相机:

1. 声明权限:

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

2. 检查权限:如果没有权限,则去申请权限,若有权限就直接打开系统相机

    /**
     * 检查权限并拍照。
     * 调用相机前先检查权限。
     */
    private void checkPermissionAndCamera() {
        int hasCameraPermission = ContextCompat.checkSelfPermission(getApplication(),
                Manifest.permission.CAMERA);
        if (hasCameraPermission == PackageManager.PERMISSION_GRANTED) {
            //有调起相机拍照。
            openCamera();
        } else {
            //没有权限,申请权限。
            ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA},
                    PERMISSION_CAMERA_REQUEST_CODE);
        }
    }

3. 调用系统相机:

    /**
     * 调起相机拍照
     */
    private void openCamera() {
        Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // 判断是否有相机
        if (captureIntent.resolveActivity(getPackageManager()) != null) {
            File photoFile = null;
            Uri photoUri = null;

            if (isAndroidQ) {
                // 适配android 10
                photoUri = createImageUri();
            } else {
                try {
                    photoFile = createImageFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }

                if (photoFile != null) {
                    mCameraImagePath = photoFile.getAbsolutePath();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        //适配Android 7.0文件权限,通过FileProvider创建一个content类型的Uri
                        photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", photoFile);
                    } else {
                        photoUri = Uri.fromFile(photoFile);
                    }
                }
            }

            mCameraUri = photoUri;
            if (photoUri != null) {
                captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
                captureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                startActivityForResult(captureIntent, CAMERA_REQUEST_CODE);
            }
        }
    }

4. 创建保存文件的图片的路径,这里根据Android不同的版本进行了不同的处理

    /**
     * 创建图片地址uri,用于保存拍照后的照片 Android 10以后使用这种方法
     */
    private Uri createImageUri() {
        String status = Environment.getExternalStorageState();
        // 判断是否有SD卡,优先使用SD卡存储,当没有SD卡时使用手机存储
        if (status.equals(Environment.MEDIA_MOUNTED)) {
            return getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues());
        } else {
            return getContentResolver().insert(MediaStore.Images.Media.INTERNAL_CONTENT_URI, new ContentValues());
        }
    }

    /**
     * 创建保存图片的文件
     */
    private File createImageFile() throws IOException {
        String imageName = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if (!storageDir.exists()) {
            storageDir.mkdir();
        }
        File tempFile = new File(storageDir, imageName);
        if (!Environment.MEDIA_MOUNTED.equals(EnvironmentCompat.getStorageState(tempFile))) {
            return null;
        }
        return tempFile;
    }

5. 调用相机后返回结果,注:如果mCameraImagePath要用这个变量去保存图片地址时,必须将其设置为static属性,不然当结果返回时,他为null(因为返回结果时,相当于重新进入了这个Activity)

@Override
  protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
      super.onActivityResult(requestCode, resultCode, data);
      Intent intent = new Intent(MainActivity.this,YourActivity.class);
      if (requestCode == CAMERA_REQUEST_CODE) {
          if (resultCode == RESULT_OK) {
              //将拍照后的图片设置给imageview
//                if (isAndroidQ) {
//                    // Android 10 使用图片uri加载
//                    ivPhoto.setImageURI(mCameraUri);
//                } else {
//                    // 使用图片路径加载
//                    ivPhoto.setImageBitmap(BitmapFactory.decodeFile(mCameraImagePath));
//                }
              //将拍照后,文件的路径传给下一个Activity
              intent.putExtra("mPicPath",mCameraImagePath);
              startActivity(intent);
          }
      }
  }

6. 变量名:

    // 申请相机权限的requestCode
    private static final int PERMISSION_CAMERA_REQUEST_CODE = 0x00000012;
    //用于保存拍照图片的uri
    private Uri mCameraUri;
    // 用于保存图片的文件路径,Android 10以下使用图片路径访问图片
    //如果不加static,当跳转之后再回来,这个变量就为null了,但不是长久之计
    private static String mCameraImagePath;
    // 是否是Android 10以上手机
    private boolean isAndroidQ = Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q;

    private static final int CAMERA_REQUEST_CODE = 200;

7. 在Manifest中,声明provider

        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>

8. 对于provider中的android:resource="@xml/file_paths"需要在res下面创建一个xml的目录,然后创建一个xml文件file_paths

<?xml version="1.0" encoding="utf-8"?>
<resource xmlns:android="http://schemas.android.com/apk/res/android">
    <paths>
        <!-- 这个是保存拍照图片的路径,必须配置。 -->
        <external-files-path
            name="images"
            path="Pictures" />
    </paths>
</resource>

二、系统相册

1.声明权限:

    <!--SD卡权限-->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

2.打开相册:

    //从相册中选择照片
    private void openAlbum() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent,CHOOSE_PHOTO);
    }

3. 处理返回的结果,注:这里我对不同的Android版本进行了处理

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Intent intent = new Intent(MainActivity.this,PuzzleMain.class);
        if (requestCode == CHOOSE_PHOTO){
            if (requestCode != RESULT_OK) {
                String path;
                //判断手机的版本号
                if (Build.VERSION.SDK_INT >= 19) {
                    //4.4及以上的系统使用的这个方法处理图片
                    path = handleImageOnKitKat(data);
                }else {
                    //4.4以下的系统使用的图片处理方法
                    path = handleImageBeforeKitKat(data);
                }
                intent.putExtra("mPicPath", path);
                startActivity(intent);
            }
        }
    }

4. 根据不同的版本对data进行不同的处理

    private String handleImageOnKitKat(Intent data) {

        String imagePath = null;
        Uri uri = data.getData();
        if (DocumentsContract.isDocumentUri(this,uri)) {
            //如果document类型的Uri,则通过document id处理
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];//解析出数字格式的id
                String selection = MediaStore.Images.Media._ID+"="+id;
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection);
            }else if("com.android.providers.downloads.documents".equals(uri.getAuthority())){
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://" +
                        "downloads//public_downloads"),Long.valueOf(docId));
                imagePath = getImagePath(contentUri,null);
            }
        }else if("content".equalsIgnoreCase(uri.getScheme())){
            //如果是普通content类型的uri,则使用普通的方法处理
            imagePath = getImagePath(uri,null);
        }else if("file".equalsIgnoreCase(uri.getScheme())){
            //如果使用file类型的uri,直接获取图片的路径即可
            imagePath = uri.getPath();
        }
        return imagePath;
    }

    private String handleImageBeforeKitKat(Intent data) {
        Uri uri = data.getData();
        String imagePath = getImagePath(uri,null);
        return imagePath;
    }

5. 解析Url,得到路径

    private String getImagePath(Uri externalContentUri, String selection) {
        String path = null;
        //通过Uri和selection来获取真实的图片路径
        Cursor cursor = getContentResolver().query(externalContentUri,
                null,selection,null,null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));

            }
            cursor.close();
        }
        return path;
    }

6. 调用相册使用的变量:

    //相册
    private static final int CHOOSE_PHOTO = 100;

相关文章

网友评论

      本文标题:【Android】调用系统相机和相册

      本文链接:https://www.haomeiwen.com/subject/pqigfhtx.html