如何检测android中的电话呼叫广播接收器

时间:2011-05-13 10:30:06

标签: android

我正在android中构建一个应用程序,当我的手机中有任何电话时,它将执行一个动作。我用广播接收器和电话状态监听器试过这个。但它没有用。如果我使用活动,那么手机状态监听器工作得很好,但它不适用于广播接收器。我做错了什么?请任何身体帮助......

谢谢&问候

6 个答案:

答案 0 :(得分:3)

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

它的工作!!

答案 1 :(得分:3)

以下是a Chinese BBS的示例。

public class PhoneStatReceiver extends BroadcastReceiver{        

        private static final String TAG = "PhoneStatReceiver"; 

        private static boolean incomingFlag = false;

        private static String incoming_number = null;



        @Override

        public void onReceive(Context context, Intent intent) {

                //如果是拨打电话

                if(intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)){                        

                        incomingFlag = false;

                        String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);        

                        Log.i(TAG, "call OUT:"+phoneNumber);                        

                }else{                        

                        //如果是来电

                        TelephonyManager tm = 

                            (TelephonyManager)context.getSystemService(Service.TELEPHONY_SERVICE);                        



                        switch (tm.getCallState()) {

                        case TelephonyManager.CALL_STATE_RINGING:

                                incomingFlag = true;//标识当前是来电

                                incoming_number = intent.getStringExtra("incoming_number");

                                Log.i(TAG, "RINGING :"+ incoming_number);

                                break;

                        case TelephonyManager.CALL_STATE_OFFHOOK:                                

                                if(incomingFlag){

                                        Log.i(TAG, "incoming ACCEPT :"+ incoming_number);

                                }

                                break;



                        case TelephonyManager.CALL_STATE_IDLE:                                

                                if(incomingFlag){

                                        Log.i(TAG, "incoming IDLE");                                

                                }

                                break;

                        } 

                }

        }

}

AndroidManifest.xml

中注册
<receiver android:name=".filter.PhoneStatReceiver">  

            <intent-filter>

                 <action android:name="android.intent.action.PHONE_STATE"/>           

                 <action android:name="android.intent.action.NEW_OUTGOING_CALL" />

            </intent-filter>

</receiver>

<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>

<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"></uses-permission>

答案 2 :(得分:2)

答案 3 :(得分:1)

我在这里读过 https://gist.github.com/ftvs/e61ccb039f511eb288ee

对我来说很好。 Android版本5.0。

接下来是我的任务。

我的应用程序必须观察所有调用事件。并区分呼入,呼出电话。来电完成后,必须随时创建新的来电。设置号码中指定的电话号码。此电话号码是门禁控制器的号码。 (https://www.pal-es.com/3g-eng) 它为为用户打开自动门而不是在白名单中作弊。此应用程序可在独立的智能手机中使用,仅用于完成此任务。

一些功能也可以在这里找到。

例如:

  1. 如何从Runnable线程更新textView值
  2. 我外向 不能从BroadcastReceiver类调用,因为这是不可能的。它 需要从MainActivity获取。玩得开心)))试试看。

MainActivity.java

package com.example.root.test02;

import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
    https://androidexample.com/Introduction_To_Broadcast_Receiver_Basics/index.php?view=article_discription&aid=60&aaid=85
    https://androidexample.com/Incomming_Phone_Call_Broadcast_Receiver__-_Android_Example/index.php?view=article_discription&aid=61
    https://stackoverflow.com/questions/5990590/how-to-detect-phone-call-broadcast-receiver-in-android
    https://stackoverflow.com/questions/1083527/how-to-block-calls-in-android
    https://stackoverflow.com/questions/5571249/how-do-i-retrieve-the-incoming-phone-calls-number-while-ringing-and-store-it-in
    https://gist.github.com/ftvs/e61ccb039f511eb288ee
*/

public class MainActivity extends AppCompatActivity {

    public TextView textView;
    public String MetallurgTelNumber = "+79091112233"; // need redirect calls to this phone number

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        PhonecallReceiver rv = new PhonecallReceiver();

        Thread myThread = new Thread(myRunnable);
        myThread.start();

        textView = (TextView) findViewById(R.id.incoming_calls_log);
        textView.setText("Журнал входящих звонков:");

