2015-10-28 2 views
0

Je développe une application d'inscription des étudiants sur Android à la suite d'un didacticiel. J'ai besoin de créer un nouvel étudiant pour obtenir une photo enregistrée sur le téléphone.NullPointerException lors de l'obtention d'une image à partir d'un stockage interne sous Android

Le problème est que je ne peux pas charger l'image à partir de l'URI récupéré.

Mes impressions journal "Script":

Img uri: content://com.android.providers.media.documents/document/image%3A30 

Mais mon imgString est nulle. J'utilise l'émulateur de genymotion d'ailleurs.

Voici le code pour appeler la galerie ...

public void loadImage(View view){ 
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
    intent.setType("image/*"); 
    startActivityForResult(intent, IMG_SDCARD_ACTIVITY); 
} 

Et c'est le onActivityResult pour traiter la réponse de la galerie ...

@Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     File file; 
     String pass = null; 
     Log.i("Script", "RequestCode: "+requestCode+" ResultCode: "+resultCode); 
     if(requestCode == IMG_SDCARD_ACTIVITY && resultCode == Activity.RESULT_OK){ 
      try{ 
       Uri img = data.getData(); 
       Log.i("Script", "Img uri: "+img.toString()); 
       String[] cols = {MediaStore.Images.Media.DATA}; 
       Cursor cursor = getContentResolver().query(img, cols, null, null, null); 
       cursor.moveToFirst(); 

       int indexCol = cursor.getColumnIndex(cols[0]); 
       String imgString = cursor.getString(indexCol); 
       cursor.close(); 

       file = new File(imgString); //this is the line 108 where the problem is... 
       ivImg.setImageBitmap(ImageUtil.setPic(Uri.fromFile(file), 100, 100)); 
       ivImg.setContentDescription(file.getPath()); 
       pass = "passou"; 
      } 
      catch (NullPointerException e){e.printStackTrace();} 
      catch (Exception e){e.printStackTrace();} 
      finally { 
       if(pass==null){ 
        ivImg.setImageResource(R.drawable.person); 
        Toast.makeText(SalvarAlunoActivity.this, "Fail! Try again.", Toast.LENGTH_SHORT).show(); 
      } 
     } 
    } 
} 

Et ceci est la classe ImageUtil. ..

public class ImageUtil { 
    public static Bitmap setPic(Uri uriFile, int width, int height){ 
     //Get the dimensions of the view 
     int targetW = width; 
     int targetH = height; 

     //Get the dimensions of the Bitmap 
     BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
     bmOptions.inJustDecodeBounds = true; 
     BitmapFactory.decodeFile(uriFile.getPath(), bmOptions); 
     int photoW = bmOptions.outWidth; 
     int photoH = bmOptions.outHeight; 

     //Determine how much to scale down the image 
     int scaleFactor = Math.min(photoW/targetW, photoH/targetH); 

     //Decode the image file into a Bitmap sized to fill the View 
     bmOptions.inJustDecodeBounds = false; 
     bmOptions.inSampleSize = scaleFactor; 
     bmOptions.inPurgeable = true; 

     Bitmap bitmap = BitmapFactory.decodeFile(uriFile.getPath(), bmOptions); 
     return(bitmap); 
} 

}

Les impressions de journaux aussi cette erreur ...

10-28 08:19:45.602 10874-10874/? W/System.err﹕ java.lang.NullPointerException 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.io.File.fixSlashes(File.java:185) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.io.File.<init>(File.java:134) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.XXXX.contentProvider.SalvarAlunoActivity.onActivityResult(SalvarAlunoActivity.java:108) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.Activity.dispatchActivityResult(Activity.java:5423) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.deliverResults(ActivityThread.java:3347) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.handleSendResult(ActivityThread.java:3394) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.access$1300(ActivityThread.java:135) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1244) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.os.Handler.dispatchMessage(Handler.java:102) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.os.Looper.loop(Looper.java:136) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at android.app.ActivityThread.main(ActivityThread.java:5001) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invokeNative(Native Method) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at java.lang.reflect.Method.invoke(Method.java:515) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
10-28 08:19:45.606 10874-10874/? W/System.err﹕ at dalvik.system.NativeStart.main(Native Method) 

