1

我想创建一个基于某些设置挂断来电的应用程序,这在 Android 1.6 上似乎是不可能的。所以我决定编写一个应用程序,在通话被挂断时将铃声更改为静音。问题是当我调用 getSystemService(Context.AUDIO_SERVICE) 时出现异常。

这些是我的课:

接听电话

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);
        }
    }

}

并且有一个名为 TMLService 的类扩展了包含此方法的 Service

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

就像我说的,当我调用 AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE); 应用程序停止,这就是我在 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
4

5 回答 5

13

The call to getSystemService(...) will not work before onCreate() is called by the Android framework. This happens when the service is started (i.e. by [Context#bindService(...)][1] or Context#startService(...)). I've seen the same NPE when trying to call getSystemService() from a constructor (i.e. before onCreate() is called).

You're simply calling (new TMLService()).ManageIncomingCall(incomingNumber), which doesn't allow Android to initialize your service, which is the root cause of this NPE.

In order to get it working, you'll have to start the service and then call a method on the service. To call a method, I think you have to expose it using AIDL. It might be more complicated than you need for this (maybe?).

I've heard that IntentService is an easier way to do stuff in a service without the complexity of AIDL. Here's a sample of how I think IntentService should work. Haven't tested it, but hopefully its useful to get started.

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)

于 2010-12-16T09:58:44.897 回答
1
public void ManageIncomingCall(String incomingNumber)  
{
    super.onCreate();
    AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
    audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT);
}

Why Are you calling super.onCreate() in a method other than onCreate()? That sounds really, really wrong.

于 2010-12-12T20:02:45.813 回答
0

你有正确的权限吗?如果您错过了烫发,那么该应用程序会在某处的日志中抱怨这一点

于 2010-12-12T17:33:09.147 回答
0

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

The first thing I'd do is surround the code in ManageIncomingCall() with a try/catch block. It might at least give an explanation as to what is going on.

于 2010-12-15T00:54:39.790 回答
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)

You are getting a NullPointerException at line 94 of TMLService.java, I am guessing that this is the line where you call:

audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT);

and I am guessing that audioManage is null.

于 2010-12-15T22:23:56.947 回答