        TextView version = (TextView) findViewById(R.id.tvVersion);
        version.setText("v3.0");
    }

    public void CallToMetallurgGates()
    {
        Intent callIntent = new Intent(Intent.ACTION_CALL);
        callIntent.setData(Uri.parse("tel:" + MetallurgTelNumber));
        startActivity(callIntent);
    }


    Runnable myRunnable = new Runnable() {
        @Override
        public void run()
        {
            while (true)
            {
                try
                {
                    Thread.sleep(50); // Waits for 1 second (1000 milliseconds)
                    if (MyProperties.getInstance().NewIncomingCall)
                    {
                        CallToMetallurgGates();
                        MyProperties.getInstance().NewIncomingCall = false;
                        MyProperties.getInstance().CallId++;

                        String dbg_str = Integer.toString(MyProperties.getInstance().CallId) + " " + MyProperties.getInstance().PhoneNumber;

                        textView.post(new Runnable() {
                            public void run() {
                                SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
                                String currentDateandTime = sdf.format(new Date());
                                textView.append("\n" + currentDateandTime);
                                textView.append("\n(" + Integer.toString(MyProperties.getInstance().CallId) + "): " + MyProperties.getInstance().PhoneNumber);
                                textView.append("\nЗвоню на ворота: " + MetallurgTelNumber);
                            }
                        });


                        Thread.sleep(5000); // Waits for 1 second (1000 milliseconds)
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

        }
    };
}

PhonecallReceiver.java

package com.example.root.test02;

import java.util.Date;

import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;


import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

import java.util.Date;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;

import com.example.root.test02.MainActivity;



public class PhonecallReceiver  extends BroadcastReceiver {

        // как только происходит входящий звонок
    protected void onIncomingCallStarted(Context ctx, String number, Date start) {
        Log.d("onIncomingCallStarted",number);
    }

        // как только снимается (hook off) трубка и делается исходящий
    protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
        Log.d("onOutgoingCallStarted",number);
    }

        // когда нажимается кнопка Завершить на входящем звонке
    protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
        Log.d("onIncomingCallEnded",number);
        MyProperties.getInstance().NewIncomingCall = true;
        MyProperties.getInstance().PhoneNumber = number + " завершенный";
    }

        // когда нажимается кнопка Завершить на исходящем звонке
    protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
        Log.d("onOutgoingCallEnded",number);
    }

        // когда не сняли трубку при входящем звонке (пропуск звонка)
    protected void onMissedCall(Context ctx, String number, Date start) {
        MyProperties.getInstance().NewIncomingCall = true;
        MyProperties.getInstance().PhoneNumber = number + " пропущенный";

    }

    //Incoming call-  goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
    //Outgoing call-  goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
    public void onCallStateChanged(Context context, int state, String number) {
        if(lastState == state){
            //No change, debounce extras
            return;
        }
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                isIncoming = true;
                callStartTime = new Date();
                savedNumber = number;
                onIncomingCallStarted(context, number, callStartTime);
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                //Transition of ringing->offhook are pickups of incoming calls.  Nothing done on them
                if(lastState != TelephonyManager.CALL_STATE_RINGING){
                    isIncoming = false;
                    callStartTime = new Date();
                   onOutgoingCallStarted(context, savedNumber, callStartTime);
                }
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                //Went to idle-  this is the end of a call.  What type depends on previous state(s)
                if(lastState == TelephonyManager.CALL_STATE_RINGING){
                    //Ring but no pickup-  a miss
                    onMissedCall(context, savedNumber, callStartTime);
                }
                else if(isIncoming){
                    onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
                }
                else{
                    onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
                }
                break;
        }
        lastState = state;
    }

    private static int lastState = TelephonyManager.CALL_STATE_IDLE;
    private static Date callStartTime;
    private static boolean isIncoming;
    private static String savedNumber;  //because the passed incoming is only valid in ringing

    public void onReceive(Context context, Intent intent) {

        //We listen to two intents.  The new outgoing call only tells us of an outgoing call.  We use it to get the number.
        if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
            savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
        }
        else{
            String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
            String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
            int state = 0;
            if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
                state = TelephonyManager.CALL_STATE_IDLE;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
                state = TelephonyManager.CALL_STATE_OFFHOOK;
            }
            else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
                state = TelephonyManager.CALL_STATE_RINGING;
            }

            onCallStateChanged(context, state, number);
        }
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.root.test02">

    **<uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <uses-permission android:name="android.permission.CALL_PHONE" />**

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.AppCompat.Light">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        **<receiver android:name="com.example.root.test02.PhonecallReceiver">
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
            </intent-filter>
        </receiver>**
    </application>

</manifest>

MyProperties.java

package com.example.root.test02;

public class MyProperties {
    private static MyProperties mInstance= null;

    public boolean NewIncomingCall = false;
    public int CallId = 0;
    public String PhoneNumber = "";


    protected MyProperties(){}

    public static synchronized MyProperties getInstance() {
        if(null == mInstance){
            mInstance = new MyProperties();
        }
        return mInstance;
    }
}

答案 4 :(得分:0)

希望这符合您的目的,

请检查一下。

<receiver android:name="ClassName">
  <intent-filter>             
    <action android:name="android.intent.action.ANSWER">/action>
  </intent-filter>
</receiver>

答案 5 :(得分:0)

我最初经历了同样的事情但后来我将以下权限添加到我的清单。

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
当然,在我的代码中,当我接到电话时,我正在显示一个祝酒词。 因此,您可能需要添加与您的要求相对应的其他权限。