Rheinwerk Computing < openbook >

 
Inhaltsverzeichnis
Vorwort
Teil I Grundlagen
1 Android – eine offene, mobile Plattform
2 Hallo Android!
3 Von der Idee zur Veröffentlichung
Teil II Elementare Anwendungsbausteine
4 Wichtige Grundbausteine von Apps
5 Benutzeroberflächen
6 Multitasking
Teil III Gerätefunktionen nutzen
7 Telefonieren und surfen
8 Sensoren, GPS und Bluetooth
Teil IV Dateien und Datenbanken
9 Dateien lesen, schreiben und drucken
10 Datenbanken
Teil V Multimedia und Produktivität
11 Multimedia
12 Kontakte und Organizer
A Einführung in Kotlin
B Jetpack Compose
C Häufig benötigte Codebausteine
D Literaturverzeichnis
E Die Begleitmaterialien
Stichwortverzeichnis

Ihre Meinung?
Spacer
<< zurück
Android 11 von Thomas Künneth
Das Praxisbuch für App-Entwickler
Buch: Android 11

Android 11
Pfeil 7 Telefonieren und surfen
Pfeil 7.1 Telefonieren
Pfeil 7.1.1 Anrufe tätigen und SMS versenden
Pfeil 7.1.2 Auf eingehende Anrufe reagieren
Pfeil 7.2 Telefon- und Netzstatus
Pfeil 7.2.1 Systemeinstellungen auslesen
Pfeil 7.2.2 Netzwerkinformationen anzeigen
Pfeil 7.2.3 Carrier Services
Pfeil 7.3 Das Call Log
Pfeil 7.3.1 Entgangene Anrufe ermitteln
Pfeil 7.3.2 Änderungen vornehmen und erkennen
Pfeil 7.4 Webseiten mit WebView anzeigen
Pfeil 7.4.1 Einen einfachen Webbrowser programmieren
Pfeil 7.4.2 JavaScript nutzen
Pfeil 7.5 Webservices nutzen
Pfeil 7.5.1 Auf Webinhalte zugreifen
Pfeil 7.5.2 Senden von Daten
Pfeil 7.6 Zusammenfassung
 
Zum Seitenanfang

7    Telefonieren und surfen Zur vorigen ÜberschriftZur nächsten Überschrift

In diesem Kapitel zeige ich Ihnen, wie Sie Anrufe tätigen, entgegennehmen und den Netzstatus ermitteln. Sie betten ferner die Browserkomponente WebView in Ihre App ein und kommunizieren mit Webservices.

Vielleicht fragen Sie sich, warum Sie in Ihren Apps Anrufe tätigen sollten, obwohl jedes Smartphone eine (mehr oder weniger) komfortable Wählfunktion enthält. Dasselbe gilt für das Anzeigen von Webinhalten. Googles Chrome ist ein sehr mächtiger Browser und entweder bereits vorinstalliert oder mit ein paar Klicks heruntergeladen. Die Kunst der Entwicklung mobiler Anwendungen besteht darin, Vorhandenes in neuem Kontext wiederzuverwenden und so für den Benutzer einen echten Mehrwert zu schaffen. Stellen Sie sich eine Aufgabenverwaltung vor. Sie haben als »To do« eingetragen, einen Termin mit Ihrem Steuerberater zu vereinbaren. Wenn Sie die Aufgabe antippen, bietet Ihnen die App an, eine E-Mail zu erstellen oder einen Anruf zu tätigen. Die technischen Grundlagen sind durch Intents vorhanden. Ihnen als App-Entwickler kommt die keinesfalls immer einfache Aufgabe zu, diese Bausteine auf innovative, sinnvolle Weise zu verbinden.

 
Zum Seitenanfang

7.1    Telefonieren Zur vorigen ÜberschriftZur nächsten Überschrift

Um per App ein Telefonat zu beginnen, sind nur sehr wenige Zeilen Quelltext nötig. Auch das Entgegennehmen von Anrufen verursacht kaum Aufwand.

 
Zum Seitenanfang

7.1.1    Anrufe tätigen und SMS versenden Zur vorigen ÜberschriftZur nächsten Überschrift

