Несколько месяцев назад появился у меня чудесный автомобиль Volvo V50 родом из Бельгии. Бортовой компьютер и магнитолу успешно перепрошили на русский язык у официального дилера, а вот с отображением русских имен из записной книжки телефона при использовании штатной громкой связи вышла беда: все кириллические символы показывались в виде подчеркиваний. Я пользуюсь Samsung Galaxy S3 прошитым CyanogenMod 11, поэтому возникла идея подправить стандартный Bluetooth.apk для обеспечения возможности видеть имя звонящего.
Небольшое исследование показало, что в основном автомобили используют два вида профилей для получения записей телефонной книги:
- PBAP — Phone Book Access Profile
- HFP — Handsfree Profile
Первый является более навороченным и передает данные в формате vCard, который включает в себя практически все данные о контакте: имя, фамилию, организацию, адрес электронной почты и так далее.
Второй отправляет только имя, телефон и идентификатор записной книжки.
Путем анализа логов системы выяснилось, что мой автомобиль использует HFP с общением посредством AT-команд. За данный профиль отвечает следующий файл /packages/apps/Bluetooth/src/com/android/bluetooth/hfp/AtPhonebook.java
После недолгих поисков находим функцию int processCpbrCommand(BluetoothDevice device), в конце которой происходит формирование строки ответа на команду:
record = "+CPBR: " + index + ",\"" + number + "\"," + regionType + ",\"" + name + "\""; record = record + "\r\n\r\n"; atCommandResponse = record; log("processCpbrCommand - atCommandResponse = "+atCommandResponse); mStateMachine.atResponseStringNative(atCommandResponse, getByteAddress(device));
Именно здесь и было бы неплохо исправить передаваемое имя. В моем случае было решено транслитерировать его. Для этих целей в класс AtPhonebook я добавил массив соответствия символов, а также функцию траслитерации:
private static final String[] charTable = new String[65536]; static { charTable['А'] = "A"; charTable['Б'] = "B"; charTable['В'] = "V"; charTable['Г'] = "G"; charTable['Д'] = "D"; charTable['Е'] = "E"; charTable['Ё'] = "E"; charTable['Ж'] = "ZH"; charTable['З'] = "Z"; charTable['И'] = "I"; charTable['Й'] = "I"; charTable['К'] = "K"; charTable['Л'] = "L"; charTable['М'] = "M"; charTable['Н'] = "N"; charTable['О'] = "O"; charTable['П'] = "P"; charTable['Р'] = "R"; charTable['С'] = "S"; charTable['Т'] = "T"; charTable['У'] = "U"; charTable['Ф'] = "F"; charTable['Х'] = "H"; charTable['Ц'] = "C"; charTable['Ч'] = "CH"; charTable['Ш'] = "SH"; charTable['Щ'] = "SH"; charTable['Ъ'] = "'"; charTable['Ы'] = "Y"; charTable['Ь'] = "'"; charTable['Э'] = "E"; charTable['Ю'] = "U"; charTable['Я'] = "YA"; for (int i = 0; i < charTable.length; i++) { char idx = (char) i; char lower = new String(new char[] {idx}).toLowerCase().charAt(0); if (charTable[i] != null) { charTable[lower] = charTable[i].toLowerCase(); } } } public static String toTranslit(String text) { char charBuffer[] = text.toCharArray(); StringBuilder sb = new StringBuilder(text.length()); for (char symbol : charBuffer) { String replace = charTable[symbol]; sb.append(replace == null ? symbol : replace); } return sb.toString(); }
После этого нужно вызвать функцию при передаче команды:
record = "+CPBR: " + index + ",\"" + number + "\"," + regionType + ",\"" + toTranslit(name) + "\""; record = record + "\r\n\r\n";
Теперь остается лишь скомпилировать приложение Bluetooth и вставить в архив с прошивкой CM.
Тесты после перепрошивки показали полную работоспособность решения. Теперь все имена из записной книжки отображаются транслитом.
В процессе поиска готового решения выяснилось, что проблемы бывают и с профилем PBAP, опять же с автомобилями Volvo, например XC60.
Модуль громкой связи в данном авто использует кодировку CP1251, тогда как стандартное приложение Bluetooth телефона на Android передает данные по профилю PBAP с указанием кодировки UTF-8, что выражается в отображении данных символами подчеркивания.
Для решения данной проблемы можно изменить конструктор класса BluetoothPbapVcardComposer (/packages/apps/Bluetooth/src/com/android/bluetooth/pbap/BluetoothPbapVcardComposer.java)
public BluetoothPbapVcardComposer(final Context context, final int vcardType, long filter, final boolean careHandlerErrors) { super(context, vcardType, "CP1251", careHandlerErrors); mVCardType = vcardType; mCharset = "CP1251"; mFilter = filter; }
Здесь можно явно задать кодировку для суперкласса.
В принципе можно попробовать провернуть трюк с транслитерацией и здесь, копать нужно в сторону формирования vCard (функция buildVCard)
К сожалению XC60 или другой машины, использующей PBAP, у меня пока нет, поэтому проверить не смог.
Прикладываю пару вариантов пересобранного Bluetooth.apk
- Транслит HFP (http://yadi.sk/d/QlGKIPfXLMNXx)
- CP1251 PBAP (http://yadi.sk/d/qrbUVrtuLMRan)
Данное решение может также помочь и обладателям других авто со встроенной громкой связью, не понимающей русский язык.
ссылка на оригинал статьи http://habrahabr.ru/post/217381/
Добавить комментарий