Ниже я попробую описать ряд неприятных особенностей с которыми может столкнуться разработчик для платформы 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, учитывать тремор сенсоров
Как это происходит: Вы хотите сделать управление, например как в игре iDracula
И не можете.
Причина: Вы получаете координаты касания парами — две X координаты, две Y координаты. Узнать к какому касанию принадлежит та или иная координата вы не можете. В результате, если вы проводите пальцами навстречу друг другу по какой-то оси, и то после совпадения координат по данной оси вы уже не можете определить к какому нажатию относиться какая координата. Я понимаю что описание достаточно туманное — поэтому можете посмотреть вот это видео —
Либо скачать на ваш телефон приложение MultiTouch Visualizer.
Почему: Особенности реализации сенсора на некоторых моделях телефонов — Nexus One, Desire.
Что делать: Отказаться от подобного управления, либо разносить его по Y координате.
Как это происходит: Вы пишите следующий код
Где Task это достаточно «жирный объект», которые выделяет много памяти. И обнаруживаете, что памяти используется больше чем планировалось. Посмотрев результирующий байт код вы обнаруживаете, что это компилируется совсем не в такой код который вы хотели, и именно в код
В результате вы имеет два экземпляра Task в памяти. Не беда думаете вы, мы сейчас явно укажем что один экземпляр можно удалить из памяти.
Но посмотрев на результирующий байт код вы видите, что оптимизатор решил что так как переменная out of scope, выкинул ваше явное зануление объекта, и у вас все равно два экземпляра в памяти. И тогда рождается магия.
Причина: Бага :)
Почему: // TODO: Найти разработчика отвечающего за это, пытать и узнать почему.
Что делать: Магия
Грабли большого размера
Как это происходит: Вы выкладываете свое приложение размером в 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 текстуры)
Почему: В лучших традициях
Что делать:
Чувствительные грабли
Как это происходит: Вы создали ваше приложение, добавили туда классную музыку, добавили туда управление с использование акселерометра. Пользователи жалуются что управление ужасное.
Причина: При проигрывания музыкального трека на максимальной громкости, особенно где много басов, при неподвижном телефоне значение поворота снятые со сенсоров меняются от -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: Найти разработчика отвечающего за это, пытать и узнать почему.
Что делать: Магия