我最近工作挺忙,距离上一次写博客转眼已经过了一个多月,每次学到和用到点新东西,其实都有分享的欲望,但奈何文笔太差,而一篇文章包括构思,排版,修改发布的时间最少要花费2个小时(这其中还不包括写完后未保存,突然关掉浏览器的惨剧…),但是今天不知怎么的突然头脑发热,决定把睡觉的2个小时用来写篇博客(请原谅我放荡不羁爱睡觉zZ...)。

  最近做的一个项目是为某企业做得一个门店拜访APP。需要用到拍照上传的功能。刚开始确定需求的时候,客户只要求实现拍照上传的功能,这个简单,直接调用系统的拍照不就行了,代码如下:

public void btnClick(View view){
if(view.getId()==R.id.kpi_btn_takePhoto){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent, 0);
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode== 0&&resultCode==RESULT_OK) {
Bundle extras = data.getExtras();
Bitmap b = (Bitmap) extras.get("data");
//TO DO 保存照片到sdcard和上传图片代码省略…
}
super.onActivityResult(requestCode, resultCode, data);
}

  上面的btnClick()方法是点击拍照按钮时触发的方法,而且基本满足了客户的需求,拿给客户一看,客户一看,恩,看着我一笑,顿觉满园菊花香。

  但变更需求注定是程序员的最大敌人,果然,第二天,客户就来电话了,说用你们APP拍的照片模糊,尺寸不够(别邪恶哦(⊙o⊙)…)…没办法,那就改呗,但上面的方法是不能再用了,因为上面的方法只能获取一个缩略图。要想通过拍照获取原图并进行压缩,我们就要用到下面这个方法了,请看:

                             
public void btnClick(View view){
  if(view.getId()==R.id.kpi_btn_takePhoto){
    Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
    mPhotoPath= Environment.getExternalStorageDirectory().getAbsolutePath()+”t.jpg”;
    mPhotoFile = new File(mPhotoPath);
    if (!mPhotoFile.exists()) {
      mPhotoFile.createNewFile();
    }
    intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mPhotoFile));
    startActivityForResult(intent,CAMERA_RESULT);
  }
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (requestCode== 0&&resultCode==RESULT_OK) {
    Bitmap bitmap = getSmallBitmap (mPhotoPath);
    //TO DO 保存照片到sdcard和上传图片代码省略…
  }
  super.onActivityResult(requestCode, resultCode, data);
}
public Bitmap getSmallBitmap(String filePath) {
  final BitmapFactory.Options options = new BitmapFactory.Options();
  options.inJustDecodeBounds = true;
  BitmapFactory.decodeFile(filePath, options);
  options.inSampleSize =calculateInSampleSize(options, 600, 800);
  options.inJustDecodeBounds = false;
  return BitmapFactory.decodeFile(filePath, options);
}

  其中,getSmallBitmap()方法主要是对原图进行了等比压缩,经过这样处理后,图像几乎没怎么失真,而且只有200多K,发给客户一看,客户又高兴了(我绝对不会说客户都有着一颗逗比的心…我也绝对不会去捡肥皂的,哼!)。

  虽然知道需求可能还会变,但这次等待的时间有点久了,这次是在项目快上线的时候问题来了,你说,很多程序员加班加点容易吗(满满的负能量)。。。

  回到几天前,因为上线前,客户那边也是要对APP进行测试几天的,于是公司就采购了几台不同型号的手机,但是没装存储卡就发过去了,但客户测试拍照功能的时候问题就来了,其实这也只能怪我们这边,机子自己都没测,就发给客户那边了。因为前面我们拍照设置的保存路径是放在sdcard卡里,没插sdcard,这样一来,拍照功能就不能用了,我们开始的想法是叫客户那边自己插个sdcard,但客户却一定要说这是一个bug(呵呵,我会说微信,毁图秀秀没sdcard都拍不了照吗?)。。。无奈,客户是干爹,不爽归不爽,为了钱还是得服务不是?既然手机没用外存储卡,那么我们应用程序只能通过去访问data/data/package name/下的目录啦,想到做到,那就开始动手呗。代码如下:

