拍照失败并显示“需要 android:camera”
Posted
技术标签:
【中文标题】拍照失败并显示“需要 android:camera”【英文标题】:Taking photo fails with "requires android:camera" 【发布时间】:2016-06-23 11:12:56 【问题描述】:我用下面的代码拍照
Intent takePhotoIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
File photoPath = new File(getExternalFilesDir(null), "postcard.jpg");
takePhotoIntent.putExtra(MediaStore.EXTRA_OUTPUT,
Uri.fromFile(photoPath));
log.debug("start camera for ", photoPath.getAbsolutePath());
startActivityForResult(takePhotoIntent, REQUEST_TAKE_PHOTO);
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
if (requestCode == REQUEST_TAKE_PHOTO)
if (resultCode == RESULT_OK)
log.debug("photo successfully created");
else
log.error("problem to take photo resultCode=", resultCode);
else
log.debug("not my request: ", requestCode);
这在 android 5 上运行良好,但在 Android 6 上失败并出现 resultCode=0
(RESULT_CANCELED) 和 logcat 错误消息:
03-09 07:56:13.759 878-3735/? W/ActivityManager:Appop 拒绝: 开始意图 act=android.media.action.IMAGE_CAPTURE flg=0x3 cmp=com.google.android.GoogleCamera/com.android.camera.CaptureActivity 剪辑=文本/uri列表 U:file:///storage/emulated/0/Android/data/censored.package.name.here/files/postcard.jpg (有附加功能)来自 ProcessRecord55cce35 21309:censored.package.name.here/u0a136 (pid=21309, uid=10136) 需要安卓:相机
我在 Android Manifest 中有以下内容:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
我也检查一下应用是否真的有摄像头权限,这个检查通过了。
checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
另外值得注意的是,我在项目中包含了一个也使用相机的 aar。这个包含的库在清单中有这个:
<uses-feature android:name="android.hardware.camera" android:required="false"/>
<uses-feature android:name="android.hardware.camera.front" android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
<uses-feature android:name="android.hardware.camera.flash" android:required="false"/>
<uses-feature android:name="android.hardware.screen.landscape" android:required="false" />
<uses-feature android:name="android.hardware.wifi" android:required="false"/>
有人知道错误消息的含义或如何解决此问题吗? Google 在这种情况下没有帮助。
到目前为止,我还没有通过一个小示例成功重现该问题。这似乎是与另一个应用程序部分的一些交互。
【问题讨论】:
***.com/questions/32789027/…希望这会有所帮助 @O'one 谢谢,但不,这是一个不同的问题。我获得了许可,而且错误消息也不同。 你可以通过将target sdk设置为22来尝试它,因为它也会在23上运行,如果它运行那么肯定会由于权限问题而发生。 @O'one 与目标 sdk 22 完全相同。 确保相机应用已启用相机和存储权限 【参考方案1】:经过一天多的试验和调试,它现在可以工作了。代码还是一样的。
我想,通过设置收回相机权限,然后重新启用它就可以了,但我不完全确定。
如果有人遇到同样的问题,请将此作为答案发布。
【讨论】:
【参考方案2】:-- 用于捕获图像、保存到 SD 卡、从图库中选择、压缩、旋转图像等的完整代码。200% 工作。
public class A extends AppCompatActivity implements View.OnClickListener, AsyncTaskCompleteListener
private static final String IMAGE_DIRECTORY = "/idyme";
private static int MAX_IMAGE_DIMENSION = 200;
private final String TAG = "RegisterFragment";
private Button btnVerify, btnUploadImage;
private String ImgPath = null, filePath = null,
profileImageFilePath, profileImageData = null,imageVideoType = "", imageVideoPath = "";
private ImageView ivImage;
private AQuery aQuery;
private Uri uri = null;
private ImageOptions imageOptions;
ActionBar actionBar;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vip_registration);
ivImage = (ImageView) findViewById(R.id.ivProfile);
aQuery = new AQuery(this);
imageOptions = new ImageOptions();
imageOptions.memCache = true;
imageOptions.fileCache = true;
imageOptions.fallback = R.drawable.userimage;
@Override
public void onClick(View v)
// onRegisterButtonClick();
switch (v.getId())
case R.id.btnUploadImage:
showPictureDialog();
private void showPictureDialog()
AlertDialog.Builder pictureDialog = new AlertDialog.Builder(this);
pictureDialog.setTitle(getResources().getString(
R.string.dialog_chhose_photo));
String[] pictureDialogItems =
getResources().getString(R.string.dialog_from_gallery),
getResources().getString(R.string.dialog_from_camera);
pictureDialog.setItems(pictureDialogItems,
new DialogInterface.OnClickListener()
@Override
public void onClick(DialogInterface dialog, int which)
switch (which)
case 0:
choosePhotoFromGallary();
break;
case 1:
takePhotoFromCamera();
break;
);
pictureDialog.show();
private void choosePhotoFromGallary()
Intent galleryIntent = new Intent(Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(galleryIntent, Constants.CHOOSE_PHOTO);
private void takePhotoFromCamera()
Calendar cal = Calendar.getInstance();
File file = new File(Environment.getExternalStorageDirectory(),
(cal.getTimeInMillis() + ".jpg"));
if (!file.exists())
try
file.createNewFile();
catch (IOException e)
e.printStackTrace();
else
file.delete();
try
file.createNewFile();
catch (IOException e)
e.printStackTrace();
// uri = Uri.fromFile(file);
uri = getOutputMediaFileUri();
Intent cameraIntent = new Intent(
android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(cameraIntent, Constants.TAKE_PHOTO);
public Uri getOutputMediaFileUri()
return Uri.fromFile(getOutputMediaFile());
private String getRealPathFromURI(Uri contentURI)
String result;
String[] proj = MediaStore.Images.Media.DATA;
Cursor cursor = this.getContentResolver().query(contentURI, proj, null, null, null);
if (cursor == null) // Source is Dropbox or other similar local file
// path
result = contentURI.getPath();
else
cursor.moveToFirst();
int idx = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
result = cursor.getString(idx);
cursor.close();
return result;
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == this.RESULT_CANCELED)
return;
if (requestCode == Constants.CHOOSE_PHOTO)
if (data != null)
Uri contentURI = data.getData();
profileImageData = getRealPathFromURI(contentURI);
// new AQuery(getApplicationContext()).id(ivMeme).image(
// profileImageData, imageOptions);
try
String path = saveImage(scaleImage(this, contentURI));
imageVideoPath = path;
aQuery.id(R.id.ivProfile).image(
imageVideoPath, imageOptions);
catch (IOException e)
e.printStackTrace();
Utils.showToast("Failed", this);
else if (requestCode == Constants.TAKE_PHOTO)
// old
if (uri != null)
profileImageFilePath = uri.getPath();
if (profileImageFilePath != null
&& profileImageFilePath.length() > 0)
File myFile = new File(profileImageFilePath);
String path = saveImage(BitmapFactory
.decodeFile(profileImageFilePath));
imageVideoPath = path;
aQuery.id(R.id.ivProfile).image(
imageVideoPath, imageOptions);
else
Utils.showToast("Failed", this);
else
Utils.showToast("Failed", this);
public String saveImage(Bitmap myBitmap)
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
File wallpaperDirectory = new File(
Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
// have the object build the directory structure, if needed.
if (!wallpaperDirectory.exists())
wallpaperDirectory.mkdirs();
try
File f = new File(wallpaperDirectory, Calendar.getInstance()
.getTimeInMillis() + ".jpg");
f.createNewFile();
FileOutputStream fo = new FileOutputStream(f);
fo.write(bytes.toByteArray());
MediaScannerConnection.scanFile(this,
new String[]f.getPath(),
new String[]"image/jpeg", null);
fo.close();
AppLog.Log("TAG", "File Saved::-> " + f.getAbsolutePath());
return f.getAbsolutePath();
catch (IOException e1)
e1.printStackTrace();
return "";
private static File getOutputMediaFile()
// External sdcard location
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
IMAGE_DIRECTORY);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists())
if (!mediaStorageDir.mkdirs())
Log.d(IMAGE_DIRECTORY, "Oops! Failed create " + IMAGE_DIRECTORY
+ " directory");
return null;
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss",
Locale.getDefault()).format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "VID_" + timeStamp + ".mp4");
return mediaFile;
public static Bitmap scaleImage(Context context, Uri photoUri)
throws IOException
InputStream is = context.getContentResolver().openInputStream(photoUri);
BitmapFactory.Options dbo = new BitmapFactory.Options();
dbo.inJustDecodeBounds = true;
BitmapFactory.decodeStream(is, null, dbo);
is.close();
int rotatedWidth, rotatedHeight;
int orientation = getOrientation(context, photoUri);
if (orientation == 90 || orientation == 270)
rotatedWidth = dbo.outHeight;
rotatedHeight = dbo.outWidth;
else
rotatedWidth = dbo.outWidth;
rotatedHeight = dbo.outHeight;
Bitmap srcBitmap;
is = context.getContentResolver().openInputStream(photoUri);
if (rotatedWidth > MAX_IMAGE_DIMENSION
|| rotatedHeight > MAX_IMAGE_DIMENSION)
float widthRatio = ((float) rotatedWidth)
/ ((float) MAX_IMAGE_DIMENSION);
float heightRatio = ((float) rotatedHeight)
/ ((float) MAX_IMAGE_DIMENSION);
float maxRatio = Math.max(widthRatio, heightRatio);
// Create the bitmap from file
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = (int) maxRatio;
srcBitmap = BitmapFactory.decodeStream(is, null, options);
else
srcBitmap = BitmapFactory.decodeStream(is);
is.close();
/*
* if the orientation is not 0 (or -1, which means we don't know), we
* have to do a rotation.
*/
if (orientation > 0)
Matrix matrix = new Matrix();
matrix.postRotate(orientation);
srcBitmap = Bitmap.createBitmap(srcBitmap, 0, 0,
srcBitmap.getWidth(), srcBitmap.getHeight(), matrix, true);
String type = context.getContentResolver().getType(photoUri);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
if (type.equals("image/png"))
srcBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
else if (type.equals("image/jpg") || type.equals("image/jpeg"))
srcBitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] bMapArray = baos.toByteArray();
baos.close();
return BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);
public static int getOrientation(Context context, Uri photoUri)
/* it's on the external media. */
Cursor cursor = context.getContentResolver().query(photoUri,
new String[]MediaStore.Images.ImageColumns.ORIENTATION,
null, null, null);
if (cursor.getCount() != 1)
return -1;
cursor.moveToFirst();
return cursor.getInt(0);
-- 需要权限:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
【讨论】:
你没看懂,这就是我在做的,哪一个不行。以上是关于拍照失败并显示“需要 android:camera”的主要内容,如果未能解决你的问题,请参考以下文章
HarmonyOSJS鸿蒙Js camera怎么拍照并使用image显示出来