Возможность вызова телефона Android

Как я могу узнать, имеет ли данное устройство возможность совершать телефонные звонки?

Например, мой Galaxy Tablet не может, это не телефон. Я хочу обнаружить, что перед вызовом isIntentAvailable(context, Intent.ACTION_DIAL) . Я попытался проверить isIntentAvailable для этого, но, похоже, это не так.

 if (((TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE)).getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) { // no phone } 

EDIT Я удивлен, что он вернулся PHONE_TYPE_CDMA . Вот еще одна возможность:

 if (((TelephonyManager)getContext().getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number() == null) { // no phone } 

Для этого потребуется разрешение READ_PHONE_STATE .

Устройствам не обязательно нужен Context.TELEPHONY_SERVICE для совершения телефонных звонков. Подумайте, что произойдет, если вы установите Skype:

  • Введите номер телефона в приложении Dialer / Phone и нажмите «Call».
  • Всплывающее окно появляется под названием «Полное действие с использованием» и предлагает приложения «Dialer» или «Skype» (он также может отображать и другие приложения).

Итак, я считаю, что Skype будет работать на Wi-Fi-устройстве без каких-либо возможностей телефона (согласно Context.TELEPHONY_SERVICE ).

Я думаю, что вы были правы с вашей оригинальной идеей, но вам нужно проверить, какие приложения зарегистрированы для обработки Intent.ACTION_CALL вместо Intent.ACTION_DIAL , например

 Intent callIntent = new Intent(Intent.ACTION_CALL); callIntent.setData(Uri.parse("tel:5551231234")); List callAppsList = context.getPackageManager().queryIntentActivities(callIntent, 0); 

Тем не менее, я не знаю никаких надежных и надежных способов выяснить, смогут ли эти приложения обрабатывать телефонный звонок. Рассмотрим следующие случаи:

1) Установлен только Wi-Fi Xoom с установленной Skype. Он должен иметь действительное соединение wifi, и пользователь должен настроить Skype для использования своей учетной записи, иначе вызов не будет выполнен.

2) Устройство с поддержкой телефонии без SIM-карты или SIM-карта, которая заблокирована или закончилась. Устройство считает, что оно может обрабатывать телефонию, но вызов приводит к ошибке «Not registered on network».

3) Устройство с поддержкой телефонии без Wi-Fi или мобильного соединения (или потому, что оно находится в режиме полета / полета). Устройство думает, что оно может обрабатывать телефонию, но вызов завершится неудачно.

Существуют способы обнаружения некоторых из этих сценариев (например, проверка getSystemService(Context.TELEPHONY_SERVICE).getSimState() ), но я думаю, что это, вероятно, приведет к хрупкому коду, который может сломаться, когда ситуация изменится в будущем. Например, можете ли вы всегда надежно определить, какое приложение в списке является приложением Dialer / Phone по умолчанию? Что, если Android изменит имя пакета для него в следующей версии.

Надеюсь, это дало вам полезную информацию – я хотел показать, что это более сложно, чем может показаться на первый взгляд!

Я думаю, что лучший подход заключался бы в том, чтобы запросить PackageManager, чтобы определить, доступны ли функции телефонии на устройстве. Устройство должно иметь только функции телефонии, если у него есть телефон. Я тестировал это на Nexus 7, у которого нет телефона, и он работает. У меня нет устройства с телефоном для проверки обратного случая.

 PackageManager pm = getPackageManager(); if (pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)){ //has Telephony features. } 

Стив,

Проверьте TelephonyManager . Он имеет getPhoneType() которая вернет PHONE_TYPE_NONE в вашем случае.

Вы можете проверить только функцию TELEPHONY или GSM и CDMA отдельно:

 private boolean hasTelephony() { return getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY); } 

или

 private boolean hasGsmOrCdma() { PackageManager pm = getPackageManager(); boolean gsmSupported = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_GSM); boolean cdmaSupported = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA); //if necessary write somehow what exactly the devise supports return gsmSupported || cdmaSupported; } 

работает хорошо!

Большинство / все эти решения здесь работают в некоторых случаях, но не для всех.

