调用系统相机拍照

拍照保存本地更新相册的2种方法 ,兼容4,5,6,7操作系统;
从相册获取照片以及路径;
动态申请权限;
bit64和bitmap相互转化

1.创建File的应用关系缓存目录,getExternalCacheDir() 通过他读取。
不存在sd卡的其他路径下,当6.0以上时需要动态申请拍照权限。此做法可以刚好避免申请权限,存放路径是/sdcard/Android/data/<package name>/cache

  private Uri uriForFile;
    private ImageView imag;


 private void initPhoto() {
        TextView takePhoto = findViewById(R.id.photo);
        imag = findViewById(R.id.image);
        takePhoto.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                long time = System.currentTimeMillis();
                SimpleDateFormat format = new SimpleDateFormat("MM-dd HH:mm:ss");
                Date d1 = new Date(time);
                String title = format.format(d1);

                File outputImage = new File(getExternalCacheDir(), title + ".png");//存放照片的照片,将他才能在手机SDk上的应用关联缓存目录
                try {
                    if (outputImage.exists()) {
                        outputImage.delete();
                    }
                    outputImage.createNewFile();
                    if (Build.VERSION.SDK_INT >= 24) {
                        uriForFile = FileProvider.getUriForFile(menuActivity.this, "com.example.stf.uri_one.fileprovider", outputImage); //此标红出7.0以后需要,特殊的文件共享
                    } else {
                        uriForFile = Uri.fromFile(outputImage);
                    }
                    Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");//隐士启动相机
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, uriForFile);
                    startActivityForResult(intent, 1);

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        });
    }

2.将照片显示出来并更新到相册

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        switch (requestCode) {
            case 1:
                if (resultCode == RESULT_OK) {
                    try {
//两种方式,一种直接去本地读取,生成bitmap显示出来,另一种是借助glide加载
//                        Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uriForFile));
//                        imag.setImageBitmap(bitmap);
//                        Log.i("stf", "--bitmap-2>" + getBitmap(bitmap) / 1024 + "-uriForFile->" + uriForFile);
                        Glide
                                .with(menuActivity.this)
                                .load(uriForFile)
                                .into(imag);
                   intoAlbum(uriForFile);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
                break;
            default:
                break;
        }

    }

补充:查看bitmap的在内存中的大小

public long getBitmap(Bitmap bitmap) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {    //API 19
            return bitmap.getAllocationByteCount();
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {//API 12
            return bitmap.getByteCount();
        }
        // 在低版本中用一行的字节x高度
        return bitmap.getRowBytes() * bitmap.getHeight();
    }

// 更新到相册

    private void intoXiangCe(Uri uriForFile) {
        File file = new File(uriForFile.getPath());
        Context mContext = menuActivity.this;
        try {
            MediaStore.Images.Media.insertImage(mContext.getContentResolver(), file.getAbsolutePath(), 
          file.getName(), null);//图片插入到系统图库
        } catch (Exception e) {
            e.printStackTrace();
        }
        mContext.sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.parse("file://" + 
     file.getAbsolutePath())));

    }

3 .7.0拍照特殊配置
在清单文件中声明:
provider

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

说明:name属性是固定值;android:authorities 属性值必须和刚才拍照时的一直;
另外需要添加 file_paths.xml文件。如下

QQ截图20180419160828.jpg

1)在res文件夹下建立xml文件夹
2)在xml文件夹建立file_paths.xml文件
3)编辑file_paths.xm文件

<?xml version = "1.0" encoding ="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="imgs"
        path="" />
<!--external-path 是制定Uri共享的,name属性是可以随便填写,path属性的值表示共享的具体路径,空表示将整个sdk进行共享,当然也可以只共享单独的路径-->
</paths>

为了兼容6.0以下更低的版本,固定的权限还是要加上

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

4.从相册里面获取照片和其路径

1)先动态获取权限

 private void initxiangce() {
        View viewById = findViewById(R.id.photos2);
        viewById.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (ContextCompat.checkSelfPermission(menuActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                    ActivityCompat.requestPermissions(menuActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
                } else {
                    openAlbm();
                }
            }
        });

  }

2)弹出申请权限的对话框并进行判断是否已经给权限了

