zoukankan      html  css  js  c++  java
  • 安卓开发,调用系统相册或相机选择图片

    1.使用glide进行图片的展示效果

    关于glide

    2.PermissionGen动态权限获取

    关于PermissionGen

    代码:

    一、准备工作

    1.在AndroidManifest.xml添加权限

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

    2.在build.gradle中添加依赖

    dependencies {
    
        implementation 'com.github.bumptech.glide:glide:4.10.0'
        implementation 'com.lovedise:permissiongen:0.0.6'
    
    }

    二、主代码

    1.util工具类(toast和照片)

    import android.content.Context;
    import android.widget.Toast;
    
    public class ToastUtil {
        public static Toast mToast;
        public static void showMsg(Context context, String msg){
            if(mToast == null){
                mToast = Toast.makeText(context,msg,Toast.LENGTH_SHORT);
            }else{
                mToast.setText(msg);
            }
            mToast.show();
        }
    }
    Toast
    import android.content.ContentValues;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Environment;
    import android.provider.MediaStore;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import java.io.File;
    
    /**
     * CSDN_LQR
     * 图片选择工具类
     */
    public class LQRPhotoSelectUtils {
    
        public static final int REQ_TAKE_PHOTO = 10001;
        public static final int REQ_SELECT_PHOTO = 10002;
        public static final int REQ_ZOOM_PHOTO = 10003;
    
        private AppCompatActivity mActivity;
        //拍照或剪切后图片的存放位置(参考file_provider_paths.xml中的路径)
        private String imgPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + String.valueOf(System.currentTimeMillis()) + ".jpg";
        //FileProvider的主机名:一般是包名+".fileprovider",严格上是build.gradle中defaultConfig{}中applicationId对应的值+".fileprovider"
        private String AUTHORITIES = "packageName" + ".fileprovider";
        private boolean mShouldCrop = false;//是否要裁剪(默认不裁剪)
        private Uri mOutputUri = null;
        private File mInputFile;
        private File mOutputFile = null;
    
        //剪裁图片宽高比
        private int mAspectX = 1;
        private int mAspectY = 1;
        //剪裁图片大小
        private int mOutputX = 800;
        private int mOutputY = 480;
        PhotoSelectListener mListener;
    
        /**
         * 可指定是否在拍照或从图库选取照片后进行裁剪
         * <p>
         * 默认裁剪比例1:1,宽度为800,高度为480
         *
         * @param activity   上下文
         * @param listener   选取图片监听
         * @param shouldCrop 是否裁剪
         */
        public LQRPhotoSelectUtils(AppCompatActivity activity, PhotoSelectListener listener, boolean shouldCrop) {
            mActivity = activity;
            mListener = listener;
            mShouldCrop = shouldCrop;
            AUTHORITIES = activity.getPackageName() + ".fileprovider";
            imgPath = generateImgePath();
        }
    
        /**
         * 可以拍照或从图库选取照片后裁剪的比例及宽高
         *
         * @param activity 上下文
         * @param listener 选取图片监听
         * @param aspectX  图片裁剪时的宽度比例
         * @param aspectY  图片裁剪时的高度比例
         * @param outputX  图片裁剪后的宽度
         * @param outputY  图片裁剪后的高度
         */
        public LQRPhotoSelectUtils(AppCompatActivity activity, PhotoSelectListener listener, int aspectX, int aspectY, int outputX, int outputY) {
            this(activity, listener, true);
            mAspectX = aspectX;
            mAspectY = aspectY;
            mOutputX = outputX;
            mOutputY = outputY;
        }
    
        /**
         * 设置FileProvider的主机名:一般是包名+".fileprovider",严格上是build.gradle中defaultConfig{}中applicationId对应的值+".fileprovider"
         * <p>
         * 该工具默认是应用的包名+".fileprovider",如项目build.gradle中defaultConfig{}中applicationId不是包名,则必须调用此方法对FileProvider的主机名进行设置,否则Android7.0以上使用异常
         *
         * @param authorities FileProvider的主机名
         */
        public void setAuthorities(String authorities) {
            this.AUTHORITIES = authorities;
        }
    
        /**
         * 修改图片的存储路径(默认的图片存储路径是SD卡上 Android/data/应用包名/时间戳.jpg)
         *
         * @param imgPath 图片的存储路径(包括文件名和后缀)
         */
        public void setImgPath(String imgPath) {
            this.imgPath = imgPath;
        }
    
        /**
         * 拍照获取
         */
        public void takePhoto() {
            File imgFile = new File(imgPath);
            if (!imgFile.getParentFile().exists()) {
                imgFile.getParentFile().mkdirs();
            }
            Uri imgUri = null;
    
            //        if (Build.VERSION.SDK_INT >= 24) {//这里用这种传统的方法无法调起相机
            //            imgUri = FileProvider.getUriForFile(mActivity, AUTHORITIES, imgFile);
            //        } else {
            //            imgUri = Uri.fromFile(imgFile);
            //        }
            /*
            * 1.现象
                在项目中调用相机拍照和录像的时候,android4.x,Android5.x,Android6.x均没有问题,在Android7.x下面直接闪退
               2.原因分析
                Android升级到7.0后对权限又做了一个更新即不允许出现以file://的形式调用隐式APP,需要用共享文件的形式:content:// URI
               3.解决方案
                下面是打开系统相机的方法,做了android各个版本的兼容:
            * */
    
            if (Build.VERSION.SDK_INT < 24) {
                // 从文件中创建uri
                imgUri = Uri.fromFile(imgFile);
            } else {
                //兼容android7.0 使用共享文件的形式
                ContentValues contentValues = new ContentValues(1);
                contentValues.put(MediaStore.Images.Media.DATA, imgFile.getAbsolutePath());
                imgUri = mActivity.getApplication().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
            }
    
    
            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imgUri);
            mActivity.startActivityForResult(intent, REQ_TAKE_PHOTO);
        }
    
        /**
         * 从图库获取
         */
        public void selectPhoto() {
            Intent intent = new Intent(Intent.ACTION_PICK, null);
            intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
            mActivity.startActivityForResult(intent, REQ_SELECT_PHOTO);
    //        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    //        intent.setType("image/*");
    //        mActivity.startActivityForResult(intent, REQ_SELECT_PHOTO);
        }
    
        private void zoomPhoto(File inputFile, File outputFile) {
            File parentFile = outputFile.getParentFile();
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            Intent intent = new Intent("com.android.camera.action.CROP");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setDataAndType(getImageContentUri(mActivity, inputFile), "image/*");
            } else {
                intent.setDataAndType(Uri.fromFile(inputFile), "image/*");
            }
            intent.putExtra("crop", "true");
    
            //设置剪裁图片宽高比
            intent.putExtra("mAspectX", mAspectX);
            intent.putExtra("mAspectY", mAspectY);
    
            //设置剪裁图片大小
            intent.putExtra("mOutputX", mOutputX);
            intent.putExtra("mOutputY", mOutputY);
    
            // 是否返回uri
            intent.putExtra("return-data", false);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(outputFile));
            intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
    
            mActivity.startActivityForResult(intent, REQ_ZOOM_PHOTO);
        }
    
        public void attachToActivityForResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == AppCompatActivity.RESULT_OK) {
                switch (requestCode) {
                    case LQRPhotoSelectUtils.REQ_TAKE_PHOTO://拍照
                        mInputFile = new File(imgPath);
                        if (mShouldCrop) {//裁剪
                            mOutputFile = new File(generateImgePath());
                            mOutputUri = Uri.fromFile(mOutputFile);
                            zoomPhoto(mInputFile, mOutputFile);
                        } else {//不裁剪
                            mOutputUri = Uri.fromFile(mInputFile);
                            if (mListener != null) {
                                mListener.onFinish(mInputFile, mOutputUri);
                            }
                        }
                        break;
                    case LQRPhotoSelectUtils.REQ_SELECT_PHOTO://图库
                        if (data != null) {
                            Uri sourceUri = data.getData();
                            String[] proj = {MediaStore.Images.Media.DATA};
                            Cursor cursor = mActivity.managedQuery(sourceUri, proj, null, null, null);
                            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                            cursor.moveToFirst();
                            String imgPath = cursor.getString(columnIndex);
                            mInputFile = new File(imgPath);
    
                            if (mShouldCrop) {//裁剪
                                mOutputFile = new File(generateImgePath());
                                mOutputUri = Uri.fromFile(mOutputFile);
                                zoomPhoto(mInputFile, mOutputFile);
                            } else {//不裁剪
                                mOutputUri = Uri.fromFile(mInputFile);
                                if (mListener != null) {
                                    mListener.onFinish(mInputFile, mOutputUri);
                                }
                            }
                        }
                        break;
                    case LQRPhotoSelectUtils.REQ_ZOOM_PHOTO://裁剪
                        if (data != null) {
                            if (mOutputUri != null) {
                                //删除拍照的临时照片
                                File tmpFile = new File(imgPath);
                                if (tmpFile.exists())
                                    tmpFile.delete();
                                if (mListener != null) {
                                    mListener.onFinish(mOutputFile, mOutputUri);
                                }
                            }
                        }
                        break;
                }
            }
        }
    
        /**
         * 安卓7.0裁剪根据文件路径获取uri
         */
        private Uri getImageContentUri(Context context, File imageFile) {
            String filePath = imageFile.getAbsolutePath();
            Cursor cursor = context.getContentResolver().query(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    new String[]{MediaStore.Images.Media._ID},
                    MediaStore.Images.Media.DATA + "=? ",
                    new String[]{filePath}, null);
    
            if (cursor != null && cursor.moveToFirst()) {
                int id = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.MediaColumns._ID));
                Uri baseUri = Uri.parse("content://media/external/images/media");
                return Uri.withAppendedPath(baseUri, "" + id);
            } else {
                if (imageFile.exists()) {
                    ContentValues values = new ContentValues();
                    values.put(MediaStore.Images.Media.DATA, filePath);
                    return context.getContentResolver().insert(
                            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
                } else {
                    return null;
                }
            }
        }
    
        /**
         * 产生图片的路径,带文件夹和文件名,文件名为当前毫秒数
         */
        private String generateImgePath() {
            return getExternalStoragePath() + File.separator + String.valueOf(System.currentTimeMillis()) + ".jpg";
            //        return Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + String.valueOf(System.currentTimeMillis()) + ".jpg";//测试用
        }
    
    
        /**
         * 获取SD下的应用目录
         */
        private String getExternalStoragePath() {
            StringBuilder sb = new StringBuilder();
            sb.append(Environment.getExternalStorageDirectory().getAbsolutePath());
            sb.append(File.separator);
            String ROOT_DIR = "Android/data/" + mActivity.getPackageName();
            sb.append(ROOT_DIR);
            sb.append(File.separator);
            return sb.toString();
        }
    
        public interface PhotoSelectListener {
            void onFinish(File outputFile, Uri outputUri);
        }
    }
    LQRPhotoSelectUtils

    2.MainActivity

    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.appcompat.app.AppCompatActivity;
    import androidx.core.app.ActivityCompat;
    import androidx.core.content.ContextCompat;
    
    import android.Manifest;
    import android.app.Activity;
    import android.content.Intent;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.bumptech.glide.Glide;
    import com.example.camera.utils.LQRPhotoSelectUtils;
    import com.example.camera.utils.ToastUtil;
    
    import java.io.File;
    
    import kr.co.namee.permissiongen.PermissionGen;
    
    public class MainActivity extends AppCompatActivity {
    
        //定义控件
        private Button mBtnTakePhoto;
        private Button mBtnSelectPic;
        private Button mBtnFinish;
        private ImageView mIvPic;
        private TextView mTvPath;
        private TextView mTvUri;
    
        private static final int REQUEST_CODE = 0x001;
        private LQRPhotoSelectUtils mLqrPhotoSelectUtils;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //绑定控件
            mBtnTakePhoto = findViewById(R.id.btn_take_photo);
            mBtnSelectPic = findViewById(R.id.btn_select_pic);
            mTvPath = findViewById(R.id.tvPath);
            mTvUri = findViewById(R.id.tvUri);
            mIvPic = findViewById(R.id.iv_pic);
            mBtnFinish = findViewById(R.id.btn_finish);
    
            init();
            initListener();
        }
        private void init() {//初始化
            //创建LQRPhotoSelectUtils(一个Activity对应一个LQRPhotoSelectUtils)
            mLqrPhotoSelectUtils = new LQRPhotoSelectUtils(this, new LQRPhotoSelectUtils.PhotoSelectListener() {
                @Override
                public void onFinish(File outputFile, Uri outputUri) {
                    //当拍照或从图库选取图片成功后回调
                    mTvPath.setText(outputFile.getAbsolutePath());//显示图片路径
                    mTvUri.setText(outputUri.toString());//显示图片uri
                    //System.out.println(outputUri.toString());
                    Glide.with(MainActivity.this).load(outputUri).into(mIvPic);//使用Glide进行图片展示
                }
            }, true);//是否裁剪。true裁剪,false不裁剪
    
            //检查权限
            if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED||
                ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED||
                ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED){
                    ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA}, REQUEST_CODE);
            }else{
                ToastUtil.showMsg(MainActivity.this, "已经获得了所有权限");
            }
        }
    
        private void initListener(){//初始化监听器
            mBtnTakePhoto.setOnClickListener(new View.OnClickListener(){
                @Override
                public void onClick(View v) {
                    //获取权限,调用拍照方法
                    PermissionGen.with(MainActivity.this)
                            .addRequestCode(LQRPhotoSelectUtils.REQ_TAKE_PHOTO)
                            .permissions(Manifest.permission.READ_EXTERNAL_STORAGE,
                                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                                    Manifest.permission.CAMERA
                            ).request();
                    //拍照
                    mLqrPhotoSelectUtils.takePhoto();
                }
            });
    
            mBtnSelectPic.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    // 选择图片
                    mLqrPhotoSelectUtils.selectPhoto();
                }
            });
    
            mBtnFinish.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (mTvPath.getText().toString().equals("图片路径:")){
                        // 如果一张图片都没选
                        ToastUtil.showMsg(getApplicationContext(), "您还没有选择图片呢!");
                    }else{
                        ToastUtil.showMsg(getApplicationContext(), "选择图片成功:"+mTvPath.getText().toString());
                        Bundle bundle = new Bundle();
                        Intent intent = new Intent();
                        bundle.putString("uri", mTvUri.getText().toString());
                        intent.putExtras(bundle);
                        setResult(Activity.RESULT_OK, intent);
                        finish();
                    }
                }
            });
        }
    
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            if (requestCode == REQUEST_CODE) {
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    initListener();
                } else {
                    Toast.makeText(this, "您已拒绝授予权限", Toast.LENGTH_LONG).show();
                }
            }
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            //在Activity中的onActivityResult()方法里与LQRPhotoSelectUtils关联
            mLqrPhotoSelectUtils.attachToActivityForResult(requestCode, resultCode, data);
        }
    }

    3.xml界面

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
    
        <Button
            android:id="@+id/btn_take_photo"
            android:text="拍照"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
        <Button
            android:id="@+id/btn_select_pic"
            android:text="从图库中选取"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    
        <TextView
            android:id="@+id/tvPath"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:text="图片路径:"/>
    
        <TextView
            android:id="@+id/tvUri"
            android:layout_width="wrap_content"
            android:layout_height="50dp"
            android:text="图片Uri:"/>
        <ImageView
            android:id="@+id/iv_pic"
            app:srcCompat="@drawable/head_portrait"
            android:layout_width="300dp"
            android:layout_height="300dp"/>
    
        <Button
            android:id="@+id/btn_finish"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:text="完成"/>
    </LinearLayout>

    演示:

  • 相关阅读:
    go学习-环境安装1-WIN10如何安装wsl2
    go学习-环境安装2-wsl2安装docker
    go学习-使用swagger生成接口文档
    go学习-WSL安装gcc
    go学习-如何修改Docker0的IP地址的默认网段
    go学习-go-sqlmock数据库操作测试
    go学习-环境安装3-wsl安装golang
    java基础学习-Stream API
    go学习-gorm
    go学习-获取form表单提交数据
  • 原文地址:https://www.cnblogs.com/Arisf/p/14667525.html
Copyright © 2011-2022 走看看