拍照问题一览

很多APP 都有拍照的需求 但是用户一旦多起来 问题也会比较多 因为拍照会一并跟着压缩 上传甚至会有加水印 兼容问题也随之而来

这里从头到尾讲一下,看看能不能帮到大家:

1 第一个问题是权限问题 毕竟没有权限是没办法做后面的操作的

RxPermissions.getInstance(this)
                .request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)
                .subscribe(new Action1() {
                    @Override
                    public void call(Boolean granted) {
                        if (!granted) {
                            showToast("请把相机和存储权限打开");
                            return;
                        }
                        File sd = Environment.getExternalStorageDirectory();
                        String path = sd.getPath() + "/RxjavaImg"; // 在根目录创建一个文件夹来存放图片  可以自己创建
                        File file = new File(path);
                        if (!file.exists()) {
                            file.mkdir();
                        }
                        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);//打开摄像机列表选项
                        intent.putExtra("return-data", false);
                        final Intent intent_camera = getPackageManager().getLaunchIntentForPackage("com.android.camera");
                        if (intent_camera != null) {
                            String s = GetAction_image_capture();
                            int index = s.indexOf("com");
                            if (index == -1) {    //不存在的话  有一些手机 这个会有异常情况  如果没有这个需求的话 可以把setPackage这段注释掉 不影响使用
                                intent.setPackage("com.android.camera");  // 设置为手机自带的默认拍照软件
                            } else {
                                intent.setPackage(s);  // 有些手机 并不是com.android.camera 相对比较奇特 所以我用了一个判断前缀应用包名com开头的区分一下
                            }
                        }
                        intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(AppConfig.CAMERA_TEMP)));  // 里面的AppConfig.CAMERA_TEMP 为保存的文件路径 最后是.jpg的
                        startActivityForResult(intent, CAMERA);

                    }
                });

这里的操作包括了权限的请求 和最开始的拍照请求 最终图片保存到对应的目录

2 第二个问题就是拍照完后的回调

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

               if (requestCode == CAMERA && resultCode == RESULT_OK) {
                  showLoadingDialog("加载中....");
                    /**
                     *  在这里进行回调  有大佬让我全部操作都写一个Rxjava里面 现在还在琢磨
                     * 这里取到用户拍完照的图片  然后进行压缩 显示
                     * getCompressPics()是 核心方法 下面会有写  AppConfig.CAMERA_TEMP是原图路径
                     * */
                          getCompressPics(AppConfig.CAMERA_TEMP);
                  } 

}

