Broadcast Receiver

Broadcast Receiver ist eine Android-Komponente, die auf System- oder Anwendungsereignisse wartet. Ein solches Ereignis kann z.B. eine Information über eine neue SMS, einen eingehenden oder ausgehenden Anruf oder einen niedrigen Batteriestand sein.

Mit Hilfe des Broadcast-Empfängers werde ich zeigen, wie man eingehende Anrufe in einer Android-App erkennt.

Erstellen Broadcast Receiver

Es gibt zwei Möglichkeiten zur Registrierung und Erstellung eines Rundfunkempfängers.

Die erste Möglichkeit ist die Registrierung im Anwendungscode.

class MainActivity : AppCompatActivity() {

    private val filter = IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED)

    private val broadcast = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {

        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onResume() {
        super.onResume()
        registerReceiver(broadcast, filter)
    }

    override fun onPause() {
        super.onPause()
         unregisterReceiver(broadcast)
    }
}

Die Registrierung im Anwendungscode bedeutet, dass unsere Anwendung nur zuhört, wenn sie aktiv ist.

Bei der zweiten Möglichkeit wird unser BroadcastReceiver auch dann gestartet, wenn die Anwendung gerade inaktiv ist, d. h. wir hören kontinuierlich zu. Um eingehende Anrufe zu erkennen, ist die folgende Option die bessere Wahl.

Erstellen Sie eine neue Klasse, die die BroadcastReceiver-Klasse erweitert, und implementieren Sie die Methode onReceive().

class CallReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, p1: Intent?) {
    }
}

Dann sollte der Rundfunkempfänger in der Datei AndroidManifest.xml registriert werden.

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

Permission

Geben Sie in der Datei AndroidManifest.xml die Berechtigung zum Lesen des Telefonstatus und zum Lesen des Anrufprotokolls.

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

Read Phone State Listener

In der Methode onReceive wird ein PhoneStateListener erstellt.

class CallReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, p1: Intent?) {
        val telephonyManager: TelephonyManager = context?.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager;
        telephonyManager.listen(object: PhoneStateListener(){
            override fun onCallStateChanged(state: Int, phoneNumber: String?) {
                super.onCallStateChanged(state, phoneNumber)
            
            }
        }, PhoneStateListener.LISTEN_CALL_STATE);
    }
}

Wenn ein neuer Anruf kommt, wird die Methode onCallStateChanged aufgerufen.

Im Folgenden wird erklärt, was die Parameter von onCallStateChanged bedeuten.

CALL_STATE_IDLE – keine Aktivität

CALL_STATE_RINGING – Klingeln. Ein neuer Anruf ist eingegangen und läutet oder wartet. Im letzteren Fall ist bereits ein anderer Anruf aktiv.

CALL_STATE_OFFHOOK – Abgehoben. Es gibt mindestens einen Anruf, der gewählt wird, aktiv ist oder gehalten wird, und es läuten keine Anrufe oder warten.

class CallReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context?, p1: Intent?) {
        val telephonyManager: TelephonyManager = context?.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager;
        telephonyManager.listen(object: PhoneStateListener(){
            override fun onCallStateChanged(state: Int, phoneNumber: String?) {
                super.onCallStateChanged(state, phoneNumber)
                when (state) {
                    TelephonyManager.CALL_STATE_IDLE -> {
                        Log.i(TAG,"not in call")
                    }
                    TelephonyManager.CALL_STATE_RINGING -> {
                        Log.i(TAG, "ringing")
                    }
                    TelephonyManager.CALL_STATE_OFFHOOK -> {
                        Log.i(TAG, "call is dialing, active or on hold")
                    }
                }
            }
        }, PhoneStateListener.LISTEN_CALL_STATE);
    }
}

Wie ändert sich der Status bei einem eingehenden Anruf?

Wenn es klingelt, wechselt der Status von IDLE zu RINGING. Wenn der Anruf entgegengenommen wird, wechselt er zu OFFHOOK, zu IDLE, wenn aufgelegt wird. Um Änderungen zu registrieren, müssen Sie zusätzliche Variablen erstellen.

class ServiceReceiver : BroadcastReceiver() {

    var laststate: Int = 0
    var isIncoming: Boolean = false

    override fun onReceive(context: Context?, p1: Intent?) {
        val telephonyManager: TelephonyManager = context?.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager;
        telephonyManager.listen(object: PhoneStateListener(){
            override fun onCallStateChanged(state: Int, phoneNumber: String?) {
                super.onCallStateChanged(state, phoneNumber)
                if (state == TelephonyManager.CALL_STATE_RINGING) {
                    isIncoming = true
                }
                if (state == TelephonyManager.CALL_STATE_OFFHOOK && laststate != TelephonyManager.CALL_STATE_RINGING) {
                    isIncoming = false
                }
                if (state == TelephonyManager.CALL_STATE_IDLE && laststate == TelephonyManager.CALL_STATE_OFFHOOK) {
                   Log.i(TAG, "incoming call end, phone number: $phoneNumber")
                }
                laststate = state
            }
        }, PhoneStateListener.LISTEN_CALL_STATE);
    }
}

Bei abgehenden Anrufen ändert sich der Status anders. Von IDLE zu OFFHOOK, wenn gewählt wird, zu IDLE, wenn aufgelegt wird. Ausgehende Anrufe können also auf ähnliche Weise erkannt werden.