• Как мы :hover на iOS побеждали…

      Ни для кого, думаю, не секрет, что touch-устройства обрабатывают «мышиные» события несколько иначе, не так, как это происходит на десктоп-браузерах…

      Самый яркий для меня пример, это обработка псевдокласса :hover. Для начала iOS7, например, не будет реагировать на hover если только на элемент, или его родителя, не навешена обработка события click. Это хорошо видно вот на этом примере: jsfiddle.net/H8EmG — сколько не тыкай пальцем в текст — никаких подчеркиваний не увидишь. А в этом примере jsfiddle.net/H8EmG/1 «тычок» пальцем в текст будет приводить к его подчеркиванию. Интересный факт — пока не ткнем в другой элемент, текст так и будет сидеть под ховером…

      Другой интересный пример, это обработка появления элементов «по-наведению»: jsfiddle.net/ASRm9/1 Попробуйте нажать на текст. Сперва вы увидите текст «HOVER!», появившийся внутри строки, а вот второе нажатие уже вызовет alert('click'). Это происходит потому, что iOS понимает что за :hover что-то скрыто, и старается не сломать поведение, заложенное автором сайта.

      Но однажды мы столкнулись с такой багой, объяснить которую мы не смогли до сих пор, а на ее локализацию потребовался не один день отладки на iPad… Желающие подробностей, а также хитрого, как мне кажется, способа решения, наверное, всех проблем с :hover разом — прошу под кат…

      Читать дальше →
    • Выполнение задач в бэкграунде

        На Stackoverflow часто встречаются вопросы по выполнению на Android фоновых задач, в т.ч. и повторяющихся с заданным промежутком времени. Как правило, первое, что используется, это Service.

        Такой подход в некоторых случаях может привести к тормозам и низкой скорости ответа пользовательского интерфейса. Расскажу когда так бывает и как с этим бороться…
        Читать дальше →
      • Делаем простейший сборщик ошибок для Android

          При разработке приложения неизбежно приходится сталкиваться с ошибками в коде и/или окружении. И очень печально когда подобные ошибки встречаются не на тестовом телефоне/эмуляторе а у живых пользователей. Еще печальнее если это не ваш друг бета-тестер и толком никто не может объяснить что и где свалилось.

          Обычно при внезапном падении приложения Android предлагает отправить отчет об ошибке, где будет и подробный стэк-трейс и информация о версии вашего приложения. К сожалению пользователи не всегда нажимают кнопку «отправить отчет» а для дебаг-приложений или приложений не из маркета такая функциональность и вовсе недоступна.

          Что же делать? На помощь приедет возможность языка Java обрабатывать исключения (Exceptions), в том числе и непойманные (unhandled).

          Читать дальше →
        • Мошеннические Android-приложения. Ковыряем врага

            Я являюсь разработчиком Android-приложения и слежу за появлением новых ссылок на него с помощью подписок Google. Сегодня утром я с радостью обнаружил в ящике письмо, в котором присутствовала новая ссылка на мое приложение. Все отлично! И отзыв положительный, и количество загрузок отличное от 0 вот только версия почему-то старая и… размер APK целых 3 мегабайта против оригинальных ~200К

            После загрузки и распаковки APK (вспоминаем что APK это просто ZIP-архив) в нем обнаружилась «набивка» из 153 PNG файлов (переименованных зачем-то в .temp) со свидетелем из Фрязино и собственно «приложение»…

            Как и следовало ожидать, от оригинального приложения там ничего не осталось. Ни иконки, ни, тем более, кода. А при дальнейшем рассмотрении (похоже что) ВСЕ файлы на androides-os.com — одна и та же программа! Я скачал несколько разных программ из разных разделов и все они были одного размера и с одинаковым содержимым!

            Внутри оказалось нечто, которое по беглому анализу ресурсов оказалось приложением, запрашивающим активацию путем отправки SMS. Попробуем разобраться, куда и что отправляется…

            Читать дальше →
          • Простой, казалось бы, вопрос по JavaScript

              Есть простейший с виду код:

              setInterval(function(){
                   var xhr = new XMLHttpRequest();
                   xhr.open('GET', 'json.txt', true);
                   xhr.onreadystatechange = function() {
                      if(this.readyState == 4 && this.status == 200) {
                         console.log(this.responseText);
                      }
                   };
                   xhr.send('');
              }, 500);
              


              Если оставить этот код работающим в, например, Google Chorme, скажем, на 1 час, он съедает память. Съедает методично. Если посмотреть в Developer Tools на профиль использования памяти видно что память таки чистится GC но не до конца. Со временем минимальная точка на графике после GC растет.

              image

              Аналогично рост потребления памяти видно и по about:memory. «Отжир» памяти стабильно видно и в FF…

              Важное...
              • Файл json.txt лежит на localhost, его загрузка не занимает более 500мс гарантированно (я проверял).
              • Вывод в консоль я тоже отключал — память по прежнему отжирается.
              • EDIT без включенных developer tools — тоже течет, видно на about:memory.


              Кроме этого кода более на данной странице никакого кода нет вообще.

              Возможно я не понимаю как работает GC в JS, но по моему понятию тут нечему течь и нечему жить вечно. Может кто-то объяснить почему?

              P.S. «Настоящей» утечки таки нет, если обновить страницу — память очищается.
              P.P.S. Есть локальная жизненна потребность («требования бизнеса») оставлять подобный по структуре код на гораздо большие промежутки чем 1 час.

              UPD: Оказывается есть даже тикет в хромиуме: code.google.com/p/chromium/issues/detail?id=52411
              UPD: Якобы fixed in 9, но я проверяю на 10.
            • Библиотека для работы с API Яндекс.Денег и демонстрационное Android-приложение

                Добрый день, хабросообщество.

                Хочу поделиться своей разработкой — Android-библиотекой для работы с API Яндекс.Денег.

                Не далее чем 15 апреля Яндекс открыл API для работы с Я.Деньгами. Как и все ранее открытые API по работе с сервисами Яндекса, он основывается на авторизации через OAuth. В текущей реализации API позволяет запрашивать информацию об аккаунте, запрашивать список операций по счету и совершать платежи по шаблонам. Подробно — в документации, вопросы можно задать в клубе разработчиков.

                В результате была запилена библиотека и демо-приложение для Android, работающее с кошельком через API.
                Далее подробности
                • +29
                • 2,8k
                • 2
              • Геопланировщик Hypocampo — теперь с Яндекс.Картами

                   

                  С момента первого анонса на хабре геопланировщика Hypocampo вышло несколько апдейтов, как с новым функционалом, так и с багфиксами. Многим понравилась идея, но для боле удобного использования не хватало Яндекс.Карт. Последняя версия, 0.1.4, преодолела это ограничение и теперь наряду с провайдером геокодирования можно выбрать и провайдера карт (поддерживаются Google и Yandex).
                  О прочих полезных нововведениях - под катом...
                • Интеграционное тестирование web-приложения с Selenium WebDriver

                    Интеграционное тестирование (в отличие от Unit- или модульного тестирования) это тестирование не отдельных атомарных компонентов системы (классов) а результата их взаимодействия между собой в какой-либо среде.

                    Волею судеб я занимаюсь разработкой своего рода интерфейсного фреймворка заточенного на определенные корпоративные нужды. Среда исполнения фреймворка — браузер, а по сему язык — JavaScript.

                    О том, как можно Unit-тестировать JavaScript я писал ранее, сейчас же расскажу о процессе интеграционного тестирования, применяемого в команде.
                    Читать дальше →
                  • Hypocampo — геопланировщик


                      Добрый день, %username%.

                      Всем нам когда-то приходилось планировать задачи, и всем нам приходилось забывать запланированное. Иногда это случалось потому, что в нужном месте мы не вспомнили о нужном деле.

                      Хочу представить свою разработку, призванную помочь избежать таких досадных недоразумений.

                      Hypocampo — приложение для Android, позволяющее планировать задачи привязывая их не ко времени, а к месту. Суть проста — выбираем место, добавляем к нему задачи. При нахождении вас в точке, для которой имеются запланированные активные задачи срабатывает напоминание.
                      Читать дальше →
                    • Небольшое замечание для тех, кто переходит на 1.4.3

                        Особенность в 1.4.3 — проявляется в FF3.6.11

                        Простой пример:
                        <table>
                        	<tr>
                        		<td myAttr='1'>1.1</td>
                        		<td>1.2</td>
                        		<td>1.3</td>
                        		<td myAttr='1'>1.4</td>
                        	</tr>
                        	<tr>
                        		<td myAttr='1'>2.1</td>
                        		<td>2.2</td>
                        		<td>2.3</td>
                        		<td myAttr='1'>2.4</td>
                        	</tr>
                        </table>
                        


                        Ранее, до 1.4.3, результат выполнения следующей jQuery-инструкции был равен 2 (выбраны элементы 1.2 и 1.3)
                            $('tr').eq(0).find('td').eq(0).nextUntil('td[myattr=1]').length
                        


                        В 1.4.3 результат будет равен… 3 (выбираются элементы 1.2, 1.3 и 1.4).
                        Судя по всему, дело в изменении алгоритмов поиска jQuery а именно, переходе на использование matchesSelector. Чтобы вернуть поведение в нужное русло надо взять значение аттрибута в кавычки:

                            $('tr').eq(0).find('td').eq(0).nextUntil('td[myattr="1"]').length
                        


                        Легкой отладки тебе, %username%!

                        UPD: Что интересно, IE8 (а скорее всего IE<9) не подвержен «багу». У него просто не реализован matchesSelector!

                        UPD: Есть подозрение, что это баг в FF3.6.11. В Chrome7 (у него есть matchesSelector!) баг не воспроизводится.