使用具有PhoneStateListener功能的BroadcastReceiver

时间:2014-03-19 11:47:58

标签: android broadcastreceiver phone-state-listener

我正在尝试制作一个MissCall应用程序,它会在收到未接来电时自动发送消息。我已经完成了我的应用程序并且工作正常!
以下是完整的方案:
问题:
该应用程序工作正常但是当我重新启动设备时,该应用程序无法正常工作!。只有当我开始使用我的应用程序至少一次之后,它才能正常工作,直到关闭它才能正常工作。
这是我的代码:

package com.example.misscallapp;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class Pref_Main extends PreferenceActivity {
    int checkIt = 0;
    TelephonyManager tm;
    CallStateListener callStateListener = new CallStateListener();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.prefs);
        tm = (TelephonyManager) getBaseContext().getSystemService(
                Context.TELEPHONY_SERVICE);
        tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    private class CallStateListener extends PhoneStateListener {

        @Override
        public void onCallStateChanged(int state, String incomingNumber) { 
           // Is called whenever there is a change in call state
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                // called when someone is ringing to this phone

                Toast.makeText(getBaseContext(), "Incoming: " + incomingNumber,
                        Toast.LENGTH_LONG).show();
                checkIt = 1;
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                checkIt = 0;
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                if (checkIt == 1) {
                    Intent i = new Intent(getBaseContext(),MyService.class);
                    i.putExtra("phno", incomingNumber);
                    startService(i); // service that sends the SMS
                }
                break;
            }
        }

    }



}

解决方案:
我发现解决方法是使用 BroadcastReceiver 。所以我注册了BroadcastReceiver,但它没有给我 PhoneStateListener 的功能
例如,我尝试使用下面的代码,但它没有用,因为 BroadcastReceivers 仅在收到与PhoneStateListener相反的东西时被调用,package com.example.misscallapp; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.telephony.TelephonyManager; import android.widget.Toast; public class CallReceiverBroadcast extends BroadcastReceiver { int checkIt = 0; @Override public void onReceive(Context context, Intent intent) { Bundle extras = intent.getExtras(); if (extras != null) { String state = extras.getString(TelephonyManager.EXTRA_STATE); String incomingNumber = extras.getString(TelephonyManager.EXTRA_INCOMING_NUMBER); if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { Toast.makeText(context , "Incoming: " + incomingNumber, Toast.LENGTH_LONG).show(); checkIt = 1; } if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { // Call received checkIt = 0; } if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) { if (checkIt == 1) { Toast.makeText(context , "This is not shown ", Toast.LENGTH_LONG).show(); Intent i = new Intent(context,MyService.class); i.putExtra("phno", incomingNumber); context.startService(i); } } } } } 每次调用方法onCallStateChanged通话状态发生了变化:

package com.example.misscallapp;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class CallReceiverBroadcast extends BroadcastReceiver {
    int checkIt = 0;
    Context contextt;
    TelephonyManager tm;
    CallStateListener callStateListener = new CallStateListener();
    @Override
    public void onReceive(Context context, Intent intent) {
        contextt = context;
        tm = (TelephonyManager) context.getSystemService(
                Context.TELEPHONY_SERVICE);
        tm.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);

    }

    private class CallStateListener extends PhoneStateListener {

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                // called when someone is ringing to this phone

                Toast.makeText(contextt, "Incoming: " + incomingNumber,
                        Toast.LENGTH_LONG).show();
                checkIt = 1;
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                checkIt = 0;
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                if (checkIt == 1) {
                 //startting the service
                    break;
                }
            }

        }

    }
}

我也尝试过一种解决方法,但它显示了负面结果,如:

onReceive()

上面的代码满足了所有的要求,但是它发送了对称的进展,就好像它是第一次发送1的未接来电一样,如果它是第十次则发送10条消息!
我真的需要帮助, 先感谢您 。


编辑1:
问题在于每次TelphoneManager方法被称为新instance is created CallReceiverBroadcast并注册为Phoone State的监听者。
解决方案:
我创建了{{1}}类静态的每个变量!并且在一定程度上解决了问题!! 但是每次调用服务时仍然会调用两次,这意味着有两个类的实例如何注册为听众,但我不知道为什么。虽然我可以通过一些条件解决它,但它会导致不必要的开销,任何有更好解决方案的人都会受到高度赞赏

3 个答案:

答案 0 :(得分:1)

这是因为一旦你接到了未接来电,那么你就是AT TelephonyManager.CALL_STATE_IDLE阶段并且消息将发送到相应的消息,但是你的服务正在运行模式,为什么它会发送10个或多个短信。

答案 1 :(得分:0)

在第一个版本中,侦听器在启动时不会自动重启(也可能被系统杀死),这就是它在启动时无效的原因。 你也忘了取消注册听众。

在您的第二个版本中,只要您的Manifest设置正确,只要有电话状态更改就应调用onReceive(),例如

  <receiver android:name=".CallReceiverBroadcast" >
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
  </receiver>

但是,Android可能会在调用onReceive()之间回收广播接收器,这意味着在checkIt的调用之间可能无法保留onReceive()变量。您可能需要使用静态变量才能工作。

在第三个版本中,每当调用onReceive()时,您就会创建并注册多个版本的调用状态侦听器。 (注意,tm应指向电话管理器的同一实例),这可能是多次调用它们的原因。

根据您将变量转换为静态变量的方式,问题可能无法解决,因为您可能仍在创建/注册CallStateListener的新实例,尽管您将其存储到静态变量中。

要解决这些问题,您应该通过覆盖广播接收器的onDestroy()取消注册呼叫状态监听器

@Override
public void onDestroy() {
        tm.listen(callStateListener, PhoneStateListener.LISTEN_NONE);
}

但是请注意,没有保证在onReceive()返回后,托管接收者的进程不会被销毁。如果您可以修复它,那么在onReceive()返回之前执行所有处理的第二个版本更可取。

答案 2 :(得分:0)

尝试创建一个bootbroadcast接收器,并在其接收时启动您的服务以检测呼叫。这可确保您的服务在每次设备重启后自动激活。