2016-05-04 1 views
0

Dans mon application, je suis en train de prendre une photo, l'enregistrer et l'ajouter à un ImageView avec ce code, je suis de la Android Developers tutorialimage incompatible Android sauver avec getExternalFilesDir

private static final int REQUEST_IMAGE_CAPTURE = 1; 
private String lastImagePath; 

//Create temporary image file using getExternalFilesDir() 
private File createImageFile() throws IOException{ 
    String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); 
    String imageFileName = "JPEG_" + timestamp + "_"; 
    File storageDir = getActivity().getExternalFilesDir(Environment.DIRECTORY_PICTURES); 
    File image = File.createTempFile(imageFileName, ".jpg", storageDir); 
    lastImagePath = image.getAbsolutePath(); 
    return image; 
} 

//Start picture intent and save to file 
private void takePicture(){ 
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 
    File photoFile = null; 
    if(takePictureIntent.resolveActivity(getActivity().getPackageManager())!= null){ 
     try{ 
      photoFile = createImageFile(); 
     }catch (IOException e){ 
      Log.e(TAG, "Error Creating image file"); 
      e.printStackTrace(); 
     } 
     if (photoFile !=null){ 
      Log.e(TAG, photoFile.getAbsolutePath()); 
      takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile)); 
      startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); 
     } 
    } 
} 

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data){ 
    super.onActivityResult(requestCode, resultCode, data); 
    if(requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK){ 

     //Ensure the path has been set 
     if(lastImagePath !=null){ 
      Log.e(TAG, "LastImagePath: " + lastImagePath); 

      //DEBUG:see if it actually created the file 
      File file = new File(lastImagePath); 
      if(file.exists()){ 
       Log.e(TAG, "File exists"); 
      } 

      //Decode file 
      Bitmap image = BitmapFactory.decodeFile(lastImagePath); 

      //DEBUG: see if image is null 
      if(image == null){ 
       Log.e(TAG, "Image is null"); 
      }else{ 
       Log.e(TAG, "Image is not null"); 
      } 

      //convert full sized image to thumbnail and add it to imageView 
      Bitmap thumbnail = ThumbnailUtils.extractThumbnail(image, 200, 200); 
      image1.setImageBitmap(thumbnail); 
     }else{ 
      Log.e(TAG, "lastImagePath is null"); 
     } 
    } 
} 

Parfois, ce code fonctionne comme attendu et prend une image, l'enregistre, le charge dans le programme et l'ajoute à la vue de l'image. Mais d'autres fois, cela ne fonctionne pas du tout et semble ne pas prendre l'image.

est ici la sortie logcat pour une capture d'image réussie où l'image apparaît dans le ImageView

05-04 17:27:49.218 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: /storage/emulated/0/Android/data/com.noah.stickynotes_clientside/files/Pictures/JPEG_20160504_172748_-1847663626.jpg 
05-04 17:28:03.886 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: LastImagePath: /storage/emulated/0/Android/data/com.noah.stickynotes_clientside/files/Pictures/JPEG_20160504_172748_-1847663626.jpg 
05-04 17:28:04.359 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: File exists 
05-04 17:28:04.825 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: Image is not null 

Et voici la sortie logcat pour une capture d'image échoué là où il n'y a pas d'image dans le ImageView

05-04 17:29:00.070 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: /storage/emulated/0/Android/data/com.noah.stickynotes_clientside/files/Pictures/JPEG_20160504_172900_-1359930406.jpg 
05-04 17:29:06.581 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: LastImagePath: /storage/emulated/0/Android/data/com.noah.stickynotes_clientside/files/Pictures/JPEG_20160504_172900_-1359930406.jpg 
05-04 17:29:06.583 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: File exists 
05-04 17:29:06.583 4964-4964/com.noah.stickynotes_clientside E/SUBMIT_FRAGMENT: Image is null 

Cela semble fonctionner de manière aléatoire et échoue 80% du temps. J'utilise getExternalFilesDir parce que je veux que les photos soient privées à l'application. J'ai également ajouté l'autorisation WRITE_EXTERNAL_STORAGE à mon fichier manifeste.

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 

Je comprends aussi que je pouvais utiliser la vignette de l'image, mais je veux avoir l'image en taille parce que je vais l'ajouter à une classe plus tard.

Quelqu'un at-il des idées sur ce qui ne va pas?

Répondre

2

Votre processus se termine lorsque votre application est en arrière-plan. C'est normal pour Android, même si vous ne l'attendez pas ici. Vous devez conserver votre EXTRA_OUTPUT dans l'état d'instance enregistré Bundle.

