IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Problème OutOfMemoryError avec des Bitmap sur Android


Sujet :

Android

  1. #1
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut Problème OutOfMemoryError avec des Bitmap sur Android
    Bonjour,

    Je suis actuellement en train de développer une application android permettant de tracer des lignes sur un plan quadriller. Seulement après avoir tracer ces lignes j'effectue une sauvegarde de mon plan, après rechargement de celui ci, des fois le message suivant apparaît :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    05-13 15:29:53.831: E/AndroidRuntime(5074): FATAL EXCEPTION: main
    05-13 15:29:53.831: E/AndroidRuntime(5074): java.lang.OutOfMemoryError
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at android.graphics.Bitmap.nativeCreate(Native Method)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at android.graphics.Bitmap.createBitmap(Bitmap.java:640)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at android.graphics.Bitmap.createBitmap(Bitmap.java:620)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at com.example.ligne.indoor.Source.drawSource(Source.java:158)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at com.example.ligne.indoor.PlanSimulation.draw(PlanSimulation.java:103)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at com.example.ligne.indoor.Floor.draw(Floor.java:128)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at com.example.ligne.indoor.Plan.onDraw(Plan.java:364)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at android.view.View.draw(View.java:13776)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at android.view.View.getDisplayList(View.java:12727)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at android.view.View.getDisplayList(View.java:12771)
    05-13 15:29:53.831: E/AndroidRuntime(5074): 	at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3205)
    on m'indique donc des erreurs à chaque fois au niveau des bitmaps, par exemple pour Plan.onDraw

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    	protected void onDraw(Canvas canvas) {
    		canvas.save();
    		paint.setStyle(Style.FILL_AND_STROKE);
    		Bitmap tmp = drawEchelle();
    		Bitmap ori = drawOrigin();
    		if (ori != null)
    			canvas.drawBitmap(ori, 0, 0, paint);
    		if (tmp != null)
    			canvas.drawBitmap(tmp, 0, 0, paint);
     
    		currentFloor.draw(getWidth(), getHeight());
    		canvas.drawBitmap(currentFloor.getBitmap(), 0, 0, paint);
    	}

    Je ne sais pas comment éviter ce problème, si quelqu'un a des idées ?

  2. #2
    Modérateur
    Avatar de dinobogan
    Homme Profil pro
    ingénieur
    Inscrit en
    Juin 2007
    Messages
    4 073
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France

    Informations professionnelles :
    Activité : ingénieur
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 4 073
    Points : 7 163
    Points
    7 163
    Par défaut
    Ton image est trop grande et ne peux pas tenir en entier en RAM.
    Pour ce cas il n'y a pas 36 solutions : soit tu charges une petite partie de l'image (par exemple la taille de l'écran plus une marge autour s'il faut scroller) soit tu construits à la volée l'image en la dessinant à l'écran (si les éléments composants l'image sont calculable).
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
    Que la force de la puissance soit avec le courage de ta sagesse.

  3. #3
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Je vous remercie de votre réponse je comprends bien ce que vous me dites, mais j'ai du mal a voir en quoi dans mon exemple j'ai se soucis, du fais que je ne fais que dessiner un plan quadriller et sinon ajouter des lignes

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Développeur Android
    Inscrit en
    Décembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur Android

    Informations forums :
    Inscription : Décembre 2008
    Messages : 18
    Points : 30
    Points
    30
    Par défaut
    salut,
    cela ne résoudra pas ton problème de fond, mais tu peux demander à avoir de la mémoire Heap en plus.

    Pour cela, ajoute dans le fichier AndroidManifest.xml, à l'intérieur des tags <application>, la ligne suivante (si ce n'est déjà fait) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    android:largeHeap="true"
    .

    ça ne fonctionne pas avec les anciennes version d'android.

    L'augmentation de mémoire dépendra du terminal Android utilisé, et des applications lancés dessus (ex: de 32 à 64mo, 64 à 96mo, etc...)
    Android n'alloue qu'une petite partie de la mémoire (8-12-16-24-32mo...) pour chaque activité, ce qui rends toute application manipulant les bitmaps assez délicate à réaliser.

  5. #5
    Membre régulier
    Homme Profil pro
    Étudiant
    Inscrit en
    Octobre 2014
    Messages
    118
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2014
    Messages : 118
    Points : 84
    Points
    84
    Par défaut
    Merci pour ta réponse je viens de rajouter cela au manifest mais j'ai toujours le même probleme, mon code est le suivant :

    J'ai une classe Mur qui dessine mes lignes de couleur grise et rouge lorsque je les selectionne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
     
     
    public void drawElement(int width, int height) {
     
    		double nbPixelByTwo = (2 * Wall.getNbMetre_by_pixel());
    		double scaleModify = (Plan.getScale() / Plan.getScaleStd());
     
    		if (isSelected()) {
     
    			if (bitmapWall != null) {
    				bitmapWall.recycle();
    				bitmapWall = null;
    			}
     
    			bitmapWall = Bitmap.createBitmap(width, height, Config.ARGB_8888);
    			canvasWall = new Canvas(bitmapWall);
    			paintWall = new Paint();
     
    			/** Couleur du Mur selectionne **/
    			paintWall.setColor(Color.RED);
     
    			/** Epaisseur du trait **/
    			paintWall.setStrokeWidth(getEpaisseur());
     
    			/** Dessine le Mur **/
    			canvasWall.drawLine(
    					(float) ((getPosX_DebElt() / nbPixelByTwo) * scaleModify),
    					(float) ((getPosY_DebElt() / nbPixelByTwo) * scaleModify),
    					(float) ((getPosX_FinElt() / nbPixelByTwo) * scaleModify),
    					(float) ((getPosY_FinElt() / nbPixelByTwo) * scaleModify),
    					paintWall);
     
    		} else {
     
    			if (bitmapWall != null) {
    				bitmapWall.recycle();
    				bitmapWall = null;
    			}
     
    			bitmapWall = Bitmap.createBitmap(width, height, Config.ARGB_8888);
    			canvasWall = new Canvas(bitmapWall);
    			paintWall = new Paint();
     
    			/** Couleur du Mur **/
    			paintWall.setColor(Color.GRAY);
     
    			/** Definir une épaisseur de trait **/
    			paintWall.setStrokeWidth(getEpaisseur());
     
    			/** Dessine le Mur **/
    			canvasWall.drawLine(
    					(float) ((getPosX_DebElt() / nbPixelByTwo) * scaleModify),
    					(float) ((getPosY_DebElt() / nbPixelByTwo) * scaleModify),
    					(float) ((getPosX_FinElt() / nbPixelByTwo) * scaleModify),
    					(float) ((getPosY_FinElt() / nbPixelByTwo) * scaleModify),
    					paintWall);
    		}
    	}
    et sinon j'utilise egalement des bitmaps lorsque j'effectue le tracer de mon plan quadrillé

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Développeur Android
    Inscrit en
    Décembre 2008
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur Android

    Informations forums :
    Inscription : Décembre 2008
    Messages : 18
    Points : 30
    Points
    30
    Par défaut
    je n'ai pratiquement jamais utilisé l'objet canvas, du coup je sais pas comment il fonctionne.

    Faudrait isoler un peu plus le problème... tu pourrait sortir (via logcat) des valeurs de width et height de ta fonction drawElement ?
    pour voir déjà à ce niveau la résolution du bitmap :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bitmapWall = Bitmap.createBitmap(width, height, Config.ARGB_8888);

  7. #7
    Membre actif Avatar de Altak
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2014
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 170
    Points : 245
    Points
    245
    Par défaut
    Lut,

    Pour éviter que ton appli plante sur le chargement de tes bitmap, englobe le avec un try/catch :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    try {
    ...
    } catch (OutOfMemoryError e) {
    	e.printStackTrace();
    	return null;
    }
    Ca ne supprime pas le probleme mais ca évite que ton appli crash en plein utilisation.

  8. #8
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Citation Envoyé par Altak Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    try {
    ...
    } catch (OutOfMemoryError e) {
    	e.printStackTrace();
    	return null;
    }
    TRES MAUVAIS IDEE !
    Si à un moment on a une erreur de type Error, ça veut dire qu'on est dans un état "non récupérable", donc que quoi qu'il arrive, ce qui se passe après risque de péter dans tous les sens. Une Error, ça veut dire que la JVM jette l'éponge. Quand la JVM jette l'éponge, on évite de continuer à lui donner du boulot !

    Je t'invite à aller lire la page suivante pour gérer correctement le chargement de Bitmap (avec les options de chargement) :
    http://developer.android.com/trainin...aps/index.html
    Je ne suis pas mort, j'ai du travail !

  9. #9
    Membre actif Avatar de Altak
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2014
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 170
    Points : 245
    Points
    245
    Par défaut
    Je dois avouer ne pas connaitre les best practice pour ce genre de chose mais si l'utilisation de tes bitmap n'est pas critique pour le fonctionnement de ton app, je ne vois pas ou est le probleme...
    J'utilise ce try/catch pour le chargement d'image que je récupère depuis un web service. Lorsque cela arive (il est possible que je doivent récuperer de trés grande image par exemple...), je clean la mémoire et j'affiche une image par default.
    Cela ne change en rien le comportement de mon application...

  10. #10
    Membre chevronné
    Avatar de eulbobo
    Homme Profil pro
    Développeur Java
    Inscrit en
    Novembre 2003
    Messages
    786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Novembre 2003
    Messages : 786
    Points : 1 993
    Points
    1 993
    Par défaut
    Citation Envoyé par Altak Voir le message
    Je dois avouer ne pas connaitre les best practice pour ce genre de chose mais si l'utilisation de tes bitmap n'est pas critique pour le fonctionnement de ton app, je ne vois pas ou est le probleme...
    Le problème c'est que tu corriges un problème en utilisant une solution qui "tombe en marche".
    Tu n'as strictement aucune garantie que ton application pourra continuer de fonctionner normalement quand ta JVM te balance une Error. Pour l'instant ça marche, tant mieux pour toi. Mais j'ai envie de dire que tu as de la chance.

    Tu as de la chance parce que le "je clean la mémoire" fonctionne. Normalement, en java, la gestion de la mémoire est entièrement pilotée par la JVM, et l'appel à System.gc() "peut" nettoyer la mémoire.. Mais ça peut aussi ne rien faire du tout !
    Et il y a des cas dans lesquels quoi qu'il arrive tu ne pourras pas nettoyer la mémoire (le cas où la JVM passe plus de temps à essayer de faire de la place avec le garbage collector qu'à faire avancer le programme).

    De manière générale, personne n'a aucune garantie du fonctionnement interne des fonctions natives qui dépendent complètement du système sur lequel elles tournent (et donc de la version de Java installée, sur quel OS). Donc il faut éviter de trop compter dessus parce que ça marche chez toi !
    Je ne suis pas mort, j'ai du travail !

  11. #11
    Membre actif Avatar de Altak
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2014
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Octobre 2014
    Messages : 170
    Points : 245
    Points
    245
    Par défaut
    Re,

    Dans tout les cas, je n'ai aucune idée de la taille des images que je peut devoir afficher.
    Ce catch est comme une sécurité supplémentaire puisque de toute façon, je ne peux pas éviter le outOfMemory et comme l'affichage de ces images n'est pas indispensable au fonctionnement de mon appli, Cela m’évite de planter et l'utilisateur a juste une image par défaut (j'ai tester sur 3 devices différents qui ont des caractéristiques complétement différente).

    Pour mes prochaines appli, je passerai sans doute par des lib du genre Picasso. Ca m’évitera de gérer ca moi-même :p

    GL HF

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de mémoire avec des Bitmap
    Par Ryu2000 dans le forum Android
    Réponses: 11
    Dernier message: 06/04/2012, 11h34
  2. Problèmes avec des calculs sur des doubles
    Par Tora21 dans le forum Débuter avec Java
    Réponses: 6
    Dernier message: 20/06/2011, 13h40
  3. Problèmes avec des annotations sur mon Mac
    Par fk04 dans le forum Eclipse Java
    Réponses: 3
    Dernier message: 08/09/2010, 21h54
  4. [Unix] problème avec des permissions sur un fichier
    Par bulbo dans le forum Administration système
    Réponses: 3
    Dernier message: 20/02/2008, 15h04
  5. Problémes mémoire avec le bde sur des bases paradox
    Par Keke des Iles dans le forum Bases de données
    Réponses: 2
    Dernier message: 27/05/2004, 16h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo