Пишем приложение «Спокойный сон»
Современные телефоны на Android – далеко не просто «звонилки». При помощи как сторонних, так и предустановленных программных средств мобильные гаджеты умеют самостоятельно получать обновления в социальных сетях, принимать электронную почту и так далее – и зачастую всё это сопровождается звуковыми уведомлениями.
Удобно – до тех пор, пока не нужно лечь спать, а смартфон в 3 часа ночи радостно «жужжит» про обновление статуса Васи Пупкина «Вконтакте». Приходится отключать все оповещения на ночь. Программу, которая будет это делать, мы и будем создавать.
В качестве среды разработки мы будем использовать Eclipse. Не забываем, что понадобятся также установленные Android SDK и JDK.
Начнем с интерфейса. Его создание происходит во встроенном редакторе, и в целом всё интуитивно понятно – это конструктор форм. Развернутые рекомендации и советы по поводу создания пользовательского интерфейса для Android-приложений можно прочитать в посвященном этому разделе официального сайта разработчиков для ОС Android – http://developer.android.com/intl/zh-TW/guide/practices/ui_guidelines/index.html. По указанной ссылке также выложены шаблоны для программ 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();
Чтобы сохранять деятельность приложения, даже когда оно не открыто, то есть в фоне, существуют сервисы. Кстати, это одно из ключевых отличий от iOS, и мы хотим сказать, что оно дает множество очков в пользу ОС Android в извечном противостоянии. Но ближе к делу. Для того, чтобы создать сервис, нужно сначала создать собственный класс, унаследованный от 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"); }
Всего есть два типа взаимодействия с сервисами – это передача параметров при старте или же с использованием AIDL (Android IDL). В первом случае, после запуска сервиса – его можно только закрыть. А при использовании второго типа взаимодействия можно создать интерфейс, позволяющий управлять сервисом – в нашем случае, например, менять начало и конец ночи. Создаем файл с расширением .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() нет, то, вероятно, файл, содержащий интерфейс имеет расширение не .aidl, а .java.
Напомним, что важно не забыть добавить сервис в «манифест» (AndroidManifest.xml).
Для использования созданного интерфейса, при нажатии на кнопку «Применить», нужно выполнить пару простых действий. Сначала понадобится объект с типом интерфейса:
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(); }
Для отображения процесса работы сервиса пользователю, мы будем использовать механизмом Android-оповещений. Это может быть вибрация, звук или иконка в строке состояния. Если открыть строку состояния – можно увидеть оповещение в развернутом виде. Текстовые оповещения, в свою очередь, бывают двух видов – сообщающие о новых событиях или сообщающие просто о работе программы. Первый тип оповещений можно удалять из списка, нажав на «Очистить уведомления». Первый вариант в нашем приложении содержал такие оповещения каждую минуту – чтобы они не пропадали с экрана. Но, как показывает практика, устройство начинает жутко подтормаживать уже через 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), и дальше следовать указаниям.
В целом, создавать приложения для Android не слишком сложно – достаточно приловчится, а дальше, как говориться, «дело техники». Главное – желание самосовершенствоваться в навыках программирования.
а готовый apk можно скачать?