2015-11-28

О человеческих часах

Надеюсь, все читали великолепного Брукса, ту его книжку с говорящим названием «Мифический человеко-месяц». Ну это как раз про то, что девять женщин могут родить ребёнка за один месяц. Или, цитируя Григория Остера: «Известно, чем больше денег вкладываешь в строительство, тем быстрее оно идёт. Родик вложил столько денег, что завод ремней построился буквально за один час». На самом деле нет.
Warren Buffett
Возможно. мне повезло. Так получилось, что я никогда не работал на Одеске и прочих хитрых фрилансерных платформах, где идёт почасовая оплата, а чтобы ты честно отпахал эти часы, ведётся тотальный контроль. Ну вы знаете. Жмёте кнопку, что начинаете работать над задачей. Начинает считаться время. Начинают считаться нажатия кнопочек клавиатуры, движения и клики мышки. Начинают делаться скриншоты вашего экрана, исподтишка. И так, пока вы не нажмёте кнопочку, что вы перестали работать над задачей.
У меня было не так. Я работал в офисе. Я знал, когда прихожу на работу. Я знал, когда ухожу с работы. Я знал, что между этими моментами времени, за вычетом получаса или часа на обед, проходит восемь часов. И, таким образом, я нахожусь на работе, а, значит, подразумевается, что я работаю, по сорок часов в неделю.
И я считал вполне нормальным работать именно по сорок часов в неделю. Неважно, рано утром или поздно вечером. Неважно, с понедельника по пятницу или иногда по воскресеньям. Главное, чтобы в сумме выходило сорок часов за неделю.
И я трекал время в таск-трекере. Но восемь часов в день. Или по шесть и десять часов за два дня. Но в сумме сорок часов в неделю. Исходя из собственных внутренних ощущений о том, сколько времени на какую задачу я потратил. Лишь бы сумма сходилась.
И тут обнаружилась странность. Чем меньше я непосредственно писал код, и чем больше я занимался менеджерскими обязанностями, тем сложнее было связать часы, проведённые на работе, с конкретными задачами в таск-трекере. Вот тут я вроде этим занимался, вот тут — этим. А куда делись еще два-три часа? Так появлялись бесконечные (не потому, что их много, а потому, что они никогда не заканчивались) задачи со словом «communication» в названии. Ну или «management».
Ещё был в истории моей трудовой деятельности непродолжительный период, когда я выторговал себе возможность не трекать часы. Совсем. Я продолжал находиться на работе по восемь часов в день. Я продолжал пользоваться таск-трекером, чтобы банально не забывать, что нужно сделать. Но вместо оценок в часах я выставлял дату, к которой задача должна быть сделана. И правильно и вовремя менял статусы задач.
И я был счастлив. Здорово, когда над тобой не висит обязанность отчитаться за каждый час, проведённый в офисе. Здорово, когда не нужно мучительно вспоминать, что ты сделал за день, или, ужас какой, за неделю. Все твои обязательства выражаются в том, что задачи должны быть сделаны к тому сроку, который ты сам и указываешь. Всё.
И вот теперь, ради успокоения заказчика, я оказался под гнётом той самой одескоподобной штуки, которая следит за тобой и делает скриншоты. Заказчик тешит себя надеждой, что, поразглядывав скриншоты, он убедится, что разработчики действительно работают, и что они действительно кодят то, что он хочет.
Боже, почему я должен постоянно думать, какой именно задачей я занимаюсь прямо сейчас? Если мне приходится болтать с коллегами по поводу двух проектов, мне приходится тыкать в этой штуковине правильный проект. Это очень тяжело, так жёстко контролировать контекст своей мозговой активности.
Почему я должен постоянно беспокоиться, чтобы на скриншоты не попал какой-нибудь не тот чатик? Нет, то, что посторонние чаты отвлекают от Работы — это другой вопрос. Нифига чаты не отвлекают. Уведомления отключены. К тому же, если я действительно застрял в решении какой-то сложной задачи, фиг меня отвлечешь, даже если встать рядом и орать на ухо. Но тут мне надо всегда помнить, что, когда я переключаюсь на чат с супругой, чтобы за две минуты обсудить планы на вечер, мне нужно остановить всебдящую тулзу.
Но самым удивительным оказалось другое открытие. За восемь часов нахождения в офисе у меня получается затрекать хорошо если шесть часов времени работы над задачами. Ветераны Одеска говорят, что это нормально. Но я всё никак не могу привыкнуть к тому, что часа два-три опять куда-то пропадают. Пропадают они, если честно трекать время. Встал сходить попить чаю — остановил трекинг. Вышел в туалет — остановил трекинг.
Оказалось, что два-три часа каждый день тратятся не на кодинг, не на митинги. А на... Ну на жизнь. «Если программист смотрит в окно, это не значит, что он ничего не делает». Если я пошёл пить чай, я действительно отлучился от рабочего места минут на пятнадцать-двадцать. Я действительно не занят в это время работой над конкретным проектом. Я общаюсь. Я обсуждаю проблемы, в том числе и на этом проекте. Я обсуждаю проблемы на других проектах. Я хвастаюсь достижениями. Я делюсь опытом. Я учусь. Я отдыхаю от предыдущей задачи, чтобы со свежими силами взяться за следующую. Я живу. Два-три часа каждый день в офисе я не работаю, чтобы эффективно работать.
А у вас какой расклад получается?
К чему это я? Я считаю, что повсеместное использование человеко-часов — абсолютное зло. Час работы конкретного человека над конкретной задачей не говорит ни о чём. Ни об эффективности работы этого человека. Ни о прогрессе выполнения задачи. Человеко-часы — это просто порочная привычка, к величайшему сожалению прочно засевшая в мозгах всех участников процесса разработки ПО.
Мы продолжаем использовать человеко-часы для оценки трудоёмкости задач. Но ведь это неверно. Разным людям нужно совершенно разное время для выполнения одной и той же задачи. Плюс погрешность оценки. Во всех этих наших прогрессивных методологиях оценивают совсем по-другому. В Скраме важным является лишь обязательство команды (всей команды) выполнить определённый набор задач за определённый срок итерации. Каким образом принято это решение, как при этом оценивались задачи: в поинтах, в попугаях, раскладыванием по корзинкам — не важно. Важно выполнить обязательство. В Канбане вообще не важна абсолютная трудоёмкость задачи, важно лишь знать, какая задача труднее, а какая проще, чтобы правильно выбрать, какую вытащить в разработку. А метрики, скорости и прочие показатели, которые могут указать, когда же действительно будут завершены нужные задачи, считаются вовсе не от первоначальных оценок, а от моментов времени, когда задача переходит из одного статуса в другой.
Мы продолжаем использовать человеко-часы для расчёта заработной платы. Может, это удобно в каком-нибудь автосервисе, где все работы заранее определены производителем авто, и их трудоёмкость раз и навсегда задана в нормо-часах, и вот эти нормо-часы и оплачиваются. Но разве в программировании определены все задачи, которые приходится решать? Почему за час митинга по одному и тому же проекту менеджеру Пете заплатят в два раза больше, чем джуниору Васе, если Петя лишь спросил, как дела на проекте, а Вася полчаса распинался, как крокодил не ловится? Кто из них потратил больше сил? Сколько заплатят еще пятерым разработчикам, которые присутствовали на том же митинге, но не проронили не слова? А можно ли мерять меру участия в словах?
Нормочасы
Опять таки, отмеряя время на задачи в точных часах, я обнаружил, что количество мыслетоплива, потраченное за час настенного времени, существенно зависит от характера задачи и от настроения. Задача на хитрый кодинг, когда впадаешь в поток, тихо и незаметно съедает кучу времени. И потом кажется, что ещё можешь горы свернуть. Лучший случай для жёсткого учёта времени: мыслетоплива субъективно потрачено мало, а времени прошло много. Мне, к сожалению, такие задачи попадаются редко.
Наборот, когда не знаешь, за что взяться, с какой стороны подойти, пробуешь то да другое, а ничего не выходит, время ползёт еле еле, и выдыхаешься махом. Вымотался уже весь, а смотришь, лишь полтора часа прошло. В работе, например, суппорта (не первой линии) таких задач много. Очень фигово при жёстком учёте времени.
Когда настроение хорошее, время летит незаметно. Когда хмур и печален, время ползёт слишком медленно. Лучше, когда время летит, тогда меньше мыслетоплива тратишь за час, проще честно зафигакать аж десять часов полноценной работы.
Нельзя раньше
Ну и наши заказчики продолжают использовать человеко-часы для расчета длительности и стоимости проекта. Наивнейшим образом перемножая рейты на человеко-часы и полтора землекопа, получают якобы правильные цифры. Нифига эти цифры не правильные. Просто под них потом всё подгоняется, дабы не переписывать контракты, не пересчитывать бюджеты, и не ударить в грязь лицом. А чтобы еще и не прогореть, хитрые менеджеры заранее перемножают всё на Пи. А, как известно, благодаря эффекту выпрямления сроков, нельзя просто так взять и завершить проект раньше. Поэтому все буферы будут съедены, все бюджеты исчерпаны, и цифры с довольно высокой вероятностью сойдутся. Это не заслуга наших точных оценок и правильного перемножения человеков на их часы, это — заслуга правильно заложенного (и съеденного) буфера.
Между прочим, практика бездумной продажи часов разработчика исключительно как часов работы конкретного человека не важно над чем, главное, тому, кто платит деньги, носит весёлое название «body shop». В некотором роде это аналогично «Flesh Fair» из «И.И.»
Flesh Fair
Разработчики, вы действительно хотите мучиться и подгонять часы, проведённые в офисе, под выполненные задачи? Вы действительно хотите, чтобы незнакомый дядя постоянно пялился бы в экран вашего компьютера, не доверяя вам? Вы действительно хотите, чтобы продавались часы вашего сидения перед монитором, а не реально нанесённая польза? Может, вы хотите просто получать зарплату и просто делать то, что вам нравится и что у вас хорошо получается? И иногда получать премию, если заказчику сильно понравится то, что вы сделали.
Менеджеры, вы действительно считаете, что человеко-часы можно умножать на людей, оценки разных задач суммировать, сумму делить снова на людей, и на восемь часов в день, и получать календарную продолжительность проекта? Вы действительно считаете, что, взяв красивый рейт, желательно побольше, и зависящий от должности сотрудника, а не от его пользы на проекте и реальных умений, и умножив его на часы, можно получить реальный бюджет проекта? Может, вы не хотите всего этого перемножать, а хотите определить лишь две цифры: деньги и время?
Заказчики, за что вы платите деньги? За то, что менеджер Петя и джуниор Вася будут пытаться вам не соврать, что посвятили согласованное количество часов именно вашей проблеме? Или за то, что менеджер Петя и джуниор Вася (и не важно, кто там еще будет им помогать) действительно решат вашу проблему (или не решат, тут уже риски и репутация Пети и Васи) за оговорённые сроки и деньги? Неужели вы думаете, что сможете проверить, что озвученные Петей и Васей часы являются адекватной оценкой, и сможете удостовериться, что они потратили именно столько часов именно на вас? Может, у вас просто есть проблема, которую нужно решить за адекватный срок и за разумные, имеющиеся у вас, деньги? И, может, вам всё равно, сколько народу будет над этим работать и будут ли они спать ночами, если работа в конце концов будет выполнена?
Project Triangle
Но как же без человеко-часов? Есть варианты. Например, то, что называется FFF (fixed price, fixed timing, flexible scope). Заказчик определяет лишь две цифры: стоимость и срок, и хочет, чтобы за указанную цену, в указанный срок, кто-нибудь решил его задачу наилучшим возможным способом. А сам обязуется постоянно следить за тем, что решение задачи действительно движется в благоприятном направлении. Исполнитель собирает команду разработчиков (а точнее — решателей проблем), которая с хорошей вероятностью сможет решить данную проблему в указанный срок. Берёт их зарплату за этот срок, добавляет ожидаемую прибыль (она же буфер на риски) и получает бюджет. Как только все цифры и желания у заказчика и исполнителя сойдутся, работа начинается. Не правда ли, две цифры — это проще, чем куча попугаев, помноженных на питонов?

2015-11-14

Об Интентах

Продолжаю хвастаться своими андроидными приложениями.
В своём сдкартопосылательном приложении я изрядно подружился с андроидными интентами. Intent — это, буквально, намерение. Интенты — это основа Андроида как операционной системы. Это способ межпроцессного взаимодействия. Это сообщения, которые приложения или система посылают другим приложениям, а те как-то реагируют.
Intent workflow
В Андроид ничего не может произойти без Интента. Система может сообщить всем заинтересованным приложениям, что, например, появилось подключение к Сети. Одно приложение, скажем, Ланчер, в котором мы видим значки всех установленных приложений, может послать Интент другому приложению, с указанием отобразить определённый стартовый экран (в терминологиях Андроида — Активити), что приводит к запуску этого приложения и отображению этого самого экрана. Собственно, только для ответа на некий Интент приложения и могут запускаться.
Интент может содержать конкретное имя конкретного компонента (Активности или других) конкретного приложения. Может содержать URI, указывающий на некие данные других приложений, ресурсов в Сети или даже локальные файлы, с указанием MIME типа этих данных. Может содержать произвольный набор (ассоциативный массив) других данных, так называемые Extra, включая сериализованные объекты. Ну и Интент обязательно содержит действие (Action) и его категорию, которое ожидается быть выполненным на стороне получателя Интента.
Intent class
Скажем, запуск программы из Ланчера — это ACTION_MAIN в CATEGORY_LAUNCHER. Открытие файла или URL — это ACTION_VIEW в CATEGORY_DEFAULT или CATEGORY_BROWSABLE, URI и MIME тип того, что нужно открыть, явно передаются в Интенте. Расшарить/поделиться/послать что-то — это ACTION_SEND в CATEGORY_DEFAULT, а что именно посылается добавляется к Интенту либо текстом как EXTRA_TEXT, либо как URI в EXTRA_STREAM.
Это всё было бы не так интересно, если бы приложения не сообщали бы, какие Интенты они умеют принимать. Каждое Андроид приложение объявляет в своём манифесте, из каких компонентов оно состоит, и какие Интенты эти компоненты готовы принимать. Например, если приложение объявляет, что у него есть Активность, которая принимает Интенты с ACTION_MAIN в CATEGORY_LAUNCHER, то значок именно этой Активности появится в Ланчере, и именно эта активность будет запущена при тыкании по значку. А если такой Активности в приложении нет, то оно не появится в Ланчере, и чтобы удалить его, вам придётся залезть в настройки :) Но сам Ланчер — это обычная программа, и он запрашивает у системы, какие именно Активности умеют принимать ACTION_MAIN, и, исходя из полученного списка, рисует свой экран доступных приложений.
Любая другая программа тоже может проделать такой фокус. Скажем, запросить, какие приложения умеют открывать URI, начинающиеся на http://. Это, в каком-то приближении, будет список всех установленных в системе браузеров.
Получается, что в Андроид, после установки приложения, всегда известно, какого рода Интенты этим приложением обрабатываются. И часто используются Интенты, не адресованные конкретному приложению, а, например, отсылающие http:// URI любым приложениям, готовым его принять. При этом отображается диалог выбора конкретного получателя, наверняка часто такой видели. Технически подобный диалог — просто некоторая Активность, принадлежащая некоемому системному приложению.
Intent filters
Итак, мои приложения.
Второе по популярности (двадцать четыре тысячи активных пользователей) — браузерооткрывательное приложение. Дело в том, что почти все браузеры под Андроид, естественно, умеют открывать http:// URL, а также, что не всем известно, открывать и file:// URL. Поэтому, если вы сохранили HTML версию какого-нибудь сайта локально, вы на самом деле можете её открыть в любом удобном браузере и читать. Но беда в том, что если открытие http:// прописано у браузеров в манифесте, то про file:// они типа не знают. Единственным исключением была Опера. Получается, что, чтобы открыть локальный файл в браузере, вам приходится вбивать полный file:// URL в адресную строку вручную. Жутко неудобно. Функционал вроде есть, но воспользоваться им нормально не получается. А ведь нынешние браузеры весьма неплохо отображают картинки и даже видео.
Вот моё приложение и добавляет возможность открывать локальные html и текстовые файлы, а также файлы изображений и видео в любом установленном браузере. Чтобы непосредственно добраться до файла, вам ещё будет необходим какой-нибудь файловый менеджер.
Приложение в своём манифесте заявляет, что умеет открывать файлы. Ещё оно составляет список браузеров в системе, тех, кто умеет открывать http://. Когда к нему приходит Интент, оно просто отображает диалог выбора браузера, либо молча выбирает заранее выбранный браузер, и перенаправляет Интент браузеру. Всё.
И пошла игра с Интентами.
Ненавижу сокращённые URL. По ним совершенно не ясно, куда они ведут. А ведь по доменному имени, по нормальному, согласно ЧПУ, пути, часто можно понять больше, чем даже из заголовка статьи. И вот, чтобы делиться из этих наших твиттеров или RSS лент нормальными читабельными URL я создал урлоудлинятельную программу. Между делом оказалось ещё очень удобным удалять всякие незначащие параметры из URL, которые используются исключительно для трекинга рекламных кампаний, но не несут смысла.
Программа получает Интент с ACTION_SEND. Извлекает из него расшаренный текст. Ищет в тексте URL. Резолвит все редиректы, пока не получит финальный адрес страницы, для этого нужен Интернет. Удаляет из URL параметры, согласно настройкам. Заменяет в тексте URL на результат преобразования. Расшаривает текст далее, где его можно послать другой программе. Просто вклиниваемся еще одним шагом в стандартный процесс расшаривания ссылок.
Похожим образом работает и единственная (ну почти) программа, написанная на заказ — ебаеторговательная программа. Ебай — это, как вы знаете, такой интернет-аукцион. И есть такой, не вполне честный, способ выигрывать торги. Вы натравливаете на лот аукциона, от своего имени, некоего бота, который, за секунды до окончания торгов, внезапно делает ставку чуть-чуть выше текущей максимальной. Это называется sniping.
Так вот, нашлись ребята, которым очень нравился один такой снайперный бот. Только у создателей этого бота не было (и сейчас нет) мобильного приложения. Но зато был мобильный сайт. И вот для этих ребят я написал приложение. Оно получает Интент, которым стандартное приложение Ебая расшаривает ссылку на лот. Ведь это же вполне удобно и безобидно, куда-то ссылку отправить. Приложение находит идентификатор лота в пересылаемом тексте и формирует URL на мобильный сайт снайперного бота с идентификатором лота, чтобы бот сразу начал спайпить данный лот. Ну и формирует новый Интент, на открытие этого сайта. И сайт открывается в браузере. Опять вклиниваемся с процедуру расшаривания ссылки, и получаем новый удобный функционал.
Забавно, чем закончилось текущее существование этого приложения. При очередном обновлении его забанил Гугль в Гуглоплее. Мотивируя это тем, что я использую название и логотип этого самого снайперного бота. Это правда, но у меня было неформальное разрешение на их использование. Формального разрешения авторы бота мне так и не дали, может, не хотят светиться перед Гуглом. А переделать название и лого у меня еще руки не дошли.
Sniping
Я обожаю PlantUML. Так, что даже захотел иметь возможность писать диаграммы на планшете. Делать полноценный текстовый редактор я не рискнул. Ведь уже есть достойные редакторы, нечего с ними бодаться. Поэтому я снова решил поиграть с Интентами.
Сценарий такой. Редактируем текст в редакторе. Когда нужно, посылаем текст в наше приложение посредством Интента с ACTION_SEND. Приложение формирует из текста диаграммы URL на картинку на plantuml.com. Скачивает эту картинку. Открывает картинку в Активности для предварительного просмотра, откуда её можно переслать или открыть в другом приложении. Используем Интенты, чтобы как-то сынтегрироваться с другими приложениями, которые даже не подозревают, что с ними интегрируются. Так получилось плантуэмэльное приложение.
PlantUML
А недавно я задумался о несправедливости. Почему Интенты для расшаривания (ACTION_SEND) и Интенты для открывания (ACTION_VIEW) так неравнозначны? Расшарить текущий документ (или что там сейчас открыто) можно почти из любого приложения. А почему нельзя переоткрыть это же в другом приложении? Почему нельзя открыть текущую страницу в другом браузере? А почему, наоборот, нельзя послать куда-нибудь ссылку из текущего документа? Это худо-бедно возможно в некоторых популярных почтовых клиентах и браузерах. Но обычно ссылка может быть открыта только в этом же приложении.
И я начал делать расшаривательнооткрывательную программу. Она позволяет открывать то, что расшаривается, и расшаривать то, что открывается. На практике, если вы часто кидаете ссылки туда-сюда, оказалось очень удобно. Пока готово на 80%, уже можно пробовать. Пишу на Котлине.

