Issue
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)
Solution
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
.
Answered By - David Conrad
Answer Checked By - Pedro (JavaFixing Volunteer)