Почему приложение 1С на Android завершается с ошибкой при совершении или получении звонка?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе эксплуатации мобильных приложений на платформе 1С:Предприятие разработчики часто сталкиваются с ситуацией, когда после обновления операционной системы Android (особенно до версий 9, 10 и выше) функции телефонии, которые раньше работали исправно, начинают вызывать принудительное закрытие приложения (crash). Это происходит как при попытке набора номера из интерфейса 1С, так и при входящем звонке, если в приложении реализованы обработчики событий телефонии.

В данной статье мы подробно разберем причины возникновения этой проблемы, проанализируем логи ошибок Java и выясним, какие изменения в манифесте приложения и версии платформы необходимы для восстановления работоспособности.

Анализ исходного кода и типичной реализации звонка

Рассмотрим стандартный фрагмент кода на языке 1С, который используется для инициализации звонка и подключения обработчика событий. Обычно разработчики используют объект СредстваТелефонии, как показано в примере ниже:


#Если МобильноеПриложениеКлиент Тогда
    Если СредстваТелефонии.ПоддерживаетсяНаборНомера() Тогда
        СтруктураЗвонка.Номер = Номер;
        СредстваТелефонии.НабратьНомер(Номер, ВызватьСразу);
        
        Если СредстваТелефонии.ПоддерживаетсяОбработкаЗвонков() Тогда
            ПодпискаНаЗвонки = Новый ОписаниеОповещения("ОбработчикЗвонков", СтруктураЗвонка.Форма, Новый Структура("IDЗадачи", IDЗадачи));
            СредстваТелефонии.ПодключитьОбработчикЗвонков(ПодпискаНаЗвонки);
        КонецЕсли;
    КонецЕсли;    
#КонецЕсли

Проанализируем ситуацию: на старых версиях Android этот код работает корректно. Однако на современных устройствах вызов метода НабратьНомер или срабатывание ПодключитьОбработчикЗвонков приводит к моментальному вылету. При этом сам системный «дозвонщик» Android может начать вызов, но приложение 1С закрывается с критической ошибкой.

Разбор ошибки SecurityException: недостаток прав доступа

Первая и самая важная причина кроется в тексте ошибки, который можно увидеть в системном логе (logcat) устройства:

java.lang.SecurityException: Permission Denial: opening provider com.android.providers.contacts.CallLogProvider ... requires android.permission.READ_CALL_LOG or android.permission.WRITE_CALL_LOG

Выясним причину этой ошибки. Начиная с Android 9 (API level 28), компания Google ужесточила политику конфиденциальности. Ранее для получения номера телефона входящего или исходящего вызова было достаточно общего разрешения READ_PHONE_STATE. Теперь же доступ к информации о номерах (журналу вызовов) выделен в отдельную «опасную» группу разрешений. Если приложение пытается программно обратиться к данным вызова (даже просто получить номер, на который оно само инициировало звонок), система блокирует доступ и выбрасывает исключение SecurityException.

Разбор ошибки NullPointerException в платформе 1С

Вторая ошибка, которая часто сопровождает падение (особенно в версии платформы 8.3.13 и близких к ней), выглядит следующим образом:

java.lang.RuntimeException: Error receiving broadcast Intent ... Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.String.equals(java.lang.Object)' on a null object reference at com.e1c.mobile.TelephonyToolsImpl$3.onReceive

Проанализируем ситуацию: когда происходит событие изменения состояния телефона (PHONE_STATE), внутренняя библиотека мобильной платформы 1С пытается обработать входящие данные. Поскольку у приложения нет прав на чтение журнала звонков (см. предыдущий пункт), Android возвращает пустое значение (null) вместо номера телефона в целях безопасности. Программный код платформы 8.3.13 не ожидает получения null и пытается вызвать метод сравнения строк equals() для этого объекта. Это приводит к NullPointerException внутри Java-части мобильной платформы.

Шаги по решению проблемы

Для устранения данных ошибок необходимо выполнить комплекс действий, связанных как с настройкой сборки приложения, так и с обновлением технологической платформы.

Шаг 1. Настройка разрешений в конфигурации 1С

В первую очередь проверим настройки в самой конфигурации. Разберем необходимые действия:

  1. Откроем свойства корневого узла конфигурации в дереве метаданных.
  2. Перейдем на закладку Используемые возможности мобильного устройства.
  3. Убедимся, что установлены флажки для пунктов Телефония и Контакты.

Однако стоит учитывать, что в старых версиях сборщика мобильных приложений (соответствующих платформе 8.3.13) флажок «Телефония» может не добавлять в манифест разрешение READ_CALL_LOG, так как на момент выпуска версии это не требовалось системой Android.

Шаг 2. Ручное редактирование AndroidManifest.xml

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

  1. При использовании Сборщика мобильных приложений перейдем к этапу подготовки проекта.
  2. В файле AndroidManifest.xml, который формируется в каталоге сборки, необходимо вручную добавить следующие строки внутри тега <manifest>:

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

Это позволит операционной системе понять, что приложение претендует на доступ к данным о вызовах. При первом запуске или при первом звонке Android предложит пользователю подтвердить эти права в явном виде.

Шаг 3. Обновление версии мобильной платформы

Поскольку ошибка NullPointerException является внутренней ошибкой реализации платформы 1С (некорректная обработка отсутствующего номера), наиболее эффективным решением будет переход на более современную версию платформы.

Выясним преимущества перехода:

Рекомендация: Если ваша конфигурация позволяет, выполните сборку мобильного приложения на платформе версии не ниже 8.3.15. Это решит проблему с падением из-за null-ссылок в коде телефонии.

Итоги и выводы

Мы проанализировали критическую проблему падения 1С при звонках и определили, что она носит двойственный характер: ограничение прав доступа на уровне ОС Android и программная недоработка в старой версии мобильной платформы 1С.

Для успешного решения задачи выполним следующие действия: добавим разрешения READ_CALL_LOG и WRITE_CALL_LOG в манифест приложения и обновим платформу 1С:Предприятие до актуальной версии, в которой исправлены ошибки обработки пустых значений от системных провайдеров данных. Это обеспечит стабильную работу функций телефонии и интеграции с CRM-системами на базе мобильной 1С.

← На главную