Android ACTION_IMAGE_CAPTURE意图

人生难得几回搏,此时不搏待何时。这篇文章主要讲述Android ACTION_IMAGE_CAPTURE意图相关的知识,希望能为你提供帮助。
我们正在尝试使用原生相机应用程序让用户拍摄新照片。如果我们省略EXTRA_OUTPUT extra并返回小的Bitmap图像,它的工作正常。但是,如果我们在开始之前对其意图进行了putExtra(EXTRA_OUTPUT,...),那么一切都会有效,直到您尝试点击相机应用中的“确定”按钮。 “确定”按钮无效。相机应用程序保持打开状态,没有任何锁定。我们可以取消它,但文件永远不会被写入。我们到底要做些什么才能让ACTION_IMAGE_CAPTURE将拍摄的照片写入文件?
编辑:这是通过MediaStore.ACTION_IMAGE_CAPTURE意图完成的,只是为了清楚
答案【Android ACTION_IMAGE_CAPTURE意图】这是一些版本的android中的well documented bug。也就是说,在google体验构建的android上,图像捕获不能像记录的那样工作。在公用事业类中,我通常使用的是这样的东西。

public boolean hasImageCaptureBug() {// list of known devices that have the bug ArrayList< String> devices = new ArrayList< String> (); devices.add("android-devphone1/dream_devphone/dream"); devices.add("generic/sdk/generic"); devices.add("vodafone/vfpioneer/sapphire"); devices.add("tmobile/kila/dream"); devices.add("verizon/voles/sholes"); devices.add("google_ion/google_ion/sapphire"); return devices.contains(android.os.Build.BRAND + "/" + android.os.Build.PRODUCT + "/" + android.os.Build.DEVICE); }

然后当我启动图像捕获时,我创建一个检查错误的意图。
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); if (hasImageCaptureBug()) { i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp"))); } else { i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); } startActivityForResult(i, mRequestCode);

然后在我返回的活动中,我根据设备做不同的事情。
protected void onActivityResult(int requestCode, int resultCode, Intent intent) { switch (requestCode) { case GlobalConstants.IMAGE_CAPTURE: Uri u; if (hasImageCaptureBug()) { File fi = new File("/sdcard/tmp"); try { u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null)); if (!fi.delete()) { Log.i("logMarker", "Failed to delete " + fi); } } catch (FileNotFoundException e) { e.printStackTrace(); } } else { u = intent.getData(); } }

这可以节省你必须编写一个新的相机应用程序,但这个代码也不是很好。最大的问题是
  1. 你永远不会从有bug的设备上获得全尺寸的图像。您将获得插入图像内容提供程序的512px宽的图片。在没有bug的设备上,一切都作为文档工作,你得到一个很大的正常图片。
  2. 你必须保持清单。如上所述,设备可以使用安装了错误的android版本(例如cyanogenmod's builds)进行闪存。如果发生这种情况,您的代码将崩溃。修复是使用整个设备指纹。
另一答案使用Activity Result Code解决这个问题非常简单。试试这个方法
Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); File outFile = getFileStreamPath(Config.IMAGE_FILENAME); outFile.createNewFile(); outFile.setWritable(true, false); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT,Uri.fromFile(outFile)); startActivityForResult(intent, 2);

另一答案我创建了一个简单的库,它将管理从不同来源(图库,相机)选择图像,可能将其保存到某个位置(SD卡或内部存储器)并返回图像,所以请自由使用它并改进它 -if (reqCode == RECORD_VIDEO) { if(resCode == RESULT_OK) { if (uri != null) { compress(); } } else if(resCode == RESULT_CANCELED & & data!=null){ Toast.makeText(MainActivity.this,"No Video Recorded",Toast.LENGTH_SHORT).show(); } }
另一答案Android-ImageChooser指出,该文件需要由相机写入。
在我的使用中,我想将文件存储在内部存储中。我这样做:
Praveen

