美文网首页首页投稿(暂停使用,暂停投稿)
安卓不同机型和API版本中拍照和相册选取照片功能实现

安卓不同机型和API版本中拍照和相册选取照片功能实现

作者: utf8_1436 | 来源:发表于2017-08-19 16:21 被阅读0次

    该demo针对不同机型和不同API进行功能实现,满足大部分手机拍照和相册选取照片功能实现。
    1使用知乎相册框架compile 'com.zhihu.android:matisse:0.4.3'进行图库相册选取
    2使用compile 'com.github.bumptech.glide:glide:3.7.0'框架(Glide)进行图片加载


    如下效果

    1点击选择图片按钮弹出popuwindow


    01.png

    2拍照:


    02.png

    3相册选取:


    03.png
    4选择的结果: 04.png

    SelectPicPopup的代码:

    package study.lzl.photoselectdemo;
    
    import android.content.Context;
    import android.graphics.drawable.BitmapDrawable;
    import android.os.Bundle;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.WindowManager;
    import android.webkit.WebView;
    import android.widget.Button;
    import android.widget.PopupWindow;
    
    /**
     * @author: Created by lzl on 2017/8/14.
     * @function:
     * @description:
     */
    
    public class SelectPicPopup implements View.OnClickListener {
        /**
         * UI
         */
        private PopupWindow mPopupWindow;
        private Button mCameraBtn;//相册
        private Button mPicBtn;//图库
        private Button mCancelBtn;//取消
        private Context mContext;//上下文环境对象
    
        private OnBtnClickListener click;
    
        public PopupWindow getmPopupWindow() {
            return mPopupWindow;
        }
    
        /**
         * 单参构造
         * @param mContext
         */
        public SelectPicPopup(Context mContext) {
            this.mContext = mContext;
            mPopupWindow=new PopupWindow(mContext);
            mPopupWindow.setBackgroundDrawable(new BitmapDrawable());
            mPopupWindow.setWidth(WindowManager.LayoutParams.MATCH_PARENT);//宽度充满父窗体
            mPopupWindow.setHeight(WindowManager.LayoutParams.WRAP_CONTENT);//高度包裹内容
            mPopupWindow.setTouchable(true);//设置可以被触摸
            mPopupWindow.setFocusable(true);//设置占据焦点
            mPopupWindow.setOutsideTouchable(true);//设置可以点击外部区域(点击外部区域将消失)
            mPopupWindow.setContentView(initView());
            mPopupWindow.setAnimationStyle(R.style.AnimBottom);//设置转场动画
            mPopupWindow.getContentView().setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    mPopupWindow.setFocusable(false);
                    dismiss();
                    return false;
                }
            });
        }
    
        private View initView() {
            View view= LayoutInflater.from(mContext).inflate(R.layout.layout_popup,null);
            mCameraBtn= (Button) view.findViewById(R.id.camera_btn);
            mCameraBtn.setOnClickListener(this);
    
            mPicBtn= (Button) view.findViewById(R.id.pic_btn);
            mPicBtn.setOnClickListener(this);
            mCancelBtn= (Button) view.findViewById(R.id.cancel_btn);
            mCancelBtn.setOnClickListener(this);
            return view;
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.camera_btn:
                    click.getFlag(0);
                    break;
                case R.id.pic_btn:
                    click.getFlag(1);
                    break;
                case R.id.cancel_btn:
                    dismiss();
                    break;
            }
        }
    
        protected void dismiss(){
            if (mPopupWindow!=null&&mPopupWindow.isShowing()){
                mPopupWindow.dismiss();
            }
        }
    
        /**
         *
         * @param rootView
         */
        protected void showPopup(View rootView){
            mPopupWindow.showAtLocation(rootView, Gravity.BOTTOM,0,0);
        }
    
        protected interface OnBtnClickListener{
            void getFlag(int flag);
        }
    
        protected void setOnBtnClick(OnBtnClickListener click){
            this.click=click;
        }
    }
    
    

    自定义的popuwindow使用的style如下:

    <!--popuwindow style-->
        <style name="AnimBottom" parent="@android:style/Animation">
            <item name="android:windowEnterAnimation">@anim/popup_alpha_out</item>
            <item name="android:windowExitAnimation">@anim/popup_alpha_in</item>
        </style>
    

    引用的两个anim文件:
    1anim/popup_alpha_out:

    <?xml version="1.0" encoding="utf-8"?>
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="300"
        android:fromAlpha="0.0"
        android:toAlpha="1.0"
        >
    
    </alpha>
    

    2anim/popup_alpha_in:

    <?xml version="1.0" encoding="utf-8"?>
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="300"
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        >
    
    </alpha>
    

    布局文件:layout_popup.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/half_transparent_black">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:layout_alignParentBottom="true"
            android:background="@color/page_bg_color">
            <Button
                android:id="@+id/camera_btn"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:background="#ffffff"
                android:text="拍照"
                android:textColor="#000"
                />
            <View
                android:layout_width="match_parent"
                android:layout_height="0.5dp"
                android:background="#65000000"/>
            <Button
                android:id="@+id/pic_btn"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:text="相册"
                android:textColor="#000"
                android:background="#ffffff"/>
            <Button
                android:id="@+id/cancel_btn"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:layout_marginTop="10dp"
                android:background="#ffffffff"
                android:textColor="#000"
                android:text="取消"/>
        </LinearLayout>
    </RelativeLayout>
    

    MainActivity的代码:

    package study.lzl.photoselectdemo;
    
    import android.content.ContentResolver;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.ActivityInfo;
    import android.content.pm.PackageManager;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.os.Build;
    import android.provider.MediaStore;
    import android.support.annotation.NonNull;
    import android.support.v4.content.ContextCompat;
    import android.support.v4.content.FileProvider;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    import com.zhihu.matisse.Matisse;
    import com.zhihu.matisse.MimeType;
    import com.zhihu.matisse.engine.impl.GlideEngine;
    
    import java.io.File;
    import java.util.List;
    
    /**
     * 演示图片选择来源,并将图片正确显示在控件上,该控件可以对图片进行手势操作:包括大小缩放和平移拖拽
     */
    public class MainActivity extends AppCompatActivity {
        private ImageView imageV;
        private Uri imageUrl;//照片地址uri对象
        private int destType = FileHelper.JPEG;
        private static final int REQUEST_CODE_TAKE_PIC_CAMERA = 100;//拍照请求码
    
        private static final int REQUEST_CODE_CHOOSE = 233;//图库选取照片请求码
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            initView();
        }
    
        private void initView() {
            imageV= (ImageView) findViewById(R.id.image);
            findViewById(R.id.select_btn).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    final SelectPicPopup popup=new SelectPicPopup(getApplicationContext());
                    popup.showPopup(findViewById(R.id.activity_main));
                    popup.setOnBtnClick(new SelectPicPopup.OnBtnClickListener() {
                        @Override
                        public void getFlag(int flag) {
                            if (flag==1){//相册
                                popup.dismiss();
                                selectPicFromGallery();
                            }else if (flag==0){//拍照
                                popup.dismiss();
                                if (hasPermission(PerMissionContants.HARDWEAR_CAMERA_PERMISSION)){
                                    openCamera();
                                }else {
                                    requestPermission(PerMissionContants.HARDWEAR_CAMERA_CODE,PerMissionContants.HARDWEAR_CAMERA_PERMISSION);
                                    Toast.makeText(getApplicationContext(),"权限:"+hasPermission(PerMissionContants.HARDWEAR_CAMERA_PERMISSION),Toast.LENGTH_SHORT).show();
                                }
                            }
                        }
                    });
                }
            });
        }
    
        /**
         * 打开相册进行拍照
         */
        private void openCamera() {
            Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            //创建一个临时文件夹存储拍摄的照片
            File file = FileHelper.createFileByType(getApplicationContext(), destType, System.currentTimeMillis()+"");
            imageUrl=Uri.fromFile(file);//解析出uri对象
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//版本过高的拍照路径
                Log.e("进入1","进入1");
                file = new File(getApplicationContext().getCacheDir(), System.currentTimeMillis()+".jpg");
                imageUrl = Uri.fromFile(file);
    
                Toast.makeText(getApplicationContext(), "TODO", Toast.LENGTH_SHORT).show();
                // 将文件转换成content://Uri的形式
                Uri contentUri = FileProvider.getUriForFile(getApplicationContext(), getPackageName() + ".provider", file);
                // 申请临时访问权限
                takePictureIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);
    
            } else {
                Log.e("进入2","进入2");
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUrl);
            }
    
    
            if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
                Log.e("进入3","进入3");
                startActivityForResult(takePictureIntent, REQUEST_CODE_TAKE_PIC_CAMERA);
            }
        }
    
        /**
         * 打开相册选取照片
         */
        private void selectPicFromGallery() {
            Matisse.from(MainActivity.this)
                    .choose(MimeType.allOf())
                    .countable(true)
                    .spanCount(4)
                    .maxSelectable(1)
                    .restrictOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED)
                    .thumbnailScale(0.85f)
                    .imageEngine(new GlideEngine())
                    .forResult(REQUEST_CODE_CHOOSE);
        }
    
        /**
         * 发起权限请求
         */
        private void requestPermission(int code,String...permissions){
            if (Build.VERSION.SDK_INT>=23){//判断是否大于6.0版本(当前手机的安卓系统是否是6.0或以上)
                requestPermissions(permissions,code);
            }
        }
    
        /**
         * 校验权限是否通过(安卓6.0以上的动态权限需要调用该方法)
         * @param permissions
         * @return
         */
        private boolean hasPermission(String...permissions){
            for (String permission:permissions) {
                if (ContextCompat.checkSelfPermission(getApplicationContext(),permission)!= PackageManager.PERMISSION_GRANTED){
                    return false;
                }
            }
            return true;
        }
    
        /**
         * 权限请求回调结果处理
         * @param requestCode
         * @param permissions
         * @param grantResults
         */
        @Override
        public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (requestCode==PerMissionContants.HARDWEAR_CAMERA_CODE){//拍照权限
                if (grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
                    Toast.makeText(getApplicationContext(),"权限请求结果",Toast.LENGTH_SHORT).show();
                    openCamera();
                }
    
            }
        }
    
        @Override
        protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode==REQUEST_CODE_TAKE_PIC_CAMERA&&resultCode==RESULT_OK){//拍照请求回调成功
                if (imageUrl!=null){
                    //根据uri获取图片的真实路径
                    String path=getRealFilePath(getApplicationContext(),imageUrl);
                    Bitmap bitmap=BitmapFactory.decodeFile(path);//根据图片的路径字符串解析成bitmap
                    imageV.setImageBitmap(bitmap);
                }
            }else if (requestCode==REQUEST_CODE_CHOOSE&&resultCode==RESULT_OK){
                List<Uri> uriList=Matisse.obtainResult(data);
                if (uriList.size()==1){
                    String path=getRealFilePath(getApplicationContext(),uriList.get(0));
                    Bitmap bitmap=BitmapFactory.decodeFile(path);//根据图片的路径字符串解析成bitmap
                    imageV.setImageBitmap(bitmap);
                }
            }
        }
    
        /**
         * 该方法根据图片uri得出其真实路径
         * @param context 上下文
         * @param uri 图片对应的uri对象
         * @return 图片的真实路径字符串
         */
        public String getRealFilePath(final Context context, final Uri uri) {
            if (null == uri) return null;
            final String scheme = uri.getScheme();
            String data = null;
            if (scheme == null)
                data = uri.getPath();
            else if (ContentResolver.SCHEME_FILE.equals(scheme)) {
                data = uri.getPath();
            } else if (ContentResolver.SCHEME_CONTENT.equals(scheme)) {
                Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
                if (null != cursor) {
                    if (cursor.moveToFirst()) {
                        int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                        if (index > -1) {
                            data = cursor.getString(index);
                        }
                    }
                    cursor.close();
                }
            }
            return data;
        }
    }
    
    

    布局文件:activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="study.lzl.photoselectdemo.MainActivity">
    
        <Button
            android:id="@+id/select_btn"
            android:background="@color/colorAccent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="选择照片"
            android:textColor="@color/colorPrimary"/>
    
        <ImageView
            android:id="@+id/image"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:layout_centerInParent="true"/>
    
    </RelativeLayout>
    
    

    动态权限常量类:PerMissionContants

    package study.lzl.photoselectdemo;
    
    import android.Manifest;
    
    /**
     * @author: Created by lzl on 2017/8/15.
     * @function:
     * @description:
     */
    
    public class PerMissionContants {
        /**
         * 拍照权限码
         */
        public static final int HARDWEAR_CAMERA_CODE=0x01;
        /**
         * 拍照用到的权限字符串数组:1打开数组的权限  2文件的写入权限(拍照要缓存) 3所拍照片的获取(从本地缓存或者相册中获取)
         */
        public static final String[] HARDWEAR_CAMERA_PERMISSION=new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE};
    }
    
    

    文件操作助手类:FileHelper

    package study.lzl.photoselectdemo;
    
    import android.content.Context;
    import android.net.Uri;
    import android.os.Environment;
    import android.text.TextUtils;
    
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * Created by rookie on 2017/2/28.
     */
    
    public class FileHelper {
        public static final int JPEG = 1;
        static final int PNG = 0;
    
    
        /**
         * 返回系统缓存路径
         *
         * @param mContext
         * @return
         */
        public static String getTempDirectoryPath(Context mContext) {
            File cachePath;
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                cachePath = mContext.getExternalCacheDir();
            } else {
                cachePath = mContext.getCacheDir();
            }
            cachePath.mkdirs();
            return cachePath.getAbsolutePath();
        }
    
        /**
         * 在系统缓存中创建一个文件
         *
         * @param mContext
         * @param type
         * @param name
         * @return
         */
        public static File createFileByType(Context mContext, int type, String name) {
            if (TextUtils.isEmpty(name)) {
                name = ".pic";
            }
    
            switch (type) {
                case JPEG:
                    name = name + ".jpg";
                    break;
                case PNG:
                    name = name + ".png";
                    break;
                default:
                    break;
    
            }
            return new File(getTempDirectoryPath(mContext), name);
    
        }
    
        /**
         * Removes the "file://" prefix from the given URI string, if applicable.
         * If the given URI string doesn't have a "file://" prefix, it is returned unchanged.
         *
         * @param uriString the URI string to operate on
         * @return a path without the "file://" prefix
         */
        public static String stripFileProtocol(String uriString) {
            if (uriString.startsWith("file://")) {
                uriString = uriString.substring(7);
            }
            return uriString;
        }
    
        public static String getPicutresPath(int encodingType) {
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
            String imageFileName = "IMG_" + timeStamp + (encodingType == JPEG ? ".jpg" : ".png");
            File storageDir = Environment.getExternalStoragePublicDirectory(
                    Environment.DIRECTORY_DCIM);
            String galleryPath = storageDir.getAbsolutePath() + File.separator + "Camera" + File.separator + imageFileName;
            return galleryPath;
        }
    
        public static boolean copyResultToGalley(Context context, Uri originUri, Uri galleryUri) {
            boolean result = false;
            InputStream inputStream = null;
            OutputStream outputStream = null;
    
            try {
                inputStream = context.getContentResolver().openInputStream(originUri);
                outputStream = context.getContentResolver().openOutputStream(galleryUri);
    
                byte[] buffer = new byte[2048];
    
                int len;
                while ((len = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
                outputStream.flush();
                result = true;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                if (outputStream != null) {
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return result;
        }
    }
    
    ***
    
    

    注意事项:
    1在app.gradle配置文件中配置使用到的两个框架:

    dependencies {
        compile fileTree(dir: 'libs', include: ['*.jar'])
        androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
            exclude group: 'com.android.support', module: 'support-annotations'
        })
        compile 'com.android.support:appcompat-v7:25.3.1'
        testCompile 'junit:junit:4.12'
        //项目中需要用到的第三方框架
        compile 'com.zhihu.android:matisse:0.4.3'
        compile 'com.github.bumptech.glide:glide:3.7.0'
    }
    

    2安卓6.0以上版本使用的是动态权限管理:因此增加一个类进行权限的申请处理:PerMissionContants

    相关文章

      网友评论

        本文标题:安卓不同机型和API版本中拍照和相册选取照片功能实现

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