Notez également que since file:Uri values are being banned, vous devriez envisager d'utiliser FileProvider.

This sample app démontre ces deux choses. Certes, le code est plus compliqué:

/*** 
Copyright (c) 2008-2016 CommonsWare, LLC 
Licensed under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance with the License. You may obtain a copy 
of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required 
by applicable law or agreed to in writing, software distributed under the 
License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
OF ANY KIND, either express or implied. See the License for the specific 
language governing permissions and limitations under the License. 

From _The Busy Coder's Guide to Android Development_ 
https://commonsware.com/Android 
*/ 

package com.commonsware.android.camcon; 

import android.app.Activity; 
import android.content.Intent; 
import android.content.pm.PackageManager; 
import android.content.pm.ResolveInfo; 
import android.net.Uri; 
import android.os.Build; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.support.v4.content.FileProvider; 
import java.io.File; 
import java.util.List; 

public class CameraContentDemoActivity extends Activity { 
    private static final String EXTRA_FILENAME= 
    "com.commonsware.android.camcon.EXTRA_FILENAME"; 
    private static final String FILENAME="CameraContentDemo.jpeg"; 
    private static final int CONTENT_REQUEST=1337; 
    private static final String AUTHORITY= 
    BuildConfig.APPLICATION_ID+".provider"; 
    private static final String PHOTOS="photos"; 
    private File output=null; 
    private Uri outputUri=null; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    Intent i=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); 

    if (savedInstanceState==null) { 
     output=new File(new File(getFilesDir(), PHOTOS), FILENAME); 

     if (output.exists()) { 
     output.delete(); 
     } 
     else { 
     output.getParentFile().mkdirs(); 
     } 
    } 
    else { 
     output=(File)savedInstanceState.getSerializable(EXTRA_FILENAME); 
    } 

    outputUri=FileProvider.getUriForFile(this, AUTHORITY, output); 

    if (savedInstanceState==null) { 
     i.putExtra(MediaStore.EXTRA_OUTPUT, outputUri); 

     if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) { 
     i.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION); 
     } 
     else { 
     List<ResolveInfo> resInfoList= 
      getPackageManager() 
      .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY); 

     for (ResolveInfo resolveInfo : resInfoList) { 
      String packageName = resolveInfo.activityInfo.packageName; 
      grantUriPermission(packageName, outputUri, 
      Intent.FLAG_GRANT_WRITE_URI_PERMISSION | 
       Intent.FLAG_GRANT_READ_URI_PERMISSION); 
     } 
     } 

     startActivityForResult(i, CONTENT_REQUEST); 
    } 
    } 

    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 

    outState.putSerializable(EXTRA_FILENAME, output); 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, 
            Intent data) { 
    if (requestCode == CONTENT_REQUEST) { 
     if (resultCode == RESULT_OK) { 
     Intent i=new Intent(Intent.ACTION_VIEW); 

     i.setDataAndType(outputUri, "image/jpeg"); 
     i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 
     startActivity(i); 
     finish(); 
     } 
    } 
    } 
} 

En ce qui concerne votre problème, je sauve ma position de sortie dans le Bundle en onSaveInstanceState() et de l'utiliser à nouveau dans onCreate() si j'ai un Bundle qui est en cours de restauration.

+0

Merci pour votre réponse rapide, mais je suis encore un peu confus. J'ai implémenté le concept d'enregistrement de l'emplacement du fichier dans 'Bundle' dans' onSaveInstanceState() 'mais il semble que la fonction ne soit jamais appelée. Je ne sais pas si c'est parce que le code dans le PO est dans un fragment, pas une activité ou si cela affecterait mon problème. –

+0

@NoahLutz: "mais il semble que la fonction ne soit jamais appelée" - elle devrait l'être chaque fois que votre application passe en arrière-plan (c'est-à-dire qu'elle est arrêtée mais pas détruite). Vous n'avez même pas besoin de démarrer la caméra pour cela. Il suffit d'appuyer sur HOME lorsque votre fragment d'activité + est au premier plan. "Je ne sais pas si c'est parce que le code dans l'OP est dans un fragment, pas une activité ou si cela affecterait mon problème" - les fragments ont leur propre 'onSaveInstanceState()', qui devrait être appelé. – CommonsWare

+0

Ok, j'ai 'onSaveInstanceState()' pour exécuter et enregistrer l'emplacement dans le paquet, pour une raison quelconque, l'apk n'a pas réussi à se déployer la première fois, mais maintenant il semble fonctionner! Merci beaucoup! –