3 第三个 这里应该是核心问题了 图片压缩 打水印 和最后的回传

    public void getCompressPics(final String pathString) {
        File file = new File(pathString);
        final String paths[] = new String[2];
        LubanText.get(PhotoBaseActivity3.this)
                .load(file)
                .putGear(LubanText.THIRD_GEAR)/** 兼容性最好*/
                        .asObservable()
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .map(new Func1() {
                    @Override
                    public File call(File file) {
                        /**加水印  这里传的是 文件地址   操作的 都是一样的东西*/
                        return Watermark(file.getPath(), 80);
                    }
                })
                .subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .unsubscribeOn(Schedulers.io())
                .doOnError(new Action1() {
                    @Override
                    public void call(Throwable throwable) {
                        throwable.printStackTrace();
                    }
                })
                .onErrorResumeNext(new Func1>() {
                    @Override
                    public Observable call(Throwable throwable) {
//                        Toast.makeText(mContext, "由于没有读写权限导致无法正常压缩", Toast.LENGTH_SHORT).show();

                        dismissLoadingDialog(); //取消加载框  不写的话 注释掉就可以了
//                        String s = "/storage/emulated/0/RxjavaImg/image/2017-07-19/1500447991691.jpg";
                                onReceiveCamera1(AppConfig.CAMERA_TEMP);  // onReceiveCamera1()这个方法是一个回调 把 图片路径返回 回去
                             return Observable.empty();
                    }
                })
                .subscribe(new Action1() {
                    @Override
                    public void call(File file) {
                        LogUtil.e("msg", "file:" + file);
                        LogUtil.e("msg", file.length() / 1024 + "k");
                        LogUtil.e("msg", 
               
                        pach = file + "";
                        /**处理完之后回调回去  返回给对应的类*/
                          dismissLoadingDialog();  //取消加载框  不写的话 注释掉就可以了
                         onReceiveCamera1(pach);  // onReceiveCamera1()这个方法是一个回调 把 图片路径返回 回去
                    }
                });
    }

回调之后 要干嘛就干嘛了 下面是支持的方法 还有最重要的水印

4 第四个 水印


 /***
     * 打水印的方法
     * 三次修改版
     * 1 就是先缩放读取原图,
     * 2 然后加水印,
     * 3 再生成新的图片文件
     */
    private File Watermark(String filePath, int Ratio) {

        /**
         * 最终保存的图片尺寸
         * 宽度  高度  压缩率
         * 宽高并不会固定为输入尺寸 只是参考
         * 压缩率直接影响 文件大小
         * 有问题 直接修改这里的数值!!
         * .putGear(LubanText.CUSTOM_GEAR) 这里也有影响
         *  */
        int Width = 720;
        int Height = 1280;
        int ratio = Ratio;

        /**保存的图片名称  记得要创建一下   最终提交的图片  */
        String PathName = AppConfig.APP_IMAGE_FOLDER + System.currentTimeMillis() + ".jpg";


        File preFile = new File(PathName);
        try {
            /** 创建一下*/
            if (!preFile.exists()) {
                preFile.createNewFile();
            }
            /** 缩放并读取图片文件    质量问题 直接调后面两个长宽度  按照等比 缩放的 所以没问题* */
            Bitmap resizedBitmap = BitmapUtilsText.getZoomImage(filePath, Width, Height);

//  ImageTool.generatorContactCountIcon 这个是打水印的方法 百度一下 挺多的 

            if (true || true) {
                LogUtil.e("msg", "打水印" + PathName);
           isHasWaterMark1 = "2017年12月31日11.11.11";
           s = "广州市天河区超级超级美女店!";
                resizedBitmap = ImageTool.generatorContactCountIcon(resizedBitmap, this, isHasWaterMark1, s);
            }

            /**保存操作 这里放的是新地址*/
            BufferedOutputStream bos2;
            bos2 = new BufferedOutputStream(new FileOutputStream(preFile));
            resizedBitmap.compress(Bitmap.CompressFormat.JPEG, ratio, bos2);

            LogUtil.e("msg", "file:getWidth" + resizedBitmap.getWidth());
            LogUtil.e("msg", "file:getHeight" + resizedBitmap.getHeight());
            LogUtil.e("msg", "拍照后保存的图片文件大小" + preFile.length() / 1024 + "kb");

            resizedBitmap.recycle();
            resizedBitmap = null;
            bos2.flush();
            bos2.close();

        } catch (Exception e) {
            LogUtil.e("msg", "添加水印出现异常");
            e.printStackTrace();
        }

        return preFile;
    }

5 第5个 支撑上面运行的方法

 //获取手机内部原生的应用相机包名
    private String GetAction_image_capture() {
        String Action_image_capture = "";
        Intent infoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        ResolveInfo resolveInfo = getPackageManager().resolveActivity(infoIntent, 0);
        if (resolveInfo != null) {
            Log.d("PhotoBaseActivity3", "手机默认相机名称为" + resolveInfo.activityInfo.packageName);
            Action_image_capture = resolveInfo.activityInfo.packageName;
        }
        return Action_image_capture;
    }

    /**
     * 接收到相机拍照的图片
     */
    protected abstract void onReceiveCamera1(String path);
 不知道还有没有遗漏 也就仅供参考罢了  亲自测试了 华为 小米 oppo vivo 努比亚 索尼  乐视 等等几十台手机,还在提高兼容度 有不对的地方 希望大家指出  最后 感谢  浪浪大佬的耐心指导  非常感谢!

你可能感兴趣的:(拍照问题一览)