【问题标题】:Android Broadcast Receiver Not triggeringAndroid广播接收器未触发
【发布时间】:2016-07-17 10:56:29
【问题描述】:

在我的代码中找出问题 - 在帖子底部回答。

我正在学习如何在 android 中使用广播接收器。 我已经创建了一个接收器类并将其注册到清单中。

当我运行我的应用时,它不会触发。

我认为这是因为接收器必须至少手动调用一次,然后才能被 android 操作系统自动触发。 虽然我是新手,但我可能会弄错。

我正在向 tutorialspointvogella 网站学习。

我需要知道如何让它在我接到来电时真正触发。

这是我的清单文件:

<?xml version="1.0" encoding="utf-8"?>

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

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

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

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

我的广播类如下,位于 java 文件夹中

package com.teqnet.receivers;

import java.util.Date;

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

public class PhoneCallReceiver extends BroadcastReceiver {


private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber;  


@Override
public void onReceive(Context context, Intent intent) {
    Toast.makeText(context,"Receiver Triggered",Toast.LENGTH_LONG).show();

    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;
            Toast.makeText(context,"Phone Ringing",Toast.LENGTH_LONG).show();
        }


        onCallStateChanged(context, state, number);
    }
}

//Derived classes should override these to respond to specific events of interest
protected void onIncomingCallStarted(Context ctx, String number, Date start){}
protected void onOutgoingCallStarted(Context ctx, String number, Date start){}
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){}
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end){}
protected void onMissedCall(Context ctx, String number, Date start){}

//Deals with actual events

//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;
            Toast.makeText(context,savedNumber,Toast.LENGTH_LONG).show();
           // 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;
}

}

最后是我的主要活动文件。请注意,我没有在那里做任何事情,因为我只是试图触发 toast 消息以确认接收器正在被触发

package com.teqnet.receivers;

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

public class MainActivity extends AppCompatActivity {

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

在您的清单文件中,确保您的接收器列在应用程序标签中。 我正在发布更正后的清单文件。

    <?xml version="1.0" encoding="utf-8"?>

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

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <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="PhoneCallReceiver" >
       <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
       </intent-filter>
       <intent-filter>
           <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
       </intent-filter>
    </receiver>
</application>

一个简单的错误,但花了我一天的时间;)。 祝大家好运。

【问题讨论】:

    标签: android


    【解决方案1】:

    转到设置,转到应用程序,选择当前是特定文件类型的默认启动器的应用程序。尝试在此处手动选择您的应用。如果它有效,那么您需要在第一次启动时要求为用户设置默认权限。

    否则试试这个;

    import java.util.Date;
    
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.telephony.TelephonyManager;
    
    public abstract class PhonecallReceiver extends BroadcastReceiver {
    
        //The receiver will be recreated whenever android feels like it.  We need a static variable to remember data between instantiations
    
        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
    
    
        @Override
        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);
            }
        }
    
        //Derived classes should override these to respond to specific events of interest
        protected void onIncomingCallStarted(Context ctx, String number, Date start){}
        protected void onOutgoingCallStarted(Context ctx, String number, Date start){}
        protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end){}
        protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end){}
        protected void onMissedCall(Context ctx, String number, Date start){}
    
        //Deals with actual events
    
        //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;
        }
    }
    

    将以下内容添加到 AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    
    <!--This part is inside the application-->
        <receiver android:name=".CallReceiver" >
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            </intent-filter>
        </receiver>
    

    使用示例:

    public class CallReceiver extends PhonecallReceiver {
    
        @Override
        protected void onIncomingCallStarted(Context ctx, String number, Date start) {
        }
    
        @Override
        protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
        }
    
        @Override
        protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
        }
    
        @Override
        protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
        }
    
        @Override
        protected void onMissedCall(Context ctx, String number, Date start) {
        }
    
    }
    

    更多:Tutorial & Source

    【讨论】:

    • 在我的安卓手机上?
    • 我的手机不允许我更改应用程序的任何设置。我可以强制停止或卸载,仅此而已;(。通过我的手机进行测试。
    • 我就是从那里得到这个示例的,但我不想通过扩展广播接收器在类中实现它。我想在电话响铃时呼叫服务。这就是为什么我只是想让它触发接收器,这样我就可以检查它是否有效;)
    • 完全按照教程重做,还在此接收器的清单中添加了 enabled = true 。没有快乐
    猜你喜欢
    • 2022-07-16
    • 1970-01-01
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多