Как указывает @DanJ. Нет простого способа добиться этого.

У меня были проблемы с проверкой PackageManager.FEATURE_TELEPHONY и getPhoneType , потому что оба, похоже, проверяют, способно ли устройство в теории, и предположим, что он может совершать вызовы, если это так. Это прерывается, если у вас есть телефон без SIM-карты, и, возможно, если у вас нет покрытия / вне диапазона. То же самое происходит с подходом к проверке того, какие приложения могут обрабатывать вызов, потому что телефонное приложение все еще установлено, но оно сломается (по крайней мере, на моей галактике s3), когда нет SIM-карты.

Тем не менее, как только вы проверите, что вы можете сделать, что мне кажется работать в большинстве случаев, и это проверить ваш телефон subscriberId , в основном «что такое имя / идентификатор вашего сетевого провайдера».

Вы можете сделать это:

 if(((TelephonyManager)getContext() .getSystemService(Context.TELEPHONY_SERVICE)) .getSubscriberId() == null) { //No network id ~= can't make calls } 

Здесь мы проверяем, нет ли у нас сети, поэтому можем «безопасно» предположить, что устройство не может позвонить. Этот подход дает ложные негативы в случае, когда у вас есть VoIP-телефон или что-то вроде Skype установлено.

Этот подход требует, чтобы вы добавили разрешение:

  

@ Решение TedHopp требует разрешения READ_SMS которое кажется мне более навязчивым.


Ох, как я хочу, phone.canMakeCallsWithoutCrashing() был делом в android.

Я еще не проверил это, но вот решение, которое я придумал, похоже, должно работать нормально. Я не думаю, что это требует каких-либо специальных разрешений, так как это просто поиск bools, установленных в производстве.

 static boolean isRunningOnPhone(Context context){ UiModeManager uiModeManager = (UiModeManager) context.getSystemService(UI_MODE_SERVICE); PackageManager packageManager = context.getPackageManager(); boolean a = packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); boolean b = packageManager.hasSystemFeature(PackageManager.FEATURE_SIP_VOIP) || context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA) || context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA); boolean c = packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN); boolean d; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { d = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE); }else { d = !(uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR); } boolean e = !(uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION); boolean f = uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_APPLIANCE; boolean g = true; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { g = !(uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_WATCH); } return a && b && c && d && e && f && g; } 
  • Фрагмент onSaveInstanceState () никогда не вызывается
  • Как я могу отклонить предложения в EditText?
  • Убедитесь, что приложение находится на первом запуске
  • Android обнаружит, что нажатие клавиши «Готово» для клавиатуры OnScreen
  • Мигающий текст в представлении android
  • Android Broadcast Receiver bluetooth events catching
  • Почему BitmapFactory.decodeByteArray возвращает значение null?
  • Android - получить значение от HashMap
  • Лучший способ загрузки изображения с url в Android
  • Моя камера Android Uri возвращает нулевое значение, но исправление Samsung на месте, помощь?
  • BroadcastReceiver Vs WakefulBroadcastReceiver
  • Interesting Posts

    Утилита отключения дисплея ноутбука

    Список всех файлов во всех подпапках

    Как я могу изменить сетевой пароль, который сохранил проводник Windows?

    Как переопределить параметр CopyLocal (Private) для ссылок в .NET из MSBUILD

    Как реализовать Android Pull-to-Refresh

    Хранить и работать с большими номерами в C

    Как перевести эту обработку изображений из Matlab в OpenCV?

    Почему кажется, что мой генератор случайных чисел не является случайным в C #?

    Как лучше всего моделировать произвольную одномерную случайную переменную с использованием ее вероятностной функции?

    CSS3 Анимация и отображение Нет

    Предотвратите установку установщиком Windows 10 с помощью предустановленного серийного ключа без отключения UEFI

    Что происходит, когда вы закрываете консольное приложение c ++

    Невозможно преобразовать lambda-выражение для ввода «string», потому что это не тип делегата

    Как создать глобальную переменную?

    Использование EntityManager внутри объектов Doctrine 2.0

    Давайте будем гением компьютера.