Нулевой указатель после захвата изображения с помощью камеры Android
в моем приложении, я использую камеру устройств Android для захвата изображения. для некоторых устройств он работает нормально, а некоторые нет. Я только что протестировал его на LG nexus 4 E960, после того как я снял изображение, мое приложение попало в катастрофу, не сохранив результат.
это мой код:
//Using intent to open camera
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(intent,CAMERA_CAPTURE);
в activityResult:
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(resultCode==RESULT_OK)
{
if(requestCode==CAMERA_CAPTURE)
{
Bitmap pictTaken = null ;
Bundle extras = data.getExtras();
if(extras.keySet().contains("data"))
{
pictTaken = (Bitmap) extras.get("data");
picUri = getIntent().getData();
}
else{
picUri = getIntent().getData();
try {
pictTaken = decodeUri(picUri);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Intent cropIntent= new Intent (this, Crop.class);
cropIntent.putExtra("data", picUri.toString());
cropIntent.putExtra("pict", pictTaken);
cropIntent.putExtra("code","camera");
startActivity(cropIntent);
}
}
после захвата и сохранения, изображение появится в следующем действии под названием Crop.class
вот мой logcat
12-12 13:26:36.340: E/AndroidRuntime(23575): FATAL EXCEPTION: main
12-12 13:26:36.340: E/AndroidRuntime(23575): Process: com.example.cobaandroid, PID: 23575
12-12 13:26:36.340: E/AndroidRuntime(23575): java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { act=inline-data (has extras) }} to activity {com.example.cobaandroid/com.example.cobaandroid.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.app.ActivityThread.deliverResults(ActivityThread.java:3368)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3411)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.app.ActivityThread.access$1300(ActivityThread.java:138)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1247)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.os.Handler.dispatchMessage(Handler.java:102)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.os.Looper.loop(Looper.java:136)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.app.ActivityThread.main(ActivityThread.java:5050)
12-12 13:26:36.340: E/AndroidRuntime(23575): at java.lang.reflect.Method.invoke(Native Method)
12-12 13:26:36.340: E/AndroidRuntime(23575): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
12-12 13:26:36.340: E/AndroidRuntime(23575): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
12-12 13:26:36.340: E/AndroidRuntime(23575): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
12-12 13:26:36.340: E/AndroidRuntime(23575): at com.example.cobaandroid.MainActivity.onActivityResult(MainActivity.java:226)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.app.Activity.dispatchActivityResult(Activity.java:5433)
12-12 13:26:36.340: E/AndroidRuntime(23575): at android.app.ActivityThread.deliverResults(ActivityThread.java:3364)
12-12 13:26:36.340: E/AndroidRuntime(23575): ... 9 more
У меня возникла проблема с открытием/использованием камеры, работающей на большинстве устройств Android, основная цель этого проекта в значительной степени зависит от использования камеры. пожалуйста, передайте мне вашу помощь, спасибо..
Ответы
Ответ 1
попробуйте под кодом,
Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File file=getOutputMediaFile(1);
picUri = Uri.fromFile(file); // create
i.putExtra(MediaStore.EXTRA_OUTPUT,picUri); // set the image file
startActivityForResult(i, CAPTURE_IMAGE);
где getOutputMediaFile (int) будет,
/** Create a File for saving an image */
private File getOutputMediaFile(int type){
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES), "MyApplication");
/**Create the storage directory if it does not exist*/
if (! mediaStorageDir.exists()){
if (! mediaStorageDir.mkdirs()){
return null;
}
}
/**Create a media file name*/
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File mediaFile;
if (type == 1){
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
"IMG_"+ timeStamp + ".png");
} else {
return null;
}
return mediaFile;
}
и, наконец,
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
Intent i;
switch (requestCode) {
case CAPTURE_IMAGE:
//THIS IS YOUR Uri
Uri uri=picUri;
break;
}
}
}
Приветствия....:)
Ответ 2
Для тех, кто не смог решить эту проблему с помощью любого из ответов здесь, вот путь.
У вас есть член picUri
, в котором вы сохраняете URI временного файла изображения до того, как вызывается startActivityForResult
для запуска приложения Camera.
Когда приложение приостанавливается, эта информация может потеряться (как и в моем случае), и вы найдете ее как null
, когда вы вернетесь к активности, чтобы использовать ее для получения сохраненного изображения с камеры.
Затем вы получите NullPointerException
.
Правильный способ сохранить picUri
- сохранить его onSaveInstanceState(Bundle)
и восстановить его onRestoreInstanceState(Bundle)
, чтобы предотвратить потерю информации.
Вот как это сделать:
// Save the activity state when it going to stop.
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("picUri", picUri);
}
// Recover the saved state when the activity is recreated.
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
picUri= savedInstanceState.getParcelable("picUri");
}
Дала мне головную боль в течение двух часов.
Ответ 3
заменить
picUri = getIntent().getData();
с
picUri = data.getData();
и попробуйте один раз...
Ответ 4
Вы должны указать камеру для сохранения пути изображения, как показано ниже:
Uri picUri;
Intent intentAmbil = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/picture.jpg";
File imageFile = new File(imageFilePath);
picUri = Uri.fromFile(imageFile); // convert path to Uri
intentAmbil.putExtra( MediaStore.EXTRA_OUTPUT, picUri );
startActivityForResult(intentAmbil, REQUEST_MAKE_PHOTO);
@Override
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_MAKE_PHOTO:
if (resultCode == Activity.RESULT_OK) {
// do something with mMakePhotoUri
}
return;
default: // do nothing
super.onActivityResult(requestCode, resultCode, data);
}
}
Ответ 5
Попробуйте этот
if (resultCode != RESULT_CANCELED) {
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
if (requestCode == CAMERA_REQUEST) {
if (data != null) {
Bitmap photo = (Bitmap) data.getExtras().get("data");
imageView.setImageBitmap(photo);
}
}
}
Drawable drawable = imageView.getDrawable();
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
bitmap1 = bitmapDrawable.getBitmap();
}
}
}
if (bitmap1 != null) {
bitmap1 = Bitmap.createScaledBitmap(bitmap1, 512, 512, false);
imageView.setImageBitmap(bitmap1);
@SuppressWarnings("unused")
String path = SaveImage_Sta(bitmap1, "stat");
} else {
Log.i("bitmap............", "bitmap1 is null");
}
Ответ 6
в некоторых устройствах onActivityResult вызывается не на активном возобновлении, а активность перезапускается после обратного вызова из намерения камеры, поэтому picurl может снова быть пустым - мы можем использовать класс приложения для сохранения ссылки на переменную
Мы можем создать собственный класс приложений
1. В манифесте Android мы должны указать класс приложения, который мы будем использовать
<application android:name=".MyApplication"
>
<activity
........
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity>
....
</activity>
....
</application>
2.Создание класса приложения
public class MyApplication extends Application {
private Uri picUri;
public void getPicUri()
{
return picUri;
}
public void setPictUri(Uri auri)
{
picUri = aUri;
}
}
3. Внутри использования активности
//call the camera intent and pass the created a tempfile uri and use the tempfile uri
MyApplication myApplication = (MyApplication)getApplication();
myApplication.setPictUri(aUri);
....
....
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case REQUEST_MAKE_PHOTO:
if (resultCode == Activity.RESULT_OK) {
// do something with mMakePhotoUri
MyApplication myApplication = (MyApplication)getApplication();
myApplication.getPicUri();// use the pic uri
}
return;
default: // do nothing
super.onActivityResult(requestCode, resultCode, data);
}
}
Ответ 7
У меня такая же проблема в моем приложении.
Проблема в том, что когда выполняется onActivityResult, данные имеют нулевое значение, поэтому вы не можете получить что-либо из камеры.
Должен быть другой способ решить это, а не использовать класс Application, потому что он становится очень сложным, когда вы обрабатываете несколько фотографий.
Ответ 8
Смотрите, я сделал еще одну вещь, возможно, это сэкономит ваше время. Дело в том, что объектом данных в onActivityResult() является основное содержание, на которое нужно обратить внимание. Объект данных имеет значение null, когда дело касается p = кода для следующего перемещения. Что вы сделаете, так это просто установить условие if-else и запустить проект.
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(data !=null){
if(resultCode==RESULT_OK)
{
if(requestCode==CAMERA_CAPTURE)
{
Bitmap pictTaken = null ;
Bundle extras = data.getExtras();
if(extras.keySet().contains("data"))
{
pictTaken = (Bitmap) extras.get("data");
picUri = getIntent().getData();
}
else{
picUri = getIntent().getData();
try {
pictTaken = decodeUri(picUri);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Intent cropIntent= new Intent (this, Crop.class);
cropIntent.putExtra("data", picUri.toString());
cropIntent.putExtra("pict", pictTaken);
cropIntent.putExtra("code","camera");
startActivity(cropIntent);
}
}
}else{
//on cancel event or something else you want to do
}
}
Проверьте это, это легко и сделает вашу работу в пути.