Am einfachsten initiieren Sie ein Gespräch, indem Sie die zu wählende Nummer an die eingebaute Telefonanwendung übergeben, die in Abbildung 7.1 zu sehen ist. Der Aufruf funktioniert so:

val intent = Intent(Intent.ACTION_DIAL,
Uri.parse("tel:+49 (999) 44 55 66"))
startActivity(intent)

Die Methode startActivity() ist in allen Klassen vorhanden, die von android.content.Context ableiten, also beispielsweise in Activities und Services. Da der Benutzer in dieser Aufrufvariante sieht, dass er einen Anruf tätigen wird, sind keine speziellen Berechtigungen erforderlich.

Die Telefon-App

Abbildung 7.1    Die Telefon-App

Mein Beispiel AnrufDemo demonstriert, wie Sie den Code in eine Activity einbetten. Listing 7.1 zeigt die Hauptklasse AnrufDemoActivity:

package com.thomaskuenneth.androidbuch.anrufdemo

import android.Manifest
import android.content.*
import android.content.pm.*
import android.net.Uri
import android.os.Bundle
import android.widget.*
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

private const val REQUEST_CALL_PHONE = 123
class AnrufDemoActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sofort.setOnClickListener {
// sofort wählen
val intent = Intent(Intent.ACTION_CALL,
Uri.parse("tel:+49 (999) 44 55 66"))
try {
startActivity(intent)
} catch (e: SecurityException) {
Toast.makeText(this,
R.string.no_permission,
Toast.LENGTH_LONG).show()
}
}
sofort.isEnabled =
if (checkSelfPermission(Manifest.permission.CALL_PHONE) !=
PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(Manifest.permission.CALL_PHONE),
REQUEST_CALL_PHONE)
false
}
else
true
dialog.setOnClickListener {
// Wähldialog anzeigen
val intent = Intent(Intent.ACTION_DIAL,
Uri.parse("tel:+49 (999) 44 55 66"))
startActivity(intent)
}
sms.setOnClickListener {
// SMS senden
val telnr = "123-456-789"
val smsUri = Uri.parse("smsto:$telnr")
val sendIntent = Intent(Intent.ACTION_SENDTO,
smsUri)
sendIntent.putExtra("sms_body",
"Hier steht der Text der Nachricht...")
startActivity(sendIntent)
}
}

override fun onRequestPermissionsResult(requestCode: Int,
permissions: Array<String>,
grantResults: IntArray) {
if (requestCode == REQUEST_CALL_PHONE &&
(grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
sofort.isEnabled = true
}
}
}

Listing 7.1    Die Klasse »AnrufDemoActivity«

Die App zeigt die Schaltflächen Wähldialog, sofort wählen und SMS erstellen an. Klicken Sie auf sofort wählen, beginnt das Programm ohne weiteren Zwischenschritt den Wählvorgang. Der Code unterscheidet sich gegenüber der Variante mit Wähldialog nur in der Aktion des Intents. Anstelle von ACTION_DIAL verwenden Sie die Konstante ACTION_CALL. Wichtig ist hierbei aber, in der Manifestdatei (siehe Listing 7.2) die Berechtigung android.permission.CALL_PHONE anzufordern. CALL_PHONE ist eine gefährliche Berechtigung.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.thomaskuenneth.androidbuch.anrufdemo">
<uses-permission android:name="android.permission.CALL_PHONE" />
<application
...

Listing 7.2    Auszug aus der Manifestdatei des Projekts »AnrufDemo«

Aus diesem Grund müssen Sie mit checkSelfPermission() prüfen, ob der Anwender die Berechtigung bereits erteilt hat. Falls nicht, rufen Sie mit requestPermissions() den Ihnen bereits bekannten Abfragedialog auf. Das Ergebnis können Sie in der Methode onRequestPermissionsResult() verarbeiten. Mein Beispiel aktiviert Sofort wählen. Wichtig ist, auf das Werfen einer SecurityException zu reagieren. Je nachdem, wie Sie den Quelltext Ihrer App gestalten, kann es nämlich durchaus vorkommen, dass nach dem Gewähren einer Berechtigung, aber vor der eigentlichen Aktion – in meinem Fall startActivity() – diese wieder entzogen wird.