public void btnClick(View view) {
Intent intent = new ntent(MediaStore.ACTION_IMAGE_CAPTURE);
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
//有sdcard
mPhotoPath= Environment.getExternalStorageDirectory().getAbsolutePath()+”t.jpg”;
File file=new File(mPhotoPath);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new file));
}else{
//没有sdcard,只能获取缩略图
}
tartActivityForResult(intent, 0);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode== 0&&resultCode==RESULT_OK) {
Bitmap bitmap = getSmallBitmap (mPhotoPath);
//TO DO 保存照片到sdcard和上传图片代码省略…
}
super.onActivityResult(requestCode, resultCode, data);
}
public Bitmap getSmallBitmap(String filePath) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(filePath, options);
options.inSampleSize = calculateInSampleSize(options, 600, 800);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(filePath, options);
}

  弄完一测试,效果不错,有挂载存储卡就存储在存储卡上,没挂载存储卡就存应用中。于是,马上就将新版本发布到服务器上让客户自己下载去了,毕竟上线在即啊。但,毕竟未完待续…

  第二天,客户电话又来了,原来,我们前面拍照的图片是通过等比压缩来实现图片压缩的,因此不同的手机,压缩后照片像素就会不同,有600*800的,有1280*800,等等。但客户想要拍照后获取的是固定像素的照片,并且要求大小是150-200K,好吧,拿了工资还是得干活不是,百度,google一番,发现Bitmap 有个createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter)方法,可以获得一个固定像素大小的bitmap,bingo!第一个要求有解决方案了。至于压缩到固定范围,因为不同的手机,拍的照片所占大小肯定是不同的,但是他们都是可以不断压缩的呀,那我们写一个循环来不断压缩,直压缩到小于200K不就行了?ok,有了解决方案就好办事,10分钟后,结果如下:

public void btnClick(View view) {
Intent intent = new ntent(MediaStore.ACTION_IMAGE_CAPTURE);
String state = Environment.getExternalStorageState();
if (state.equals(Environment.MEDIA_MOUNTED)) {
//有sdcard
mPhotoPath= Environment.getExternalStorageDirectory().getAbsolutePath()+”t.jpg”;
File file=new File(mPhotoPath);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new file));
}else{
//没有sdcard,只能获取缩略图
}
tartActivityForResult(intent, 0);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if (requestCode== 0&&resultCode==RESULT_OK) {
Bitmap bitmap =Bitmap.createScaledBitmap(BitmapFactory.decodeFile(filePath), 600, 800, true);
int quality=98;
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);
while (baos.toByteArray().length / 1024 > 200) {
quality-= 1;// 每次都减少1
baos.reset();// 重置baos即清空baos
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, baos);// 这里压缩options%,把压缩后的数据存放到baos中 }
//TO DO 保存照片到sdcard和上传图片代码省略…
}
super.onActivityResult(requestCode, resultCode, data);
}

  ok,至此,拍照上传模块总算有了一个较为完美的解决方案,当然不可能是十全十美的,还是欢迎大家善意指正。