2015-11-01

О мобильном

А давайте немного похвастаюсь своими мобильными приложениями. Я ведь, помимо прочего, пописываю свободные программы под Android. И немного рассказывал об этом на прошлом Droidсon в Москве.
Всё началось во времена первого айфона. Упоротые гики привозили эти самые айфоны из Штатов. А я ждал. Я не хотел доверяться Эпл, мне не нравилось уже тогда заметное их стремление подсадить пользователей исключительно на их продукцию. И тут появился Андроид. В лице HTC Hero. Это был практически первый гуглофон, доступный в широкой продаже, и даже официально в России. И я понял, что это тот айфон, который мне нужен. А когда приобрёл его, внезапно понял, что под него можно писать программы. И начал писать программы.
Welcome to Omsk
Пытаюсь вспомнить, с какой программы всё началось, и не могу. Наверное, всё же с погоды. Ну не было в раннем Андроиде нормальных погодных приложений и виджетов. А захотелось видеть хотя бы температуру воздуха в родном городе. Тем более, что была, и до сих пор здравствует знаменитая Муха. Это датчик температуры в центре Омска, с 2003 года публикующий показания (и графики) в интернетах.
Так возникла омскопогодная программа. Началась она с виджета на рабочий стол. Но Боря вдруг спросил: "А можно эту температуру вывести в строке состояния сверху экрана?". Так и родилась гениальнейшая идея: показывать температуру в строке состояния. Ныне эта идея так или иначе реализована во всех приличных погодных программах.
Реализация идеи встретила серьезное сопротивление со стороны Android SDK. Дело в том, что Андроид не позволяет рисовать что попало в строке состояния. Там могут выводиться только картинки-ресурсы, уже вкомпилированные в приложение. Хорошо, впрочем, что саму картинку можно выбирать. Вот так и получилось решение: включить в приложение картинки с показаниями температуры от -50 до +100 градусов (для Цельсия и Фаренгейта).
Потом в омскопогодную программу добавились графики температуры с той же Мухи. А потом я решил, что Омском ограничиваться не стоит и начал делать всепогодную программу. Поддержку омскопогодной программы я забросил, но девятьсот шестьдесят шесть каких-то чудаков до сих пор ею пользуются.
OpenWeatherMap
Всепогодной программе нужен был источник погоды во всех городах, а не только в Омске. И у Гугла он был. Помните iGoogle? Такая кастомизируемая стартовая страница с разными виджетам. Был там и виджет погоды. И данные он запрашивал во вполне понятном XML. Хороший был источник данных, но, раз уж был неофициальным, тихо, но заметно, умер. Пришлось в срочном порядке искать альтернативу. И единственным открытым и бесплатным погодным API оказался OpenWeatherMap.
OpenWeatherMap в ту пору только зарождался. Не было рекламы на страницах. Не было платных тарифов и ограничений в количестве запросов. Не раздавали API key. Пожалуй, я даже немного приложил руку к их развитию. Как минимум одно минорное обновление API было выпущено для исправления багов, которые нашёл я.
В общем, за неделю по вечерам была создана новая реализация запрашивателя погоды, и всепогодное приложение продолжило работать.
Другой челлендж во всепогодной программе случился с теми самыми картинками-иконками для циферок температуры. Еще на заре Андроида оказалось, что у HTC в Sense строка состояния вверху экрана — чёрная, а у обычного Андроида — белая. Потом она и у Андроида стала чёрная. А с приходом Ice Cream Sandwich еще и поменялся масштаб отображения иконок.
Для разных случаев, в зависимости от модели устройства или хотелок юзера нужны были разные иконки. А набор из 150 иконок занимал порядочный мегабайт. Для устройств времен HTC Hero — весьма много.
Поэтому я решил делать всепогодное приложение расширяемым. И подключать различные шкурки с разными иконками. Родился целый API по взаимодействию основного кода, который отвечал за своевременное обновление погоды, и шкурок, которые отвечали за отображение.
Сам я написал и поддерживаю пять шкурок. И была надежда, что кто-то захочет написать ещё. С другими цветами цифр, с виджетом, а не уведомлением, ещё с чем-нибудь. Но никто так и не написал. А сейчас наличие этих пяти шкурок смотрится странным, весь этот пяток мегабайт уже не стыдно просто включить в одно приложение.
Android MicroSD
Пожалуй, исторически второй программкой, но самой популярной из моих программок стала сдкартопосылательная программа. С ума сойти, её скачали более трёх миллионов восьмисот тысяч раз, и активно пользуются более четырёхсот тысяч человек. Почуяв успех, я впилил туда донейт в один бакс. Просто возможность дать мне доллар, если программа понравится. Без рекламы, без смс, без ограничения функционала без оплаты. И платят, что-то около сотни в месяц выходит.
А идея была простая. В то время не было Гуглофоточек. И встроенная в телефон Галерея, для просмотра нафотканного, оставляла желать лучшего. Она не умела организовывать фотографии, но умела отображать фото из разных папок на файловой системе как альбомы. Приходилось раскидывать файлы по папочкам в неуклюжих на тот момент файловых менеджерах, где было неудобно фоточки смотреть. А потом смотреть в Галерее, где неудобно было их раскидывать. Захотелось упростить задачу.
После изучения предметной области оказалось, что штука «Послать на» (она же «Share to» или «Send to») в Андроид — достаточно универсальна. Это стандартный Интент, который используется везде и всюду, и может пересылать абсолютно любой файл, а не только картинки. Идея расширилась: позволять пересылать любые файлы из любых приложений в любую папку на файловой системе.
Конечно, это можно было сделать в файловом менеджере. Но — гораздо дольше. Смотрите: надо найти файл, надо его выделить, надо вырезать или скопировать его, выбрав пункт меню, надо найти папку, куда его положить, надо снова выбрать пункт меню для вставки. А я придумал, как короче: нужно файл «послать на» SD карту, выбрать папки (а так как папки с прошлого раза запоминаются, то в 95% случаев этот шаг можно пропустить), нажать «скопировать» или «переместить». В два раза меньше действий.
Идея простая. И мне непонятно, почему до сих пор, аж уже в шестом Андроиде, это не стало функцией системы. Сейчас частично этот функционал встраивают в некоторые файловые менеджеры, но универсальности моей программы ещё никто не переплюнул.
Впрочем, в систему это не встроили, потому что незачем простому юзеру знать про какие-то там файловые системы.
Раньше на Андроиде не было доступных пользователю файлов на самом телефоне. Надо было обязательно вставлять SD карту, куда и кидались файлы тех же фоточек. Потому приложение и называется «Отправить на SD карту». Потом от SD карты отказались, и эмулируемая файлопомойка перекочевала в сам девайс. Потом некоторые производители вернулись к SD карте. И в Андроиде оказалось две файлопомойки. Где-то в этот момент, в Kit Kat, Гугль сделали мне подлянку. Внезапно оказалось, что приложения, честно запросившие пермишены на полный доступ на запись к общей файлопомойке, не могут в эту файлопомойку писать. А могут писать только в тот специально отведенный уголочек, в подпапку Android\<имя пакета приложения>, который аккуратно подчищается после удаления приложения.
Вроде как производители неправильно поняли Гугль. Имелось в виду, что все приложения имеют доступ на запись в свой приватный уголочек, а те, которые запросят пермишен на запись в файлопомойку (т.е. и моя сдкартопосылательная программа), должны по-прежнему иметь возможность писать куда угодно. Не знаю, кто кого как понял, но до сих пор я вижу на устройствах то невозможность писать на SD карту, то невозможность писать во внутреннюю память. Что попало. Понятно, что невозможность писать в произвольный каталог файловой системы делает мою программу полностью бесполезной. Файловые менеджеры тоже от этой глупости страдают. Хотя предустановленные файловые менеджеры магическим образом могут писать куда угодно.
Hacking Android
Получается, у меня какой-то талант натыкаться на какие-то мелкие недочеты в системе и затыкать их своими программами. Чтобы сделать мелкие вещи более удобными. Таких программ у меня много.
Продолжение следует.