繁体   English   中英

摘要:使用Camera Intent拍摄照片并以正确的方向显示照片(希望所有设备都可以使用)

[英]Summary: Take a picture utilizing Camera Intent and display the photo with correct orientation (works on hopefully all devices)

这似乎是世界上最简单的事情:使用默认的相机活动在Android应用中拍照。 但是,StackOverflow和Web上的几个帖子中都有许多陷阱,例如,Null Intents被传回,图片的方向不正确或OutOfMemoryErrors。

我正在寻找一个允许我的解决方案

  1. 通过相机意图启动相机活动,
  2. 检索照片的Uri,和
  3. 检索照片的正确方向。

而且,我想尽可能避免设备配置(制造商,型号,操作系统版本)的具体实现。 所以我想知道:实现这一目标的最佳方法是什么?

更新:2014年1月2日:我努力避免基于设备制造商实施不同的策略。 不幸的是,我没有绕过它。 通过数百个帖子并与几个开发人员交谈,没有人找到适用于所有设备的解决方案,而无需实现设备制造商特定的代码。

在StackOverflow上发布我的解决方案之后,一些开发人员让我在github上发布我的代码。 所以现在就是: github上的AndroidCameraUtil

该代码已在各种Android API级别> = 8的设备上成功测试。有关完整列表,请参阅github上的自述文件。

CameraIntentHelperActivity提供主要功能,下面还将对其进行更详细的描述。

调用默认的相机活动:

  • 对于三星和索尼设备 :我通过调用startActivityForResult的方法调用相机活动。 我只设置了常量CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE。 我没有设置任何其他意图的额外内容。
  • 对于所有其他设备 :我使用方法调用startActivityForResult调用相机活动,如前所述。 然而,这一次,我另外设置了额外的MediaStore.EXTRA_OUTPUT,并提供了一个URI,我想要存储图像。

在这两种情况下,我都记得相机活动开始的时间。


关于相机活动结果:

  1. Mediastore:首先,我尝试阅读从MediaStore中捕获的照片。 在MediaStore内容上使用mangedQuery,我检索正在拍摄的最新图像,以及它的orientation属性和时间戳。 如果我找到一个图像并且在调用相机意图之前没有拍摄,那就是我正在寻找的图像。 否则,我会忽略结果并尝试以下方法之一。
  2. 意图额外:其次,我尝试从返回意图的intent.getData()获取图像Uri。 如果这也不成功,我继续第3步。
  3. 默认照片Uri :如果上述所有步骤都不起作用,我会使用我传递给相机活动的图像Uri。

此时,我检索了照片Uri及其传递给我的UploadPhotoActivity的方向。


图像处理

请仔细查看我的BitmapHelper类。 它基于该教程中详细描述的代码。

此外,如果需要,shrinkBitmap方法还会根据先前提取的方向信息旋转图像。


我希望这对你们中的一些人有所帮助。

我用Sony Xperia Go,三星Galaxy SII,三星Galaxy SIII mini和三星Galaxy Y测试了这个代码,它适用于所有设备!

但是在LG E400(2.3.6)上它没有用,你在画廊中得到了双张图片。 所以我在void startCameraIntent()中添加了manufacturer.contains(“lge”)并修复了问题。

if(!(manufacturer.contains("samsung")) && !(manufacturer.contains("sony")) && !(manufacturer.contains("lge"))) {
    String filename = System.currentTimeMillis() + ".jpg";
    ContentValues values = new ContentValues();
    values.put(MediaStore.Images.Media.TITLE, filename);
    cameraPicUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraPicUri);
}

在带有CM 10.1的Galaxy S3上,我在BitmapHelper中得到一个nullpointer异常:

bm = BitmapFactory.decodeFileDescriptor(fileDescriptor.getFileDescriptor(),null,options);

随后我的UploadPhotoActivity失败了:

  try { photo = BitmapHelper.readBitmap(this, cameraPicUri); if (photo != null) { photo = BitmapHelper.shrinkBitmap(photo, 600, rotateXDegrees); thumbnail = BitmapHelper.shrinkBitmap(photo, 100); ImageView imageView = (ImageView) findViewById(R.id.sustainable_action_photo); imageView.setImageBitmap(photo); } else { Log.e(TAG,"IMAGE ERROR 1"); } } catch (Exception e) { Log.e(TAG,"IMAGE ERROR 2"); e.printStackTrace(); } 

在第二个日志(IMAGE ERROR 2)。 经过几次尝试,我的相机坏了,我得到了“无法连接相机” - 恐怖。

在nexus 7上测试它,它完美地工作。

编辑:将其缩小到这个:

fileDescriptor = context.getContentResolver()。openAssetFileDescriptor(selectedImage,“r”);

虽然selectedImage包含:

文件:///storage/emulated/0/DCIM/Camera/IMG_20131023_183343.jpg

fileDescriptor返回FileNotFoundException。 我检查了文件系统,图像未保存在此位置。 TakePhotoActivity中的cameraPicUri指向不存在的图像。 我目前正在检查一切都出错了。

编辑2:我发现错误:由于该设备是三星,并告诉应用程序它是一个三星设备,您的三星特定修复程序已应用。 Cyanogenmod虽然不需要那些修复,但最终代码中断了。 一旦你删除

(manufacturer.contains(“samsung”))&&

有用。 由于这是一个自定义ROM,你当然无法计划。 我试图找出一种方法来检测设备是否正在运行cyanogenmod,然后将其包含在您的代码中。

谢谢你一个漂亮的相机修复!

编辑3: 我修改它以在Galaxy S3上的Cyanogenmod上运行,将代码更改为: 嗯,现在它有时可以工作,有时它不会。 奇怪。

if(getPackageManager()。hasSystemFeature(“com.cyanogenmod.android”)||(!(manufacturer.contains(“samsung”))&&!(manufacturer.contains(“sony”))&&!(manufacturer.contains(“ LGE“))))

使用Sony Xperia Z5时遇到一些问题。

我添加了这个,它变得更好了。

if (buildType.contains("sony")&& buildDevice.contains("e5823")) {
                setPreDefinedCameraUri = true;}

但是22次中有4次它重新启动了相机并且重启了两次。 由于每次测试我都重新启动了应用程序。 有没有办法绕过这个或我接受这个结果?

问题是,如果相机重新启动,我可以按两次后退按钮并进行操作,图像就在我的Imageview中并保存

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM