8 July 2010

Разработка под Android, грабли большие и не очень

Development for Android
Ниже я попробую описать ряд неприятных особенностей с которыми может столкнуться разработчик для платформы Android. Не все они являются особенностью именно операционной системы Android, но так или иначе шансы встретиться с ними есть.


Грабли большого размера


Как это происходит: Вы выкладываете свое приложение размером в 10 мегабайт в Android Market, и вам приходит гневное письмо от пользователя — «Как можно делать такие ужасные программы, она даже не хочет устанавливаться на мой телефон, она меня обманывает. У меня было 15 мегабайт свободно на телефоне, я попытался установить ваше приложение в описании которого написано что оно занимает 10 мегабайт — она мне сказала что места не достаточно, я удалил ненужные программы и у меня 25 мегабайт свободно — все равно говорит не достаточно места, я удалил программы которые нужны мне и стало 35 мегабайт свободного места — она все равно не хочет устанавливаться. WTF! Зачем вы пишите неверный размер своей программы!» (мой вольный перевод с английского реального письма).
Причина: Для установки приложения размером X мегабайт, нужно от 2X до 4X свободного места.
Почему: Сначала файл приложения скачается на устройство и займет там X мегабайт места, потом он будет распакован для проверки — еще от X до 2X мегабайт в среднем, потом он будет перемещен в приложения в файловой системе еще X мегабайт.
Что делать: Если вы делаете приложение больше 5 мегабайт размером, то будьте готовы писать функциональность для скачивания и размещения на флэшке части ресурсов, а так же проверки на возможное отсутствие флэшки или удаление част ваших файлов, причем в процессе работы приложения.

Грабли со встроенной флэш памятью


Как это происходит: Вы делаете приложение интенсивно работающие с файлами. Замеряете время работы и получаете вполне приемлемые цифры — оверхэд файловой операции порядка 5 миллисекунд. Приложение работает быстро, вы довольны. После установки ряда приложений, вы замечаете что время работы вашей программы выросло в 5 раз.
Причина: Особенности реализации файловой системы — чем меньше свободного места на флэшке, тем больше времени занимают операции с файлами. Время доступа вырастает с 5 мс до 300мс, в теории время доступа может вырасти до 200 раз.
Почему: Файловая система пытается сохранить жизнь вашей флэшки, поэтому отслеживает интенсивные операции с файлами и часто востребованные файлы пытается перемещать с места на место. Чем больше файлов, и чем меньше свободного места, тем больше ей на это нужно времени.
Что делать: Вместо множества маленьких файлов, один большой файл с индексами. И будем надеяться что никто не будет использовать ваше приложение месяцами и не убьет свою флэшку.

Грабли ограниченные


Как это происходит: Вам приходит прототип нового планшета на Android c размером экрана 1280 на 800 с целым гигабайтом памяти на борту. Вы в радостном предвкушение начинаете портировать ваш квест — загружаете первый полноэкранный задник, второй, шестой — и получаете OOME (OutOfMemoryError).

Причина: 16Мб памяти на процесс (24Мб на N1/Desire), это включает себя «нативную кучу», где хранятся Bitmap (и OpenGL текстуры)
Почему: В лучших традициях демократии диктатуры — лучше пускай всем приложениям будет доступно по немногу памяти, чем дать возможность одному приложения использовать всю память, из-за чего могут быть проблемы у других приложений. Ну и много других нюансов.

Что делать: 640кб 24 Мб памяти хватит всем

Чувствительные грабли


Как это происходит: Вы создали ваше приложение, добавили туда классную музыку, добавили туда управление с использование акселерометра. Пользователи жалуются что управление ужасное.
Причина: При проигрывания музыкального трека на максимальной громкости, особенно где много басов, при неподвижном телефоне значение поворота снятые со сенсоров меняются от -10 до +10 градусов.
Почему: Динамик слишком близко расположен к сенсорам
Что делать: Не давать выставлять музыку на максимальную громкость, не использовать треки в стиле heavy metal, учитывать тремор сенсоров

Грабли с поддержкой MultiTouch


Как это происходит: Вы хотите сделать управление, например как в игре iDracula
Управление

И не можете.
Причина: Вы получаете координаты касания парами — две X координаты, две Y координаты. Узнать к какому касанию принадлежит та или иная координата вы не можете. В результате, если вы проводите пальцами навстречу друг другу по какой-то оси, и то после совпадения координат по данной оси вы уже не можете определить к какому нажатию относиться какая координата. Я понимаю что описание достаточно туманное — поэтому можете посмотреть вот это видео —

Либо скачать на ваш телефон приложение MultiTouch Visualizer.
Почему: Особенности реализации сенсора на некоторых моделях телефонов — Nexus One, Desire.
Что делать: Отказаться от подобного управления, либо разносить его по Y координате.

Магические грабли


Как это происходит: Вы пишите следующий код

while(true) {
Task task = queue.getTaskBlocking();
task.execute();
}


Где Task это достаточно «жирный объект», которые выделяет много памяти. И обнаруживаете, что памяти используется больше чем планировалось. Посмотрев результирующий байт код вы обнаруживаете, что это компилируется совсем не в такой код который вы хотели, и именно в код

Task task;
while(true) {
task = queue.getTaskBlocking();
task.execute();
}


В результате вы имеет два экземпляра Task в памяти. Не беда думаете вы, мы сейчас явно укажем что один экземпляр можно удалить из памяти.

while(true) {
Task task = queue.getTaskBlocking();
task.execute();
task = null;
}


Но посмотрев на результирующий байт код вы видите, что оптимизатор решил что так как переменная out of scope, выкинул ваше явное зануление объекта, и у вас все равно два экземпляра в памяти. И тогда рождается магия.

class Magic {
static private int n = 0;
static public void doMagic(Object obj) {
if (obj != null) n++;
}
static public int getMagic() { return n; }
}
while(true) {
Task task = queue.getTaskBlocking();
task.execute();
task = null;
Magic.doMagic(task);
}


Причина: Бага :)
Почему: // TODO: Найти разработчика отвечающего за это, пытать и узнать почему.
Что делать: Магия
Tags:androidпрограммированиеbugmagic
Hubs: Development for Android
+91
27.4k 154
Comments 58