This code snippet is reading camera picture Exif metadata using ExifInterface: Apparently, one particular picture has no or invalid datetime and .getDateTime() is returning null. In the code I assign it to a long, dt, and that results in the exception that is shown below. Of course, if I un-comment the null-check just prior to the assignment, all is well.
So, I have 1 question and 1 lesson:
I’m assuming getDateTime() is really the culprit. Can an assignment cause such a exception?
As you see, the offending line is within try/catch but it wasn’t catching it because I was catching only IOException. When it was changed to Exception, it caught.
String latlong = ""; long dt = 0; ExifInterface exifInterface; try { exifInterface = new ExifInterface(pf.getAbsolutePath()); if (exifInterface != null) { float[] latLng = new float[2]; if (exifInterface.getLatLong(latLng)) { //file has exif latlong info //etc, latLng[0] is your latitute value and latLng[1] your longitude value latlong = latLng[0] + "," + latLng[1]; } //if (exifInterface.getDateTime() != null) dt = exifInterface.getDateTime(); picInfo.comments = exifInterface.getAttribute(ExifInterface.TAG_USER_COMMENT); } else { System.out.println(">>>>>>>>>>>>>ERROR: cameraPicTask.doInBackground"); System.out.println(">>>>>>>>>>>>>-----: null exifInterface for: " + pf.getAbsolutePath()); } } catch (IOException e) { e.printStackTrace(); }
E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2 Process: com.example.mypics, PID: 7912 java.lang.RuntimeException: An error occurred while executing doInBackground() at android.os.AsyncTask$4.done(AsyncTask.java:415) at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383) at java.util.concurrent.FutureTask.setException(FutureTask.java:252) at java.util.concurrent.FutureTask.run(FutureTask.java:271) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'long java.lang.Long.longValue()' on a null object reference at com.example.mypics.PicsActivity$cameraPicTask.doInBackground(PicsActivity.java:211) at com.example.mypics.PicsActivity$cameraPicTask.doInBackground(PicsActivity.java:185) at android.os.AsyncTask$3.call(AsyncTask.java:394) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at java.lang.Thread.run(Thread.java:920)
Advertisement
Answer
It seems exifInterface.getDateTime()
returns a Long
, and in this case, it returns null
. You assign it to long dt
which involves an unboxing operation. The compiler emits code to convert the Long
to a long
by calling longValue()
on it, which throws the NPE. You can see it in your stack trace:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method ‘long java.lang.Long.longValue()’ on a null object reference
Even if you were to assign it to a Long
first:
Long dateTime = exifInterface.getDateTime(); long dt = dateTime;
it would still have to unbox it, and thus, yes, an assignment can throw a NullPointerException
.