Android在有存储卡和无存储卡情况下拍照后固定尺寸和压缩大小的更多相关文章

  1. KVM虚拟机内无agent情况下的监控方法

    KVM虚拟机内无agent情况下的监控(ceilometer实现) 今天看到大家在群里讨论KVM虚拟机的监控问题,而且是要求VM内无agent情况下的监控.这方面确实没有深入研究,但尚有些openst ...

  2. 关于img标签浏览器自带的边框,清除边框的解决方式(即img[src=""] img无路径情况下,灰色边框去除解决方法)

    详解img[src=""] img无路径情况下,灰色边框去除解决方法 1.Js解决办法 <html> <head> <meta charset=&qu ...

  3. 迁移/home目录至新硬盘分区总结--无备份情况下

    搞了一天,终于成功迁移.由于一开始就没备份过程实在很曲折. 希望本篇对那些没有备份习惯的朋友们有所帮助. 准备工作: sudo vim /etc/fstab 在文件中加入: /dev/sdb8     ...

  4. Oracle 无备份情况下的恢复--临时文件/在线重做日志/ORA-00205

    13.5 恢复临时文件 临时文件没有也不应该备份.通过V$TEMPFILE可以找到所有的临时文件. 此类文件的损坏会造成需要使用临时表空间的命令执行失败,不至于造成实例崩溃或session中断.由于临 ...

  5. Oracle 无备份情况下的恢复--控制文件/数据文件

    13.3无备份恢复控制文件 没有备份恢复控制文件其实就是在nomount状态,create control创建一个新的控制文件. dba必须知道4个信息才能正确的创建:数据库名.在线日志路径及其大小. ...

  6. Oracle备份恢复之无备份情况下恢复undo表空间

    UNDO表空间存储着DML操作数据块的前镜像数据,在数据回滚,一致性读,闪回操作,实例恢复的时候都可能用到UNDO表空间中的数据.如果在生产过程中丢失或破坏了UNDO表空间,可能导致某些事务无法回滚, ...

  7. 无归档情况下使用BBED处理ORA-01113错误

    在丢失归档情况下,恢复时常会遇到ora-01113错误,以下实验模拟表空间offline,然后在丢失归档文件的情况下使用BBED修改文件头信息,最后恢复数据文件: 数据库版本: SQL> sel ...

  8. [Android自动化] 在 pip-9.0.1 版本情况下安装 uiautomator2 报错的解决办法

    1.在命令窗口中使用命令: pip install uiautomator2 时报 pip 版本过低,需要先升级 pip 版本,理论上会按照提示进行升级 pip 操作,但执行升级命令时到最后却还是报错 ...

  9. CentsOS7无网情况下安装mysql5.7

    1.需求就不用讲了,客户现场,政府环境,银行环境,大多是没网的,所以无网安装是很有必要的 mysql下载路径:https://dev.mysql.com/downloads/mysql/ 查看自己Li ...

随机推荐

  1. babel ---- presets字段设定转码规则

    presets字段设定转码规则,官方提供以下的规则集,你可以根据需要安装. # ES2015转码规则 $ npm install --save-dev babel-preset-es2015 # re ...

  2. HDU 5212 Code【莫比乌斯反演】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5212 题意: 给定序列,1≤i,j≤n,求gcd(a[i],a[j])∗(gcd(a[i],a[j] ...

  3. Codeforces 576D Flights for Regular Customers(矩阵加速DP)

    题目链接  Flights for Regular Customers 首先按照$d$的大小升序排序 然后分成$m$个时刻,每条路径一次处理过来. $can[i][j]$表示当前时刻$i$能否走到$j ...

  4. tomcat7.0.55配置单向和双向HTTPS连接(二)

    上一篇文章:tomcat7.0.55配置单向和双向HTTPS连接 只是简要的配置了一下HTTPS,还有许多问题没有解决,本篇来解决这些文件 首先按照这篇文章:Widows下利用OpenSSL生成证书来 ...

  5. 洛谷—— P1503 鬼子进村

    https://www.luogu.org/problemnew/show/P1503 题目背景 小卡正在新家的客厅中看电视.电视里正在播放放了千八百次依旧重播的<亮剑>,剧中李云龙带领的 ...

  6. CF623

    AIM Tech Round (Div. 1) <br > 这真是一套极好的题目啊.....虽然我不会做 <br > 代码戳这里 <br > A.Graph and ...

  7. java反射原理运用

    1.首先用Java反射机制的要做到的一个目的:我们都知道通过得到一个对象中的指定方法或者属性等,基于这个原理我们来做一个 通用的功能,让客户端可以通过传入的对象和一个标识去调用这个对象里自己想要的方法 ...

  8. spring版本不兼容JDK问题

    在实验书上Spring项目的时候出现一个问题,导入包和使用注释的时候eclipse出现报错. 导入包报错:The import org cannot be resolved 注释报错:componen ...

  9. java并发之hashmap

    在Java开发中经常会使用到hashmap,对于hashmap又了解多少,经常听到的一句话是hashmap是线程不安全的,那为什么是线程不安全的,如何才能保证线程安全,JDK又给我们提供了那些线程安全 ...

  10. spring springmvc js websocket 监听

    第一步:web.xml中支持异步.所有的filter及servlet <filter> <filter-name>characterEncoding</filter-na ...