Android: Error upload image in different android versions
android, java, web-services
Solution
Okay, regarding this exception
java.lang.NullPointerException: Attempt to invoke virtual method 'char[] java.lang.String.toCharArray()' on a null object reference
You might get this exception while using Photos app, but not quite often in Gallery app. This might be important to know because in Android's latest version 5.0 Lollipop, they have removed Gallery app now they have Photos app only (Different vendors may have their own other in-built apps for photos & of course user can use any external apps also)
And because of this you are getting `filePath = null'. Now the question is why is it null?.
So there may be two reasons..
1st is your `uriToPath(Uri uri)` method is not working correctly & 2nd is your `Uri` which you are getting from `data.getData()` is not correct.
Your `uriToPath(Uri uri)` method seems to be correct, so the problem is in your `Uri`. You might have noticed that if you are fetching images from Gallery app, there are less chances that you are getting `null` in `filePath`, but if you are using Photos app the chances increase.
It happens because your Photos app shows photos which may not be on your local device, these photos are actually on the Google server. So when you ask for `Uri` by selecting a photo, it gives the Uri which is linked to that server.
The Uri might be like this `content://com.google.android.apps.photos.content/0/https%3A%2F%2Flh3.googleusercontent.com%2FL-3Jm0TaSqnuKkitli5mK0-d`
& its not of your local device. Local device's `Uri` will be like this
`content://media/external/images/media/49518`
Because of this difference your `uriToPath(Uri uri)` is returning `null`.
So check the `Uri` first & accordingly fetch image from local device or server.
You can use DocumentsProvider API so you won't have to worry about the local & server's files.
private Bitmap getBitmapFromUri(Uri uri) throws IOException {
ParcelFileDescriptor parcelFileDescriptor =
getContentResolver().openFileDescriptor(uri, "r");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();
return image;
}
But if you have some local photos in Photos app then on selecting those you will get the local Uri, which will give you the correct file path.
You can also download the photos (which are on Google server) in Photos app itself & later use it.
Problem
I am having problem with upload image in different android versions. I need to send images for php server, so i'm using a webservice. I did test with the versions Froyo e Jelly Beans, they works but the KitKat don't work. I was reading about MediaStore and I saw different ways and I don't if my its right or wrong. I debbuged my project and I could see, in KitKat the path is NULL, Logcat tell me "Java Null Pointer" just in KitKat. How can i do a application works for all version. UploadImage.java ``` package br.gov.rj.barraemexposicao; import android.app.ProgressDialog; import android.content.ActivityNotFoundException; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.provider.MediaStore; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; public class EnviaFoto extends ActionBarActivity { final int PICK_FILE_RESULT_CODE = 1; final int CAMERA_IMAGE =2; TextView messageText; Button uploadButton; Button btnTiraFoto; Button selectImage; ImageView imgFoto; int serverResponseCode = 0; ProgressDialog dialog = null; String upLoadServerUri = "http://www.kweekdesign.com.br/test/recebe/UploadToServer.php"; String filePath = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_envia_foto); selectImage = (Button) findViewById(R.id.selectImage); imgFoto = (ImageView) findViewById(R.id.imgFoto); messageText = (TextView)findViewById(R.id.messageText); uploadButton = (Button)findViewById(R.id.uploadButton); btnTiraFoto = (Button) findViewById(R.id.btnTiraFoto); upLoadServerUri = "http://www.kweekdesign.com.br/test/recebe/UploadToServer.php"; addListeners(); } public String uriToPath(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(uri, projection, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } @Override protected void onActivityResult (int requestCode, int resultCode, Intent data){ if (data != null && (requestCode == PICK_FILE_RESULT_CODE || requestCode == CAMERA_IMAGE)){ filePath = uriToPath(data.getData()); imgFoto.setImageURI(data.getData()); uploadButton.setVisibility(1); } } public int uploadFile(String sourceFileUri) { String fileName = sourceFileUri; HttpURLConnection conn = null; DataOutputStream dos = null; String lineEnd = "\r\n"; String twoHyphens = "--"; String boundary = "*****"; int bytesRead, bytesAvailable, bufferSize; byte[] buffer; int maxBufferSize = 1 * 1024 * 1024; File sourceFile = new File(sourceFileUri); if (!sourceFile.isFile()) { dialog.dismiss(); Log.e("uploadFile", "Source File not exist :" + filePath); runOnUiThread(new Runnable() { public void run() { messageText.setText("Source File not exist :"+filePath); } }); return 0; } else { try { // open a URL connection to the Servlet FileInputStream fileInputStream = new FileInputStream(sourceFile); URL url = new URL(upLoadServerUri); // Open a HTTP connection to the URL conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); // Allow Inputs conn.setDoOutput(true); // Allow Outputs conn.setUseCaches(false); // Don't use a Cached Copy conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("ENCTYPE", "multipart/form-data"); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); conn.setRequestProperty("uploaded_file", fileName); dos = new DataOutputStream(conn.getOutputStream()); dos.writeBytes(twoHyphens + boundary + lineEnd); dos.writeBytes("Content-Disposition: form-data; name=\"uploaded_file\";filename=\"" + fileName + "\"" + lineEnd); dos.writeBytes(lineEnd); // create a buffer of maximum size bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); buffer = new byte[bufferSize]; // read file and write it into form... bytesRead = fileInputStream.read(buffer, 0, bufferSize); while (bytesRead > 0) { dos.write(buffer, 0, bufferSize); bytesAvailable = fileInputStream.available(); bufferSize = Math.min(bytesAvailable, maxBufferSize); bytesRead = fileInputStream.read(buffer, 0, bufferSize); } // send multipart form data necesssary after file data... dos.writeBytes(lineEnd); dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd); // Responses from the server (code and message) serverResponseCode = conn.getResponseCode(); String serverResponseMessage = conn.getResponseMessage(); Log.i("uploadFile", "HTTP Response is : " + serverResponseMessage + ": " + serverResponseCode); if(serverResponseCode == 200){ runOnUiThread(new Runnable() { public void run() { String msg = "Envio feito com sucesso!"; messageText.setText(msg); Toast.makeText(EnviaFoto.this, "File Upload Complete.", Toast.LENGTH_SHORT).show(); } }); } //close the streams // fileInputStream.close(); dos.flush(); dos.close(); } catch (MalformedURLException ex) { dialog.dismiss(); ex.printStackTrace(); runOnUiThread(new Runnable() { public void run() { messageText.setText("MalformedURLException Exception : check script url."); Toast.makeText(EnviaFoto.this, "MalformedURLException", Toast.LENGTH_SHORT).show(); } }); Log.e("Upload file to server", "error: " + ex.getMessage(), ex); } catch (Exception e) { dialog.dismiss(); e.printStackTrace(); runOnUiThread(new Runnable() { public void run() { messageText.setText("Got Exception : see logcat "); Toast.makeText(EnviaFoto.this, "Got Exception : see logcat ", Toast.LENGTH_SHORT).show(); } }); Log.e("Upload file to server Exception", "Exception : " + e.getMessage(), e); } dialog.dismiss(); return serverResponseCode; } // End else block } private void addListeners(){ selectImage.setOnClickListener(new View.OnClickListener(){ public void onClick(View view){ Intent intent = new Intent(Intent.ACTION_GET_CONTENT); Intent chooser = Intent.createChooser(intent,"Escolha a foto"); intent.setType("image/*"); try { startActivityForResult(chooser, PICK_FILE_RESULT_CODE ); }catch (ActivityNotFoundException e){ Log.e("tag", e.getMessage()); } } }); uploadButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dialog = ProgressDialog.show(EnviaFoto.this, "", "Enviando foto...", true); new Thread(new Runnable() { public String uriToPath(Uri uri) { String[] projection = { MediaStore.Images.Media.DATA }; Cursor cursor = managedQuery(uri, projection, null, null, null); int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } protected void onActivityResult (int requestCode, int resultCode, Intent data){ if (data != null && requestCode == PICK_FILE_RESULT_CODE){ filePath = uriToPath(data.getData()); imgFoto.setImageURI(data.getData()); uploadButton.setVisibility(1); } } public void run() { runOnUiThread(new Runnable() { public void run() { messageText.setText("Enviando foto..."); } }); uploadFile(filePath); } }).start(); } }); btnTiraFoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { startActivityForResult(new Intent(MediaStore.ACTION_IMAGE_CAPTURE), CAMERA_IMAGE); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.envia_foto, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } } ``` Manifest ``` <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="br.gov.rj.barraemexposicao" > <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="19" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="br.gov.rj.barraemexposicao.EnviaFoto" android:label="@string/app_name" android:screenOrientation="portrait" > <intent-filter> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="br.gov.rj.barraemexposicao.Enquete" android:label="@string/title_activity_enquete" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> ``` LogCat ``` 07-04 08:46:54.084 13565-13565/br.gov.rj.barraemexposicao I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018_msm8226_LNX.LA.3.5.1_RB1__release_AU () OpenGL ES Shader Compiler Version: E031.24.00.08 Build Date: 03/07/14 Fri Local Branch: Remote Branch: quic/LNX.LA.3.5.1_RB1.1 Local Patches: NONE Reconstruct Branch: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018 + f2fd134 + NOTHING 07-04 08:46:54.157 13565-13565/br.gov.rj.barraemexposicao D/OpenGLRenderer﹕ Enabling debug mode 0 07-04 08:47:03.105 13565-13565/br.gov.rj.barraemexposicao D/AndroidRuntime﹕ Shutting down VM 07-04 08:47:03.121 13565-13565/br.gov.rj.barraemexposicao E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: br.gov.rj.barraemexposicao, PID: 13565 java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2, result=-1, data=Intent { act=inline-data (has extras) }} to activity {br.gov.rj.barraemexposicao/br.gov.rj.barraemexposicao.EnviaFoto}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference at android.app.ActivityThread.deliverResults(ActivityThread.java:3432) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3475) at android.app.ActivityThread.access$1300(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5086) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getScheme()' on a null object reference at android.content.ContentResolver.acquireUnstableProvider(ContentResolver.java:1420) at android.content.ContentResolver.query(ContentResolver.java:445) at android.content.ContentResolver.query(ContentResolver.java:404) at br.gov.rj.barraemexposicao.EnviaFoto.uriToPath(EnviaFoto.java:80) at br.gov.rj.barraemexposicao.EnviaFoto.onActivityResult(EnviaFoto.java:97) at android.app.Activity.dispatchActivityResult(Activity.java:5446) at android.app.ActivityThread.deliverResults(ActivityThread.java:3428) at android.app.ActivityThread.handleSendResult(ActivityThread.java:3475) at android.app.ActivityThread.access$1300(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1258) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5086) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 07-04 08:47:05.066 13565-13565/br.gov.rj.barraemexposicao I/Process﹕ Sending signal. PID: 13565 SIG: 9 07-04 08:51:33.298 15518-15518/br.gov.rj.barraemexposicao I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018_msm8226_LNX.LA.3.5.1_RB1__release_AU () OpenGL ES Shader Compiler Version: E031.24.00.08 Build Date: 03/07/14 Fri Local Branch: Remote Branch: quic/LNX.LA.3.5.1_RB1.1 Local Patches: NONE Reconstruct Branch: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018 + f2fd134 + NOTHING 07-04 08:51:33.393 15518-15518/br.gov.rj.barraemexposicao D/OpenGLRenderer﹕ Enabling debug mode 0 07-04 08:52:08.015 15518-15530/br.gov.rj.barraemexposicao W/CursorWrapperInner﹕ Cursor finalized without prior close() 07-04 08:52:10.068 15518-16522/br.gov.rj.barraemexposicao E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-34287 Process: br.gov.rj.barraemexposicao, PID: 15518 java.lang.NullPointerException: Attempt to invoke virtual method 'char[] java.lang.String.toCharArray()' on a null object reference at java.io.File.fixSlashes(File.java:185) at java.io.File.<init>(File.java:134) at br.gov.rj.barraemexposicao.EnviaFoto.uploadFile(EnviaFoto.java:102) at br.gov.rj.barraemexposicao.EnviaFoto$6$1.run(EnviaFoto.java:277) at java.lang.Thread.run(Thread.java:811) 07-04 08:52:10.815 15518-15518/br.gov.rj.barraemexposicao E/WindowManager﹕ android.view.WindowLeaked: Activity br.gov.rj.barraemexposicao.EnviaFoto has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{65280820 V.E..... R......D 0,0-684,192} that was originally added here at android.view.ViewRootImpl.<init>(ViewRootImpl.java:359) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) at android.app.Dialog.show(Dialog.java:286) at android.app.ProgressDialog.show(ProgressDialog.java:116) at android.app.ProgressDialog.show(ProgressDialog.java:99) at br.gov.rj.barraemexposicao.EnviaFoto$6.onClick(EnviaFoto.java:250) at android.view.View.performClick(View.java:4456) at android.view.View$PerformClick.run(View.java:18465) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5086) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 07-04 09:03:23.546 18083-18083/br.gov.rj.barraemexposicao I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018_msm8226_LNX.LA.3.5.1_RB1__release_AU () OpenGL ES Shader Compiler Version: E031.24.00.08 Build Date: 03/07/14 Fri Local Branch: Remote Branch: quic/LNX.LA.3.5.1_RB1.1 Local Patches: NONE Reconstruct Branch: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018 + f2fd134 + NOTHING 07-04 09:03:23.614 18083-18083/br.gov.rj.barraemexposicao D/OpenGLRenderer﹕ Enabling debug mode 0 07-04 09:04:14.226 18083-18096/br.gov.rj.barraemexposicao W/CursorWrapperInner﹕ Cursor finalized without prior close() 07-04 09:04:14.428 18083-18083/br.gov.rj.barraemexposicao I/Adreno-EGL﹕ <qeglDrvAPI_eglInitialize:410>: EGL 1.4 QUALCOMM build: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018_msm8226_LNX.LA.3.5.1_RB1__release_AU () OpenGL ES Shader Compiler Version: E031.24.00.08 Build Date: 03/07/14 Fri Local Branch: Remote Branch: quic/LNX.LA.3.5.1_RB1.1 Local Patches: NONE Reconstruct Branch: AU_LINUX_ANDROID_LNX.LA.3.5.1_RB1.04.04.02.048.018 + f2fd134 + NOTHING 07-04 09:04:17.318 18083-19131/br.gov.rj.barraemexposicao E/AndroidRuntime﹕ FATAL EXCEPTION: Thread-34498 Process: br.gov.rj.barraemexposicao, PID: 18083 java.lang.NullPointerException: Attempt to invoke virtual method 'char[] java.lang.String.toCharArray()' on a null object reference at java.io.File.fixSlashes(File.java:185) at java.io.File.<init>(File.java:134) at br.gov.rj.barraemexposicao.EnviaFoto.uploadFile(EnviaFoto.java:100) at br.gov.rj.barraemexposicao.EnviaFoto$6$1.run(EnviaFoto.java:275) at java.lang.Thread.run(Thread.java:811) 07-04 09:04:18.179 18083-18083/br.gov.rj.barraemexposicao E/WindowManager﹕ android.view.WindowLeaked: Activity br.gov.rj.barraemexposicao.EnviaFoto has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{65280100 V.E..... R......D 0,0-684,192} that was originally added here at android.view.ViewRootImpl.<init>(ViewRootImpl.java:359) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) at android.app.Dialog.show(Dialog.java:286) at android.app.ProgressDialog.show(ProgressDialog.java:116) at android.app.ProgressDialog.show(ProgressDialog.java:99) at br.gov.rj.barraemexposicao.EnviaFoto$6.onClick(EnviaFoto.java:248) at android.view.View.performClick(View.java:4456) at android.view.View$PerformClick.run(View.java:18465) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5086) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) ``` Updated after Instance Dialog ``` 07-04 09:54:17.341 26763-26763/br.gov.rj.barraemexposicao D/AndroidRuntime﹕ Shutting down VM 07-04 09:54:17.364 26763-26763/br.gov.rj.barraemexposicao E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: br.gov.rj.barraemexposicao, PID: 26763 java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{br.gov.rj.barraemexposicao/br.gov.rj.barraemexposicao.EnviaFoto}: java.lang.InstantiationException: br.gov.rj.barraemexposicao.EnviaFoto at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2124) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) at android.app.ActivityThread.access$800(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5086) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) Caused by: java.lang.InstantiationException: br.gov.rj.barraemexposicao.EnviaFoto at java.lang.Class.newInstance(Class.java:1561) at android.app.Instrumentation.newActivity(Instrumentation.java:1084) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2115) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) at android.app.ActivityThread.access$800(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5086) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) ```