Vibrate

Make the device vibrate.

Add permission:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.example.android.myapp">

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

    <application
        ...
    </application>

</manifest>

If used in conjunction with ViewModel/LiveData then set up the variables in ViewModel:

import ...

class MyViewModel : ViewModel() {

    companion object {
        private const val DONE = 0L
        private const val ONE_SECOND = 1000L
        private const val COUNTDOWN_TIME = 6000L
        private const val PANIC_TIME = 2000L
        private val FIRST_BUZZ_PATTERN = longArrayOf(100, 100, 100, 100, 100, 100) // Define vibrate patterns
        private val SECOND_BUZZ_PATTERN = longArrayOf(0, 1000)
        private val NO_BUZZ_PATTERN = longArrayOf(0)
    }

    enum class BuzzType(val pattern: LongArray) {
        FIRST(FIRST_BUZZ_PATTERN),
        SECOND(SECOND_BUZZ_PATTERN),
        NO_BUZZ(NO_BUZZ_PATTERN)
    }

    // Buzzer state
    private val _eventBuzz = MutableLiveData<LongArray>() // Create a LiveData object for the value of the buzz LongArray
    val eventBuzz: LiveData<LongArray> // Encapsulate the data
        get() = _eventBuzz

    // Timer value
    private val _currentTime = MutableLiveData<Long>()
    val currentTime: LiveData<Long>
        get() = _currentTime

    private val timer: CountDownTimer

    init {
        timer = object : CountDownTimer(COUNTDOWN_TIME, ONE_SECOND) {
            override fun onTick(millisUntilFinished: Long) {
                _currentTime.value = millisUntilFinished/ ONE_SECOND
                if (millisUntilFinished <= PANIC_TIME) {
                    _eventBuzz.value = BuzzType.FIRST.pattern // Fire a buzz if we are 2 seconds from completion
                }
            }

            override fun onFinish() {
                _currentTime.value = DONE
            }
        }
        timer.start()

    }

    fun onPushButton() {
        _eventBuzz.value = BuzzType.SECOND.pattern
    }

    fun onBuzzComplete() {
        _eventBuzz.value = BuzzType.NO_BUZZ.pattern
    }
}

Back in our Fragment:

import ...

class MyFragment : Fragment() {

    private lateinit var viewModel: MyViewModel

    private lateinit var binding: MyFragmentBinding

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {

        // Inflate view and obtain an instance of the binding class
        binding = DataBindingUtil.inflate(
                inflater,
                R.layout.my_fragment,
                container,
                false
        )

        viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)

        viewModel.eventBuzz.observe(this, Observer { eventBuzz ->
            if (eventBuzz.isNotEmpty()) buzz(eventBuzz)
        })

        binding.myViewModel = viewModel

        binding.setLifecycleOwner(this)

        return binding.root

    }

    private fun buzz(pattern: LongArray) {
        val buzzer = activity?.getSystemService<Vibrator>()

        buzzer?.let {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                buzzer.vibrate(VibrationEffect.createWaveform(pattern, -1))
            } else {
                //deprecated in API 26
                buzzer.vibrate(pattern, -1)
            }
        }
    }
}