Skip to content

Commit

Permalink
feat: implement haptic feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
Irineu333 committed Sep 30, 2023
1 parent 949fcc3 commit 102b193
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 9 deletions.
5 changes: 4 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
</intent>
</queries>

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

<application
android:name=".SpeakTouchApplication"
android:allowBackup="true"
Expand All @@ -16,7 +18,8 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.SpeakTouch"
tools:targetApi="31">
tools:targetApi="31"
android:icon="@null">

<service
android:name=".service.SpeakTouchService"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Handle haptic feedback.
*
* Copyright (C) 2023 Irineu A. Silva.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.neo.speaktouch.intercepter

import android.content.res.Resources
import android.os.Vibrator
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import com.neo.speaktouch.R
import com.neo.speaktouch.intercepter.interfece.Interceptor
import com.neo.speaktouch.utils.`object`.VibratorCompat

class HapticInterceptor(
val vibrator: Vibrator,
val resources: Resources
) : Interceptor {

override fun handle(event: AccessibilityEvent) {

if (!vibrator.hasVibrator()) return

if (event.eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
handleFocusVibration(event.source ?: return)
}
}

private fun handleFocusVibration(nodeInfo: AccessibilityNodeInfo) {

if (nodeInfo.isClickable) {
VibratorCompat.vibrate(
vibrator,
resources.getIntArray(
R.array.click_vibration
).toLongArray()
)
return
}

VibratorCompat.vibrate(
vibrator,
resources.getIntArray(
R.array.short_vibration
).toLongArray()
)
return
}
}

private fun IntArray.toLongArray(): LongArray {
return LongArray(size) { this[it].toLong() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ class SpeechInterceptor(
speak(reader.getContent(nodeInfo))
}

fun shutdown() {
override fun finish() {

Timber.i("shutdown")
Timber.i("finish")

textToSpeech.shutdown()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,5 @@ import android.view.accessibility.AccessibilityEvent

interface Interceptor {
fun handle(event: AccessibilityEvent)
fun finish() = Unit
}
23 changes: 17 additions & 6 deletions app/src/main/java/com/neo/speaktouch/service/SpeakTouchService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ package com.neo.speaktouch.service
import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityEvent
import com.neo.speaktouch.intercepter.FocusInterceptor
import com.neo.speaktouch.intercepter.HapticInterceptor
import com.neo.speaktouch.intercepter.SpeechInterceptor
import com.neo.speaktouch.intercepter.interfece.Interceptor
import com.neo.speaktouch.utils.extension.getInstance
import com.neo.speaktouch.utils.extension.getLog
import com.neo.speaktouch.utils.`object`.VibratorCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import timber.log.Timber

class SpeakTouchService : AccessibilityService() {
Expand All @@ -35,23 +39,30 @@ class SpeakTouchService : AccessibilityService() {
super.onCreate()

interceptors.add(FocusInterceptor())

interceptors.add(SpeechInterceptor.getInstance(this))

interceptors.add(
HapticInterceptor(
vibrator = VibratorCompat.createVibrator(this),
resources = resources
)
)
}

override fun onAccessibilityEvent(event: AccessibilityEvent) {

Timber.d(event.getLog())

interceptors.forEach { it.handle(event) }
interceptors.forEach {
it.handle(event)
}
}

override fun onDestroy() {
super.onDestroy()

interceptors
.getInstance<SpeechInterceptor>()
.shutdown()

interceptors.forEach(Interceptor::finish)
interceptors.clear()
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Vibration compatibility.
*
* Copyright (C) 2023 Irineu A. Silva.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.neo.speaktouch.utils.`object`

import android.content.Context
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator

object VibratorCompat {

fun vibrate(
vibrator: Vibrator,
pattern: LongArray,
repeat: Int = -1
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
vibrator.vibrate(
VibrationEffect.createWaveform(
pattern,
VibrationEffect.DEFAULT_AMPLITUDE
)
)
} else {
vibrator.vibrate(pattern, repeat)
}
}

fun createVibrator(context: Context): Vibrator {
return context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
}
}
20 changes: 20 additions & 0 deletions app/src/main/res/values/vibration.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer-array name="click_vibration">
<item>0</item>
<item>10</item>
<item>20</item>
<item>20</item>
<item>10</item>
<item>40</item>
</integer-array>

<integer-array name="short_vibration">
<item>0</item>
<item>10</item>
<item>30</item>
<item>30</item>
<item>30</item>
</integer-array>
</resources>

0 comments on commit 102b193

Please sign in to comment.