Mi ci è voluto un po 'per farlo funzionare e ho fatto diverse cose e finalmente funziona. Non posso dire con certezza quale delle cose che ho fatto sia la soluzione al problema, ma tutte insieme costituiscono la soluzione operativa.
Ci sono diversi motivi per cui l'attività della telecamera non ritorna. Due quelli principali sono:
percorso per la nuova immagine non è valido o non esistente, o non possono essere creati
applicazione percorso stato sospeso e salvato perdersi.
Quindi ecco il mio codice per risolvere tutti questi problemi, tutti insieme funzionanti.
Per prima cosa ho creato classe helper ImageServices
:
class ImageServices {
private static String getTempDirectoryPath(Context ctx) {
File cache;
// SD Card Mounted
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/");
}
// Use internal storage
else {
cache = ctx.getCacheDir();
}
// Create the cache directory if it doesn't exist
if (!cache.exists()) {
cache.mkdirs();
}
return cache.getAbsolutePath();
}
public static Uri getOutputImageFileUri(Context ctx) {
// TODO: check the presence of SDCard
String tstamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
File file = new File(getTempDirectoryPath(ctx), "IMG_" + tstamp + ".jpg");
return Uri.fromFile(file);
}
}
Il codice è in parte ispirato da developer.android.com e in parte da CameraLauncher class del progetto Apache Cordova.
Nella mia attività di gestore di eventi per il pulsante per scattare una foto assomiglia a questo:
private Uri imageFileUri;
private static final int MAKE_PHOTO_RESULT_CODE = 100;
private static final int PICK_PHOTO_RESULT_CODE = 101;
public void onMakePhoto(View v) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
imageFileUri = ImageServices.getOutputImageFileUri(this);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
Log.i("babies", "Taking picture: requested " + imageFileUri);
startActivityForResult(intent, MAKE_PHOTO_RESULT_CODE);
}
Metodo onActivityResult
in realtà non contiene molto, come imageFileUri punta già al file esistente e necessaria il rendering è fatto in onResume
metodo, che viene chiamato quando l'attività si rimette in primo piano:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
switch(requestCode) {
case MAKE_PHOTO_RESULT_CODE:
assert imageFileUri != null;
break;
case ...
...other cases...
break;
}
}
}
Ma questo non è ancora sufficiente, come imageFileUri
si perde come la vostra applicazione viene sospeso. E su dispositivi regolari le probabilità sono vicine al 100%.Così la prossima è necessario memorizzare il valore di imageFileUri
di Stato esempio:
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (imageFileUri == null) {
outState.putString("file-uri", "");
}
else {
outState.putString("file-uri", imageFileUri.toString());
}
};
e caricarlo di nuovo in - più semplice è direttamente in onCreate
:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
if (savedInstanceState != null) {
String fileUri = savedInstanceState.getString("file-uri");
if (!fileUri.equals("")) imageFileUri = Uri.parse(fileUri);
}
}
Così, ancora una volta, in cima a molte altre soluzioni presentato su questo sito, così come altrove, ci sono due differenze importanti:
- più intelligente
getTempDirectoryPath
ispirato da Apache Cordova
- permettendo
imageFileUri
per sopravvivere applicazione sospesa
E ora - almeno per me - tutto funziona bene.
Hai dimenticato di chiamare 'Toast.show();' dentro 'onActivityResult()'. Deve essere 'Toast.makeText (questo," Registrato con successo! ", Toast.LENGTH_LONG) .show();' –