@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {

        switch (requestCode) {
            case 1:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    openAlbm();
                } else {
                    Toast.makeText(menuActivity.this, "暂无权限", Toast.LENGTH_SHORT).show();
                }
                break;
            default:
                break;
        }

    }

3)进入相册

 private void openAlbm() {
        Intent intent = new Intent("android.intent.action.GET_CONTENT");
        intent.setType("image/*");
        startActivityForResult(intent, 2);
 }

4)选取照片后获取到path


 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        switch (requestCode) {
              case 2:
                if (resultCode == RESULT_OK) {
                    // 判断手机系统的版本号
                    if (Build.VERSION.SDK_INT >= 19) {
                        // 4.4系统以上使用这个方法处理照片
                        handleImageOnKitKat(data);
                    } else {
                        //4.4 一下系统使用这个方法处理照片
                        handleImageBeforeKitKat(data);
                    }
                }
                break;
            default:
                break;
        }
    }

4.4以上

 @TargetApi(Build.VERSION_CODES.KITKAT)
    private void handleImageOnKitKat(Intent data) {
        String imagePath = null;
        Uri uri = data.getData();
        Log.i("stf", "uri--->" + uri);
        if (DocumentsContract.isDocumentUri(this, uri)) {
            //documents 类型的uri ,则通过documment的id处理
            String docId = DocumentsContract.getDocumentId(uri);
            if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                String id = docId.split(":")[1];//解析出数字格式的id
                String selection = MediaStore.Images.Media._ID + "=" + id;
                imagePath = getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, selection);

            } else if ("com.android.providers.downsloads.documents".equals(uri.getAuthority())) {

                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downsloads/public_downloads"), Long.valueOf(docId));
                imagePath = getImagePath(contentUri, null);
            }
        } else if ("content".equalsIgnoreCase(uri.getScheme())) {
            //如果content类型uri ,使用普通方式处理
            imagePath = getImagePath(uri, null);

        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            //如果是file类型的uri,直接获取图片的路径即可
            imagePath = uri.getPath();
        }
        displayImage(imagePath);
    }

4.4以下

  private void handleImageBeforeKitKat(Intent data) {
        displayImage(getImagePath(data.getData(), null));
    }

辅助方法

根据uri取路径path

    private String getImagePath(Uri uri, String selection) {
        String path = null;
        //通过uri和selection 来获取真实图片的路劲
        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;
    }

根据路径设置bitmap

    private void displayImage(String imagePath) {
        if (imagePath != null) {
            Bitmap bitmap = BitmapFactory.decodeFile(imagePath);
            imag3.setImageBitmap(bitmap);
        } else {
            Toast.makeText(menuActivity.this, "照片路径不存在", Toast.LENGTH_SHORT).show();
        }
    }

压缩照片

public boolean compressImage(String path) {
        int height = 800;
        boolean res = false;
        Bitmap bmp = BitmapFactory.decodeFile(path);
        if (bmp != null) {
            int w = bmp.getWidth();
            int h = bmp.getHeight();
            if (height >= h) {
                bmp.recycle();
            } else {
                Bitmap resize = Bitmap.createScaledBitmap(bmp, w * height / h, height, false);
                bmp.recycle();

                try {
                    FileOutputStream out = new FileOutputStream(path);
                    if (resize.compress(Bitmap.CompressFormat.JPEG, 75, out)) {
                        out.flush();
                        out.close();
                        res = true;
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return res;
    }

对照片进行Base64加密

 public String getImageString(String path) {
        String res = null;
        try {
            File file = new File(path);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int count = 0;
            while ((count = fis.read(buffer)) >= 0) {
                baos.write(buffer, 0, count);
            }
//            res = new String(org.kobjects.base64.Base64.encode(baos.toByteArray()));
            res = new String(Base64.encode(baos.toByteArray(), Base64.DEFAULT));  //进行Base64编码
            baos.close();
            fis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

64位的流,转换为照片bitmap

  initSetImageWater(file);

 private void initSetImageWater(String str) {
        byte[] decode = Base64.decode(str, Base64.DEFAULT);
        Glide.with(mContext)
                .load(decode)
                .into(mImgWater);
        decode = null;

    }

清单文件中添加权限

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容