65 votes

Comment obtenir le résultat de la caméra sous la forme d'un uri dans un dossier de données?

Je suis entrain de créer une application dans laquelle je veux capturer une image et puis je veux envoyer l'image dans l'e-mail en tant que pièce jointe.

Je suis de l'ouverture d'une caméra à l'aide d' android.provider.MediaStore.ACTION_IMAGE_CAPTURE intention d'action et je suis de passage de l'Uri du fichier comme paramètre EXTRA_OUTPUT pour obtenir l'image dans le fichier. Cela fonctionne parfaitement, et je suis en mesure d'obtenir l'image capturée si j'utilise l' external storage uri comme EXTRA_OUTPUT mais si j'utilise le dossier data uri, elle ne fonctionne pas et l'appareil photo n'est pas de clôture et de son tous les boutons ne sont pas de travail.

Voici mon code pour obtenir le résultat dans le répertoire de stockage externe

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = Environment.getExternalStorageDirectory();
out = new File(out, imagename);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);

Et ce code est pour obtenir l'image dans le dossier de données

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
File out = getFilesDir();
out = new File(out, MyPharmacyOptions.PRESCRIPTION_IMAGE_NAME);
i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(out));
startActivityForResult(i, CAMERA_RESULT);

Je savais que le dossier de données n'est pas accessible à la troisième demande donc peut-être cela provoque un problème j'ai donc créer un fournisseur de contenu à partager le fichier.

Voici le contenu de mon fournir classe

public class MyContentProvider extends ContentProvider {
    private static final String Tag = RingtonContentProvider.class.getName();
    public static final Uri CONTENT_URI = Uri
            .parse("content://x.y.z/");
    private static final HashMap<String, String> MIME_TYPES = new HashMap<String, String>();

    static {
        MIME_TYPES.put(".mp3", "audio/mp3");
        MIME_TYPES.put(".wav", "audio/mp3");
        MIME_TYPES.put(".jpg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }

        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
            throws FileNotFoundException {
        File f = new File(getContext().getFilesDir(), uri.getPath());

        if (f.exists()) {
            return (ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY));
        }

        throw new FileNotFoundException(uri.getPath());
    }

    @Override
    public Cursor query(Uri url, String[] projection, String selection,
            String[] selectionArgs, String sort) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public Uri insert(Uri uri, ContentValues initialValues) {
        File file = new File(getContext().getFilesDir(), uri.getPath());
        if(file.exists()) file.delete();
        try {
            file.createNewFile();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return Uri.fromFile(file);
    }

    @Override
    public int update(Uri uri, ContentValues values, String where,
            String[] whereArgs) {
        throw new RuntimeException("Operation not supported");
    }

    @Override
    public int delete(Uri uri, String where, String[] whereArgs) {
        File f = new File(getContext().getFilesDir(), "image1.jpg");
        if(f.exists()) f.delete();
        f = new File(getContext().getFilesDir(), "image2.jpg");
        if(f.exists()) f.delete();

        getContext().getContentResolver().notifyChange(CONTENT_URI, null);

    }
}

Donc pour utiliser ce contenu à fournir, je suis à l'aide de code suivant pour passer à l'uri de l'activité de la caméra

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
Uri uri = MyContentProvider.CONTENT_URI;
uri = Uri.withAppendedPath(uri, imagename);
getContentResolver().insert(uri, null);
getContentResolver().notifyChange(RingtonContentProvider.CONTENT_URI, null);
Log.d(Tag, uri.toString());
i.putExtra(MediaStore.EXTRA_OUTPUT, uri);

startActivityForResult(i, CAMERA_RESULT);

Maintenant, si je passe l'url, puis d'autres externes répertoire de stockage de l'appareil photo est en cours d'ouverture, mais il n'est pas de clôture dans l'émulateur, mais dans le dispositif de la caméra va fermé, mais je ne suis pas d'obtenir le résultat.

Je l'ai déclaré à ce contenu à fournir, dans le fichier de manifeste

<provider
android:name=".contentproviders.MyContentProvider"
android:authorities="x.y.z" />

J'ai également donné la permission d' écrire le stockage externe et aussi pour utiliser l'appareil photo.

Je suis capable de capturer l'image à l'aide de l'appareil de stockage externe, mais je veux stocker l'image dans le répertoire de données au lieu de stockage externe, parce que si le stockage externe n'est pas disponible je veux capturer l'image et que vous voulez envoyer du courrier.

Si je créer du contenu fournissent ensuite, je peux aussi partager mon image à l'application e-mail.

Si nous fournissez pas les extras avec l'appareil photo de l'intention, il sera de retour l'image comme un byte[] dans l'activité résultat sous forme de données supplémentaire, mais c'est dans le but de la vignette, donc je ne peux pas obtenir l'image à haute résolution à l'aide de cette façon.

Jetez un oeil dans ma question et donner vos suggestions. Merci.

68voto

Dharmendra Points 14394

Il y a deux façons de résoudre ce problème. Vous pouvez obtenir l'image à partir de l' onActivityResult si vous commencez à l'activité de la caméra à l'aide de ACTION_IMAGE-CAPTURE. À l'aide de fournisseur de contenu, vous pouvez enregistrer l'image dans la mémoire interne du téléphone(répertoire des Fichiers de votre application) de l'activité de la caméra.

1. La première solution est très facile. démarrer l'activité de la caméra à l'aide de ce code

Intent cameraIntent=new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_REQUEST);

après la capture de l'image, vous obtiendrez le résultat dans la ActivtyResult.

if (requestCode == CAMERA_REQUEST) {  
    Bitmap photo = (Bitmap) data.getExtras().get("data"); 
 }

Remarque: Cette première solution fonctionne bien, mais l'image bitmap que vous obtenez en onActivityResult() est de faible résolution. Si vous voulez l'image en haute résolution, alors vous devriez vous préférez une autre solution.

2. La deuxième solution est un peu long mais c'est très important.

Dans ce cas, vous devrez créer un fournisseur de contenu qui va l'utiliser pour partager vos locaux (Application interne) fichier de l'activité de la caméra.

Voici ci-dessous mon fournisseur de Contenu de classe que j'ai changé et les faire corriger.

public class MyFileContentProvider extends ContentProvider {
    public static final Uri CONTENT_URI = Uri.parse
                                    ("content://com.example.camerademo/");
    private static final HashMap<String, String> MIME_TYPES = 
                                     new HashMap<String, String>();

