我的应用程序中有一个自定义相机,用于捕捉图片,并将其保存在文件夹中的SD卡中。我能够捕获图像,但我需要在另一个活动中获取图像。我在onActivityResult事件中获得了失败传递结果和NullPointer异常。我知道图像正在保存,因为我可以看到图像的路径,但图像本身会在一段随机的时间后显示在文件夹中。我不确定这是否是NullPointerException的原因。我一直在尝试StackOverflow的各种解决方案,但没有解决问题。请尽快帮助我。
以下是我的代码片段: CustomCameraActivity.java文件:
public class CustomCameraActivity extends Activity {
private static final String TAG = "CameraActivity";
CameraPreview camPreview;
Button btn_take_pic, btn_use_pic;
Camera mCamera;
String fileName;
Activity act;
Context ctx;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ctx = this;
act = this;
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_custom_camera);
camPreview = new CameraPreview(this,
(SurfaceView) findViewById(R.id.surfaceView));
camPreview.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT));
((FrameLayout) findViewById(R.id.preview)).addView(camPreview);
camPreview.setKeepScreenOn(true);
addListenerForButton();
}
private void addListenerForButton() {
btn_take_pic = (Button) findViewById(R.id.btn_take_pic);
btn_take_pic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "Before taking picture");
mCamera.stopPreview();
mCamera.startPreview();
mCamera.takePicture(null, null, jpegCallback);
Log.e(TAG, "After taking picture");
btn_take_pic.setText("Retake");
// mCamera.startPreview();
}
});
btn_use_pic = (Button) findViewById(R.id.btn_usePhoto);
btn_use_pic.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
File file = getOutputMediaFile();
Log.e("use_pic buttn ", file.getPath());
Intent intent = new Intent();
intent.putExtra("output", file.getPath());
finish();
}
});
}
...
PictureCallback jpegCallback = new PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Log.e(TAG, "Reached jpegcallback");
File pictureFile = getOutputMediaFile();
if (pictureFile == null) {
Log.e("blah3", "picture file was null!");
return;
}
try {
FileOutputStream fos = new FileOutputStream(pictureFile);
fos.write(data);
fos.close();
} catch (FileNotFoundException e) {
Log.e(TAG, "picture file not found!");
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
Log.e(TAG, "hooray " + pictureFile.toURI().getRawPath());
}
};
private static File getOutputMediaFile() {
Log.e(TAG, "Get me the o/p file");
File mediaStorageDir = new File(
Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"PostcareApp");
if (!mediaStorageDir.exists()) {
if (!mediaStorageDir.mkdirs()) {
Log.e("PostcareApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
File mediaFile;
mediaFile = new File(mediaStorageDir.getPath() + File.separator
+ "IMG_" + timeStamp + ".jpg");
Log.e(TAG, "Before returning " + mediaFile.getAbsolutePath());
return mediaFile;
}
需要图片的活动:
public class HowItWorksActivity extends Activity {
ImageButton btn_Account, btn_Photo, btn_Edit, btn_Flip, btn_Post;
RelativeLayout rl;
private static final int CAMERA_PIC_REQUEST = 2500;
private static final int SELECT_PICTURE = 1;
Bitmap postcard_image;
Uri uri_image;
...
private void takepicture() {
Intent cameraIntent = new Intent(HowItWorksActivity.this,CustomCameraActivity.class);
startActivityForResult(cameraIntent,CAMERA_PIC_REQUEST);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.e("Howitworks..", "in activityresult");
String imgfile = (String) getIntent().getExtras().get("output");
Log.e("image ", imgfile);
if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) {
postcard_image = BitmapFactory.decodeFile(imgfile);
postcard_image = Bitmap.createScaledBitmap(postcard_image,
metrics.widthPixels, 600, true);
imgview.setImageBitmap(postcard_image);
}
}
这是LogCat文件:
12-06 12:27:40.779: E/CameraActivity(16607): Get me the o/p file
12-06 12:27:40.779: E/CameraActivity(16607): Before returning /mnt/sdcard/Pictures/PostcareApp/IMG_20131206_122740.jpg
12-06 12:27:40.779: E/use_pic buttn(16607): /mnt/sdcard/Pictures/PostcareApp/IMG_20131206_122740.jpg
12-06 12:27:41.309: E/Howitworks..(16607): in activityresult
12-06 12:27:41.499: E/AndroidRuntime(16607): FATAL EXCEPTION: main
12-06 12:27:41.499: E/AndroidRuntime(16607): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2500, result=0, data=null} to activity {com.sample.postcare2/com.sample.postcare2.HowItWorksActivity}: java.lang.NullPointerException
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.app.ActivityThread.deliverResults(ActivityThread.java:3387)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3437)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.app.ActivityThread.access$1100(ActivityThread.java:139)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1291)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.os.Handler.dispatchMessage(Handler.java:99)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.os.Looper.loop(Looper.java:154)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.app.ActivityThread.main(ActivityThread.java:4944)
12-06 12:27:41.499: E/AndroidRuntime(16607): at java.lang.reflect.Method.invokeNative(Native Method)
12-06 12:27:41.499: E/AndroidRuntime(16607): at java.lang.reflect.Method.invoke(Method.java:511)
12-06 12:27:41.499: E/AndroidRuntime(16607): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
12-06 12:27:41.499: E/AndroidRuntime(16607): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
12-06 12:27:41.499: E/AndroidRuntime(16607): at dalvik.system.NativeStart.main(Native Method)
12-06 12:27:41.499: E/AndroidRuntime(16607): Caused by: java.lang.NullPointerException
12-06 12:27:41.499: E/AndroidRuntime(16607): at com.sample.postcare2.HowItWorksActivity.onActivityResult(HowItWorksActivity.java:217)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.app.Activity.dispatchActivityResult(Activity.java:4740)
12-06 12:27:41.499: E/AndroidRuntime(16607): at android.app.ActivityThread.deliverResults(ActivityThread.java:3383)
12-06 12:27:41.499: E/AndroidRuntime(16607): ... 11 more
答案 0 :(得分:0)
你必须为Uri使用静态,就像这样
private static Uri uri_image.
希望这能解决你的问题
答案 1 :(得分:0)
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
// Image captured and saved to fileUri specified in the Intent
Toast.makeText(this, "this is the uri for the iamge path:\n" +
data.getData(), Toast.LENGTH_LONG).show();
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture
} else {
// Image capture failed, advise user
}
}
答案 2 :(得分:0)
我已经解决了这个问题。实际上我们需要以下java文件 1. OnPictureSavedListener(界面) 2.扩展Activity的CustomCameraActivity实现了OnPictureSavedListener 3.预览哪些扩展了SurfaceView 4.实现android.hardware.Camera.PictureCallback的PhotoHandler 5. PhotoHelper它包含创建目录的方法和获得最佳预览大小的方法等 和一个名为activity_custom_camera.xml的xml文件。 需要遵循以下条款
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
这是接口OnPictureSavedListener
package ali.customcamera;
public interface OnPictureSavedListener {
public void onPictureSaved(String imagePath);
}
2:这是CustomCameraActivity类
package ali.customcamera;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class CustomCameraActivity extends Activity implements
OnPictureSavedListener, Preview.Callback {
private Preview mPreview;
Button btnCapture;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_camera);
mPreview = (Preview) findViewById(R.id.preview);
btnCapture = (Button) findViewById(R.id.btnCapture);
btnCapture.setOnClickListener(captureClick);
}
OnClickListener captureClick = new OnClickListener() {
@Override
public void onClick(View v) {
// Progresss.start(CustomCameraActivity.this);
PhotoHandler photoHandler = new PhotoHandler(
CustomCameraActivity.this, CustomCameraActivity.this, 0);
mPreview.takeScreenshot(photoHandler);
btnCapture.setClickable(false);
}
};
// this is where we get the path of the image saved in sdcard
@Override
public void onPictureSaved(String imagePath) {
// Progresss.stop();
btnCapture.setClickable(true);
if (imagePath != null && !imagePath.equals("")){
Intent i = getIntent();
i.putExtra("imagePath",imagePath );
setResult(2500, i);
finish();
}
}
@Override
public void cameraReady() {
// TODO Auto-generated method stub
}
@Override
public void cameraNotAvailable() {
// TODO Auto-generated method stub
}
}
3:这是预览课程
package ali.customcamera;
import java.io.IOException;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
public class Preview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder mHolder;
private Camera mCamera;
private Callback mCallback;
Activity mActivity;
static boolean hasCamera = false;
Context context;
List<Camera.Size> previewSizes;
Camera.Size previewSize;
private PhotoHandler photoHandler;
private int width;
private int height;
private boolean configured;
public Preview(Context context) {
super(context);
this.context = context;
initHolder();
}
public Preview(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.context = context;
initHolder();
}
public Preview(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
initHolder();
}
public void setCallback(Callback c) {
mCallback = c;
mActivity = (Activity) c;
}
public interface Callback {
public void cameraReady();
public void cameraNotAvailable();
}
@SuppressWarnings("deprecation")
private void initHolder() {
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
mHolder = getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void takeScreenshot(PhotoHandler mPhotoHandler ) {
try {
this.photoHandler = mPhotoHandler;
photoHandler.setCamDimensions(previewSize.width, previewSize.height);
photoHandler.setSurfaceDimensions(width, height);
mCamera.takePicture(null, null, null, mPhotoHandler);
} catch (Exception e) {
e.getCause();
}
}
public void surfaceCreated(SurfaceHolder holder) {
mHolder = holder;
initCamera();
}
public void initCamera() {
if (!hasCamera) {
try {
mCamera = Camera.open();
hasCamera = true;
} catch (RuntimeException e) {
hasCamera = false;
mCallback.cameraNotAvailable();
return;
}
try {
mCamera.setPreviewDisplay(mHolder);
} catch (IOException exception) {
mCamera.release();
mCamera = null;
hasCamera = false;
}
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
width = w;
height = h;
if(!configured){
configureCamera();
}
try
{
mCamera.startPreview();
} catch (Exception e) {
}
}
private void configureCamera(){
Parameters parameters = mCamera.getParameters();
previewSizes = parameters.getSupportedPreviewSizes();
Display display = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
previewSize = PhotoHelper.getOptimalPreviewSize(previewSizes, width, height, true);
//parameters.setPreviewSize(previewSize.height, previewSize.width);//AQAG
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setDisplayOrientation(90);
}
else if(display.getRotation() == Surface.ROTATION_90)
{
previewSize = PhotoHelper.getOptimalPreviewSize(previewSizes, width, height, false);
parameters.setPreviewSize(previewSize.width, previewSize.height);
//parameters.setPreviewSize(previewSize.height, previewSize.width);
}
else if(display.getRotation() == Surface.ROTATION_180)
{
previewSize = PhotoHelper.getOptimalPreviewSize(previewSizes, width, height, true);
//parameters.setPreviewSize(previewSize.height, previewSize.width); AQAG
parameters.setPreviewSize(previewSize.width, previewSize.height);
}
else if(display.getRotation() == Surface.ROTATION_270)
{
previewSize = PhotoHelper.getOptimalPreviewSize(previewSizes, width, height, false);
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setDisplayOrientation(180);
}
mCamera.setParameters(parameters);
}
public void surfaceDestroyed(SurfaceHolder holder) {
releaseCamera();
}
public void releaseCamera() {
if (hasCamera) {
mCamera.stopPreview();
mCamera.release();
mCamera = null;
hasCamera = false;
}
}
}
4:这是PhotoHandler类
package ali.customcamera;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.util.Log;
public class PhotoHandler implements PictureCallback {
private final Context context;
private OnPictureSavedListener picTakenListener;
private int camWidth;
private int camHeight;
private int surfaceWidth;
private int surfaceHeight;
private int offset = 0;
public PhotoHandler(Context context, OnPictureSavedListener listener, int offset/*, boolean isPortrait*/ ) {
this.context = context;
// this.topImage = topOverlayImg;
this.picTakenListener = listener;
// this.isPortrait = isPortrait;
this.offset = offset;
}
public void setCamDimensions(int width, int height){
camWidth = width;
camHeight = height;
/*dWidth= width;
dHeight = height ;*/
}
public void setSurfaceDimensions(int width, int height){
surfaceWidth = width;
surfaceHeight = height;
}
@Override
public void onPictureTaken(byte[] data, Camera camera) {
File pictureFile = PhotoHelper.getOutputMediaFile(PhotoHelper.MEDIA_TYPE_IMAGE);
if (pictureFile == null){
return;
}
try {
//Save camera image to file
FileOutputStream fos = new FileOutputStream(pictureFile);
int len1 = data.length;
fos.write(data,0, len1);
fos.close();
} catch (FileNotFoundException e) {
Log.d("Camera", "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d("Camera", "Error accessing file: " + e.getMessage());
}
camera.startPreview();
if(picTakenListener!=null){
picTakenListener.onPictureSaved(pictureFile.getAbsolutePath());
}
}
}
5:这是PhotoHelper类
package ali.customcamera;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.hardware.Camera;
import android.os.Environment;
import android.util.Log;
public class PhotoHelper {
public static final int MEDIA_TYPE_IMAGE = 1;
public static final int MEDIA_TYPE_VIDEO = 2;
// private static final String dirName = "CustomCamera";
public static File getOutputMediaFile(int type){
// To be safe, you should check that the SDCard is mounted
// using Environment.getExternalStorageState() before doing this.
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DCIM/*DIRECTORY_PICTURES*/), "CustomCamera");
// This location works best if you want the created images to be shared
// between applications and persist after your app has been uninstalled.
// Create the storage directory if it does not exist
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
Log.d("MyCameraApp", "failed to create directory");
return null;
}
}
// Create a media file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == MEDIA_TYPE_IMAGE){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".jpg");
} else if(type == MEDIA_TYPE_VIDEO) {
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"VID_"+ timeStamp + ".mp4");
} else {
return null;
}
return mediaFile;
}
public static Bitmap rotateBitmap90(Bitmap bitMap ){
Matrix mat = new Matrix();
mat.postRotate(90);
return Bitmap.createBitmap(bitMap, 0, 0,
bitMap.getWidth(), bitMap.getHeight(),
mat, true);
}
public static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h, boolean isPortrait) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio;
if(isPortrait){
targetRatio=(double)h / w;
}
else{
targetRatio=(double)w / h;
}
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
}
最后,这是布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ali.customcamera.Preview
android:id="@+id/preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/btnCapture"
style="?android:attr/buttonStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:text="Capture" />
</RelativeLayout>