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 d'accès à un singleton


Sujet :

Android

  1. #1
    Membre du Club
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Points : 43
    Points
    43
    Par défaut Problème d'accès à un singleton
    Bonjour,

    Je vous explique mon problème.

    Je voudrais prendre capturer une photo pendant le streaming.
    Donc dans la méthode "onPreviewFrame" je viens regarder si un flag est à "true" pour capturer la photo.
    Et dans mon "Service" quand je reçois un message de mon webService, je met le flag à "true".

    Voici ma classe singleton:
    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
    public class CameraManager {
     
    	private static String TAG = "CameraManager";
     
    	private static CameraManager instance = null;
     
    	private boolean shouldTakePicture = false;
     
    	private String classA = null;
     
    	private CameraManager(String classA) {
    		this.classA = classA;
    	}
     
    	public static CameraManager getInstance(String classA) {
    		Log.d(TAG, "cameraManager - getInstance -" + classA);
    		 if (CameraManager.instance == null) {
    			 Log.d(TAG, "cameraManager - instance == null - " + classA);
    	            synchronized(CameraManager.class) {
    	              if (CameraManager.instance == null) {
    	            	  CameraManager.instance = new CameraManager(classA);
    	              }
    	            }
    	         }
    	         return CameraManager.instance;
    	}
     
    	public synchronized boolean isShouldTakePicture() {
    		Log.d(TAG, "cameraManager - shouldTakePicture: " + shouldTakePicture + " - " + classA);
    		return shouldTakePicture;
    	}
     
    	public synchronized void setShouldTakePicture(boolean shouldTakePicture) {
    		this.shouldTakePicture = shouldTakePicture;
    		Log.e(TAG, "cameraManager - shouldTakePicture: " + shouldTakePicture + " - " + classA);
    	}
    }
    J'ai mis volontairement beaucoup de logs.

    Voici les logs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    04-05 12:37:33.890: D/CameraManager(1549): cameraManager - getInstance -InfosSession
    04-05 12:37:33.890: D/CameraManager(1549): cameraManager - instance == null - InfosSession
    04-05 12:37:34.350: D/CameraManager(1549): cameraManager - getInstance -VideoCaptureAndroid
    04-05 12:37:35.560: D/CameraManager(1549): cameraManager - shouldTakePicture: false - InfosSession
    04-05 12:37:35.640: D/CameraManager(1549): cameraManager - shouldTakePicture: false - InfosSession
    ....
    04-05 12:37:59.900: D/CameraManager(1549): cameraManager - shouldTakePicture: false - InfosSession
    04-05 12:37:59.950: E/CameraManager(1529): cameraManager - shouldTakePicture: true - InfosSession
    04-05 12:37:59.980: D/CameraManager(1549): cameraManager - shouldTakePicture: false - InfosSession
    04-05 12:38:00.080: D/CameraManager(1549): cameraManager - shouldTakePicture: false - InfosSession
    04-05 12:38:00.130: D/CameraManager(1549): cameraManager - shouldTakePicture: false - InfosSession
    ...
    Comme vous pouvez le constater, le flag est bien mis à "true" par mon "Service" mais la valeur récupérer dans la méthode "onPreviewFrame" est toujours à "false".

    Je ne vois pas d'où vient mon problème.

    Merci,
    Drlord.

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 96
    Points : 98
    Points
    98
    Par défaut
    Bonjour,

    Ton singleton n'est pas thread-safe voir : http://christophej.developpez.com/tu...n/multithread/

    Du coup, il faudrait vérifier si tu as une ou plusieurs instances de CameraManager et quelle est l'instance qui est exécutée.

    C'est quoi le chiffre qui est entre paranthéses dans tes log ?


    S. Combes

  3. #3
    Membre du Club
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Points : 43
    Points
    43
    Par défaut
    Le chiffre entre parenthèse correspond au PID de l'application.

    Sinon pour revenir à mon problème de thread et singleton, il me semble que dans les logs on constate bien que c'est la même instance du Singleton qui est utilisé.
    A chaque fois que fais appel à la méthode "getInstance" je lui envoie comme paramètre le nom de la classe où se fait l'appel. ET je sauvegarde ce paramètre s'il y a création du singleton. Etant donné que c'est "InfosSession" qui est la première classe à faire appel à mon singleton, c'est ce paramètre qui est affiché à chaque fois.
    Enfin c'est en tout ce que j'ai essayer de vérifier en utilisant ce paramètre...

    J'ai essayer d'utiliser la méthode décrite dans le point "3.2.1. La synchronisation de getInstance()" mais j'obtient le même résultat.

  4. #4
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 96
    Points : 98
    Points
    98
    Par défaut
    J'ai testé ta classe en modifiant quelque peu le code afin de pouvoir le faire fonctionner :
    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
     
    public class CameraManager {
     
    	private static String TAG = "CameraManager";
     
    	private static CameraManager instance = null;
     
    	private boolean shouldTakePicture = false;
     
    	private String classA = null;
     
    	private CameraManager(String classA) {
    		this.classA = classA;
    	}
     
    	public static CameraManager getInstance(String classA) {
    		System.out.println("cameraManager - getInstance -" + classA);
    		 if (CameraManager.instance == null) {
    			 System.out.println("cameraManager - instance == null - " + classA);
    	            synchronized(CameraManager.class) {
    	              if (CameraManager.instance == null) {
    	            	  CameraManager.instance = new CameraManager(classA);
    	              }
    	            }
    	         }
    	         return CameraManager.instance;
    	}
     
    	public synchronized boolean isShouldTakePicture() {
    		System.out.println("cameraManager - shouldTakePicture: " + shouldTakePicture + " - " + classA);
    		System.out.println(this);
    		return shouldTakePicture;
    	}
     
    	public synchronized void setShouldTakePicture(boolean shouldTakePicture) {
    		this.shouldTakePicture = shouldTakePicture;
    		System.out.println("cameraManager - shouldTakePicture: " + shouldTakePicture + " - " + classA);
    		System.out.println(this);
    	}
    }
    Le test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public class Main {
     
    	public static void main(String[] args) {
    		CameraManager c = CameraManager.getInstance("CameraManager");
    		c.isShouldTakePicture();
    		c.setShouldTakePicture(true);
    		c.isShouldTakePicture();
    	}
    }
    Donne les résultats :
    cameraManager - getInstance -CameraManager
    cameraManager - instance == null - CameraManager
    cameraManager - shouldTakePicture: false - CameraManager
    CameraManager@9304b1
    cameraManager - shouldTakePicture: true - CameraManager
    CameraManager@9304b1
    cameraManager - shouldTakePicture: true - CameraManager
    CameraManager@9304b1
    La classe semble fonctionner correctement.
    Par contre je pense que ton Singleton n'est toujours pas thread-safe (mais je ne sais pas les modification qu'il faudrait apporter pour qu'il le soit).
    En effet, il est possible de créer une instance de CameraManager par introspection sans passer par le getInstance.
    Voir ce sujet où j'ai présenté un test simple qui montre la chose : http://www.developpez.net/forums/d12...ler-singleton/

    Pour t'assurer que tu utilise la même instance de ton objet CameraManager ajoute les "System.out.println(this);" comme dans le code que j'ai donné


    S. Combes

  5. #5
    Membre du Club
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Points : 43
    Points
    43
    Par défaut
    Merci.

    J'ai suivi ton conseil et j'ai constater qu'il y a bien un problème avec mon singleton
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    04-05 16:02:45.700: D/CameraManager(28134): cameraManager - shouldTakePicture: false - InfosSession
    04-05 16:02:45.700: D/CameraManager(28134): cameraManager: com.csipsimple.utils.CameraManager@407a3198
    04-05 16:02:45.720: E/CameraManager(28110): cameraManager - shouldTakePicture: true - InfosSession
    04-05 16:02:45.720: E/CameraManager(28110): cameraManager: com.csipsimple.utils.CameraManager@407b4e40
    04-05 16:02:45.760: D/CameraManager(28134): cameraManager - shouldTakePicture: false - InfosSession
    04-05 16:02:45.760: D/CameraManager(28134): cameraManager: com.csipsimple.utils.CameraManager@407a3198
    Donc j'ai au moins pu tirer un enseignement, mon idée pour savoir s'il y avait une ou deux instance de mon singleton était incorrect.

    Bon sinon pour revenir à mon problème, je ne vois pas trop comment le résoudre.
    Je peux par contre peut être détailler un peu plus l'architecture du projet.
    Le singleton ainsi que la classe où il y a la méthode "onPreviewFrame" est dans une librairie. Et le "Service" est dans mon application principale.

    Je vais essayer de trouver une solution en essayant de comprendre pourquoi j'ai 2 instance de mon singleton...
    Mais je suis ouvert à des propositions

  6. #6
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Peut etre parcequ'il y a deux instances du process:
    28134 et 28110
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  7. #7
    Membre du Club
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Points : 43
    Points
    43
    Par défaut
    Oui c'est doute la cause du problème mais je ne comprend pas pourquoi cela se produit?

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 96
    Points : 98
    Points
    98
    Par défaut
    Il faut que tu identifies quelles méthodes sont suceptibles de créer un objet de type CameraManager et de faire des traces.
    Si la chose est compliquée tu peux, dans le constructeur de CameraManager :
    • provoquer une exception
    • catch de l'exception
    • printStackTrace dans le catch

    Reste plus qu'à analyser les piles d'appels

    Un moyen de contourner le problème serait de passer l'attribut "shouldTakePicture" en static.
    Mais c'est vraiment pas propre comme solution.

    S. Combes

  9. #9
    Membre du Club
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Points : 43
    Points
    43
    Par défaut
    J'ai suivi ton conseil et mon programme rentre bien 2 fois dans le constructeur.

    J'ai produit une erreur intentionnelle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    private CameraManager(String classA) {
    		try{
    			this.classA.charAt(1);
    		}
    		catch (Exception e) {
    			e.printStackTrace();
    		}
     
    //		this.classA = classA;
    	}
    Voici les logs:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    04-06 12:10:50.820: W/System.err(16842): java.lang.NullPointerException
    04-06 12:10:50.820: W/System.err(16842): 	at com.csipsimple.utils.CameraManager.<init>(CameraManager.java:16)
    04-06 12:10:50.820: W/System.err(16842): 	at com.csipsimple.utils.CameraManager.getInstance(CameraManager.java:30)
    04-06 12:10:50.820: W/System.err(16842): 	at org.webrtc.videoengine.VideoCaptureAndroid.<init>(VideoCaptureAndroid.java:88)
    04-06 12:10:50.820: W/System.err(16842): 	at org.webrtc.videoengine.VideoCaptureDeviceInfoAndroid.AllocateCamera(VideoCaptureDeviceInfoAndroid.java:292)
    04-06 12:10:50.820: W/System.err(16842): 	at dalvik.system.NativeStart.run(Native Method)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    04-06 12:13:05.960: W/System.err(16830): java.lang.NullPointerException
    04-06 12:13:05.960: W/System.err(16830): 	at com.csipsimple.utils.CameraManager.<init>(CameraManager.java:16)
    04-06 12:13:05.960: W/System.err(16830): 	at com.csipsimple.utils.CameraManager.getInstance(CameraManager.java:30)
    04-06 12:13:05.960: W/System.err(16830): 	at com.camka.service.VamService$1.handleMessage(VamService.java:297)
    04-06 12:13:05.960: W/System.err(16830): 	at android.os.Handler.dispatchMessage(Handler.java:99)
    04-06 12:13:05.960: W/System.err(16830): 	at android.os.Looper.loop(Looper.java:132)
    04-06 12:13:05.960: W/System.err(16830): 	at android.app.ActivityThread.main(ActivityThread.java:4028)
    04-06 12:13:05.960: W/System.err(16830): 	at java.lang.reflect.Method.invokeNative(Native Method)
    04-06 12:13:05.960: W/System.err(16830): 	at java.lang.reflect.Method.invoke(Method.java:491)
    04-06 12:13:05.960: W/System.err(16830): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
    04-06 12:13:05.960: W/System.err(16830): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
    04-06 12:13:05.960: W/System.err(16830): 	at dalvik.system.NativeStart.main(Native Method)
    Donc on constate bien qu'on rentre 2 fois dans le constructeur mais pourquoi?
    Alors que je n'ai pas de problème avec des singleton instancier dans mon application et j'ai aussi remarquer que si je faisait un appel à mon "CameraManager" en dehors de mon service, je n'avait pas de problème

  10. #10
    Membre régulier
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 96
    Points : 98
    Points
    98
    Par défaut
    Les appels se font depuis :
    • com.camka.service.VamService$1.handleMessage(VamService.java:297).
    • org.webrtc.videoengine.VideoCaptureAndroid.<init>(VideoCaptureAndroid.java:88)


    Ton service ne serait-il pas appellé par 2 programmes différents ?
    Car la première instance débute par : dalvik.system.NativeStart.run(Native Method)
    alors que la seconde débute par : dalvik.system.NativeStart.main(Native Method)

    Si c'est le cas normal que tu ais 2 intances distinctes vue que chaque programme à son espace mémoire pour géré ces variables.


    S. Combes

  11. #11
    Membre du Club
    Inscrit en
    Janvier 2010
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Janvier 2010
    Messages : 55
    Points : 43
    Points
    43
    Par défaut
    Merci beaucoup.
    J'ai enfin trouvé d'où cela venait.
    En gros la libraire que j'importe où il y a la gestion de la caméra est un projet android et il y avait de déclaré un nom de processus:
    "android:process= "XXX" "

    Encore merci pour vos réponses

  12. #12
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Au passage pas besoin de lancer une exception hein !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Log.i("MonAppli","TestException",new Exception());
    Marche très bien pour tout faire !
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

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

Discussions similaires

  1. [ADO] [MSACCESS] Problème d'accès à une table nommée OF
    Par FredRaid dans le forum Bases de données
    Réponses: 3
    Dernier message: 15/02/2005, 17h22
  2. Problème d'accès à une DB
    Par Mvu dans le forum ASP
    Réponses: 4
    Dernier message: 04/01/2005, 11h36
  3. [TOMCAT] JSP problème d'accès aux méthodes d'une classes
    Par gunnm dans le forum Tomcat et TomEE
    Réponses: 3
    Dernier message: 22/05/2004, 14h02
  4. problème d'acces concurentiel à un fichier
    Par Theoden dans le forum MFC
    Réponses: 2
    Dernier message: 04/03/2004, 09h49

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