onActivityResult() 在 Android 4.1.2 中捕获图像后给出空值
Posted
技术标签:
【中文标题】onActivityResult() 在 Android 4.1.2 中捕获图像后给出空值【英文标题】:onActivityResult() gives null value after capturing image in Android 4.1.2 【发布时间】:2017-02-09 17:47:52 【问题描述】:我想捕获图像,将其保存到外部存储并显示在 ImageView
中。成功捕获并保存图像,但在执行onActivityResult()
时未显示在ImageView
中。它给出null
值。
请告诉我为什么它给了我空值。
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
imageView = (ImageView) findViewById(R.id.imageView);
//camera stuff
Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
//folder stuff
imagesFolder = new File(Environment.getExternalStorageDirectory(), "MyImages");
imagesFolder.mkdirs();
File image = new File(imagesFolder, "QR_" + timeStamp + ".png");
uriSavedImage = Uri.fromFile(image);
imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);
startActivityForResult(imageIntent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
try
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE)
if (resultCode == RESULT_OK)
Toast.makeText(this, "Image saved to:\n", Toast.LENGTH_LONG).show();
Bitmap bitmap = (Bitmap) data.getExtras().get(MediaStore.EXTRA_OUTPUT);
imageView.setImageBitmap(bitmap);
else if (resultCode == RESULT_CANCELED)
// User cancelled the image capture
else
// Image capture failed, advise user
catch (Exception e)
Log.d("onActivityResult", " error "+e.getMessage());
日志错误:
10-01 10:57:14.008 18530-18530/com.example.zohaibsiddique.camera D/onActivityResult: error null
【问题讨论】:
onActivityResult() gives null value
。废话。 e.getMessage()
在 Log.d("onActivityResult", " error "+e.getMessage());
中是 null
。您的代码产生了一个问题。
你说的废话是什么意思?请使用道德词@greenapps
查看这个 SO 答案:android-camera-onactivityresult-resets-photo-path-to-null
【参考方案1】:
如果您将额外参数MediaStore.EXTRA_OUTPUT
与相机意图一起传递,那么相机活动会将捕获的图像写入该路径,并且不会在onActivityResult
方法中返回位图。
如果您检查您所传递的路径,那么您将知道实际上相机已将捕获的文件写入该路径。
如需了解更多信息,您可以关注this、this 和this
【讨论】:
那我怎样才能返回位图?【参考方案2】:您有两个选项来获取图像,从图库和从相机拍摄。如果您将EXTRA_OUTPUT
放入意图中,它不会返回Bitmap
。那么你必须使用Uri
。
用这两种方法startActivityForResult
。
private void selectFromCamera()
try
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "DCIM");
if (!file.exists())
file.mkdirs();
File localFile = new File(file + File.separator + "IMG_" + String.valueOf(System.currentTimeMillis()) + ".jpg");
imageUri = Uri.fromFile(localFile);
Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
cameraIntent.setClipData(ClipData.newRawUri(null, Uri.fromFile(localFile)));
startActivityForResult(cameraIntent, REQUEST_CAMERA);
catch (Exception localException)
Toast.makeText(ActivityAddMemory.this, "Exception:" + localException, Toast.LENGTH_SHORT).show();
private void selectFromGallery()
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, "Select File"), SELECT_FILE);
现在在onActivityForResult
里面
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent)
super.onActivityResult(requestCode, resultCode, intent);
if(resultCode == RESULT_OK)
String path=null;
Uri uri;
if (intent == null || intent.getData() == null)
uri = this.imageUri;
else
uri = intent.getData();
if(requestCode == SELECT_FILE)
path = getRealPathFromURI(uri);
else if(requestCode == REQUEST_CAMERA)
path = uri.getEncodedPath();
imageView.setImageBitmap(BitmapFactory.decodeFile(path));
下面是getRealPathFromUri
public String getRealPathFromURI(Uri uri)
String filePath = "";
String[] filePahColumn = MediaStore.Images.Media.DATA;
Cursor cursor = getContentResolver().query(uri, filePahColumn, null, null, null);
if (cursor != null)
if(cursor.moveToFirst())
int columnIndex = cursor.getColumnIndex(filePahColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
return filePath;
【讨论】:
【参考方案3】:在 onCreate() 中调用这个方法
public void startCameraIntent()
File imageFile = new File("YOUR PATH");
Uri imageFileUri = Uri.fromFile(imageFile); // convert path to Uri
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri); // set the image file name
startActivityForResult(intent, 02);
将这些行放在 onActivityResult() 中
new ImageCompression(this).execute("PATH");
创建类:
public class ImageCompression extends AsyncTask<String, Void, String>
private Context context;
private static final float maxHeight = 1280.0f;
private static final float maxWidth = 1280.0f;
public ImageCompression(Context context)
this.context = context;
@Override
protected String doInBackground(String... strings)
if (strings.length == 0 || strings[0] == null)
return null;
return compressImage(strings[0]);
protected void onPostExecute(String imagePath)
// imagePath is path of new compressed image.
imageView.setImageBitmap(BitmapFactory.decodeFile(new File(imagePath).getAbsolutePath()));
public String compressImage(String imagePath)
Bitmap scaledBitmap = null;
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bmp = BitmapFactory.decodeFile("YOUR PATH", options);
int actualHeight = options.outHeight;
int actualWidth = options.outWidth;
float imgRatio = (float) actualWidth / (float) actualHeight;
float maxRatio = maxWidth / maxHeight;
if (actualHeight > maxHeight || actualWidth > maxWidth)
if (imgRatio < maxRatio)
imgRatio = maxHeight / actualHeight;
actualWidth = (int) (imgRatio * actualWidth);
actualHeight = (int) maxHeight;
else if (imgRatio > maxRatio)
imgRatio = maxWidth / actualWidth;
actualHeight = (int) (imgRatio * actualHeight);
actualWidth = (int) maxWidth;
else
actualHeight = (int) maxHeight;
actualWidth = (int) maxWidth;
options.inSampleSize = calculateInSampleSize(options, actualWidth, actualHeight);
options.inJustDecodeBounds = false;
options.inDither = false;
options.inPurgeable = true;
options.inInputShareable = true;
options.inTempStorage = new byte[16 * 1024];
try
bmp = BitmapFactory.decodeFile(imagePath, options);
catch (OutOfMemoryError exception)
exception.printStackTrace();
try
scaledBitmap = Bitmap.createBitmap(actualWidth, actualHeight, Bitmap.Config.RGB_565);
catch (OutOfMemoryError exception)
exception.printStackTrace();
float ratioX = actualWidth / (float) options.outWidth;
float ratioY = actualHeight / (float) options.outHeight;
float middleX = actualWidth / 2.0f;
float middleY = actualHeight / 2.0f;
Matrix scaleMatrix = new Matrix();
scaleMatrix.setScale(ratioX, ratioY, middleX, middleY);
Canvas canvas = new Canvas(scaledBitmap);
canvas.setMatrix(scaleMatrix);
canvas.drawBitmap(bmp, middleX - bmp.getWidth() / 2, middleY - bmp.getHeight() / 2, new Paint(Paint.FILTER_BITMAP_FLAG));
if (bmp != null)
bmp.recycle();
ExifInterface exif;
try
exif = new ExifInterface(imagePath);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
Matrix matrix = new Matrix();
if (orientation == 6)
matrix.postRotate(90);
else if (orientation == 3)
matrix.postRotate(180);
else if (orientation == 8)
matrix.postRotate(270);
scaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), matrix, true);
catch (IOException e)
e.printStackTrace();
FileOutputStream out = null;
String filepath = getFilename();
try
new File("YOUR PATH").delete();
out = new FileOutputStream(filepath);
//write the compressed bitmap at the destination specified by filename.
scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 80, out);
/*
Uri uri = Uri.parse(filepath + "/tmp.x");
sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, uri));
*/
catch (FileNotFoundException e)
e.printStackTrace();
return filepath;
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight)
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth)
final int heightRatio = Math.round((float) height / (float) reqHeight);
final int widthRatio = Math.round((float) width / (float) reqWidth);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
final float totalPixels = width * height;
final float totalReqPixelsCap = reqWidth * reqHeight * 2;
while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap)
inSampleSize++;
return inSampleSize;
比活动类中的创建方法:
public String getFilename()
File mediaStorageDir = new File(Environment.getExternalStorageDirectory()
+ "/Tax Images");
MediaScannerConnection.scanFile(this, new String[]mediaStorageDir.toString(), null, null);
// Create the storage directory if it does not exist
if (!mediaStorageDir.exists())
mediaStorageDir.mkdirs();
String uriString = (mediaStorageDir.getAbsolutePath() + "/" + "IMAGE_NAME");
return uriString;
【讨论】:
以上是关于onActivityResult() 在 Android 4.1.2 中捕获图像后给出空值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 onActivityResult 中调用 startActivityForResult?
关于片段生命周期,何时调用片段的 onActivityResult?