Статьи

Разработка всегда включенных приложений Smart Watch

Это год, когда умные часы взлетают. По некоторым оценкам, Apple Watch продали несколько миллионов единиц в первый же день выпуска. Менее чем за год часы Android Wear были проданы более чем на 1 миллион единиц, и часы Pebble запустили успешную кампанию Kickstarter для своего нового продукта Pebble Color.

По мере роста популярности платформ для умных часов пришло время подумать о разработке приложений для умных часов. Приложения для умных часов отличаются от приложений для смартфонов тем, что большинство из них предназначены для легких взаимодействий. Пользователь может тратить часы на свой телефон, но секунды на часы. Платформы интеллектуальных часов ограничивают возможности приложения по сокращению времени взаимодействия. Например, iOS WatchKit приостанавливает работающее приложение, когда пользователи опускают запястье, а Android Wear возвращается к циферблату, когда пользователи тускнеют на экране.

Если приложение для просмотра часов требует больше времени для взаимодействия, разработчики должны проявить особую осторожность, чтобы обойти ограничения платформы. В качестве примера можно привести приложение для анализа свинга в гольфе, которое я постоянно разрабатывал и которое отслеживает ход игры в гольф. В этой статье я покажу вам некоторые способы, чтобы приложение для Android Wear всегда было включено.

Режим «всегда включен»

В знак признания необходимости в «постоянно включенных» приложениях компания Google представила часы Ambient Mode для Android Wear. Если вы используете новейшую носимую библиотеку поддержки 1.2.0 и выше, ее можно легко включить. Во-первых, убедитесь, что действие наследуется от Wearable Activity, и включите Ambient Mode при запуске действия:

public class MainActivity extends WearableActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setAmbientEnabled();
    ...
}

Затем прослушайте функции обратного вызова Ambient. В режиме Ambient стремитесь к минимальному пользовательскому интерфейсу для экономии заряда аккумулятора, например к черному фону с минимальной белой графикой и текстом.

 @Override
public void onEnterAmbient(Bundle ambientDetails) {
    super.onEnterAmbient(ambientDetails);

    mStateTextView.setTextColor(Color.WHITE);  // use minimal white graphics and text
    mStateTextView.getPaint().setAntiAlias(false);
}

@Override
public void onExitAmbient() {
    super.onExitAmbient();

    mStateTextView.setTextColor(Color.GREEN);
    mStateTextView.getPaint().setAntiAlias(true);
}

Помимо нескольких строк, которые нужно задать в файле манифеста приложения (для получения более подробной информации обратитесь к документации Android Wear ), эти строки кода — все, что требуется для включения Ambient Mode. Когда пользователь нажимает кнопку питания или проводит пальцами по экрану, вместо того, чтобы показывать часы, приложение остается наверху и входит в Ambient Mode.

Использование уведомлений для вывода приложения на передний план

Существуют ограничения для Android Wear Ambient Mode. Разработчики должны обновлять экран нечасто, например, раз в минуту. В противном случае необходимо установить будильник для периодического пробуждения процессора. Тем не менее, цикл процессора в режиме Ambient ограничен.

Если приложение требует постоянных циклов ЦП, Ambient Mode не подходит. Я работал над фитнес- приложением Android Wear , которое является прекрасным примером. Он постоянно отслеживает движения пользователей и ищет шаблоны упражнений, поэтому ему постоянно требуются циклы ЦП для вычислений.

Чтобы не терять циклы ЦП, фитнес-приложение должно отключить Ambient Mode. Если пользователь случайно коснется кнопки питания или проведет пальцами по экрану, приложение перейдет в фоновый режим. Поскольку Ambient Mode отключен, когда пользователи снова посмотрят на часы, они будут показывать часы. Это плохой пользовательский опыт, потому что легко случайно коснуться кнопки питания. Если пользователи хотят продолжить, они должны перейти в меню «Пуск» и снова найти приложение.

К счастью, есть простой трюк. Приложение может отправить уведомление, когда пользователь закрывает приложение, затем пользователь может нажать на карточку уведомления, чтобы продолжить. Приложение может запустить следующий код в onStop()

 public void onStop() {
        super.onStop();
        if (!isFinishing()) {  // if not terminating, send a notification so that we can wake up if needed
            // create intent that re-launches the activity
            Intent intent = new Intent(getApplicationContext(), MyActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        // when user dismiss the notification, terminate the app as well
            Intent deleteIntent = new Intent(getApplicationContext(), MyActivity.class);
            deleteIntent.setAction("delete");
            PendingIntent pendingDeleteIntent = PendingIntent.getActivity(getApplicationContext(), 0, deleteIntent, PendingIntent.FLAG_UPDATE_CURRENT);

            NotificationCompat.Action action = new NotificationCompat.Action.Builder(android.R.drawable.ic_media_play, null, pendingIntent).build();

            // set notification to let user know
            NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
                    .setSmallIcon(R.drawable.ic_launcher)
                    .setContentTitle("MyApplication")
                    .setContentText("Tap to resume.")
                    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.launchbg))
                    .setLocalOnly(true)
                    .setDefaults(Notification.DEFAULT_VIBRATE)   // must vibrate to wake up the watch
                    .setDeleteIntent(pendingDeleteIntent)
                    .addAction(action)
                    .extend(new NotificationCompat.WearableExtender().setContentAction(0))
                    ;


            Notification notification = builder.build();

            NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(this);
            notificationManagerCompat.notify(Constant.NOTIFICATION_RESUME, notification);
        }
  }

Когда пользователь нажимает кнопку питания, приложение просто переходит в фоновый режим, сохраняя все свои состояния. Когда пользователь нажимает на уведомление, действие будет возвращено из фона в исходное состояние.

Код выше добавляет намерение удаления в уведомлении. Это намерение срабатывает, когда пользователь отклоняет уведомление. Поскольку пользователь, возможно, сознательно нажал кнопку питания, это дает ему возможность полностью убить приложение. Внутри приложения намерение удаления фиксируется и корректно завершает приложение:

 @Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);

   String command = intent.getAction();
   if (command != null && command.equals("delete")) {
        finish();
    }
}

В Apple Watch отсутствует концепция «всегда включен». Но Apple выбрала другой подход для решения этой проблемы. Когда пользователи опускают запястье, приложение может быть приостановлено, а когда пользователи поднимают запястье, приложение снова начинает работать. Поскольку взаимодействие с фреймворком полностью отличается от Android Wear, разработка постоянно включенного приложения для Apple Watch требует нового подхода, о котором я расскажу в следующей статье.