Android 调用系统相册、相机实现头像(图片)裁剪并选取的功能

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/erweidetaiyangxi/article/details/80538645

前段时间要做一个头像选取的功能,本来想使用第三方库,结果在其他的机型好好的,在小米的一个机型上直接崩溃了。
这果断的不能忍啊,咱们自己来实现调用系统相机、相册选取图片的功能,然后进行系统裁剪返回,结果发现刚出一坑又进
入一大坑,下面是填坑指南。
以下代码亲测在小米,华为,oppo等主流机型上兼容,并且兼容android 7.0的 FileProvider。

实现效果:

      

  


public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int ACTION_TYPE_PHOTO = 0;
    private final        int CAMERA            = 10;
    private final        int ALBUM             = 20;
    private final        int CUPREQUEST        = 50;
    private CircleImageView mCivMainHead;
    private PopupWindow     mPopupWindow;
    private String          picPath;
    private File            mOutImage;
    private Uri mImageUri;
private Uri uritempFile;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mCivMainHead = (CircleImageView) findViewById(R.id.civ_main_head);
        mCivMainHead.setOnClickListener(this);
        //申请权限
        MPermissions.requestPermissions(MainActivity.this,
                ACTION_TYPE_PHOTO,
                Manifest.permission.CAMERA,
                Manifest.permission.WRITE_EXTERNAL_STORAGE,
                Manifest.permission.READ_EXTERNAL_STORAGE);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.civ_main_head:
                initPhotoTypePop();
                break;
            default:
                break;
        }
    }

    /**
     * 初始化选择头像的pop
     */
    private void initPhotoTypePop() {
        mPopupWindow = showBotoomSmallWidthPopup(MainActivity.this,
                R.layout.popu_photo, mCivMainHead);
        View contentView = mPopupWindow.getContentView();
        final TextView mobile_phones = (TextView) contentView.findViewById(R.id.mobile_phones);
        final TextView local_photo = (TextView) contentView.findViewById(R.id.local_photo);
        final TextView cancel = (TextView) contentView.findViewById(R.id.cancel);
        mobile_phones.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setMobilePhones();
            }
        });

        local_photo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setLocalPhoto();

            }
        });

        cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mPopupWindow.dismiss();
            }
        });
    }

    /**
     * 相册
     */
    private void setLocalPhoto() {
        if (mPopupWindow != null && mPopupWindow.isShowing()) {
            mPopupWindow.dismiss();
        }
        Intent albumIntent = new Intent(Intent.ACTION_PICK, null);
        albumIntent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        startActivityForResult(albumIntent, ALBUM);
    }

    /**
     * 拍照
     */
    private void setMobilePhones() {
        if (mPopupWindow !=null && mPopupWindow.isShowing()){
            mPopupWindow.dismiss();
        }
        //获得项目缓存路径
        String sdPath = getExternalCacheDir().getPath();
        //根据时间随机生成图片名
        String photoName = new DateFormat().format("yyyyMMddhhmmss",
                Calendar.getInstance(Locale.CHINA)) + ".jpg";
        picPath = sdPath + "/" + photoName;
        mOutImage = new File(picPath);
        //如果是7.0以上 那么就把uir包装
        if (Build.VERSION.SDK_INT >= 24) {
            mImageUri = FileProvider.getUriForFile(MainActivity.this, "com.test.FileProvider", mOutImage);
        } else {
            //否则就用老系统的默认模式
            mImageUri = Uri.fromFile(mOutImage);
        }
        //启动相机
        Intent intent = new Intent();
        intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
        intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
        startActivityForResult(intent, CAMERA);
    }


    /**
     * 选择图片后的回调
     *
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) {
            return;
        }
        switch (requestCode) {

            // 裁剪相机照片
            case CAMERA:
                setCropPhoto();
                break;

            //裁剪本地相册
            case ALBUM:
                Uri data1 = data.getData();
                if (data1 != null) {
                    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
                        picPath = data1.toString();
                    } else {
                        picPath = data1.getPath();
                    }
                    // Uri --> Path
                    if (picPath.contains("content://")) {
                        picPath = PathContentUtils.getFilePathFromContentUri(data1, getContentResolver());
                    }
                    mOutImage = new File(picPath);
                    setCropPhoto();
                }
                break;

            //裁剪完成
            case CUPREQUEST:
                if (data == null) {
                    return;
                }
                Bundle extras = data.getExtras();
                 String s;
                    if (Build.MANUFACTURER.contains("Xiaomi")){
                        if (uritempFile !=null){
                            s = uritempFile.getPath();
                        }else {
                            s = "";
                        }
                    }else {
                        if (extras != null){
                            Bitmap photo = extras.getParcelable("data");
                            s = FileUtils.saveBitmap(photo);
                        }else {
                            s ="";
                        }
                    }
                    
                    if(!TextUtils.isEmpty(s)){
                    Bitmap bitmap = BitmapFactory.decodeFile(s);
                      mCivMainHead.setImageBitmap(photo);
                    }
                break;
            default:
                break;
        }
    }

    private void setCropPhoto() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //如果是7.0剪裁图片 同理 需要把uri包装
            //通过FileProvider创建一个content类型的Uri
            Uri inputUri = FileProvider.getUriForFile(MainActivity.this,
                    "com.test.FileProvider", mOutImage);
            startPhotoZoom(inputUri);//设置输入类型
        } else {
            Uri inputUri = Uri.fromFile(mOutImage);
            startPhotoZoom(inputUri);
        }
    }

    //裁剪
    private void startPhotoZoom(Uri uri) {
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.setDataAndType(uri, "image/*");
        //sdk>=24
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            //去除默认的人脸识别,否则和剪裁匡重叠
            intent.putExtra("noFaceDetection", false);
            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

        }
        // 设置裁剪
        intent.putExtra("crop", "true");
        // aspectX aspectY 宽高的比例
        //华为特殊处理 不然会显示圆
        if (android.os.Build.MODEL.contains("HUAWEI")) {
            intent.putExtra("aspectX", 9998);
            intent.putExtra("aspectY", 9999);
        } else {
            intent.putExtra("aspectX", 1);
            intent.putExtra("aspectY", 1);
        }
        // outputX outputY 是裁剪图片宽高
        intent.putExtra("outputX", 200);
        intent.putExtra("outputY", 200);
        //miui系统 特殊处理 return-data的方式只适用于小图。
        if (Build.MANUFACTURER.contains("Xiaomi")){
            //裁剪后的图片Uri路径,uritempFile为Uri类变量
            uritempFile = Uri.parse("file://" + "/" + Environment.getExternalStorageDirectory().getPath() + "/" + "tt.jpg");
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uritempFile);
        }else {
            intent.putExtra("return-data", true);
        }
        intent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
        startActivityForResult(intent, CUPREQUEST);
    }

    /**
     * 从底部弹出pop
     */
    public static PopupWindow showBotoomSmallWidthPopup(final Activity activity, int layoutId, View view) {
        View convertView = LayoutInflater.from(activity)
                .inflate(layoutId, null);
        PopupWindow popupWindow = new PopupWindow(convertView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        popupWindow.setAnimationStyle(R.style.popup_bottom_style);
        popupWindow.setOutsideTouchable(true);
        popupWindow.setFocusable(true);
        ColorDrawable cd = new ColorDrawable(000000);
        popupWindow.setBackgroundDrawable(cd);
        popupWindow.showAtLocation(view, Gravity.BOTTOM, 0, 0);
        setBackgroundAlpha(activity, 0.15f);

        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                setBackgroundAlpha(activity, 1.0f);
            }
        });

        return popupWindow;
    }

    /**
     * 弹出popwindow 周围变暗
     *
     * @param activity
     * @param alpha
     */
    public static void setBackgroundAlpha(Activity activity, float alpha) {
        WindowManager.LayoutParams lp = activity.getWindow()
                .getAttributes();
        lp.alpha = alpha;
        activity.getWindow()
                .setAttributes(lp);
    }
}

FileProvider 应该在清单文件里进行注册:

 <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.test.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/rc_file_path" />
        </provider>
    </application>

记得加上权限:

<uses-permission android:name="com.oppo.launcher.permission.READ_SETTINGS" />
<uses-permission android:name="com.oppo.launcher.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.CAMERA"/>	

推荐使用mpermission进行运行时权限管理,使用到的第三方库:

//运行时权限
compile 'com.zhy:mpermission-api:1.0.0'
//圆形头像
compile 'de.hdodenhof:circleimageview:2.1.0'


展开阅读全文

没有更多推荐了,返回首页