Auch das Reagieren auf eingehende Anrufe ist mit Android sehr einfach möglich; wie Sie hierzu vorgehen, zeige ich Ihnen im folgenden Abschnitt. Vorher möchte ich Ihnen aber noch kurz erklären, wie Sie mithilfe eines Intents eine SMS versenden (Listing 7.1). Das Protokoll ist in diesem Fall smsto:. Unmittelbar darauf folgt die Nummer, an die die Kurznachricht geschickt werden soll. Uri.parse() erzeugt daraus ein Objekt des Typs android.net.Uri. Es wird als zweiter Parameter dem Konstruktor von Intent übergeben. Als Aktion verwenden Sie Intent.ACTION_SENDTO. Auch das Vorbelegen des Nachrichtentextes ist möglich. Hierzu wird einfach mit putExtra("sms_body", "…") die gewünschte Mitteilung übergeben.

 
Zum Seitenanfang

7.1.2    Auf eingehende Anrufe reagieren Zur vorigen ÜberschriftZur nächsten Überschrift

Mit android.telephony.TelephonyManager können Sie auf zahlreiche telefoniebezogene Statusinformationen zugreifen. Wie, zeige ich Ihnen anhand des Projekts TelephonyManagerDemo. Dessen Activity TelephonyManagerDemoActivity ist in Listing 7.3 zu sehen. In onCreate() wird die Benutzeroberfläche geladen und angezeigt. Der Ausdruck getSystemService(TelephonyManager.class) liefert ein Objekt des Typs android.telephony.TelephonyManager. Es enthält die Methode listen(), mit der Sie eine PhoneStateListener-Instanz registrieren. Die Methoden dieses Interface werden aufgerufen, wenn bestimmte Ereignisse eintreten. Vor der Registrierung müssen zwei Berechtigungen eingeholt werden. Deshalb habe ich den Aufruf in die gleichnamige private Methode ausgelagert.

package com.thomaskuenneth.androidbuch.telephonymanagerdemo

import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
import android.telephony.PhoneStateListener
import android.telephony.TelephonyManager
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

private const val REQUEST_PERMISSIONS = 123
class TelephonyManagerDemoActivity : AppCompatActivity() {

private lateinit var manager: TelephonyManager

private val listener = object : PhoneStateListener() {
override fun onCallStateChanged(
state: Int, incomingNumber: String
) {
textview.append(
getString(
R.string.template1,
state, incomingNumber
)
)
}

override fun onMessageWaitingIndicatorChanged(mwi: Boolean) {
textview.append(
getString(R.string.template2, mwi)
)
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textview.text = ""
manager = getSystemService(TelephonyManager::class.java)
}

override fun onStart() {
super.onStart()
if ((checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) ||
(checkSelfPermission(Manifest.permission.READ_CALL_LOG)
!= PackageManager.PERMISSION_GRANTED)
) {
requestPermissions(
arrayOf(
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.READ_CALL_LOG
),
REQUEST_PERMISSIONS
)
} else {
listen()
}
}

override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_PERMISSIONS &&
grantResults.size == 2 && grantResults[0] ==
PackageManager.PERMISSION_GRANTED && grantResults[1] ==
PackageManager.PERMISSION_GRANTED
) {
listen()
} else {
textview.append(getString(R.string.no_permissions))
}
}

override fun onDestroy() {
super.onDestroy()
manager.listen(listener, PhoneStateListener.LISTEN_NONE)
}

private fun listen() {
manager.listen(
listener, PhoneStateListener.LISTEN_CALL_STATE or
PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
)
}
}

Listing 7.3    Die Klasse »TelephonyManagerDemoActivity«

