【问题标题】:Exception on getSystemService(Context.AUDIO_SERVICE)getSystemService 异常(Context.AUDIO_SERVICE)
【发布时间】:2010-12-12 17:17:37
【问题描述】:

我想创建一个基于某些设置挂断来电的应用,这在 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

【问题讨论】:

    标签: android android-service


    【解决方案1】:

    在 Android 框架调用 onCreate() 之前,对 getSystemService(...) 的调用将不起作用。这发生在服务启动时(即通过 [Context#bindService(...)][1] 或 Context#startService(...))。在尝试从构造函数调用 getSystemService() 时(即在调用 onCreate() 之前),我看到了相同的 NPE。

    你只是调用(new TMLService()).ManageIncomingCall(incomingNumber),它不允许Android初始化你的服务,这是这个NPE的根本原因。

    为了使其正常工作,您必须启动服务,然后调用服务上的方法。要调用方法,我认为您必须使用AIDL 公开它。它可能比你需要的更复杂(也许?)。

    我听说IntentService 是在服务中做事的一种更简单的方法,而且没有 AIDL 的复杂性。这是我认为 IntentService 应该如何工作的示例。尚未对其进行测试,但希望它对入门有用。

    来电者

    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)

    【讨论】:

    • 我会奖励你积分,因为你确实解释了发生的事情......但我昨晚修好了,马上就睡着了。最后,我所要做的就是要求为另一个班级提供服务,而不是创建一个新班级。 @MyPhoneStateListener tml.v1.UI.MainActivity.GetService().ManageIncomingCall(incomingNumber);
    【解决方案2】:
    public void ManageIncomingCall(String incomingNumber)  
    {
        super.onCreate();
        AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
        audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT);
    }
    

    您为什么要以onCreate() 以外的方法调用super.onCreate()?这听起来非常非常错误。

    【讨论】:

    • 听听这个男人的建议。如果您仍然遇到同样的问题,请报告。
    • 对不起,我当时正在测试一些东西,忘了删除那条线......是的,无论有没有 super.onCreate(),错误都会持续存在
    【解决方案3】:

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

    【讨论】:

    • 我拥有这些权限(其中包括)READ_PHONE_STATE 和 MODIFY_AUDIO_SETTINGS
    【解决方案4】:

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

    我要做的第一件事是用 try/catch 块包围 ManageIncomingCall() 中的代码。它至少可以解释发生了什么。

    【讨论】:

    • 但是当你有一个 try/catch 块时,你仍然得到与“未捕获”异常相关的 logcat 条目吗?我假设您也没有重新抛出异常。
    • 在try-catch和nop之后logcat中没有异常,我不会重新抛出异常。
    【解决方案5】:
    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)
    

    您在 TMLService.java 的第 94 行收到 NullPointerException,我猜这是您调用的行:

    audioManage.setRingerMode(AudioManager.RINGER_MODE_SILENT);
    

    我猜audioManage 为空。

    【讨论】:

    • 我在 AudioManager audioManage = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
    猜你喜欢
    • 1970-01-01
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多