Mon application me demande d'appeler une intention pour prendre une photo. La photo ne peut pas être dans la galerie, mais doit se trouver dans un répertoire spécifique de la carte SD.
A l'origine, j'utilisais simplement l'EXTRA_OUTPUT, mais j'ai rapidement découvert ce qui suit : - Certains appareils l'utilisent complètement et sautent la galerie. - Certains appareils l'ignorent complètement et utilisent UNIQUEMENT la galerie. - Certains appareils sont vraiment nuls et sauvegardent une image en taille réelle dans la galerie, et sauvegardent une vignette uniquement à l'endroit que je voulais. (HTC vous savez qui vous êtes...)
Ainsi, je ne peux pas supprimer aveuglément un fichier de galerie lorsque j'ai terminé. La dernière photo ajoutée peut être ou ne pas être celle que je veux supprimer. De plus, il se peut que je doive copier ce fichier pour remplacer le mien par la suite. Comme mon activité compte 2000 lignes et que mon entreprise ne souhaite pas que l'ensemble de notre code soit publié, je ne publie que les méthodes utilisées pour réaliser cette opération. J'espère que cela vous aidera.
De plus, je précise qu'il s'agit de ma première application Android. Je ne serais pas surpris s'il y avait une meilleure façon de faire que je ne connais pas, mais c'est ce qui fonctionne pour moi !
Alors, voici ma solution :
Tout d'abord, dans le contexte de mon application, je définis une variable comme suit :
public ArrayList<String> GalleryList = new ArrayList<String>();
Ensuite, dans mon activité, je définis une méthode pour obtenir une liste de toutes les photos de la galerie :
private void FillPhotoList()
{
// initialize the list!
app.GalleryList.clear();
String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME };
// intialize the Uri and the Cursor, and the current expected size.
Cursor c = null;
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
//
// Query the Uri to get the data path. Only if the Uri is valid.
if (u != null)
{
c = managedQuery(u, projection, null, null, null);
}
// If we found the cursor and found a record in it (we also have the id).
if ((c != null) && (c.moveToFirst()))
{
do
{
// Loop each and add to the list.
app.GalleryList.add(c.getString(0));
}
while (c.moveToNext());
}
}
Voici une méthode pour renvoyer un nom de fichier unique pour ma nouvelle image :
private String getTempFileString()
{
// Only one time will we grab this location.
final File path = new File(Environment.getExternalStorageDirectory(),
getString(getApplicationInfo().labelRes));
//
// If this does not exist, we can create it here.
if (!path.exists())
{
path.mkdir();
}
//
return new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg").getPath();
}
J'ai trois variables dans mon activité qui stockent des informations sur le fichier en cours. Une chaîne de caractères (chemin d'accès), une variable Fichier, et une URI vers ce fichier :
public static String sFilePath = "";
public static File CurrentFile = null;
public static Uri CurrentUri = null;
Je ne les définis jamais directement, j'appelle seulement un setter sur le chemin du fichier :
public void setsFilePath(String value)
{
// We just updated this value. Set the property first.
sFilePath = value;
//
// initialize these two
CurrentFile = null;
CurrentUri = null;
//
// If we have something real, setup the file and the Uri.
if (!sFilePath.equalsIgnoreCase(""))
{
CurrentFile = new File(sFilePath);
CurrentUri = Uri.fromFile(CurrentFile);
}
}
Maintenant, j'appelle une intention de prendre une photo.
public void startCamera()
{
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Specify the output. This will be unique.
setsFilePath(getTempFileString());
//
intent.putExtra(MediaStore.EXTRA_OUTPUT, CurrentUri);
//
// Keep a list for afterwards
FillPhotoList();
//
// finally start the intent and wait for a result.
startActivityForResult(intent, IMAGE_CAPTURE);
}
Une fois que cela est fait, et que l'activité revient, voici mon code :
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == IMAGE_CAPTURE)
{
// based on the result we either set the preview or show a quick toast splash.
if (resultCode == RESULT_OK)
{
// This is ##### ridiculous. Some versions of Android save
// to the MediaStore as well. Not sure why! We don't know what
// name Android will give either, so we get to search for this
// manually and remove it.
String[] projection = { MediaStore.Images.ImageColumns.SIZE,
MediaStore.Images.ImageColumns.DISPLAY_NAME,
MediaStore.Images.ImageColumns.DATA,
BaseColumns._ID,};
//
// intialize the Uri and the Cursor, and the current expected size.
Cursor c = null;
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
//
if (CurrentFile != null)
{
// Query the Uri to get the data path. Only if the Uri is valid,
// and we had a valid size to be searching for.
if ((u != null) && (CurrentFile.length() > 0))
{
c = managedQuery(u, projection, null, null, null);
}
//
// If we found the cursor and found a record in it (we also have the size).
if ((c != null) && (c.moveToFirst()))
{
do
{
// Check each area in the gallary we built before.
boolean bFound = false;
for (String sGallery : app.GalleryList)
{
if (sGallery.equalsIgnoreCase(c.getString(1)))
{
bFound = true;
break;
}
}
//
// To here we looped the full gallery.
if (!bFound)
{
// This is the NEW image. If the size is bigger, copy it.
// Then delete it!
File f = new File(c.getString(2));
// Ensure it's there, check size, and delete!
if ((f.exists()) && (CurrentFile.length() < c.getLong(0)) && (CurrentFile.delete()))
{
// Finally we can stop the copy.
try
{
CurrentFile.createNewFile();
FileChannel source = null;
FileChannel destination = null;
try
{
source = new FileInputStream(f).getChannel();
destination = new FileOutputStream(CurrentFile).getChannel();
destination.transferFrom(source, 0, source.size());
}
finally
{
if (source != null)
{
source.close();
}
if (destination != null)
{
destination.close();
}
}
}
catch (IOException e)
{
// Could not copy the file over.
app.CallToast(PhotosActivity.this, getString(R.string.ErrorOccured), 0);
}
}
//
ContentResolver cr = getContentResolver();
cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
BaseColumns._ID + "=" + c.getString(3), null);
break;
}
}
while (c.moveToNext());
}
}
}
}
}
0 votes
Je suppose qu'il n'y a pas vraiment de bonne façon de procéder puisque j'utilise MediaStore.ACTION_IMAGE_CAPTURE et non une activité de caméra personnalisée. Si quelqu'un a un moyen d'enregistrer le fichier de sortie dans le dossier EXTRA_OUTPUT sans l'enregistrer dans la galerie, merci de me le faire savoir.
0 votes
Nous avons également constaté ce comportement mais seulement sur certains téléphones. (Notamment le myTouch 3G.) D'autres téléphones enregistrent uniquement dans le fichier EXTRA_OUTPUT comme prévu.
1 votes
stackoverflow.com/questions/4515032/ semble être le même problème, et suggère que cela arrive aussi sur les téléphones LG Ally.
0 votes
Y a-t-il des appareils plus concrets qui présentent ce comportement ? À ce jour ? Ou une configuration d'émulateur ? J'ai besoin de tester cela...