Worüber Android den Listener informieren soll, regelt der zweite Parameter der Methode listen(), beispielsweise LISTEN_CALL_STATE. Meine Beispielimplementierung der für diesen Fall zu überschreibenden Methode onCallStateChanged() fügt ihre Parameter zu einem String zusammen und gibt diese in einem Textfeld aus. Die Variable state gibt Auskunft darüber, aus welchem Grund die Methode aufgerufen wurde:

  • CALL_STATE_IDLE
    hat den Wert 0 und kennzeichnet das Ende eines Gesprächs bzw. keine Aktivität.

  • CALL_STATE_RINGING
    hat den Wert 1 und signalisiert einen eingehenden Anruf.

  • CALL_STATE_OFFHOOK
    hat den Wert 2 und wird gemeldet, wenn der Benutzer das Gespräch angenommen hat.

Möchten Sie informiert werden, wenn Sprachnachrichten vorliegen, übergeben Sie LISTEN_MESSAGE_WAITING_INDICATOR als zweiten Parameter an die Methode listen() und überschreiben Sie die Methode onMessageWaitingIndicatorChanged() des ebenfalls übergebenen PhoneStateListener. Um die Benachrichtigung bei Statuswechseln des Telefons zu beenden, rufen Sie die Methode listen() mit LISTEN_NONE als zweitem Parameter auf. In welcher Activity-Methode Sie dies tun, hängt vom Anwendungsfall ab. onDestroy() ist dafür gedacht, vor dem Zerstören einer Aktivität letzte Aufräumarbeiten zu erledigen.

Für das Erfragen der meisten Telefonstatus-Attribute sind Berechtigungen erforderlich. Welche genau das sind, hängt von der verwendeten Konstante (LISTEN_...) ab. LISTEN_MESSAGE_WAITING_INDICATOR braucht die Berechtigung android.permission.READ_PHONE_STATE. Sie muss, wie üblich, in die Manifestdatei eingetragen werden. Um die eingehende Rufnummer auslesen zu können, ist zusätzlich READ_CALL_LOG nötig. Fehlt die Berechtigung, ist incomingNumber leer. Beides sind gefährliche Berechtigungen. Sie müssen deshalb im Programmcode durch Aufrufe von checkSelfPermission() und requestPermissions() sicherstellen, dass der Anwender vor der Nutzung abgesicherter Funktionen die relevanten Berechtigungen erteilt hat.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.thomaskuenneth.androidbuch.telephonymanagerdemo">
<uses-permission
android:name="android.permission.READ_PHONE_STATE" />
<uses-permission
android:name="android.permission.READ_CALL_LOG" />
<application
...

Listing 7.4    Auszug aus der Manifestdatei des Projekts »TelephonyManagerDemo«

Bitte beachten Sie, dass Apps, die READ_CALL_LOG anfordern, nur dann auf Google Play veröffentlicht werden dürfen, wenn die Berechtigung für eine Hauptfunktion der App erforderlich ist.[ 9 ](https://support.google.com/googleplay/android-developer/answer/9047303) Das muss für jede App über die Play Console beantragt und durch Google genehmigt werden. Weisen Sie in der Store-Beschreibung und beim Anfordern der Berechtigung in der App selbst unmissverständlich darauf hin, um nicht in den Verdacht zu geraten, heimlich Daten zu sammeln.

Um Anrufe zu simulieren, öffnen Sie den in Abbildung 7.2 dargestellten Dialog Extended controls des Android-Emulators. Klicken Sie hierzu auf das Symbol inline image der Emulator-Steuerleiste. Wechseln Sie auf die Seite Phone, geben Sie unterhalb von From eine beliebige Telefonnummer ein, und klicken Sie dann auf CALL DEVICE. Die Schaltfläche heißt nun END CALL. Ein erneuter Klick beendet den simulierten Anruf.

Der Dialog »Extended controls« des Android-Emulators

Abbildung 7.2    Der Dialog »Extended controls« des Android-Emulators

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
Zur Rheinwerk-Konferenz für Kotlin
 Buchempfehlungen
Zum Rheinwerk-Shop: Kotlin

Kotlin


Zum Rheinwerk-Shop: Praxisbuch Usability und UX

Praxisbuch Usability und UX


Zum Rheinwerk-Shop: Flutter und Dart

Flutter und Dart


Zum Rheinwerk-Shop: App-Design

App-Design


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz
InfoInfo

 
 


Copyright © Rheinwerk Verlag GmbH 2023
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 
[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern