Освой Android играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Виброзвонок

Кот вибрирует

Доступ к виброзвонку
VibrationEffect
Тактильная обратная связь

Отступление

Общеизвестно, что впервые принцип виброзвонка использовали коты. Если приложить руку к коту, то можно почувствовать, что внутри кота работает "моторчик". Конструкторы телефонов решили позаимствовать идею, но авторские отчисления не спешат отчислять.

Британская кошка Смоки из Нортгемптоншира официально попала в Книгу рекордов Гинесса за самое громкое мурлыканье. Представители книги оценили мурлыкание короткошерстной британки в 67.7 децибелов. Рут Адамс, владелица кошки, была в полном восторге, а представитель рассказал, что это просто невероятно, но мурлыканье кошки больше громкости работающего пылесоса.

Доступ к виброзвонку

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

Прежде всего в манифесте необходимо установить разрешение android.permission.VIBRATE:


<uses-permission android:name="android.permission.VIBRATE"/>

Далее в коде вызывается системный сервис VIBRATOR_SERVICE для доступа к виброзвонку. После чего можно вызывать требуемые методы.

Неплохо бы также проверить наличие виброзвонка (например, электронная книга не имеет виброзвонка) при помощи метода hasVibrator().

Например, нужно включить виброрежим на одну секунду


// Kotlin
val vibrator = this.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val canVibrate: Boolean = vibrator.hasVibrator()
val milliseconds = 1000L

if (canVibrate) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        // API 26
        vibrator.vibrate(
                VibrationEffect.createOneShot(
                        milliseconds,
                        VibrationEffect.DEFAULT_AMPLITUDE
                )
        )
    } else {
        // This method was deprecated in API level 26
        vibrator.vibrate(milliseconds)
    }
}

// Java long mills = 1000L; Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); if (vibrator.hasVibrator()) { vibrator.vibrate(mills); }

В примере на Kotlin мы забежали немного вперёд - метод vibrate() уже устарел и нужно использовать новый код (см.ниже).

Шаблон для вибрации

Можно также использовать определённый шаблон, например, 500 миллисекунд на задержку перед виброзвонком, затем виброзвонок на 300 миллисекунд, 400 миллисекунд на паузу, снова виброзвонок на 200 миллисекунд. Второй параметр метода - номер элемента в массиве, с которого выполнять постоянные повторения. Если использовать 0, то виброзвонок будет постоянным с самого начала. Чтобы повторений не было, используйте значение -1 для одноразового вызова.


long[] pattern = { 500, 300, 400, 200 };
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator.hasVibrator()) {
    vibrator.vibrate(pattern, 2);
}

Если задержка перед вибрацией не нужна, то установите значение 0 в первом элементе шаблона.


long[] pattern = {0, 400, 200, 400};

Если вы запустите предыдущий код, то вибрация будет работать и после закрытия приложения. Чтобы избежать подобной ситуации, нужно не забывать отменять виброзвонок. Для отмены вибрации используется метод cancel(). Следующий код запускает вибрацию на две секунды при нажатии на кнопку, при отпускании пальца раньше времени вибрация прекращается:


Button button = findViewById(R.id.button);
button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

        int action = event.getAction();

        if(action == MotionEvent.ACTION_DOWN){
            vibrator.vibrate(2000);
        }else if(action == MotionEvent.ACTION_UP){
            vibrator.cancel();
        }
        return true;
    }
});

VibrationEffect

В API 26 метод vibrate() с примерами выше был признан устаревшим. Вместо него появились другие версии метода с использованием класса VibrationEffect. По сути это другая реализация шаблонов.

Класс содержит три метода

  • createOneShot(long vibrateTimeInMills, int amplitude)
  • createWaveForm(long[] vibratePattern, int[] amplitudes, int repeat)
  • createWaveForm(long[] vibratePattern, int repeat)

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

При вызове метода используется амплитуда для вибромотора от 0 (выключен) до 250 (максимальное значение). Можно использовать значение по умолчанию.


@RequiresApi(api = Build.VERSION_CODES.O)
private void createOneShotVibrationUsingVibrationEffect() {
    // 1000 : Vibrate for 1 sec
    // VibrationEffect.DEFAULT_AMPLITUDE - would perform vibration at full strength
    VibrationEffect effect = VibrationEffect.createOneShot(1000, VibrationEffect.DEFAULT_AMPLITUDE);
    vibrator.vibrate(effect);
}

Вызов другого метода класса. Зададим амплитуду вручную.


@RequiresApi(api = Build.VERSION_CODES.O)
private void createWaveFormVibrationUsingVibrationEffectAndAmplitude() {
    long[] mVibratePattern = new long[]{0, 400, 800, 600, 800, 800, 800, 1000};
    int[] mAmplitudes = new int[]{0, 255, 0, 255, 0, 255, 0, 255};
    // -1 : Play exactly once

    if (vibrator.hasAmplitudeControl()) {
        VibrationEffect effect = VibrationEffect.createWaveform(mVibratePattern, mAmplitudes, -1);
        vibrator.vibrate(effect);
    }
}

При работе с амплитудой вызывайте метод hasAmplitudeControl() для проверки наличия возможности работы с этой настройкой.

Пример на Kotlin был показан в самом начале статьи.

Тактильная обратная связь

Возможно вы замечали, что при нажатии на системные клавиши, например, кнопки BACK, система отвечает вам тактильной обратной связью. По сути это тоже включение вибромотора на короткий промежуток времени. Данная функциональность заложена в Настройках | Звук | Обратная связь (для телефона Galaxy S2, в других ищите похожее).

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

Для сравнения добавьте в разметку две кнопки. Первую кнопку оставьте в покое, а у второй пропишите атрибут android:hapticFeedbackEnabled="true":


<Button
    android:id="@+id/button2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hapticFeedbackEnabled="true"
    android:onClick="onClick"
    android:text="Button2" />

Теперь создадим обработчик нажатия кнопки и напишем в нём код:


public void onClick(View v) {
	Button button2 = findViewById(R.id.button2);
	button2.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}

Запускаем пример и поочерёдно нажимаем на две кнопки - почувствуйте разницу.

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

Существуют и другие константы, кроме VIRTUAL_KEY. Но это уже изучайте без меня.

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

Вибрация в уведомлениях

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

VibratorManager (API 31)

Гугл любит объявлять классы и методы устаревшими. Такая участь постигла и Context.VIBRATOR_SERVICE в Android 12. Пришёл новый манагер со своими методами. Придётся переписывать старые проекты.

Реклама