L'application Android de perdre des données lors de changement d'orientation
J'ai une application que j'ai copié à partir d'un tutoriel qui capture une image avec MediaStore.ACTION_IMAGE_CAPTURE
. J'ai obtenu une sorte de quelque chose d'étrange se passe quand je lance l'application sur mon téléphone.
L'application appareil photo en lui-même est en feuilletant son orientation une couple de fois au cours de l'opération, même si je ne suis pas en déplaçant le téléphone. Brièvement passe en mode paysage avant de retourner à l'tutoriel app. Par conséquent, le tutoriel app est repassez en mode portrait, une fois que le contrôle est retourné vers elle, et l'image est perdue. J'ai essayé de réglage de l'appareil photo de l'activité de l'orientation paysage, et l'image n'est pas perdu.
Mais la mise en page de l'application est prévu pour le mode portrait. Ou, si je tiens mon appareil photo en mode paysage lors de la capture de la photo, je peux tourner le téléphone après mon application est revenue à se concentrer, et ne pas perdre l'image.
J'ai fait un peu fouiller sur le web. Quelqu'un sur Stackoverflow mentionné que le changement dans l'orientation causé des appels supplémentaires onCreate
. "La raison pour laquelle onCreate()
est appelé est parce que lorsque vous faites appel à l'activité de la caméra lors de l'orientation en mode portrait, il va changer l'orientation et de détruire votre activité précédente." J'ai couru à l'application en mode de débogage avec points d'arrêt définis dans onCreate et dans le onActivityResult
méthodes. Il est vrai que onCreate
est appelé quand je prends la photo en mode portrait. L'ordre des appels est onCreate, onActivityResult, onCreate. Si je prends la photo en mode paysage (qui est où mon app photo se termine de toute façon), onCreate n'est pas appelé. Maintenant que j'ai une idée de ce qui se passe, comment puis-je empêcher que d'être un problème? Voici ce que l'application ressemble à ça:
package com.example.testapp;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
public class CameraActivity extends Activity implements View.OnClickListener {
ImageButton ib;
Button b;
ImageView iv;
Intent i;
final static int cameraData = 0;
Bitmap bmp;
@Override
protected void onCreate(Bundle savedInstanceState) {
//TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.photo_activity);
initialize();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
//TODO Auto-generated method stub
super.onConfigurationChanged(newConfig);
setContentView(R.layout.photo_activity);
initialize();
}
private void initialize() {
iv = (ImageView)findViewById(R.id.imageViewReturnedPicture);
ib = (ImageButton)findViewById(R.id.imageButtonTakePicture);
b = (Button)findViewById(R.id.buttonSetWallpaper);
b.setOnClickListener(this);
ib.setOnClickListener(this);
}
@Override
public void onClick(View arg0) {
switch (arg0.getId()) {
case R.id.buttonSetWallpaper:
try {
WallpaperManager wm = WallpaperManager.getInstance(getApplicationContext());
wm.setBitmap(bmp);
} catch (IOException e) {
//TODO Auto-generated catch block
e.printStackTrace();
}
break;
case R.id.imageButtonTakePicture:
i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(i, cameraData);
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
Bundle extras = data.getExtras();
bmp = (Bitmap)extras.get("data");
iv.setImageBitmap(bmp);
}
}
}
Et voici ce que j'ai dans le manifeste pour cette activité:
android:name="com.exemple.testapp.CameraActivity" android:label="Activité de la Caméra" android:configChanges="orientation" android:screenOrientation="portrait"
J'ai fait beaucoup de recherche, mais beaucoup de ce que je trouve manque d'exemples concrets. J'ai besoin de savoir à quoi ressemble le code, pas seulement ce que la fonctionnalité à utiliser.
Mon téléphone est un LG Motion. Quelqu'un d'autre a ce problème? Comment peut-il être fixé?
Vous devez vous connecter pour publier un commentaire.
Dans le manifeste , Dans chaque activité, j'utilise configChanges:
J'espère que cela vous aidera.
orientation
drapeau est le plus important dans la réponse et a sauvé ma journée...Vous aurez à remplacer onRetainNonConfigurationInstance et l'utilisation getLastNonConfigurationInstance pour sauvegarder/restaurer l'image bitmap.
Comme ceci:
ensuite sur votre activité u remplacer:
Qui va "sauver" l'image bitmap au cours de la rotation.
edit:
exemple à l'aide suggéré onSaveInstanceState qui va travailler mais il n'est pas conseillé, car il va utiliser beaucoup de mémoire et d'être très lent mais vous aurez besoin pour d'autres situations bientôt:
comme vous pouvez le voir, la raison pour laquelle cette solution n'est pas bon pour votre cas est parce que le Android Bundle utilisé pour ce est Android type spécial de sérialisation qui peut gérer des primitives, des Cordes et des Classes qui implémente Parcelable (ces classes vraiment que la parcelle leurs primitives). Et même tu Bitmaps ne mettre en œuvre Parcelable, il va prendre beaucoup de temps pour faire une copie de chaque octet du fichier Bitmap pour le bundle, et seront doublement de la déjà grande consommation de mémoire d'une image Bitmap.
Maintenant, nous allons voir une solution à l'aide de la
setRetainInstance
(un peu copié à partir de l'exemple que vous pouvez trouver sur\sdk\extras\android\support\samples\Support4Demos\src\com\example\android\supportv4\app\FragmentRetainInstanceSupport.Java
.Assurez-vous de vérifier les exemples, il montre quelques autres fantaisie.
et assurez-vous de supprimer la ligne
android:configChanges="orientation"
de votre manifeste parce que c'est probablement de faire plus de mal alors bon, une petite citation à ce sujet:Je suis allé à un développement mobile à la réunion du groupe du lundi et a obtenu un indice. Un programmeur qui écrit des applications pour une variété de plates-formes pour une grande entreprise a suggéré de fixer l'image bitmap à l'objet application. Comme je l'ai regardé comment je pourrais faire, j'ai enfin trouvé une solution qui fonctionne (nouvelle question en fin de post) sur la base de propositions dans le blog suivant:
http://android-er.blogspot.com/2011/10/share-bitmap-between-activities-as.html
Fondamentalement, ce qui a entraîné la configuration de l'image bitmap comme une ressource commune dans un endroit où toute activité dans l'application peut accéder. J'ai créé une nouvelle classe comme suit:
J'ai ensuite changé toutes les références bmp CameraActivity.java pour CommonResources.cameraBmp.
Lors de l'initialisation, si CommonResources.cameraBmp n'est pas null, alors je l'utilise pour mettre l'image dans l'ImageView.
onCreate et initialiser maintenant ressembler à ceci:
Et puis, pour faire un peu de nettoyage, j'ai ajouté onPause comme suit:
Ma grande question est: Ai-je géré la mémoire correctement ou je l'ai créé la collecte des ordures questions?
La façon dont vous êtes censé gérer les changements d'orientation est à la sauvegarde de votre état de l'instance. Si vous remplissez les onSaveInstanceState méthode, vous pouvez obtenir les données que vous enregistrez dans le faisceau de retour au cours de onCreate. Ceci est fait pour vous pour les vues, mais d'autres données que vous avez à vous sauver vous-même. Toute primitive, parcellable, ou serializable objet peut être enregistré de cette façon, y compris des BitMaps.
Ce faire, vous devez non seulement à survivre, les modifications de la configuration, mais pour garder votre état dans les conditions de mémoire faible aussi.
Après recherche sur le web un certain pour une solution simple, j'ai regardé un peu de code et est venu avec ce, j'espère que cela aide quelqu'un qui a des vues sur ce fil à l'avenir!
J'ai une variable globale
public Uri imageURI = null;
dans mon Activité de classe, qui est utilisé pour définir l'image de l'URI de la ImaveView je suis aide; et le code suivant dansonCreate()
etonSaveInstanceState()
J'espère que quelqu'un trouve ce utile - il suffit de demander si vous voulez plus de détails.
Avez-vous essayé d'ajouter android:launchMode="singleTop" à l'activité dans android menifest, fonctionné pour moi. Le problème est android redémarrage de l'activité lorsque des changements d'orientation et vos données sont perdues, avec cette si votre activité est déjà en cours d'exécution, il n'est pas de créer une nouvelle instance.
Soit utiliser le onSaveInstanceState et puis l'argument que vous obtenez via onCreate , ou sur le manifeste que vous serait en mesure de gérer les changements d'orientation en utilisant configChanges et paramètre sur lequel cas vous souhaitez gérer vous-même (par exemple l'orientation|screenSize|screenLayout ) .