Как совершить телефонный звонок в Android
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Осуществление телефонного звонка в Android
В Android для совершения телефонного звонка используется механизм неявных интентов (Implicit Intents), поскольку прямая работа с телефонией через API требует специальных разрешений и закрыта для прямого вызова из приложений из соображений безопасности. Основной подход — запрос на совершение вызова через системное приложение "Набор номера".
Ключевые элементы реализации
- Разрешение (Permission):
* Для приложений с `targetSdkVersion` < 31 необходимо объявить в `AndroidManifest.xml` разрешение `CALL_PHONE`:
```xml
<uses-permission android:name="android.permission.CALL_PHONE" />
```
Это **опасное разрешение** (dangerous permission), поэтому начиная с Android 6.0 (API 23) его также нужно запрашивать во время выполнения (runtime permission).
* Для приложений с `targetSdkVersion` >= 31 разрешение `CALL_PHONE` заменяется на более **ограниченное** разрешение `MANAGE_OWN_CALLS` или использованием альтернативного метода `ACTION_DIAL` (см. ниже). `MANAGE_OWN_CALLS` предназначено для приложений-телефонов и, как правило, не предоставляется обычным приложениям.
- Основной Intent:
ACTION_CALL:
* Прямой вызов с переходом в режим набора и автоматическим совершением звонка. Требует разрешения `CALL_PHONE`.
```kotlin
val phoneNumber = "tel:+71234567890"
val intent = Intent(Intent.ACTION_CALL, Uri.parse(phoneNumber))
startActivity(intent)
```
3. Альтернативный Intent: ACTION_DIAL:
* **Рекомендуемый** и более безопасный способ. Открывает системное приложение "Набор номера" с предзаполненным номером, но **не совершает звонок автоматически**. Пользователь сам должен нажать кнопку вызова. Не требует опасных разрешений.
```kotlin
val phoneNumber = "tel:+71234567890"
val intent = Intent(Intent.ACTION_DIAL, Uri.parse(phoneNumber))
startActivity(intent)
```
Формат номера должен соответствовать схеме URI `tel:` (можно также использовать `voicemail:` для голосовой почты). Рекомендуется указывать номер в формате E.164 (с кодом страны `+7` для России).
Полный пример с обработкой разрешений (Kotlin)
Вот пример реализации с проверкой разрешений для ACTION_CALL для приложений с targetSdkVersion < 31:
1. Объявление разрешения в AndroidManifest.xml:
<uses-permission android:name="android.permission.CALL_PHONE" />
2. Код Activity/Fragment:
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
class MainActivity : AppCompatActivity() {
private companion object {
private const val PERMISSION_REQUEST_CALL_PHONE = 101
private const val PHONE_NUMBER = "tel:+74951234567"
}
fun makePhoneCall() {
val intent = Intent(Intent.ACTION_CALL, Uri.parse(PHONE_NUMBER))
// Проверяем разрешение для Android 6.0+
if (ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE) !=
PackageManager.PERMISSION_GRANTED) {
// Запрашиваем разрешение
ActivityCompat.requestPermissions(
this,
arrayOf(Manifest.permission.CALL_PHONE),
PERMISSION_REQUEST_CALL_PHONE
)
} else {
// Разрешение уже предоставлено
startActivity(intent)
}
}
// Обработка результата запроса разрешений
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
PERMISSION_REQUEST_CALL_PHONE -> {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// Разрешение получено
val intent = Intent(Intent.ACTION_CALL, Uri.parse(PHONE_NUMBER))
startActivity(intent)
} else {
// Разрешение отклонено
Toast.makeText(this, "Разрешение на звонок отклонено", Toast.LENGTH_SHORT).show()
}
}
}
}
}
Рекомендации и современный подход (Android 12+, API 31+)
- Используйте
ACTION_DIALвместоACTION_CALL, если возможно. Это:
* Не требует опасных разрешений.
* Дает пользователю контроль (он видит номер и сам инициирует вызов).
* Работает на всех версиях Android без проблем с разрешениями.
-
Проверка доступности функции телефона:
fun isPhoneCallSupported(): Boolean { val intent = Intent(Intent.ACTION_DIAL) return intent.resolveActivity(packageManager) != null } -
Обработка особых номеров:
* Экстренные номера (112, 911) — используйте `ACTION_DIAL`.
* Номера с дополнительными символами (пауза `,`, ожидание `;`):
```kotlin
val numberWithPause = "tel:+74951234567,1234" // Пауза после основного номера
```
4. Для targetSdkVersion >= 31:
* Разрешение `CALL_PHONE` практически недоступно для обычных приложений.
* Используйте `ACTION_DIAL` или новое разрешение `MANAGE_OWN_CALLS` (если ваше приложение является приложением-телефоном).
* Альтернатива — использование **API связи** (`TelecomManager`), но это требует сложной интеграции и предназначено для VoIP-приложений.
Итог
- Для большинства приложений: используйте
Intent(Intent.ACTION_DIAL, Uri.parse("tel:номер"))— безопасно и без разрешений. - Для прямого вызова: используйте
ACTION_CALLс запросом разрешенияCALL_PHONE(актуально для старых приложений). - Всегда проверяйте наличие приложения для обработки телефонных вызовов с помощью
resolveActivity(). - Форматируйте номера правильно, используя код страны.
Такой подход обеспечивает безопасность, соблюдение политик Google Play и дает пользователям контроль над телефонными вызовами.