2010-12-12 5 views
1

Je voulais créer une application qui supprime un appel entrant en fonction de certains paramètres, ce qui semble impossible sur Android 1.6. J'ai donc décidé d'écrire une application qui change le Ringer en mode silencieux quand l'appel aurait été abandonné. La chose est que lorsque j'appelle getSystemService (Context.AUDIO_SERVICE), j'obtiens une exception.Exception sur getSystemService (Context.AUDIO_SERVICE)

Ce sont mes classes:

CallReceiver

public class CallReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     MyPhoneStateListener phoneListener = new MyPhoneStateListener(); 
     TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
     telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);  
    } 

} 

MyPhoneStateListener

public class MyPhoneStateListener extends PhoneStateListener { 

    public void onCallStateChanged(int state, String incomingNumber){ 

     if (state == TelephonyManager.CALL_STATE_RINGING) 
     { 
      Log.d("DEBUG", "RINGING"); 
      (new TMLService()).ManageIncomingCall(incomingNumber); 
     } 
    } 

} 

Et il y a une classe appelée TMLService qui étend son service qui contient cette méthode

public void ManageIncomingCall(String incomingNumber) 
{ 
    super.onCreate(); 
    AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
    audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT); 
} 

Comme je l'ai dit, quand j'appelle AudioManager audioManage = (AudioManager) getSystemService (Context.AUDIO_SERVICE); l'application s'arrête et c'est ce que je reçois dans le LogCat:

D/DEBUG ( 356): RINGING 
D/AndroidRuntime( 356): Shutting down VM 
W/dalvikvm( 356): threadid=3: thread exiting with uncaught exception (group=0x4001aa28) 
E/AndroidRuntime( 356): Uncaught handler: thread main exiting due to uncaught exception 
D/CallNotifier( 103): RINGING... (new) 
E/AndroidRuntime( 356): java.lang.NullPointerException 
E/AndroidRuntime( 356): at android.content.ContextWrapper.getSystemService(ContextWrapper.java:335) 
E/AndroidRuntime( 356): at tml.v1.Service.TMLService.ManageIncomingCall(TMLService.java:94) 
E/AndroidRuntime( 356): at tml.v1.Service.MyPhoneStateListener.onCallStateChanged(MyPhoneStateListener.java:14) 
E/AndroidRuntime( 356): at android.telephony.PhoneStateListener$2.handleMessage(PhoneStateListener.java:298) 
E/AndroidRuntime( 356): at android.os.Handler.dispatchMessage(Handler.java:99) 
E/AndroidRuntime( 356): at android.os.Looper.loop(Looper.java:123) 
E/AndroidRuntime( 356): at android.app.ActivityThread.main(ActivityThread.java:4203) 
E/AndroidRuntime( 356): at java.lang.reflect.Method.invokeNative(Native Method) 
E/AndroidRuntime( 356): at java.lang.reflect.Method.invoke(Method.java:521) 
E/AndroidRuntime( 356): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791) 
E/AndroidRuntime( 356): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549) 
E/AndroidRuntime( 356): at dalvik.system.NativeStart.main(Native Method) 
D/CallNotifier( 103): onNewRingingConnection(): incoming 

Répondre

13

L'appel à getSystemService(...) ne fonctionnera pas avant que onCreate() ne soit appelé par le framework Android. Cela se produit lorsque le service est démarré (c'est-à-dire par [Contexte # bindService (...)] [1] ou Context#startService(...)). J'ai vu le même NPE en essayant d'appeler getSystemService() à partir d'un constructeur (c'est-à-dire avant que onCreate() soit appelé).

Vous appelez simplement (new TMLService()).ManageIncomingCall(incomingNumber), ce qui ne permet pas à Android d'initialiser votre service, qui est la cause première de ce NPE. Pour le faire fonctionner, vous devrez démarrer le service, puis appeler une méthode sur le service. Pour appeler une méthode, je pense que vous devez l'exposer en utilisant AIDL. C'est peut-être plus compliqué que ce dont vous avez besoin (peut-être?).

J'ai entendu dire que IntentService est un moyen plus facile de faire des choses dans un service sans la complexité d'AIDL. Voici un exemple de comment je pense que IntentService devrait fonctionner. Je ne l'ai pas testé, mais j'espère que c'est utile pour commencer.

CallReceiver

public class CallReceiver extends BroadcastReceiver { 

    @Override 
    public void onReceive(Context context, Intent intent) { 
     MyPhoneStateListener phoneListener = new MyPhoneStateListener(context); 
     TelephonyManager telephony = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); 
     telephony.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE); 
    } 

} 

MyPhoneStateListener

public class MyPhoneStateListener extends PhoneStateListener { 
    private final Context mContext; 

    public MyPhoneStateListener(Context context) { 
     this.mContext = context; 
    } 

    public void onCallStateChanged(int state, String incomingNumber){ 

     if (state == TelephonyManager.CALL_STATE_RINGING) 
     { 
      Log.d("DEBUG", "RINGING"); 

      // OPTION 1: Do it on the main thread (might be bad :)) 
      //AudioManager audioManage = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE); 
      //audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT); 

      // OPTION 2: Use an IntentService (a bit easier than AIDL) 
      Intent intent = new Intent(TMLIntentService.ACTION_SILENCE_RINGER); 
      mContext.startService(intent); 
     } 
    } 

} 

TMLIntentService

public class TMLIntentService extends IntentService { 
    public static final String ACTION_SILENCE_RINGER = "org.example.intentservice.ACTION_SILENCE_RINGER"; 

    @Override 
    public void onHandleIntent(Intent intent) { 
     if(ACTION_SILENCE_RINGER.equals(intent.getAction()) { 
      AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
      audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT); 
     } 
    } 
} 

AndroidManifest.xml

<service android:name=".TMLIntentService"> 
    <intent-filter> 
     <action android:name="org.example.intentservice.ACTION_SILENCE_RINGER" /> 
    </intent-filter> 
</service> 

[1]: http://d.android.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int)

+0

Je vais vous récompenser les points parce que vous avez réellement expliqué ce qui s'est passé ... mais je l'ai réparé la nuit dernière et je me suis endormi tout de suite. À la fin, tout ce que je devais faire était de demander le service à une autre classe au lieu d'en créer une nouvelle. @ MyPhoneStateListener tml.v1.UI.MainActivity.GetService(). ManageIncomingCall (incomingNumber); – PedroC88

+0

Merci :) Je suis content que vous l'ayez fait fonctionner. –

0

Avez-vous l'autorisation correcte? Si vous manque une perm, l'application va se plaindre à ce sujet dans les journaux quelque part

+0

Je ces autorisations (entre autres) et READ_PHONE_STATE MODIFY_AUDIO_SETTINGS – PedroC88

0
public void ManageIncomingCall(String incomingNumber) 
{ 
    super.onCreate(); 
    AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 
    audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT); 
} 

Pourquoi appelez-vous super.onCreate() dans une autre méthode que onCreate()? Cela semble vraiment, vraiment faux.

+0

Écoutez ces conseils mans. Et puis rapportez si vous avez toujours le même problème. –

+0

Désolé, je testais quelque chose à ce moment et j'ai oublié d'effacer cette ligne ... oui, l'erreur persiste avec ou sans le super.onCreate() – PedroC88

0

E/AndroidRuntime( 356): Uncaught handler: thread main exiting due to uncaught exception

La première chose que je ferais est entourer le code dans ManageIncomingCall() avec un bloc try/catch. Cela pourrait au moins donner une explication sur ce qui se passe.

+0

ex.getMessage() == null – PedroC88

+0

Mais vous obtenez toujours le logcat entrée relative à une exception «non interceptée» lorsque vous avez un bloc try/catch là-dedans? Je suppose que vous ne relancez pas non plus l'exception. – Squonk

+0

Aucune exception dans le logcat après le try-catch et nop, je ne réécrit pas l'exception. – PedroC88

0
E/AndroidRuntime( 356): java.lang.NullPointerException 
E/AndroidRuntime( 356): at android.content.ContextWrapper.getSystemService(ContextWrapper.java:335) 
E/AndroidRuntime( 356): at tml.v1.Service.TMLService.ManageIncomingCall(TMLService.java:94) 

vous obtenez un NullPointerException à la ligne 94 de TMLService.java, je devine que c'est la ligne où vous appelez:

audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT); 

et je devine que audioManage est nulle.

+0

Je reçois l'exception à AudioManager audioManage = (AudioManager) getSystemService (Context.AUDIO_SERVICE); – PedroC88

Questions connexes