    static {
        MIME_TYPES.put(".jpg", "image/jpeg");
        MIME_TYPES.put(".jpeg", "image/jpeg");
    }

    @Override
    public boolean onCreate() {

        try {
            File mFile = new File(getContext().getFilesDir(), "newImage.jpg");
            if(!mFile.exists()) {
                mFile.createNewFile();
            }
            getContext().getContentResolver().notifyChange(CONTENT_URI, null);
            return (true);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

    }

    @Override
    public String getType(Uri uri) {
        String path = uri.toString();

        for (String extension : MIME_TYPES.keySet()) {
            if (path.endsWith(extension)) {
                return (MIME_TYPES.get(extension));
            }
        }
        return (null);
    }

    @Override
    public ParcelFileDescriptor openFile(Uri uri, String mode)
    throws FileNotFoundException {

        File f = new File(getContext().getFilesDir(), "newImage.jpg");
        if (f.exists()) {
            return (ParcelFileDescriptor.open(f,
                    ParcelFileDescriptor.MODE_READ_WRITE));
        }
        throw new FileNotFoundException(uri.getPath());
    }
}

Et pour commencer l'activité de la caméra utilisation, tout simplement

Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
i.putExtra(MediaStore.EXTRA_OUTPUT, MyFileContentProvider.CONTENT_URI);
startActivityForResult(i, CAMERA_RESULT);

Pour plus d'informations, vous pouvez consulter ce blog

Remarque: Ne pas tester dans l'émulateur. Quelques fois il ne fonctionne pas dans l'émulateur.

Je reçois beaucoup de commentaires sur le nul de l'intention et de la faible résolution des images donc, je suis en ajoutant un peu de contenu à comprendre facilement la solution

MODIFIER

Le Code pour obtenir des images à haute résolution de la caméra.

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 /** 
 Here destination is the File object in which your captured images will be stored
 **/
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(destination));
/**
Here REQUEST_IMAGE is the unique integer value you can pass it any integer
**/
startActivityForResult(intent, REQUEST_IMAGE);

Après cela, mettre en œuvre la méthode onActivityResult comme ci-dessous

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if(requestCode == REQUEST_IMAGE && resultCode == Activity.RESULT_OK) {
        // Now check the file which you have pass with the intent to capture.
        // Camera had stored the captured image to the file which you have passed with the intent.
    }
}

