异常的getSystemService(Context.AUDIO_SERVICE)异常、getSystemService、AUDIO_SERVICE、Context

2023-09-07 00:46:57 作者:萌萌懂懂

我想创建一个应用程序,降低来电基础的某些设置,这似乎是不可能的在Android 1.6。所以,我决定写一个应用程序,改变铃声静音通话时会一直下降。问题是,当我叫getSystemService(Context.AUDIO_SERVICE)我得到一个例外。

这些都是我的课:

CallReceiver

 公共类CallReceiver扩展的BroadcastReceiver {

    @覆盖
    公共无效的onReceive(上下文的背景下,意图意图){
        MyPhoneStateListener phoneListener =新MyPhoneStateListener();
        TelephonyManager电话=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
    }

}
 

MyPhoneStateListener

 公共类MyPhoneStateListener扩展PhoneStateListener {

    公共无效onCallStateChanged(INT状态,串incomingNumber){

        如果(国家== TelephonyManager.CALL_STATE_RINGING)
        {
            Log.d(调试,振铃);
            (新TMLService())ManageIncomingCall(incomingNumber)。
        }
    }

}
 
ApplicationContext context new ClassPathXmlApplicationContext applicationContext.xml 异常

和有一类称为TMLService延伸服务,其中包含该方法

 公共无效ManageIncomingCall(字符串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):关闭虚拟机
W / dalvikvm(356):主题ID = 3:线程退出与未捕获的异常(组= 0x4001aa28)
E / AndroidRuntime(356):未捕获的处理程序:螺纹主力退出,由于未捕获的异常
D / CallNotifier(103):正在响铃...(新)
E / AndroidRuntime(356):显示java.lang.NullPointerException
E / AndroidRuntime(356):在android.content.ContextWrapper.getSystemService(ContextWrapper.java:335)
E / AndroidRuntime(356):在tml.v1.Service.TMLService.ManageIncomingCall(TMLService.java:94)
E / AndroidRuntime(356):在tml.v1.Service.MyPhoneStateListener.onCallStateChanged(MyPhoneStateListener.java:14)
E / AndroidRuntime(356):在android.telephony.PhoneStateListener $ 2.handleMessage(PhoneStateListener.java:298)
E / AndroidRuntime(356):在android.os.Handler.dispatchMessage(Handler.java:99)
E / AndroidRuntime(356):在android.os.Looper.loop(Looper.java:123)
E / AndroidRuntime(356):在android.app.ActivityThread.main(ActivityThread.java:4203)
E / AndroidRuntime(356):在java.lang.reflect.Method.invokeNative(本机方法)
E / AndroidRuntime(356):在java.lang.reflect.Method.invoke(Method.java:521)
E / AndroidRuntime(356):在com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:791)
E / AndroidRuntime(356):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
E / AndroidRuntime(356):在dalvik.system.NativeStart.main(本机方法)
D / CallNotifier(103):onNewRingingConnection():传入
 

解决方案

getSystemService调用(...)的onCreate将无法正常工作()被称为Android框架。发生这种情况时,启动该服务(即通过[环境#bindService(...)] [1]或Context#startService(...)).我见过试图打电话的时候,同样的NPE getSystemService()从构造函数(即前的onCreate()是所谓的)。

您只是简单地调用(新TMLService())。ManageIncomingCall(incomingNumber),这不允许的Andr​​oid初始化服务,这是根本原因这NPE。

为了得到它的工作,你就必须启动该服务,然后调用该服务的方法。要调用一个方法,我认为你必须使用 AIDL 揭露它。它可能比你需要的更复杂的(可能?)。

我听说 IntentService 是一个更简单的方法做的东西,在一个服务,而不所述AIDL的复杂性。下面是我怎么想IntentService应该工作的样本。没有测试过,但希望它有用的开始。

CallReceiver

 公共类CallReceiver扩展的BroadcastReceiver {

    @覆盖
    公共无效的onReceive(上下文的背景下,意图意图){
        MyPhoneStateListener phoneListener =新MyPhoneStateListener(上下文);
        TelephonyManager电话=(TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(phoneListener,PhoneStateListener.LISTEN_CALL_STATE);
    }

}
 

MyPhoneStateListener

 公共类MyPhoneStateListener扩展PhoneStateListener {
    私人最终语境mContext;

    公共MyPhoneStateListener(上下文的背景下){
        this.mContext =背景;
    }

    公共无效onCallStateChanged(INT状态,串incomingNumber){

        如果(国家== TelephonyManager.CALL_STATE_RINGING)
        {
            Log.d(调试,振铃);

            //选择1:你是在主线程(可能是不好的:))
            // AudioManager audioManage =(AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
            //audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT);

            //方案2:使用IntentService(比AIDL容易一点)
            意向意图=新的意图(TMLIntentService.ACTION_SILENCE_RINGER);
            mContext.startService(意向);
        }
    }

}
 

TMLIntentService

 公共类TMLIntentService扩展IntentService {
    公共静态最后弦乐ACTION_SILENCE_RINGER =org.example.intentservice.ACTION_SILENCE_RINGER;

    @覆盖
    公共无效onHandleIntent(意向意图){
        如果(ACTION_SILENCE_RINGER.equals(intent.getAction()){
            AudioManager audioManage =(AudioManager)getSystemService(Context.AUDIO_SERVICE);
            audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT);
        }
    }
}
 

AndroidManifest.xml中

 <服务机器人:名称=。TMLIntentService>
    <意向滤光器>
        <作用机器人:名称=org.example.intentservice.ACTION_SILENCE_RINGER/>
     &所述; /意图滤光器>
< /服务>
 

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

I wanted to create an app that drops an incoming call based on some settings, that seems to be impossible on Android 1.6. So I decided to write an app that changes the Ringer to mute when the call would've been dropped. The thing is that when I call getSystemService(Context.AUDIO_SERVICE) I get an exception.

These are my 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);
        }
    }

}

And there is a class called TMLService that extends Service which contains this method

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

Like I said, when I call AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE); the application stops and this is what I get in the 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

解决方案

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)