Доброго времени суток!
Несколько месяцев назад появился у меня чудесный автомобиль Volvo V50 родом из Бельгии. Бортовой компьютер и магнитолу успешно перепрошили на русский язык у официального дилера, а вот с отображением русских имен из записной книжки телефона при использовании штатной громкой связи вышла беда: все кириллические символы показывались в виде подчеркиваний. Я пользуюсь Samsung Galaxy S3 прошитым CyanogenMod 11, поэтому возникла идея подправить стандартный Bluetooth.apk для обеспечения возможности видеть имя звонящего.
Небольшое исследование показало, что в основном автомобили используют два вида профилей для получения записей телефонной книги:
Первый является более навороченным и передает данные в формате vCard, который включает в себя практически все данные о контакте: имя, фамилию, организацию, адрес электронной почты и так далее.
Второй отправляет только имя, телефон и идентификатор записной книжки.
Путем анализа логов системы выяснилось, что мой автомобиль использует HFP с общением посредством AT-команд. За данный профиль отвечает следующий файл /packages/apps/Bluetooth/src/com/android/bluetooth/hfp/AtPhonebook.java
После недолгих поисков находим функцию int processCpbrCommand(BluetoothDevice device), в конце которой происходит формирование строки ответа на команду:
Именно здесь и было бы неплохо исправить передаваемое имя. В моем случае было решено транслитерировать его. Для этих целей в класс AtPhonebook я добавил массив соответствия символов, а также функцию траслитерации:
После этого нужно вызвать функцию при передаче команды:
Теперь остается лишь скомпилировать приложение Bluetooth и вставить в архив с прошивкой CM.
Тесты после перепрошивки показали полную работоспособность решения. Теперь все имена из записной книжки отображаются транслитом.
В процессе поиска готового решения выяснилось, что проблемы бывают и с профилем PBAP, опять же с автомобилями Volvo, например XC60.
Модуль громкой связи в данном авто использует кодировку CP1251, тогда как стандартное приложение Bluetooth телефона на Android передает данные по профилю PBAP с указанием кодировки UTF-8, что выражается в отображении данных символами подчеркивания.
Для решения данной проблемы можно изменить конструктор класса BluetoothPbapVcardComposer (/packages/apps/Bluetooth/src/com/android/bluetooth/pbap/BluetoothPbapVcardComposer.java)
Здесь можно явно задать кодировку для суперкласса.
В принципе можно попробовать провернуть трюк с транслитерацией и здесь, копать нужно в сторону формирования vCard (функция buildVCard)
К сожалению XC60 или другой машины, использующей PBAP, у меня пока нет, поэтому проверить не смог.
Прикладываю пару вариантов пересобранного Bluetooth.apk
Данное решение может также помочь и обладателям других авто со встроенной громкой связью, не понимающей русский язык.
Несколько месяцев назад появился у меня чудесный автомобиль 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)
Данное решение может также помочь и обладателям других авто со встроенной громкой связью, не понимающей русский язык.