`s ma première fois ici. Faites-moi savoir si j'ai besoin de mettre plus d'informations.

Merci d'avance.

+0

Quel est le problème? resultCode = -1 ou requestCode = -1 ?? – activesince93

+0

Un code de résultat de -1 est 'RESULT_OK'. S'il vous plaît expliquer plus en détail pourquoi c'est un problème. – CommonsWare

+0

En fait ce n'est vraiment pas le problème. J'ai vérifié maintenant ... La chose est que je ne peux pas charger l'image. Je vais éditer le post. – DMS

Répondre

1

Votre chemin de fichier est null. Tout en sélectionnant l'image de la Galerie, vous pouvez obtenir directement Bitmap de uri. Donc, dans votre méthode onActivityResult faire quelque chose comme:

Uri fileUri = data.getData(); 
Bitmap b = decodeUri(fileUri); 
your_image_view.setImageBitmap(b); 


// here decodeUri method will directly return you Bitmap which can be set to imageview 

private Bitmap decodeUri(Uri selectedImage) throws FileNotFoundException 
    { 
     BitmapFactory.Options o = new BitmapFactory.Options(); 

     o.inJustDecodeBounds = true; 

     BitmapFactory.decodeStream(getContentResolver() 
       .openInputStream(selectedImage), null, o); 

     final int REQUIRED_SIZE = 72; 

     int width_tmp = o.outWidth, height_tmp = o.outHeight; 

     int scale = 1; 

     while (true) 
     { 
      if (width_tmp/2 < REQUIRED_SIZE || height_tmp/2 < REQUIRED_SIZE) 
      { 
       break; 
      } 
      width_tmp /= 2; 

      height_tmp /= 2; 

      scale *= 2; 
     } 

     BitmapFactory.Options o2 = new BitmapFactory.Options(); 

     o2.inSampleSize = scale; 

     Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver() 
       .openInputStream(selectedImage), null, o2); 

     return bitmap; 
    } 

EDIT:

Pour explication Uri voir la réponse @CommonsWare. Il a également mentionné à propos de Picasso, qui est une bibliothèque très utile pour Android pour charger des images efficacement dans Android.

+0

Merci Zubair! @CommonsWare a expliqué la théorie parfaitement mais votre code plus son explication m'a sauvé, comme vous avez montré un exemple du code nécessaire pour résoudre le problème et j'ai cité l'explication de CommonsWare que je votais cette réponse. – DMS

1

A Uri is not a file. Le Uri vous revenez de votre demande ACTION_GET_CONTENT n'a pas besoin de pointer vers un fichier, sans parler d'un fichier auquel vous pouvez accéder vous-même sur le système de fichiers. En outre, le Uri que vous obtenez à partir de votre demande ACTION_GET_CONTENT ne doit pas être l'un de la MediaStore et le MediaStore ne doit pas nécessairement renvoyer une valeur DATA dans tous les cas.

Je ne sais pas ce que ImageUtil.setPic() fait, mais si elle prend une Uri en entrée, passer dans le Uri réel que vous revenez à onActivityResult(). setPic()espérons utilise un ContentResolver et openInputStream() sous les couvertures. Il est encore mieux d'utiliser une bibliothèque de chargement d'image, comme Picasso ou Universal Image Loader, de sorte que tout ce décodage E/S de disque et bitmap peut être effectué sur un thread d'arrière-plan.

+0

Idéal pour les explications sur Uri +1 –

+0

Hi CommonsWare! Merci pour la réponse. Je vais ajouter la classe ImageUtil pour une meilleure compréhension. – DMS

0

Je pense que la réponse ci-dessus couvre l'erreur que vous rencontrez plutôt bien, mais en règle générale, vous ne devriez jamais supposer que cursor.moveToFirst() fonctionnera, plutôt que de l'envelopper dans un si elle renvoie un booléen.

if(cursor.moveToFirst()) 
{ 
    //Do something here 
}