[转载]歇一歇(1)文件的单个扫描 – One Kid Sky – 博客园.
终于能有闲暇来写些东西,就当是对前段时间工作的总结。
公司年前制定一个基于GPS定位的进销存数据上报的软件,大体上就是这么个东西,本人主要负责终端开发(Android手机)。开发周期3个月,包括过年。
首先看一个问题:
项目需求1:现场拍照上传,或者选择已有文件上传。就是类似于微博中发表带图片的微博是一个道理。
首先,从现有文件选择上传这个比较容易解决:
只需要发起一个Intent:
action:Intent.ACTION_GET_CONTENT
type:image/*
startActivityForResult(intent,code);//一定要使用此方法哦,接收返回值。
比较头痛的是调用系统相机并且拍照上传,原因是这个样子的,首先,调用系统相机,拍照确认并返回到主界面,图片正常显示到你规划的 ImageView中,这个时候,你突发奇想,通过选择已有文件的方式,也就是通过调用系统相册,或者什么文件浏览器来再次加载刚才新鲜出炉的图片到你的 ImageView时,这是你会发现,不管是相册还是文件管理器中都没有这张图片,图片失踪了?
按照以往的逻辑,当我们打开相机,按下开门,在没有任何“外因”的阻止下,照片理当应该存储在SDCard中或内部存储中,可是为什么通过调用系统相机 后拍的相片却怎么也通过相册看不到呢?但是当连接上电脑浏览手机中的文件时,你会发现刚才拍的相片就在那里,然后你重启手机,浏览相册,发现刚才拍照的相 片神奇的出现了,如果有同学遇到了相同的问题,那么恭喜你,看这篇文章就看对头了。
是这个样子的,Android原生的系统相机,在拍照的结束后还做了一件事情,就是“扫描”,他会发出一个广播,来通知硬件区扫描自己,说白了就是刷 新,用过电脑的同学都明白刷新是个什么概念,当你浏览电脑文件夹时,刷新后会显示刚才操作的结果,比如图标的变化等,从“面”上讲,这是一个相同的概念。 当然,“扫描”这件事,在Android系统初始化的时候也会执行,比如开机、重启,这就是为什么,当我重启手机后,相册就能显示这张照片的原因了,难道 说,每次为了能在相册中显示新拍的相片,都要重启手机吗???那老板还不K.O 我?
手动扫描:
但是调用系统相机就不一样了,刷新设备是要开发人员自己手动完成的(到目前为,我没有找到自动刷新的方式。。。)。
看以下代码:
1 private void doCamrea() { 2 Intent capturePic = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 3 String picPartName = makePicName(); 4 String fullFileName = CurrentParameter.PATH + picPartName; 5 // 因为有的手机在接收相机Intent返回的值data时,收不到,所以在这里发送一个uri,让其相机在内部进行一个本地存储的操作 6 if (CurrentUtils.isHasSdcard()) { 7 capturePic.putExtra(MediaStore.EXTRA_OUTPUT, 8 Uri.fromFile(new File(CurrentParameter.PATH, picPartName))); 9 // 将这一张相片的名字保存在共享文件中,让scan在扫描的时候,再从这个共享文件中获取此相片名 10 SharedPreferences sd = this.getSharedPreferences( 11 CurrentParameter.SHARED_FILE_NAME, 3); 12 Editor ed = sd.edit(); 13 ed.putString("fullName", fullFileName); 14 ed.commit(); 15 } 16 17 startActivityForResult(capturePic, CurrentParameter.CAPTURE_PIC); 18 }
上面只是一个调用启动系统相机意图的方法,并没有看到过关于“扫描”的,因为并不是在这里处理,这是一个 startActivityForResult,有经验的同学都知道是什么意思了吧,结果当然是要放到Activity的回调方法 onActivityResult(……)中去做啦,但以上代码有个关键之处,请看第10行,没错,我开了一个SharedPreferences(共享 文件),并且将刚才拍照的相片的:绝对路径+文件名 保存在了这个共享文件中。暂且记住这一点,我们往下看:
onActivityResult方法:
1 /** 2 * 接受返回结果,并做业务处理 3 */ 4 @Override 5 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 6 // TODO Auto-generated method stub 7 super.onActivityResult(requestCode, resultCode, data); 8 9 switch (requestCode) { 10 // 相册 11 case CurrentParameter.LOCAL_PIC: 12 if (resultCode != RESULT_OK || data == null) 13 return; 14 Uri thisUri = data.getData(); 15 Log.i("----SysLog", thisUri.toString()); 16 picPath = getPicPath(thisUri); 17 if (picPath != null) { 18 // 设置缩略图,大小为30px 19 previewBitmap = PictureUtils.getPreview(this, picPath, 20 CurrentParameter.PREVIEW_PX); 21 picPathMap.put(marker, picPath); 22 } 23 break; 24 // 相机 25 case CurrentParameter.CAPTURE_PIC: 26 if (resultCode == RESULT_OK || (Build.MODEL.toString().equals("D539") && resultCode == 0)/*酷派D539*/) { 27 // 刷新后,相册就能显示这张图片了。 28 SharedPreferences sd = PhotoMessageEditActivity.this 29 .getSharedPreferences( 30 CurrentParameter.SHARED_FILE_NAME, 3); 31 picPath = sd.getString("fullName", "is-fuck-null"); 32 CurrentUtils.scanOneFile(this,picPath); 33 34 previewBitmap = PictureUtils.getPreview(this, picPath, 35 CurrentParameter.PREVIEW_PX); 36 picPathMap.put(marker, picPath); 37 } 38 break; 39 . 40 . 41 . 42 .
没错,这段代码我只是为大家展示一部分,因为其他的都无关紧要。从24行开始,调用系统相机后并返回结果
26行,进行resultCode的判断,如果这个值是-1,说明你拍完照点击的是完成按钮,也就是说你“确定”要把这张图片保存并显示,|| 后面是对酷派D539的适配,比较变态人家用的是0~~~~,废话不多说接着看。
28行,开始从上面第一段代码创建的共享文件中取出当先相片的绝对名称,32行,调用scanOneFile方法,进行文件扫描。到此为止整个处理过程结束,那么最后一段代码,scanOneFile方法的是如何实现扫描的。
1 /** 2 * 扫描 3 * 4 * @param filePath 5 */ 6 public static void scanOneFile(Context context, String filePath) { 7 // TODO Auto-generated method stub 8 if (filePath != null && "is-fuck-null".equals(filePath)) 9 return; 10 Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); 11 Uri uri = Uri.parse("file://" + filePath); 12 intent.setData(uri); 13 context.sendBroadcast(intent); 14 15 }
接收的参数,第一个是context对象,对二个是这张图片的全路径名称,没错是发送一个广播,data为一个uri对象,通过这个uri对象,系统会精确扫描这一文件,让它无处可藏,原形毕露。
有的同学可能会问,为什么要用共享文件来存储文件名呢?第一段代码和第二段代码不是在一个类中吗?用一个全局变量不就可以了吗?这个问题留给你们自己去实验吧。
转载请标明出处,如果有更好的解决方式,希望大家共同探讨。