Спокойной ночи!

    image Около месяца назад я приобрел HTC Hero. Основной причиной, по которой был выбран этот телефон, а не iPhone, была возможность полноценно разрабатывать приложения под Windows.

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

    Техзадание


    Проблема заключается в том, что современные телефоны умеют гораздо больше, чем просто звонить. Они могут получать обновления с твиттера, электронной почты и кучи других мест. При этом они норовят сообщить пользователю об этих обновлениях. И вроде бы все неплохо до тех пор, пока не наступит ночь. Ложишься спать, закрываешь глаза, а тут «дзинь» или «ЖЖЖ-ЖЖЖ». В какой-то момент просто выключаешь звук и вибрацию для того, чтобы заснуть.

    Как раз для этого и нужна программа. Она отключает все оповещения в заданный отрезок времени.

    Среда разработки


    Eclipse — практически единственное полноценное средство для разработки под Android. Для работы я выбрал Eclipse Classic 3.5.1.

    Также вам понадобится Android SDK. Его можно найти на странице загрузки. Там же есть краткое руководство по установке.

    С чего начать


    Для меня разработка под Java и Android — совершенно новое занятие. Поэтому первым делом я внимательно изучил уроки, которые представлены в разделе Resources.

    Также в разделе References вы найдете объемный справочник как по Andriod SDK, так и по стандартным java-пакетам. Единственное чего там не хватает, так это примеров использования. В результате сперва находишь нужный класс, а потом с помощью Google ищешь то, как им пользоваться в контексте приложения.

    Интерфейс пользователя
    image

    Разработка интерфейса пользователя происходит во встроенном редакторе и понятна каждому, кто сталкивался с конструкторами форм:
    image

    Советы по проектированию интерфейсов для Android можно прочесть в специальном разделе Dev Guide. Там же находятся рекомендации по проектированию иконок:
    image

    Мне с трудом удалось вписать свой прямоугольник в перспективу, требуемую для иконок. Как делать что-то более сложное я не представляю. Тем не менее там есть набор шаблонов для Photoshop и Illustrator, который значительно облегчает создание иконок.

    Хранение пользовательских настроек


    Для работы с пользовательскими настройками в Android существует класс PreferenceManager. Метод getSharedPreferences() принимает в качестве первого аргумента имя набора настроек, а в качестве второго — режим создания (закрытый, открытый для чтения или открытый для записи). В ответ мы получаем объект класса SharedPreferences, который позволяет записывать и считывать настройки. Если такого набора нет, то он будет создан:
    SharedPreferences preferences = getSharedPreferences("goodnight", MODE_PRIVATE);

    Для чтения различных типов данных специальные методы. Первый аргумент — название поля, а второй — значение по умолчанию:
    preferences.getBoolean("isEnabled", false)
    preferences.getInt("startHour", 23)

    Для записи необходимо получить объект SharedPreferences.Editor с помощью метода edit(), а в конце вызвать метод commit():
    Editor prefEditor =preferences.edit();
    prefEditor.putBoolean("isEnabled",isEnabledCheckBox.isChecked());
    prefEditor.putInt("startHour", startTimePicker.getCurrentHour());
    prefEditor.putInt("startMinute", startTimePicker.getCurrentMinute());
    prefEditor.putInt("endHour", endTimePicker.getCurrentHour());
    prefEditor.putInt("endMinute", endTimePicker.getCurrentMinute());
    prefEditor.commit();

    Сервисы


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

    Для создания сервиса необходимо создать собственный класс, унаследованный от android.app.Service и переопределяющий метод onBind():

    public class GoodnightService extends Service {
      @Override
      public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
      }
    }

    Также могут пригодиться методы onCreate() и onDestroy():
    @Override
      public void onCreate() {
        super.onCreate();
        Log.i("GoodnightService", "Service created");
      }
    @Override
      public void onDestroy() {
        super.onDestroy();
        Log.i("GoodnightService", "Service destroyed");
      }

    Существует два типа взаимодействия с сервисами: передача параметров при старте или использование Android IDL (AIDL). В первом случае вы запускаете сервис и после этого вы можете только закрыть его. Во втором случае вы можете создать интерфейс, с помощью которого будет возможно управлять сервисом. Т.к. я планировал менять время начала и окончания ночи, то я выбрал второй вариант.

    Для этого необходимо создать файл с расширением .aidl и в нем прописать интерфейс:
    interface IGoodnightService {
      void UpdateSettings();
    }

    Теперь необходимо скомпилировать проект для того, чтобы сгенерировать из файла .aidl IDL интерфейс. После компиляции можно обновить метод onBind() и создать новое свойство binder:
      @Override
      public IBinder onBind(Intent intent) {
        return binder;
      }

    private final IGoodnightService.Stub binder = new IGoodnightService.Stub() {
        @Override
        public void UpdateSettings() {
          Init();
          Update();
        }
      };

    Если у вас нет метода Stub(), то скорее всего файл с интерфейсом имеет расширение .java, а не .aidl.

    Еще необходимо добавить ваш сервис в манифест приложения AndroidManifest.xml:
    image

    Сервисы на стороне клиента

    Чтобы использовать созданный интерфейс, при нажатии на кнопку «Применить», необходимо выполнить несколько простых действий. Во-первых нам понадобится объект с типом нашего интерфейса:
    private IGoodnightService service;

    Во-вторых, необходимо создать своиство типа ServiceConnection, которое отслеживает состояние сервиса и необходимо для связывания с ним интерфейса:
    private ServiceConnection svcConn=new ServiceConnection() {
        public void onServiceConnected(ComponentName className,
        IBinder binder) {
          service=IGoodnightService.Stub.asInterface(binder);
       
        }
        public void onServiceDisconnected(ComponentName className) {
        service=null;
        }
        };


    И, наконец, нужно связать сервис с нашим приложением с помощью метода bindService():
    bindService(new Intent(this,GoodnightService.class), svcConn, BIND_AUTO_CREATE);

    Теперь можно смело обращаться к методам, описанным в IGoodnightService:
    try {
      service.UpdateTimers();
    } catch (RemoteException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    Оповещения


    Для того, чтобы хоть как-то показать работоспособность сервиса я воспользовался механизмом оповещений. Это может быть вибрация, звуковые сигналы или маленькая иконка в строке состояния (вторая слева):
    image

    Если открыть строку состояния, то можно увидеть оповещение в более развернутом виде:
    image

    Текстовые оповещения бывают двух видов: сообщающие о новых событиях (например, сообщение в твиттере :-)) или о том, что программа просто работает.

    Оповещения первого типа можно удалить из списка, нажав на кнопку «Очистить уведомления». Сперва я делал их каждую минуту для того, чтобы они не пропадали. Практика показала, что спустя 5-6 часов все начинало дико тормозить, а оповещения больше не обновлялись. :-) После чего был найден второй способ.

    Для создания оповещений нам понадобится NotificationManager, который можно получить с помощью метода getSystemService():
    final NotificationManager mgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);


    Теперь нужно создать само оповещение (Notification):
    Notification note = new Notification(R.drawable.status,
        getResources().getString(R.string.startMessage),
        System.currentTimeMillis());
    note.flags |= Notification.FLAG_ONGOING_EVENT;
    PendingIntent i = PendingIntent.getActivity(this, 0,
        new Intent(this, Setup.class), 0);
    String interval = String.format("%d:%02d – %d:%02d", startHour,
        startMinute, endHour, endMinute);

    note.setLatestEventInfo(this, interval,
        getResources().getString(R.string.notificationMessage), i);

    Здесь PendingIntent — это ссылка на приложение, которое будет запущено после щелчка по уведомлению. А Notification.FLAG_ONGOING_EVENT задает второй тип оповещений.

    Для отправки оповещения используется метод notify():
    mgr.notify(NOTIFY_ME_ID, note);

    Для того, чтобы удалить оповещение из строки состояния нужно вызвать метод cancel():
    mgr.cancel(NOTIFY_ME_ID);


    Выключение звука


    Для того, чтобы выключить или включить звук, нужно получить AudioManager:
    AudioManager manager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

    И установить соответствующий режим с помощью setRingerMode():
    manager.setRingerMode(AudioManager.RINGER_MODE_SILENT);


    Финальная сборка приложения


    Для того, чтобы собрать приложение в работающий apk-контейнер, нужно выбрать проект, из контекстного меню запустить мастер экспорта, расположенный в Android Tools, и сделать все, что он просит:
    image
    image
    Подробнее об этом написано в разделе Publishing.

    Микро-заключение


    Писать приложения для Android не так просто, как расширения для Chrome. Тем не менее в этом нет ничего сверхъестественно сложного. :-) Главное начать.

    Ссылка на приложение


    Бонус для тех, кто дочитал:
    image
    http://x.product-studio.ru/Goodnight.apk

    Буду рад услышать критику, пожелания и вопросы.
    Поделиться публикацией

    Комментарии 72

      +13
      Отличное руководство! Давно хотел освоить Android, займусь после НГ. Спасибо!
        0
        Тоже займусь, но для начала надо наконец получить Hero — вчера только деньги дошли)
        0
        Тоже хочу, но пока нет возможности купить аппарат на Android, а тут еще и Nokia N900 появился, теперь ломаю голову что лучше всего купить.
          –1
          Лучше — Андроид. Для n900 до сих пор кот наплакал софта. И вообще, держал в руках 810ую — гадость редкостная. Медленный, занудный, да еще и подобные трубки — это не смартфоны с симбианом, по которым сообщества большие…
            +1
            А что симбиан с сообществом? Ну есть у меня Е71, а чтоб под нее софтину найти — надо пол инета перегуглить. А потом после установки телефон глючтиь начинает… Ну и еще огребаешь гемморой с сертификатами. Я для себя сделал вывод, что обилие софта под симбиан — надуманно.
              0
              > Ну и еще огребаешь гемморой с сертификатами

              Вы знаете, я всего один раз переводил дату. Нужно всего лишь настроить диспетчер приложений:

              Установлено — Дисп. прил. — Настройки

              Прогр. устан. — Все
              Проверка сертиф. — Выключена

              Основные минусы симбиана в медленной ява-машине и переводе на русский (неудобный перевод и смена раскладки и неработающая цифровая клавиатура в русской раскладке)
                +1
                После таких манипуляций все равно не весь софт можно поставить.
            +1
            Я тоже ломал голову, но потом решил — у Android'а перспективы намного лучше. Например, платформа Maemo от Nokia имеет много проприетарных частей, и используется только на телефонах Nokia. И так будет всегда — Nokia не интересна конкуренция, компания будет проталкивать свои интересы.

            А на базе Android уже очень много устройств, и ещё больше сейчас в разработке. Это означает широкий выбор устройств, кучу приложений на все случаи жизни, большое число пользователей и прекрасную вылизанность платформы в конечном итоге. И хотя инициатором создания является частная компания (Google), она занимает свою узкую нишу разработчика ПО и интернет-сервисов, и не конкурирует ни с производителями телефонов, ни с разработчиками софта.

            Планирую скоро купить HTC Hero.
              0
              просто Нокиа, как и Эппл, продвигает на рынок собственное комплексное решение, а Андроид — это платформа, как ВинМобайл. поэтому в арсенале НТС всегда будут смартфоны с андроидом, но никогда не будет смартфона с iPhone OS.
                +1
                Именно, про это я и пишу. HTC, Samsung, Motorolla и десятки других производителей никогда не выпустят смарфон ни с iPhone OS, ни даже с Maemo.
                Просто вдумайтесь: на одной стороне Apple или Nokia со своими платформами, а на другой — прорва других компаний с единой универсальной платформой. Как думаете, на чьей стороне будет успех?

                Когда-то массовость и единство PC-архитектуры + единое ПО от Microsoft (DOS/Windows) породило мировое господство этой платформы. А компьютеры Apple, несмотря на армию фанатов, так и остались редкостью, менее 10% всех компьютеров мира, да и то благодаря включению США в статистику.

                Поэтому я не верю ни в Nokia/Maemo даже в Apple/iPhone. Конкуренция + выбор + цена + удобство + распространённость (а значит и количество игр и прочего софта) будут в пользу Android. Мне кажется, многие производители тоже пришли к такому выводу.
            +2
            Программа интересная, а как насчет важных звонков, может дать возможность пользователю создавать список контактов исключений, которым Вас можно будет будить ночью? ))
              0
              Я исхожу из того, что если что-то действительно важное, то меня разбудят. Например, по домашнему. :)
              Учту ваше пожелание.
                +2
                Можно еще добавить функцию включения будильника сразу после выключения режима без звука.
                  0
                  Спасибо. Как раз думаю над тем, как добавить будильник.
              +1
              Я так понимаю на маркете вашей программки нет?
                +2
                Нет. У меня украинский Hero, а на нем маркета нет. После НГ займусь этим вопросом.
                +1
                В херо есть такие классные колёсики установки времени в будильнике и календаре. Нельзя ли их заюзать? А то кнопочки с + и — смотрятся очень архаично.
                  0
                  Я тоже их искал, но с первой попытки не нашел: это какие-то собственные элементы от HTC. Где-то я слышал, что они доступны. Буду искать.
                  0
                  это стандартные Андроидовские кнопочки, да. До сих пор не понимаю, зачем выставлять будильник с точностью до минуты.

                  а в Херо спёрто с айфона — там наверняка целый отдел сидел и думал над юзабилити =)
                    0
                    Во-во, я как раз про них и говорю.

                    Кстати, про ваш будильник. Он встраивается в панель управлением временем стандартную?
                      0
                      Нет. А как это сделать?
                        0
                        Я не знаю. Одной из проблем WM была как раз разрозненность интерфейса. Каждый писал кто во что горазд, настройки программ разбросаны чёрт знает где. К сожалению, андроид походу повторит этот фейл.
                          0
                          Я понимаю, что вы предлагаете сделать, но для этого HTC должны опубликовать исходные коды или хотя бы список своих Intent'ов.
                            +1
                            Но из-за врождённой копирастии этого никогда не сделает. Apple коды закрывает, но хотя бы даёт прекрасный API, нокия почти вообще всё под GPL выпускает. А андроид получился ни рыба, ни мясо.
                              0
                              Тут не Андроида больше вина, а HTC. Можно самому написать такие контролы и выложить их в открытый доступ или вообще внести в исходники Андроида, ведь его код никто не закрывал.
                        0
                        Эм… та, что на Hero? это весьма сложно сделать — там закрытое приложение.
                        можно лишь отследить что через него выставили время, не больше.
                          0
                          Блин, я так и знал :(((
                    +2
                    здорово для тренировки!

                    кстати, просто удивительно что я для своего android-будильника (http://alarm.kosenkov.com) нарисовал точно такую же икноку:
                    alarm.kosenkov.com/tmp/moon.png (простите, кармы не хватает вставить картинкой)
                    да, и будильник тоже выключает звук на ночь =) ну и airplane mode для параноиков.

                    Кстати, уже 12 тысяч установок!

                    Нет ли желания объединить усилия? =)
                      0
                      Идея такого будильника классная. А какой смысл в объединении усилий? У вас вроде и так уже все готово.
                        +1
                        А у меня ещё полтора миллиона идей и мегаватты энергии для реализации! Особенно для маньяка-фотографа-дизайнера-программиста.

                        Плюс, оно на hero не работает пока =( из-за бага в прошивке
                        0
                        Какой интересный проект! Давно ищу толковый будильник для Андроида. А скачать его ниоткуда нельзя, пока он отсутствует на маркете?
                          0
                          Он на маркете сейчас!
                          ищите в health на второй странице
                      • НЛО прилетело и опубликовало эту надпись здесь
                          +1
                          Можно, но об этом не всегда помнишь. Стараюсь свести раздражающие меня факторы к минимуму.
                          +2
                          прям-таки соблазн. с силой заставляю себя не рассматривать красивые картинки.
                          после глупой wince\mo похоже это будет мой второй шаг…
                          респект автору.
                            0
                            Спасибо.
                              0
                              уточню — я в смысле программо-писания, а не слюно-пускания :-)
                            +1
                            Вы же на Java пишете, для которой имена методов с большой буквы не приняты, и не используются опытными разработчиками. Лучше используйте официальные Java Naming Conventions java.sun.com/docs/codeconv/html/CodeConventions.doc8.html
                              0
                              Спасибо. Я знаю. Просто очень давно пишу на .net и мне так привычнее. Постараюсь использовать общепринятые обозначения.
                              +1
                              Спасибо за статью — впервые захотелось купить Андроид.

                              А отлаживать приложения как? Только на телефоне, или есть эмулятор для Eclipse?
                                0
                                Есть эмулятор. Кроме того, производители железа поставляют свои скины эмулятора, чтобы проверить как всё будет работать на их экранах и т. д.
                                  0
                                  Эмулятор сам по себе, отдельно от Эклипса, в общем.

                                  С точки зрения отладки, телефон и эмулятор неотличимы; оба поддерживают полноценную step-by-step отладку.
                                    0
                                    Можно отлаживать прямо из IDE?
                                      0
                                      я именно про это.

                                      из Eclipse или Idea (моя любовь на век). про нетБинс не знаю
                                        +1
                                        Эмулятор входит в Android SDK.
                                        Есть еще плагин для Eclipse, который их связывает и позволяет отлаживать прямо в Eclipse :)
                                    +1
                                    А Вы заметили, что стиль иконок в Android 2.0 будут менять. Теперь без сложной перспективы — взгляд вертикально на иконку. Довольно стильно, приложения в Market уже начали медленно переходить.
                                      0
                                      Это правильный шаг. Надо будет посмотреть и обновить свою.
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                          +1
                                          А у меня захотелось написать подобное для своего WinMo-аппарата ) Надо перекорректировать планы на праздники…
                                          +1
                                          Отличная статья, спасибо.

                                          А как обстоят дела с отладкой на девайсе?
                                          Я под Андроид не писал, но для WM например Студия позволяет дебажить прямо на девайсе…
                                            0
                                            IDEA и eclipse позволяет дебажить прямо на девайсе.
                                              –1
                                              Выше уже писали. Андроид тоже можно отлаживать как на симуляторе, так и на самом телефоне.
                                              +1
                                              Тем кто привык к IDEA не нужно переходить на eclipse. В IDEA 9 есть вполне удобоваримая поддержка android (запуск эмулятора, отладка, автодополнение, да и много еще чего).
                                                +1
                                                +1000
                                                Сам хотел написать такое приложение, но к сожаление пока руки не дошли (работаю в отрасли далекой от программирования)
                                                Дам Вам дополнительную идею, установка расписания отключения, т.е. возможность задавать несколько интервалов отключения звука.
                                                Пример применения: в моем случае маленький ребенок спит в определенные интервалы времени, когда необходимо отключать звук, а сам забываешь либо отключать звук, либо включать
                                                  0
                                                  Спасибо. Подумаю над вашей идеей.
                                                  +1
                                                  Кстати руководству по иконкам не обязательно следовать, например в версии 2.0 анройда уже иконки плоские используются с небольшой тенью :)
                                                    +1
                                                    Огромный респект автору!) Надо тоже это дело освоить
                                                      +1
                                                      >>Основной причиной, по которой был выбран этот телефон, а не iPhone, была возможность полноценно разрабатывать приложения под Windows.

                                                      Казалось бы, причем тут Windows… Три раза перечитал, потом еще полностью прочел и понял что таки не причем.
                                                      А с эмулятором игрался еще до выхода платформы, API понравилось, но девайс на Андроиде не купил, почему-то опасаюсь в последнее время G**gle
                                                        +1
                                                        Всё это конечно здорово, уважаю людей, которые пишут сами подобные маленькие, но очень гордые програмки) Но проще и себе для здоровья полезнее просто выключать телефон на ночь. Вот чего-чего, а это столь близкой любви к сотовым не разделяю — ну хоть ночью-то можно от него избавляться, честное слово.
                                                          0
                                                          Тогда нужно заводить будильник отдельный.
                                                            0
                                                            Дык любой современный сотовый звонит в режиме будильника даже когда выключен.
                                                              0
                                                              отчасти, бывают исключения — андройдфоны от Сасунга i7500 и i5700
                                                                0
                                                                Ничего себе. Это же банальная функция, которая была даже в стареньких легендарных Сименсах С-серии (которые звонили будильником даже при дохлой батарейке, лол :)
                                                          0
                                                          спасибо за статью! познавательно!
                                                          есть кстати замечательная программа Locale для аналогичных целей, но более функциональная и с поддержкой плагинов

                                                            0
                                                            Спасибо! В маркет пока не вхож, но пытаюсь это исправить.
                                                            Делал в целях саморазвития. Так что наличие подобных программ не смущает. :-)
                                                            0
                                                            Прошу простить меня за суровый некропостинг, но у вас в коде большая ошибка. Сам с ней столкнулся, создавая приложение по вашему посту.
                                                            Дело в том, что вызов bindService() НЕ ГАРАНТИРУЕТ, что сервис будет создан и приконнекчен мгновенно. Он лишь запускает процесс запуска сервиса (сорри за тафталогию).
                                                            Соответственно, если сразу же пытаться вызывать методы сервиса, есть риск нарваться на null pointer exception, что и происходило в моём случае.
                                                            Самый, на мой взгляд, правильный вариант — вызвать метод внутри onServiceConnected().
                                                              0
                                                              Вот что-то похожее про начало разработки под Android
                                                                +1
                                                                Мда, а картинки нельзя вернуть?
                                                                  0
                                                                  а есть ли какая-нибудь подобная глушилка телефона на ночь, но чтобы умела пропускать звонки от пары особо важных номеров? никто не подскажет такую?
                                                                    0
                                                                    а можно картинки как-то воскресить? актуальный материал :)

                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.