Remarque: Si vous êtes de passage à l'URi du fichier avec l'intention et le conserver à l'esprit que la caméra ne sera pas écrire une image capturée dans ce fichier si le fichier ne sera pas accessible par l'application de l'appareil photo.

5voto

MKJParekh Points 18108

Intention d'appeler pour capturer une photo,

 Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);  
startActivityForResult(cameraIntent, CAMERA_REQUEST);  
 

Puis prenez Bitmap en ActivityResult

  if (requestCode == CAMERA_REQUEST) {   
            Bitmap photo = (Bitmap) data.getExtras().get("data");  
 }   
 

Puis écrivez cela dans la mémoire interne, voir ceci

 // The openfileOutput() method creates a file on the phone/internal storage in the context of your application  
final FileOutputStream fos = openFileOutput("my_new_image.jpg", Context.MODE_PRIVATE); 

// Use the compress method on the BitMap object to write image to the OutputStream 
bm.compress(CompressFormat.JPEG, 90, fos); 
 

Puis la prochaine fois pour lire ce fichier,

 Bitmap bitmap = BitmapFactory.decodeFile(file); 
 

3voto

Suvam Roy Points 700

Au début sauvegarder la photo dans votre stockage externe et essayez-le -

 @Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
   this.imageView = (ImageView)this.findViewById(R.id.imageView1);
   Button photoButton = (Button) this.findViewById(R.id.button1);
   photoButton.setOnClickListener(new View.OnClickListener() {

    @Override
    public void onClick(View v) {
        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 
        startActivityForResult(cameraIntent, CAMERA_REQUEST); 
    }
});
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
   if (requestCode == CAMERA_REQUEST) {  
        Bitmap bmp = intent.getExtras().get("data");
        ByteArrayOutputStream stream = new ByteArrayOutputStream();

         bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
         byte[] byteArray = stream.toByteArray(); // convert camera photo to byte array

         // save it in your external storage.
        FileOutputStream fo = new FileOutputStream(new File(Environment.getExternalStorageDirectory() + "/_camera.png"));

        fo.write(byteArray);
        fo.flush();
        fo.close();
   }  
} 
 

Cible suivante -

 File cameraFile = new File(Environment.getExternalStorageDirectory() + "/_camera.png");                 
startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_SEND)
        .setType("image/jpg")
        .putExtra(Intent.EXTRA_SUBJECT, "Subject")
        .putExtra(Intent.EXTRA_STREAM, Uri.fromFile(cameraFile))
        .putExtra(Intent.EXTRA_TEXT, textBody), "Send your message using"), Constant.EMAIL);
 

1voto

user2812818 Points 1

Vous pouvez également le faire sans avoir besoin d’un fournisseur de contenu, car vous aurez quand même besoin de la carte SD pour ouvrir l’intention de capture d’image de la caméra. Vous devriez également consulter une bibliothèque de cultures telle que crop-image au lieu d'utiliser native, car elle n'est pas bien prise en charge sur tous les périphériques.

 File mediaStorageDir;
String photoFileName = "photo.jpg";


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

    // page = getArguments().getInt("someInt", 0);
    // title = getArguments().getString("someTitle");
    // Get safe storage directory for photos
        mediaStorageDir = new File(
                Environment
                        .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                APP_TAG);
        // Create the storage directory if it does not exist
        if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()) {
            Log.d(APP_TAG, "Directory exists: " + mediaStorageDir.isDirectory());
            Log.d(APP_TAG, "Directory exists: " + mediaStorageDir.getPath());
            Log.d(APP_TAG,
                    "Directory exists: "
                            + Environment.getExternalStorageState());
            Log.d(APP_TAG, "failed to create directory");
        }

}
 

dans votre code "prenez la photo":

             Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, getPhotoFileUri(photoFileName));
 

...

 public Uri getPhotoFileUri(String fileName) {

    return Uri.fromFile(new File(mediaStorageDir.getPath() + File.separator
            + fileName));
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X