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 :

Notification depuis un service.


Sujet :

Android

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 17
    Points : 18
    Points
    18
    Par défaut Notification depuis un service.
    Bonjour à tous!

    Je viens à vous car j'ai un petit problème pour envoyer une notification depuis un background service.

    En effet j'ai un service qui travail avec un serveur php distant pour savoir si des infos sont dispo et j'aimerai une notification quand c'est le cas. J'arrive à récupérer mes infos distantes mais impossible d'afficher une notification sans que tous n'explose :p

    Du coup je me pose 2 questions,
    Est-il "propre" d'afficher une notification depuis un service ?
    Si oui pourquoi mon code ne marche pas?

    J'ai fait un tour de google et j'ai vu que certain propose du code pour le faire, mais ça ne semble pas marcher chez moi...

    Des que j'essaie de créer une notification j'ai une erreur Java.lang.NullPointerException sur la ligne suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    Je vous montre ce que j'ai fait :

    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
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
     
    package com.example.service;
     
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintStream;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.net.SocketAddress;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
     
    import com.example.f_s.MainActivity;
    import com.example.f_s.R;
     
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.os.IBinder;
     
    public class BackgroundService extends Service{
     
    	Context context;
    	@Override
    	public IBinder onBind(Intent arg0) {
    		return null;
    	}
     
    	public void onCreate() {
    		super.onCreate(); 
    		start();
        } 
     
    	@Override
        public void onDestroy() {
            super.onDestroy();
        } 
     
    	public void start(){       
     
    		OutputStream sortieSocket;
    		PrintStream bw;
     
    		KeyStore trustStore;
     
    		BufferedReader br;
     
    		String str = "";
     
    		try {
     
    			// Configuration de la socket pour accepter le ceritificat auto signé
    			trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
    			trustStore.load(null, null);			 
    	        MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
    	        sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
     
    	        // Création de la socket
    	        Socket so = sf.createSocket();
    	        SocketAddress soA = new InetSocketAddress("192.168.1.90" , 8098);
     
    	        // Connection au serveur
    	        so.connect(soA);
     
    	        // Récupération des flux sur la socket 
    	        sortieSocket = so.getOutputStream();
    	        bw = new PrintStream(sortieSocket);
    	        br = new BufferedReader(new InputStreamReader(so.getInputStream()));
     
    	        // Envoie des identifiants au serveur
    			bw.print("zefzefzfe");
    			bw.flush();
     
    			// Lecture des données du serveur 
    			while(str != null){	
    				str = br.readLine();
    				System.out.println("Réponse : "+str);
    				createNotification();
    			}
     
    			// Fermeture des ressources
    			bw.close();
    			br.close();
    			so.close();
     
    		} catch (KeyStoreException e) {
    			e.printStackTrace();
    		} catch (NoSuchAlgorithmException e) {
    			e.printStackTrace();
    		} catch (CertificateException e) {
    			e.printStackTrace();
    		} catch (IOException e) {
    			e.printStackTrace();
    		} catch (KeyManagementException e) {
    			e.printStackTrace();
    		} catch (UnrecoverableKeyException e) {
    			e.printStackTrace();
    		}		
     
    	}
     
    	public void createNotification(){
    		 NotificationManager notificationManager = null;
    		 try {
    			 notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 
    		 } catch (Exception e) {
    			 System.out.println(e.toString());
    		 }
     
            	 int icon = R.drawable.ic_launcher;
            	 CharSequence tickerText = "Pet Parrot";
            	 long when = System.currentTimeMillis();
     
            	 Notification notification = new Notification(icon, tickerText, when);
            	 notification.flags |= Notification.FLAG_AUTO_CANCEL;
            	 Context context = getApplicationContext();
            	 CharSequence contentTitle = "Hungry!";
            	 CharSequence contentText = "your parrot food meter is: ";
            	 Intent notificationIntent = new Intent(context, MainActivity.class);
            	 PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
     
            	 notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
     
            	 notificationManager.notify(1, notification);
    	}
    }
    Voici mon manifest :

    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
     
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.f_s"
        android:versionCode="1"
        android:versionName="1.0" >
     
        <uses-sdk
            android:minSdkVersion="8"
            android:targetSdkVersion="17" />
     
        <uses-permission android:name="android.permission.INTERNET" />
    	<uses-permission android:name="com.example.service.BACKGROUNDSERVICE_PERMISSION"/>
     
    	<permission android:name="com.example.service.BACKGROUNDSERVICE_PERMISSION" />
     
     
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="com.example.f_s.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
     
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity
                android:name="com.example.f_s.Test"
                android:label="@string/title_activity_test" >
            </activity>
            <activity
                android:name="com.example.f_s.LoginActivity"
                android:label="Connexion"
                android:windowSoftInputMode="adjustResize|stateVisible" >
            </activity>
     
            <service 
                android:exported="true"
                android:name="com.example.service.BackgroundService"
                android:permission="com.example.service.BACKGROUNDSERVICE_PERMISSION" 
                android:enabled="true"
              />  
     
            <receiver android:name="com.example.service.BackgroundServiceReceiver">
    	        <intent-filter>
    	            <action android:name="android.intent.action.BOOT_COMPLETED" />
    	            <category android:name="android.intent.category.HOME" />
    	        </intent-filter>
    	    </receiver>
     
        </application>
     
    </manifest>
    Merci d'avance.

  2. #2
    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
    Bonjour,
    Citation Envoyé par Fabien.31 Voir le message
    Du coup je me pose 2 questions,
    Est-il "propre" d'afficher une notification depuis un service ?
    Oui, c'est même le seul intérêt des notifications présenter une information sans qu'une UI (activité) ne soit visible.

    Pour le code,

    Commencons par "start()"... je pense que le nom de la fonction n'est pas bien choisi... en général un truc "start()" démarre quelque chose qui se termine quand on appelle "stop()"... mais c'est anecdotique
    Je pense que la partie de récupération est ok... a part le 192.168.1.90 bien entendu qui ne fonctionnera pas depuis un émulateur (puisque l'adresse est non routable). Mais j'imagine que pour tester vous modifiez cette valeur à une adresse plus appropriée.

    Par contre... tous les catch() à la fin c'est du grand n'importe quoi ! Il ne faut jamais laisser eclipse gérer les exceptions tout seul !
    Remplacer par un truc plus "Android" comme:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
           ....
        } catch (Exception ex) { // vu que toutes les exceptions sont gérées pareil...
           Log.e("Service","Erreur récupération données",ex);
        }
    Attention... le start() fait un appel réseau... hors il est appelé depuis le onCreate() du service ! ce qui est interdit ! Dans le cas ou le traitement d'un Intent peut être long penser à utiliser IntentService qui fournit toute la gestion des threads nécessaire !


    Il en est de même coté createNotification() ... le catch() devrait être remplacé par un Log correct (System.out.println n'affiche que le nom de l'exception dans le system.out... et on sait jamais ou il est ce foutu System.out... alors que le log LogCat lui....).

    CharSequence tickerText = "Pet Parrot";
    tickerText est inutile ici... avec en prime perte de connaissance ("Pet Parrot" étant un String, on perd cette information, String implémente CharSequence autant conserver String).

    Ensuite... pourquoi utiliser getApplicationContext() ?
    Un "Service" est déjà un context ! (d'ailleurs utilisé pour getSystemService() )

    Ensuite depuis un petit moment il faut utiliser un Noitification.Builder pour créer les notifications comme dans:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     new Notification.Builder(mContext)
             .setTicker(tickerText)
             .setSmallIcon(icon)
             .build();
    (si Android 2.x +, utiliser NotificationCompat.Builder ).
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 17
    Points : 18
    Points
    18
    Par défaut
    Merci beaucoup pour tous ces conseils!

    J'ai corrigé le code en suivants tes indications et oui le "192.168.1.90" est temporaire.

    J'ai donc choisi d'utiliser NotificationCompat.Builder cependant j'ai encore un soucis.

    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
     
    public void createNotification(){
    		try{
     
    			 NotificationCompat.Builder builder =  
    					 new NotificationCompat.Builder(this)  
    			         .setSmallIcon(R.drawable.ic_launcher)  
    			         .setContentTitle("Notifications Example")  
    			         .setContentText("This is a test notification");  
     
    			 Intent notificationIntent = new Intent(this, MainActivity.class);  
    			 PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent,   
    			    PendingIntent.FLAG_UPDATE_CURRENT);  
    			 builder.setContentIntent(contentIntent);  
     
    			 // Add as notification  
    			 NotificationManager manager = (NotificationManager) getSystemService(context.NOTIFICATION_SERVICE);  
    			 manager.notify(1, builder.build());
     
    		} catch (Exception ex) { // vu que toutes les exceptions sont gérées pareil...
    			Log.e("Service","Erreur notification : ", ex);
    		}
    	}
    J'ai un Java.lang.NullPointerException sur cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Intent notificationIntent = new Intent(this, MainActivity.class);
    Pourtant en regardant la doc je trouve ce constructeur :

    Intent(Context packageContext, Class<?> cls)
    Create an intent for a specific component.

    Un "Service" est déjà un context !
    J'ai tout compris de travers?

  4. #4
    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
    On pourrait avoir le logcat détaillé ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 17
    Points : 18
    Points
    18
    Par défaut
    Le voici :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    02-12 16:35:43.893: E/Service(1971): Erreur notification : 
    02-12 16:35:43.893: E/Service(1971): java.lang.NullPointerException
    02-12 16:35:43.893: E/Service(1971): 	at android.content.ComponentName.<init>(ComponentName.java:75)
    02-12 16:35:43.893: E/Service(1971): 	at android.content.Intent.<init>(Intent.java:3301)
    02-12 16:35:43.893: E/Service(1971): 	at com.example.service.BackgroundService.createNotification(BackgroundService.java:112)
    02-12 16:35:43.893: E/Service(1971): 	at com.example.service.BackgroundService.lancementSocket(BackgroundService.java:89)
    02-12 16:35:43.893: E/Service(1971): 	at com.example.service.BackgroundService.onCreate(BackgroundService.java:42)
    02-12 16:35:43.893: E/Service(1971): 	at com.example.f_s.MainActivity$2$1.run(MainActivity.java:119)
    02-12 16:35:43.893: E/Service(1971): 	at java.lang.Thread.run(Thread.java:856)
    La ligne 112 correspond à Intent notificationIntent = new Intent(this, MainActivity.class);

  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
    C'est super étonnant....

    Voici le code appelé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public Intent(Context packageContext, Class<?> cls) {
            mComponent = new ComponentName(packageContext, cls);
        }
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        public ComponentName(Context pkg, Class<?> cls) {
            mPackage = pkg.getPackageName();
            mClass = cls.getName();
        }
    Ce qui voudrait dire que "this" est null !
    Ou cls est null !!!
    Ce qui est proprement impossible dans:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    new Intent(this, MainActivity.class);
    C'est bien la dernière version du code qui est exécutée ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 17
    Points : 18
    Points
    18
    Par défaut
    Oui c'est bien le code exécuté. J'ai aussi testé avec this.context n'étant pas trop sur de moi.

    J'ai oublié de préciser quelque chose dans le onCreate() ou le manifest peut être?

  8. #8
    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
    Bon... alors là j'avoue que je suis médusé....

    Reste plus que le step-by-step debug...

    Essayes de mettre un point d'arrêt à la création de l'intent
    Et faire du step-into pour regarder les variables qui sont nulles....
    (ne pas oublier de lancer l'application en mode "debug" et non en simple "run").
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 17
    Points : 18
    Points
    18
    Par défaut
    Je t'avoue n'avoir jamais fait de débug avec Eclipse donc je te joint des screens pour que tu puisse voire par toi même.

    Je te met le dernier step que je fait avant de trouver un "Null" :


    Et l'image du step d'après :


    Merci de ta patience en tout cas!

  10. #10
    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
    Il faudrait installer les sources d'Android
    1. S'assurer que les sources sont bien téléchargés (par le sdk-manager)
    2. Dans Eclipse , dans la fenetre de debug, il doit y avoir un bouton "attach sources"... choisir répertoire externe, puis android-sdk/sources/android-17

    Sinon, ben c'est un step debugger classique ^^

    A vue de nez, je dirai que le contexte de base n'a pas été initialisé....
    Cela arrive quand on l'utilise *avant* l'appel à onCreate() d'habitude....

    A moins que pour un service, le contexte ne soit initialisé qu'après l'appel à onCreate()

    Hmmm... et si tu bouges l'appel du start() dans onStartCommand() ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2011
    Messages
    17
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2011
    Messages : 17
    Points : 18
    Points
    18
    Par défaut
    Bon bah c'était de ma faute...

    Je m'explique, je n'ai pas lu attentivement comment fonctionnait un service, du coup j'ai considéré que c'était une "simple" class Java .

    Bêtement j'avais donc fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    BackgroundService b = new BackgroundService();
    b.onCreate();
    au lieu de :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Intent intent = new Intent(MainActivity.this,BackgroundService.class);
    startService(intent);
    C'est quand tu m'as parlé du onStartCommand() et que j'ai cherché sur google ce que c'était que j'ai compris ma boulette.

    Je te remercie encore nicroman !

    Sujet résolu.

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

Discussions similaires

  1. Lancer une notification depuis un service android
    Par azstar dans le forum Android
    Réponses: 2
    Dernier message: 09/07/2012, 11h26
  2. Réponses: 3
    Dernier message: 06/09/2006, 17h51
  3. Impression d'un fichier Word depuis un service NT
    Par Gilius dans le forum Windows
    Réponses: 1
    Dernier message: 23/12/2005, 13h41
  4. [C#] Execution d'un fichier VBS depuis un service Windows
    Par 0r3L dans le forum Windows Forms
    Réponses: 2
    Dernier message: 10/11/2005, 22h58
  5. Réponses: 2
    Dernier message: 05/11/2005, 13h48

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