Android开发安卓开发博客Android开发

Android7.0拍照,权限验证,一行代码解决

2018-07-18  本文已影响105人  Wocus

前言:

此文章解决了一下问题
1.Android7.0以上拍照的适配
2.Android6.0以上权限动态的申请

实现步骤

①在mainfest标签里加入以下该权限

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

②在application下加入该provider

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

③在res目录下创建xml文件夹,在里面新建filepaths.xml文件,代码如下

<resources>
         <paths>
              <external-path path="" name="sdcard_files"/>
              <external-files-path path="" name="camera_has_sdcard"/>
              <files-path path="" name="camera_no_sdcard"/>
        <paths/>
<resources/>

④拷贝下面两个类

SelectPhotoUtil.kt

package com.wocus.wine.util

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.support.v4.content.FileProvider
import java.io.File
import java.text.SimpleDateFormat
import java.util.*

class SelectPhotoUtil(val activity: Activity, val isTailor:Boolean, val onResult: OnResult) {

    interface OnResult{
        fun onResultFile(file: File)
    }

    var file:File?=null

    /**
     * 权限申请
     */
    @SuppressLint("NewApi")
    fun requestReadExternalPermission(requestCode: Int) {
        if (activity.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            if (!activity.shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE)) {
                activity.requestPermissions(arrayOf(Manifest.permission.CAMERA, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE), requestCode)
            }
        }else{
            if (requestCode==1){
                getCamera()
            }else{
                getGallery()
            }
        }
    }

    /**
     * 拍照方式选择
     */
    fun showDialog() {
        AlertDialog.Builder(activity).setItems(arrayOf("拍照", "从相册选择")) { _, index ->
            if (index == 0) {
                requestReadExternalPermission(1)
            } else {
                requestReadExternalPermission(2)
            }
        }.create().show()
    }

    /**
     * 拍照
     */
    private fun getCamera() {
        var intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            val img_name = SimpleDateFormat("yyyyMMddHHmmss").format(Date()) + ".jpg"
            file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), img_name)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(activity, "com.wocus.wine.fileprovider", file!!))
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
            } else {
                intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file))
            }

            activity.startActivityForResult(intent, 1)
        } else {
            ToastUtil.show(activity, "储存卡不可用!")
        }
    }

    /**
     * 从相册选择
     */
    private fun getGallery() {
        var intent = Intent(Intent.ACTION_GET_CONTENT)
        intent.addCategory(Intent.CATEGORY_OPENABLE)
        intent.type = "image/*"
        val img_name = SimpleDateFormat("yyyyMMddHHmmss").format(Date()) + ".jpg"
        file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), img_name)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            intent.putExtra(MediaStore.EXTRA_OUTPUT, FileProvider.getUriForFile(activity, "com.wocus.wine.fileprovider", file!!))
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
        }
        activity.startActivityForResult(intent, 2)
    }

    /**
     * 选择图片回调
     */
    fun attachToActivityForResult(requestCode: Int, resultCode: Int, data: Intent?){
        if (resultCode == Activity.RESULT_OK) {
            when(requestCode){
                1->{
                    if (isTailor){
                        if (Build.VERSION.SDK_INT>=24){
                            getZoom(FileProvider.getUriForFile(activity,"com.wocus.wine.fileprovider",file!!))
                        }else{
                            getZoom(Uri.fromFile(file!!))
                        }
                    }else{
                        onResult.onResultFile(file!!)
                    }
                }
                2->{
                    var imgUri= File(GetImagePath.getPath(activity,data!!.data))
                    if (isTailor){
                        if(Build.VERSION.SDK_INT>=24){
                            var dataUri:Uri=FileProvider.getUriForFile(activity,"com.wocus.wine.fileprovider",imgUri)
                            getZoom(dataUri)
                        }else{
                            getZoom(data!!.data)
                        }
                    }else{
                        onResult.onResultFile(imgUri)
                    }
                }
                3->{
                    onResult.onResultFile(file!!)
                }
            }
        }
    }

    /**
     * 图片裁剪
     */
    public fun getZoom(uri: Uri){
        if (uri==null){
            return
        }
        val intent=Intent("com.android.camera.action.CROP")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            val outPutUri = Uri.fromFile(file);
            intent.setDataAndType(uri, "image/*");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);
            intent.putExtra("noFaceDetection", false);//去除默认的人脸识别,否则和剪裁匡重叠
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
        } else {
            val outPutUri = Uri.fromFile(file);
            if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
                val url = GetImagePath.getPath(activity, uri);//这个方法是处理4.4以上图片返回的Uri对象不同的处理方法
                intent.setDataAndType(Uri.fromFile(File(url)), "image/*");
            } else {
                intent.setDataAndType(uri, "image/*");
            }
            intent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);
        } // 设置裁剪
        intent.putExtra("crop", "true");
        // aspectX aspectY 是宽高的比例
        intent.putExtra("aspectX", 1);
        intent.putExtra("aspectY", 1);
        // outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 200);
        intent.putExtra("outputY", 200);
        intent.putExtra("return-data", false);
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());// 图片格式
        activity.startActivityForResult(intent, 3)
    }


    /**
     * 权限回调
     */
    fun attrRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            when (requestCode) {
                1 -> {
                    getCamera()
                }
                2->{
                    getGallery()
                }
            }
        } else {
            ToastUtil.show(activity, "授权失败");
        }
    }


}

GetImagePath.java

package com.wocus.wine.util;

import android.annotation.SuppressLint;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;

public class GetImagePath {

//  4.4以上  content://com.android.providers.media.documents/document/image:3952
//  4.4以下  content://media/external/images/media/3951
    @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    //Android 4.4以下版本自动使用该方法
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}

⑤Activity中的使用

package com.wocus.wine.activity

import android.content.Intent
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.bumptech.glide.Glide
import com.wocus.wine.R
import com.wocus.wine.util.SelectPhotoUtil
import kotlinx.android.synthetic.main.activity_pay.*
import java.io.File

class PayActivity : AppCompatActivity() {

    var selectPhoto:SelectPhotoUtil?=null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_pay)
        selectPhoto=SelectPhotoUtil(this,true,object :SelectPhotoUtil.OnResult{
            override fun onResultFile(file: File) {
                Glide.with(baseContext).load(file).into(testImg)
            }
        })
        testBtn.setOnClickListener {
            selectPhoto?.showDialog()
        }
    }

    /**
     * 权限回调
     */
    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        selectPhoto?.attrRequestPermissionsResult(requestCode,permissions,grantResults)
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    }


    /**
     * 拍照回调
     */
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        selectPhoto?.attachToActivityForResult(requestCode,resultCode,data)
        super.onActivityResult(requestCode, resultCode, data)
    }

}

调用第一步,初始化对象,参数第一个为Activity,第二个为是否剪裁,第三个为回调方法

有不懂的Q我752422962

上一篇下一篇

猜你喜欢

热点阅读