Поиск по блогу

21 мая 2011 г.

Samsung and getNeighboringCellInfo()

Samsung mobile phones always returns empty list for getNeighboringCellInfo().
I don’t know why, but some people on forums says, that Samsung doesn’t return any information about neighboring cells.
But in debug screen u can see neighbour cells:
-Enter into service mode – type *#*#197328640#*#* in dialer
-debug screen
-neighbour cell

В Android OS заблокирована возможность программно (за счет событий) отловить нажатие кнопки HOME. Сделано это, в целом, в очевидных целях: не позволить приложениям блокировать рабочий стол или запретить выход из приложения.

Но один метод есть – но отловить событие нажатия кнопки можно уже после того, как начнётся процесс запуска рабочего стола.

Вам необходимо открыть на чтение лог-файл logcat и анализировать появляющиеся записи на наличие в них следующей строки (приблизительно):
Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher/.Launcher }

Как только в логе появиться такая запись – значит происходит операция запуска отображения рабочего стола.

Как прочитать лог logcat? Об этом можно прочесть здесь у меня на блоге.

Android: Catch HOME button click event


Hi, I’m not good in English. This short article is for foreign persons (not from Russia), because they asked a lot.
This article in Russian: http://uas.name/android/android-catch-home-button-click-event-russian

Yes, there’s no way to programmable catch HOME-button click event. HOME-button-click event is not sent to applications by Android OS.

Only way I found is to read log (logcat) and parse results. When HOME activity is running – the next record appears in logcat:
Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10000000 cmp=com.android.launcher/.Launcher }

U can parse this entry by regular expression. So, this is the best way I found to catch click on HOME.

How to read and open logcat? Read here

Unable to start service - not found


Unable to start service ... not found

При создании сервиса с помощью startService(…) появлялась данная ошибка. Собственно – сообщение очевидно даёт понять о том, что класс сервиса не найден.

Проблема была в том, что все классы-сервисы я поместил в отдельный пакет (main_package).services, где (main_package) – основной пакет приложения, например com.uas.exmaple. При этом в файле AndroidManifest.xml я пометил разработанный сервис как:
<service android:name=".MyService" />

Для решения проблемы – просто добавьте в начале пути имя вашего пакета. В моем случае помогло исправление строки выше на следующую:
<service android:name=".service.MyService" />

Программная установка высоты и ширины для View


В моей разработке встала задача – динамически (программно) создать объект типа View и установить его размеры. Как известно, размеры можно задать как в физических пикселях, так и платформо-независимых пикселях (dip).

Кратко говоря – все расширение экрана мобильного телефона принимается в 320dp. Оно одинаково как для телефона с расширением в 800×480 физических пикселей, так и для телефона с размерами 400×240 физических пикселей (как в моём Samsung Galaxy3 или GT-I5800 ). Т.е. телефон сам автоматически преобразовывает dip-пиксели в физические пиксели экрана.

При проектировании дизайна с помощью xml-файлов возможно задать как dip, так и пиксели. Но при разработке приложения иногда необходимо визуальные элементы создавать программно. В данном случае у объектов View не предусмотрена возможность установки размеров в dip: методы setHeight, setWidth, setMax/MinHeight, setMaxMinWidth принимают только физические пиксели. Собственно, динамически (программно) невозможно также задать и стиль (style) для View. Почему разработчики Android не реализовали очевидно необходимые методы – мне до сих пор не понятно.

Выход, собственно есть, пусть и не очень удобный. Необходимо размеры указывать в ресурсах, извлекать их в программе и подставлять в метод getDimension или getDimensionPixelOffset. Первый метод возвращает тип float (т.е. точное значение преобразования dip в pixels). Второй метод возвращает int, который можно использовать для подстановки в методы установки размеров View.

Поясню на примере: программно создать объекта типа ImageView и задать ему размер 40dip.

1) Создайте в папке ресурсов какой-либо *.xml файл, который будет хранить данные о размерах устанавливаемых объектов. Я назвал файл attr.xml, но вы можете назвать его как угодно.

2) В XML-файле должно содержаться:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Требуемый размер в dip -->
<dimen name="app_list_row_size">40dip</dimen>
</resources>

3) Участок Java-кода, который создаёт изображение ImageView и назначает ему dip-размеры:
// преобразуем dip-пиксели в физические пиксели
int row_height = getResources().getDimensionPixelOffset(R.dimen.app_list_row_size);

// создание объекта ImageView
ImageView iv = new ImageView(this);

// устанавливаем максимальные размеры для ImageView в 40dip
iv.setMaxHeight(row_height);
iv.setMaxWidth(row_height);

Как видите – ничего сложного, но геморройно. Использование метода getDimensionPixelOffset позволяет нам преобразовать «виртуальные» пиксели (dip) в физические, тем самым обеспечив одинаковое отображение ImageView на различных телефонах.

Отлов события: Запуск приложения Android


На поиск решения у меня ушло много часов. Где-то за 6 или 7 часов я облазил весь инет, загуглил множество сайтов, форумов, просмотрел более 400 тем anddev.org. Такое количество поисковых фраз придумал =)

Проблема в том, что Андроид не оповещает нас о том, когда пользователь запускает какое-либо приложение. Он нас может оповестить об установке пакета, об удалении, о его закрытии, но не о его запуске. Ответ был найден здесь.

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

<code>
Process proc = null;

try {
proc = Runtime.getRuntime().exec("/system/bin/logcat -b main");
} catch(IOException e) {
// work exception
}

BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(
proc.getInputStream()
));

String line;

while ( true ) {
line = reader.readLine();
}
</code>

Сообщение о запуске приложения обычно представлено в логе записью типа:
02-15 21:56:43.192: INFO/ActivityManager(52): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.uas.uprotector/.LogActivity }

Для обработки сообщения и выделения имени запускаемого приложения (activity) можно воспользоваться регулярными выражениями.

Как мы видим – решение такое задачи крайне нетривиально и требовательно к ресурсам. Надеюсь, что в будущих платформах Андроид все-таки будет об этом оповещать через broadcast сообщения, которые можно отловить reciever-классами.

Кстати, для чтения логов не забудьте в манифест добавить строчку:
<uses-permission android:name="android.permission.READ_LOGS" />