美文网首页
调用系统相机拍照

调用系统相机拍照

作者: 火星局 | 来源:发表于2018-04-19 16:21 被阅读0次

拍照保存本地更新相册的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" />

相关文章

网友评论

      本文标题:调用系统相机拍照

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