美文网首页简化开发
Android 调用相册获取图片和视频 (笔记)

Android 调用相册获取图片和视频 (笔记)

作者: xq9527 | 来源:发表于2021-10-12 11:56 被阅读0次

    前言:

    这个纯属笔记 如果你是做APP 可以用方便三方库来实现更好,废话不多说我们正式开始

    效果图:

    image.png

    布局代码:

    <?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"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".TestActivity">
        <Button
            android:id="@+id/getimg"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="上传图片"
            android:layout_marginTop="10dp"
            >
        </Button>
    
        <Button
            android:id="@+id/getvideo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="上传视频"
            android:layout_marginTop="10dp"
            >
        </Button>
        <ImageView
            android:id="@+id/test_img"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">
        </ImageView>
    </LinearLayout>
    

    布局预览

    image.png

    我们就写了2个button 分别来触发这个上传图片和上传视频的事件

    从相册中选择图片

         /**
         * 从相册中选择图片
         */
        private  void openPhoto(int openPhotoCode){
            Intent intent = new Intent(Intent.ACTION_PICK, null);
            intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
            startActivityForResult(intent, openPhotoCode);
        }
    
    

    从相册中选择视频

        /**
         * 从相册中选择视频
         */
        private void choiceVideo(int openVideoCode) {
            Intent i = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(i, openVideoCode);
        }
    

    我们封装2个方法分别打开相册获取视频和图片的

    //获取图片

      findViewById(R.id.getimg).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        int hasWritePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                        List<String> permissions = new ArrayList<String>();
                        if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
                            permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                        } else {
                            openPhoto(1);
                        }
                        if (!permissions.isEmpty()) {
                            ActivityCompat.requestPermissions((Activity) mContext, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                    REQUEST_PERMISSION);
                        }
                    }else {
                        openPhoto(1);
                    }
                }
            });
    

    // 获取视频

      findViewById(R.id.getvideo).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        int hasWritePermission = checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                        List<String> permissions = new ArrayList<String>();
                        if (hasWritePermission != PackageManager.PERMISSION_GRANTED) {
                            permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                        } else {
                            choiceVideo(6);
                        }
                        if (!permissions.isEmpty()) {
                            ActivityCompat.requestPermissions((Activity) mContext, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE},
                                    REQUEST_PERMISSION);
                        }
                    }else {
                        choiceVideo(6);
                    }
                }
            });
    

    获取图片和视频结果处理

    我们在 onActivityResult 方法里面来处理 我们分别写了 getphotoResult方法和getVideoFileResult 方法来处理视频结果图片结果

       protected void onActivityResult(int requestCode, int resultCode, Intent data){
            super.onActivityResult(requestCode, resultCode, data);
            if (requestCode >=1&&requestCode<=5) {
                // 从相册返回的数据
                if (data != null) {
                    getphotoResult(requestCode,resultCode,data);
                }
            }else if (requestCode>=6&&requestCode<=10 && resultCode == RESULT_OK && null != data) {
                getVideoFileResult(requestCode,resultCode,data);
            }
            if (resultCode != Activity.RESULT_OK) {
                return;
            }
        }
    

    图片结果处理

        //处理获取到的图片文件
        private void  getphotoResult(int requestCode, int resultCode, Intent data){
            // 得到图片的全路径
            if(requestCode==1){
                Uri uri = data.getData();
                Log.e(TAG, "onActivityResult:uri "+uri );
                testimage.setImageURI(uri);
                String imagePath = ImageUtils.getImagePath(uri, null, (Activity) mContext);
                Log.e(TAG, "onActivityResult:imagePath  "+imagePath);
                if(!TextUtils.isEmpty(imagePath)){
                    File file=new File(imagePath);
                }
            }
        }
    

    视频结果处理

       //处理获取到视频文件
        private void getVideoFileResult(int requestCode, int resultCode, Intent data){
            Uri selectedVideo = data.getData();
            String[] filePathColumn = {MediaStore.Video.Media.DATA};
            Cursor cursor = getContentResolver().query(selectedVideo,
                    filePathColumn, null, null, null);
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
            String  videopath = cursor.getString(columnIndex);
            Log.e(TAG, "onActivityResult:VIDEOPATH   --- > "+ videopath);
            Double size= FileSizeUtil.getFileOrFilesSize(videopath,3);
            Log.e(TAG, "onActivityResult:size  --- >  "+size);
            if(size<30.0){
                File viodefile=new File(videopath);
            }else{
                Toast.makeText(mContext,"视频大小不能超过30MB请调整大小",Toast.LENGTH_SHORT).show();
            }
            cursor.close();
        }
    

    图片 视频 URI 转换工具类

    package com.example.camerademo;
    import android.app.Activity;
    import android.database.Cursor;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.net.Uri;
    import android.provider.MediaStore;
    import android.widget.ImageView;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    /**
     *
     * 创建人:xuqing
     * 创建时间:2020年8月25日16:42:38
     * 类说明:图片加载类
     *
     */
    public class ImageUtils {
        //加载网络图片
        public   static  void showImage(final Activity context, final String url, final ImageView
                                           imageView){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    final Bitmap bitmap=getImageBitmap(url);
                    context.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            imageView.setImageBitmap(bitmap);
                        }
                    });
    
                }
            }).start();
        }
        //将图片URL地址转换成Bitmap
        public static Bitmap getImageBitmap(String url) {
            URL imgUrl = null;
            Bitmap bitmap = null;
            try {
                imgUrl = new URL(url);
                HttpURLConnection conn = (HttpURLConnection) imgUrl
                        .openConnection();
                conn.setDoInput(true);
                conn.connect();
                InputStream is = conn.getInputStream();
                bitmap = BitmapFactory.decodeStream(is);
                is.close();
            } catch (MalformedURLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bitmap;
        }
        // 将uri 转换成path路径
        public static String getImagePath(Uri uri, String selection, Activity activity) {
            String path = null;
            Cursor cursor = activity.getContentResolver().query(uri,
                    null, selection, null, null);
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                }
    
                cursor.close();
            }
            return path;
        }
    }
    

    文件大小工具检查工具类

     package com.example.camerademo;
    import android.util.Log;
    import java.io.File;
    import java.io.FileInputStream;
    import java.text.DecimalFormat;
    
    
    /**
     *
     * 创建人:xuqing
     * 创建时间:2021年8月27日15:30:02
     * 类说明:文件大小工具类
     *
     *
     */
    
    public class FileSizeUtil {
    
    
        private static final String TAG=FileSizeUtil.class.getSimpleName();
        public static final int SIZETYPE_B = 1;//获取文件大小单位为B的double值
        public static final int SIZETYPE_KB = 2;//获取文件大小单位为KB的double值
        public static final int SIZETYPE_MB = 3;//获取文件大小单位为MB的double值
        public static final int SIZETYPE_GB = 4;//获取文件大小单位为GB的double值
    
        /**
         * 获取文件指定文件的指定单位的大小
         *
         * @param filePath 文件路径
         * @param sizeType 获取大小的类型1为B、2为KB、3为MB、4为GB
         * @return double值的大小
         */
        public static double getFileOrFilesSize(String filePath, int sizeType) {
            File file = new File(filePath);
            long blockSize = 0;
            try {
                if (file.isDirectory()) {
                    blockSize = getFileSizes(file);
                } else {
                    blockSize = getFileSize(file);
                }
            } catch (Exception e) {
                e.printStackTrace();
                Log.e(TAG,"获取文件大小失败!");
            }
            return FormetFileSize(blockSize, sizeType);
        }
    
        /**
         * 调用此方法自动计算指定文件或指定文件夹的大小
         *
         * @param filePath 文件路径
         * @return 计算好的带B、KB、MB、GB的字符串
         */
        public static String getAutoFileOrFilesSize(String filePath) {
            File file = new File(filePath);
            long blockSize = 0;
            try {
                if (file.isDirectory()) {
                    blockSize = getFileSizes(file);
                } else {
                    blockSize = getFileSize(file);
                }
            } catch (Exception e) {
                e.printStackTrace();
                Log.e(TAG,"获取文件大小失败!");
            }
            return FormetFileSize(blockSize);
        }
    
        /**
         * 获取指定文件大小
         *
         * @param file
         * @return
         * @throws Exception
         */
        private static long getFileSize(File file) throws Exception {
            long size = 0;
            if (file.exists()) {
                FileInputStream fis = null;
                fis = new FileInputStream(file);
                size = fis.available();
            } else {
                file.createNewFile();
                Log.e(TAG,"获取文件大小不存在!");
            }
            return size;
        }
    
        /**
         * 获取指定文件夹
         *
         * @param f
         * @return
         * @throws Exception
         */
        private static long getFileSizes(File f) throws Exception {
            long size = 0;
            File flist[] = f.listFiles();
            for (int i = 0; i < flist.length; i++) {
                if (flist[i].isDirectory()) {
                    size = size + getFileSizes(flist[i]);
                } else {
                    size = size + getFileSize(flist[i]);
                }
            }
            return size;
        }
    
        /**
         * 转换文件大小
         *
         * @param fileS
         * @return
         */
        private static String FormetFileSize(long fileS) {
            DecimalFormat df = new DecimalFormat("#.00");
            String fileSizeString = "";
            String wrongSize = "0B";
            if (fileS == 0) {
                return wrongSize;
            }
            if (fileS < 1024) {
                fileSizeString = df.format((double) fileS) + "B";
            } else if (fileS < 1048576) {
                fileSizeString = df.format((double) fileS / 1024) + "KB";
            } else if (fileS < 1073741824) {
                fileSizeString = df.format((double) fileS / 1048576) + "MB";
            } else {
                fileSizeString = df.format((double) fileS / 1073741824) + "GB";
            }
            return fileSizeString;
        }
    
        /**
         * 转换文件大小,指定转换的类型
         *
         * @param fileS
         * @param sizeType
         * @return
         */
        private static double FormetFileSize(long fileS, int sizeType) {
            DecimalFormat df = new DecimalFormat("#.00");
            double fileSizeLong = 0;
            switch (sizeType) {
                case SIZETYPE_B:
                    fileSizeLong = Double.valueOf(df.format((double) fileS));
                    break;
                case SIZETYPE_KB:
                    fileSizeLong = Double.valueOf(df.format((double) fileS / 1024));
                    break;
                case SIZETYPE_MB:
                    fileSizeLong = Double.valueOf(df.format((double) fileS / 1048576));
                    break;
                case SIZETYPE_GB:
                    fileSizeLong = Double.valueOf(df.format((double) fileS / 1073741824));
                    break;
                default:
                    break;
            }
            return fileSizeLong;
        }
    }
    

    其他说明 :

    Android在4.4之后的版本(包括4.4)中,从相册中选取图片返回Uri进行了改动。所以我们无法通过该Uri来取得文件路径,从而解码图片,将其显示出来。

    在4.3或以下可以直接用Intent.ACTION_GET_CONTENT打开相册;在4.4或以上,官方建议用ACTION_OPEN_DOCUMENT打开相册
    
    • 4.4之前的版本

    在4.4之前的版本,返回的Uri如下:content://media/external/images/media/8302
    我们可以通过ContentResolver的查询方法来获取路径:

    Uri uri = "content://media/external/images/media/8302";
    String imagePath = getImagePath(uri, null);
    
    private String getImagePath(Uri uri, String selection) {
            String path = null;
            Cursor cursor = getContentResolver().query(uri, null, selection, null, null);
            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                }
    
                cursor.close();
            }
            return path;
        }
    

    代码分析,当我们通过uri得到了相册数据库图片的表,然后通过索引MediaStore.Images.Media.DATA获取所得行的"_data"列的值。这样我们就得到了具体的文件路径,可以通过创建输入流来获取相应的Bitmap,并进行显示。

    • 4.4之后的版本,包括4.4

    在4.4之后的,包括4.4的版本,返回的Uri有可能是以下的一种:

    private void handleImageOnKitKat(Intent data) {
            String imagePath = null;
            Uri uri = data.getData();
    
            if (DocumentsContract.isDocumentUri(this, uri)) {
                String docId = DocumentsContract.getDocumentId(uri);
                if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                    //Log.d(TAG, uri.toString());
                    String id = docId.split(":")[1];
                    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())) {
                    //Log.d(TAG, uri.toString());
                    Uri contentUri = ContentUris.withAppendedId(
                            Uri.parse("content://downloads/public_downloads"),
                            Long.valueOf(docId));
                    imagePath = getImagePath(contentUri, null);
                }
            } else if ("content".equalsIgnoreCase(uri.getScheme())) {
                //Log.d(TAG, "content: " + uri.toString());
                imagePath = getImagePath(uri, null);
            }
        }
    

    代码分析:

    判断步骤:
    1首先对Uri的authority进行判断。是document类型的Uri还是普通的media类型的Uri。
    由于document类型有两种:media和download类型,所以需要进一步判断。因为这里涉及Uri的id部分不同。
    2 如果是普通类型,那么和4.4之前的处理完全一样。可以直接通过Uri获取文件路径。
    3 如果是media类型的document Uri,我们首先通过DocumentsContract.getDocumentId(uri);获取到"image%3A8302"。然后通过String.split方法来获取真正的id。

    参考

    Android 4.4从图库选择图片,获取图片路径并裁剪
    Android-Uri To Path

    最后总结

    调用相册或者相机 获取手机内存里面视频或者图片文件 是比较常见的需求 ,因为是做手游SDK开发所以基本很少去看这些原生写法 所以就做个笔记记录下

    demo地址 :

    https://gitee.com/qiuyu123/uploadfiledemo

    相关文章

      网友评论

        本文标题:Android 调用相册获取图片和视频 (笔记)

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