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.
JavaScriptxString 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
.