这里Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (i.resolveActivity(getPackageManager()!=null)){ try{ cacheFile = createTempFile("img",".jpg",getCacheDir()); cacheFile.setWritavle(true,false); }catch(IOException e){} if(cacheFile != null){ i.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(cacheFile)); startActivityForResult(i,REQUEST_IMAGE_CAPTURE); } } 是一个全局文件,用于指代写入的文件。然后在结果方法中返回的intent为null。然后处理意图的方法如下:
cacheFile

这里protected void onActivityResult(int requestCode,int resultCode,Intent data){ if(requestCode != RESULT_OK){ return; } if(requestCode == REQUEST_IMAGE_CAPTURE){ try{ File output = getImageFile(); if(output != null & & cacheFile != null){ copyFile(cacheFile,output); //Process image file stored at outputcacheFile.delete(); cacheFile=null; } }catch(IOException e){} } } 是一个实用程序方法,用于命名和创建应存储图像的文件,getImageFile()是一种复制文件的方法。
另一答案您可以使用此代码
copyFile()

另一答案
private Intent getCameraIntent() {PackageManager packageManager = mContext.getPackageManager(); List< ApplicationInfo> list = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES); Intent main = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); List< ResolveInfo> launchables = packageManager.queryIntentActivities(main, 0); if (launchables.size() == 1) return packageManager.getLaunchIntentForPackage(launchables.get(0).activityInfo.packageName); else for (int n = 0; n < list.size(); n++) { if ((list.get(n).flags & ApplicationInfo.FLAG_SYSTEM) == 1) { Log.d("TAG", "Installed Applications: " + list.get(n).loadLabel(packageManager).toString()); Log.d("TAG", "package name: " + list.get(n).packageName); String defaultCameraPackage = list.get(n).packageName; if (launchables.size() > 1) for (int i = 0; i < launchables.size(); i++) { if (defaultCameraPackage.equals(launchables.get(i).activityInfo.packageName)) { return packageManager.getLaunchIntentForPackage(defaultCameraPackage); } } } } return null; }

另一答案我知道这已经得到了回答,但我知道很多人都对此感到懊恼,所以我要添加评论。
我在Nexus One上遇到了同样的问题。这是来自相机应用程序启动前磁盘上不存在的文件。因此,我确保在启动相机应用程序之前存在该文件。这是我使用的一些示例代码:
String storageState = Environment.getExternalStorageState(); if(storageState.equals(Environment.MEDIA_MOUNTED)) {String path = Environment.getExternalStorageDirectory().getName() + File.separatorChar + "Android/data/" + MainActivity.this.getPackageName() + "/files/" + md5(upc) + ".jpg"; _photoFile = new File(path); try { if(_photoFile.exists() == false) { _photoFile.getParentFile().mkdirs(); _photoFile.createNewFile(); }} catch (IOException e) { Log.e(TAG, "Could not create file.", e); } Log.i(TAG, path); _fileUri = Uri.fromFile(_photoFile); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE ); intent.putExtra( MediaStore.EXTRA_OUTPUT, _fileUri); startActivityForResult(intent, TAKE_PICTURE); }else { new AlertDialog.Builder(MainActivity.this) .setMessage("External Storeage (SD Card) is required.Current state: " + storageState) .setCancelable(true).create().show(); }

我首先使用MD5哈希创建一个唯一的(某种程度上)文件名,并将其放入相应的文件夹中。然后我检查它是否存在(不应该,但无论如何都要检查它的良好做法)。如果它不存在,我得到父目录(文件夹)并创建文件夹层次结构(因此,如果文件位置不存在的文件夹,它们将在此行之后。然后在那之后我创建了文件。一旦文件被创建,我得到Uri并将其传递给intent,然后OK按钮按预期工作,并且都是黄金。
现在,当在相机应用程序上按下确定按钮时,该文件将出现在给定位置。在这个例子中,它将是/sdcard/Android/data/com.example.myapp/files/234asdioue23498ad.jpg
无需复制上面发布的“onActivityResult”中的文件。
另一答案 <

    推荐阅读