Skip to content

Commit 479cf23

Browse files
committed
* Updated fingerprint code to better support Samsung devices
* Simplified the alert sound when prompted to disarm alarm on entry
1 parent c496636 commit 479cf23

File tree

8 files changed

+84
-191
lines changed

8 files changed

+84
-191
lines changed

app/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ repositories {
3939

4040
def versionMajor = 0
4141
def versionMinor = 7
42-
def versionPatch = 5
42+
def versionPatch = 6
4343
def versionBuild = 0 // bump for dog food builds, public betas, etc.
4444

4545
def ALARM_CODE() {

app/src/main/java/com/thanksmister/iot/mqtt/alarmpanel/ui/activities/SettingsActivity.kt

+9-2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import timber.log.Timber
4040
import android.support.v4.view.ViewCompat.setAlpha
4141
import android.graphics.PorterDuff
4242
import android.graphics.drawable.Drawable
43-
43+
import android.os.BadParcelableException
4444

4545

4646
class SettingsActivity : BaseActivity(), ViewPager.OnPageChangeListener, SettingsFragment.SettingsFragmentListener {
@@ -75,6 +75,9 @@ class SettingsActivity : BaseActivity(), ViewPager.OnPageChangeListener, Setting
7575
}
7676

7777
pagerAdapter = ScreenSlidePagerAdapter(supportFragmentManager)
78+
// Fix for crash with BadPacelException
79+
// https://stackoverflow.com/questions/49228979/badparcelableexceptionclassnotfoundexception-when-unmarshalling-android-suppor
80+
viewPager.offscreenPageLimit = 2;
7881
viewPager.adapter = pagerAdapter
7982
viewPager.addOnPageChangeListener(this)
8083

@@ -97,7 +100,11 @@ class SettingsActivity : BaseActivity(), ViewPager.OnPageChangeListener, Setting
97100
if (viewPager.currentItem == 0) {
98101
super.onBackPressed()
99102
} else {
100-
viewPager.currentItem = 0
103+
try {
104+
viewPager.currentItem = 0
105+
} catch (e: BadParcelableException) {
106+
Timber.e("ViewPager Error: " + e.message)
107+
}
101108
}
102109
}
103110

app/src/main/java/com/thanksmister/iot/mqtt/alarmpanel/ui/fragments/AlarmSettingsFragment.kt

+18-33
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ import javax.inject.Inject
5050
import com.samsung.android.sdk.SsdkUnsupportedException
5151
import com.samsung.android.sdk.pass.Spass
5252
import com.samsung.android.sdk.SsdkVendorCheck
53+
import com.wei.android.lib.fingerprintidentify.FingerprintIdentify
5354
import com.wei.android.lib.fingerprintidentify.aosp.FingerprintManagerCompatApi23.isHardwareDetected
5455
import com.wei.android.lib.fingerprintidentify.aosp.FingerprintManagerCompatApi23.isHardwareDetected
55-
56-
57-
56+
import com.wei.android.lib.fingerprintidentify.base.BaseFingerprint
57+
import timber.log.Timber
5858

5959

6060
class AlarmSettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener {
@@ -120,7 +120,7 @@ class AlarmSettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSh
120120
delayHomePreference = findPreference(PREF_HOME_DELAY_TIME) as EditTextPreference
121121
delayAwayPreference = findPreference(PREF_AWAY_DELAY_TIME) as EditTextPreference
122122

123-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
123+
if (isFingerprintSupported()) {
124124
fingerprintPreference!!.isVisible = true
125125
fingerprintPreference!!.isChecked = configuration.fingerPrint
126126
} else {
@@ -224,41 +224,26 @@ class AlarmSettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSh
224224
}
225225
}
226226
PREF_FINGERPRINT -> {
227-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
228-
val checked = fingerprintPreference!!.isChecked
229-
if (isFingerprintSupported()) {
230-
configuration.fingerPrint = checked
231-
} else {
232-
Toast.makeText(activity, getString(R.string.pref_fingerprint_error), Toast.LENGTH_LONG).show()
233-
fingerprintPreference!!.isChecked = false
234-
configuration.fingerPrint = false
235-
}
227+
val checked = fingerprintPreference!!.isChecked
228+
if (isFingerprintSupported()) {
229+
configuration.fingerPrint = checked
230+
} else {
231+
Toast.makeText(activity, getString(R.string.pref_fingerprint_error), Toast.LENGTH_LONG).show()
232+
fingerprintPreference!!.isChecked = false
233+
configuration.fingerPrint = false
236234
}
237235
}
238236
}
239237
}
240238

241-
@RequiresApi(Build.VERSION_CODES.M)
239+
@SuppressLint("InlinedApi")
242240
private fun isFingerprintSupported(): Boolean {
243-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
244-
val fingerprintManager = context!!.getSystemService(Context.FINGERPRINT_SERVICE) as FingerprintManager
245-
if(SsdkVendorCheck.isSamsungDevice()) {
246-
var isFingerprintSupported = fingerprintManager.isHardwareDetected
247-
if (!isFingerprintSupported && SsdkVendorCheck.isSamsungDevice()) {
248-
val spass = Spass()
249-
try {
250-
spass.initialize(context)
251-
isFingerprintSupported = spass.isFeatureEnabled(Spass.DEVICE_FINGERPRINT)
252-
} catch (e: SsdkUnsupportedException) {
253-
isFingerprintSupported = false
254-
} catch (e: UnsupportedOperationException) {
255-
isFingerprintSupported = false
256-
}
257-
}
258-
return isFingerprintSupported
259-
} else {
260-
return (fingerprintManager.isHardwareDetected && fingerprintManager.hasEnrolledFingerprints())
261-
}
241+
val fingerPrintIdentity = FingerprintIdentify(context, BaseFingerprint.FingerprintIdentifyExceptionListener {
242+
Timber.e("Fingerprint Error: " + it.message)
243+
})
244+
245+
if(fingerPrintIdentity.isFingerprintEnable && fingerPrintIdentity.isHardwareEnable) {
246+
return true
262247
}
263248
return false
264249
}

app/src/main/java/com/thanksmister/iot/mqtt/alarmpanel/ui/fragments/ControlsFragment.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ class ControlsFragment : BaseFragment() {
286286
Timber.d("onCancel")
287287
dialogUtils.clearDialogs()
288288
}
289-
}, viewModel.getAlarmCode(), false, delayTime, configuration.systemSounds, configuration.fingerPrint)
289+
}, viewModel.getAlarmCode(), delayTime, configuration.fingerPrint)
290290
}
291291

292292
companion object {

app/src/main/java/com/thanksmister/iot/mqtt/alarmpanel/ui/fragments/MainFragment.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class MainFragment : BaseFragment() {
177177
override fun onCancel() {
178178
dialogUtils.clearDialogs()
179179
}
180-
}, configuration.alarmCode, true, delayTime, configuration.systemSounds, configuration.fingerPrint)
180+
}, configuration.alarmCode, delayTime, configuration.systemSounds, configuration.fingerPrint)
181181
}
182182
}
183183

app/src/main/java/com/thanksmister/iot/mqtt/alarmpanel/ui/views/BaseAlarmView.kt

+31-73
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,20 @@
11
package com.thanksmister.iot.mqtt.alarmpanel.ui.views
22

33
import android.annotation.SuppressLint
4-
import android.annotation.TargetApi
54
import android.content.Context
6-
import android.hardware.fingerprint.FingerprintManager
75
import android.media.AudioManager
8-
import android.os.Build
9-
import android.support.annotation.RequiresApi
6+
import android.media.MediaPlayer
7+
import android.media.RingtoneManager
8+
import android.net.Uri
109
import android.util.AttributeSet
1110
import android.view.View
1211
import android.widget.LinearLayout
13-
import com.samsung.android.sdk.SsdkUnsupportedException
14-
import com.samsung.android.sdk.SsdkVendorCheck
15-
import com.samsung.android.sdk.pass.Spass
1612
import com.thanksmister.iot.mqtt.alarmpanel.R
17-
import com.thanksmister.iot.mqtt.alarmpanel.utils.SoundUtils
1813
import com.wei.android.lib.fingerprintidentify.FingerprintIdentify
1914
import com.wei.android.lib.fingerprintidentify.base.BaseFingerprint
2015
import kotlinx.android.synthetic.main.dialog_alarm_code_set.view.*
2116
import kotlinx.android.synthetic.main.view_keypad.view.*
2217
import timber.log.Timber
23-
import android.os.Vibrator
24-
import android.content.Context.VIBRATOR_SERVICE
25-
import android.os.VibrationEffect
26-
import android.media.MediaPlayer
27-
import android.media.RingtoneManager
28-
import android.net.Uri
2918
import java.io.FileNotFoundException
3019

3120
abstract class BaseAlarmView : LinearLayout {
@@ -34,11 +23,7 @@ abstract class BaseAlarmView : LinearLayout {
3423
var enteredCode = ""
3524
var useSystemSound: Boolean = true
3625
var useFingerprint: Boolean = false
37-
var vibrator: Vibrator? = null
3826
private var mediaPlayer: MediaPlayer? = null
39-
40-
private var soundUtils: SoundUtils? = null
41-
4227
private var fingerPrintIdentity:FingerprintIdentify? = null
4328

4429
constructor(context: Context) : super(context) {
@@ -112,11 +97,13 @@ abstract class BaseAlarmView : LinearLayout {
11297
@SuppressLint("InlinedApi")
11398
override fun onVisibilityChanged(changedView: View?, visibility: Int) {
11499
super.onVisibilityChanged(changedView, visibility)
115-
// Fingerprint API only available on from Android 6.0 (M) and we only use this code if user had hardware
116-
// has setup the fingerprint, and user has activated the settings. Be aware of Samsung devices and their issues.
117-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && useFingerprint) {
118-
if (isFingerprintSupported()) {
119-
fingerPrintIdentity = FingerprintIdentify(context)
100+
101+
fingerPrintIdentity = FingerprintIdentify(context, BaseFingerprint.FingerprintIdentifyExceptionListener {
102+
Timber.e("Fingerprint Error: " + it.message)
103+
})
104+
105+
if(fingerPrintIdentity != null) {
106+
if(fingerPrintIdentity!!.isFingerprintEnable && fingerPrintIdentity!!.isHardwareEnable) {
120107
if (!this.isShown){
121108
stopFingerprintIdentity()
122109
return
@@ -127,31 +114,6 @@ abstract class BaseAlarmView : LinearLayout {
127114
}
128115
}
129116

130-
@RequiresApi(Build.VERSION_CODES.M)
131-
private fun isFingerprintSupported(): Boolean {
132-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
133-
val fingerprintManager = context!!.getSystemService(Context.FINGERPRINT_SERVICE) as FingerprintManager
134-
if(SsdkVendorCheck.isSamsungDevice()) {
135-
if (!fingerprintManager.isHardwareDetected && SsdkVendorCheck.isSamsungDevice()) {
136-
val spass = Spass()
137-
try {
138-
spass.initialize(context)
139-
return spass.isFeatureEnabled(Spass.DEVICE_FINGERPRINT)
140-
} catch (e: SsdkUnsupportedException) {
141-
Timber.e(e.message)
142-
return false
143-
} catch (e: UnsupportedOperationException) {
144-
Timber.e(e.message)
145-
return false
146-
}
147-
}
148-
} else {
149-
return (fingerprintManager.isHardwareDetected && fingerprintManager.hasEnrolledFingerprints())
150-
}
151-
}
152-
return false
153-
}
154-
155117
override fun onDetachedFromWindow() {
156118
super.onDetachedFromWindow()
157119
destroySoundUtils()
@@ -175,10 +137,12 @@ abstract class BaseAlarmView : LinearLayout {
175137

176138
override fun onFailed(isDeviceLocked: Boolean) {
177139
Timber.d("Fingerprint identity failed");
140+
fingerNoMatch()
178141
}
179142

180143
override fun onStartFailedByDeviceLocked() {
181144
Timber.d("Fingerprint identity failed by device locked");
145+
fingerNoMatch()
182146
}
183147
})
184148
}
@@ -203,45 +167,39 @@ abstract class BaseAlarmView : LinearLayout {
203167
abstract fun fingerNoMatch()
204168

205169
fun destroySoundUtils() {
206-
if(!useSystemSound)
207-
return
208-
209-
if (soundUtils != null) {
210-
soundUtils?.destroyBuzzer()
211-
}
212-
213170
if(mediaPlayer != null) {
214171
mediaPlayer?.stop()
215172
}
216173
}
217174

218175
fun playContinuousAlarm() {
219-
if(!useSystemSound)
220-
return
221-
222-
try {
223-
var alert: Uri? = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
224-
if (alert == null) {
225-
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
176+
if(useSystemSound) {
177+
try {
178+
var alert: Uri? = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM)
226179
if (alert == null) {
227-
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
180+
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
181+
if (alert == null) {
182+
alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
183+
}
228184
}
185+
mediaPlayer = MediaPlayer.create(context!!, alert)
186+
mediaPlayer?.isLooping = true
187+
mediaPlayer?.start()
188+
} catch (e: SecurityException) {
189+
playContinuousBeep()
190+
} catch(e: FileNotFoundException) {
191+
playContinuousBeep()
229192
}
230-
mediaPlayer = MediaPlayer.create(context!!, alert)
231-
mediaPlayer?.start()
232-
} catch (e: SecurityException) {
233-
playContinuousBeep()
234-
} catch(e: FileNotFoundException) {
193+
} else {
235194
playContinuousBeep()
236195
}
237196
}
238197

239198
private fun playContinuousBeep() {
240-
if (soundUtils == null) {
241-
soundUtils = SoundUtils(context)
242-
soundUtils?.init()
243-
soundUtils?.playBuzzerRepeat()
244-
}
199+
Timber.d("playContinuousBeep")
200+
mediaPlayer = MediaPlayer.create(context!!, R.raw.beep_loop)
201+
mediaPlayer?.isLooping = true
202+
mediaPlayer?.start()
245203
}
246204

247205
protected fun showFilledPins(pinsShown: Int) {

app/src/main/java/com/thanksmister/iot/mqtt/alarmpanel/utils/DialogUtils.kt

+23-5
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ class DialogUtils(base: Context?) : ContextWrapper(base), LifecycleObserver {
146146
/**
147147
* Shows the disable alarm dialog with countdown. It is important that this
148148
* dialog only be shown once and not relaunched when already displayed as
149-
* it resets the timer.
149+
* it resets the timer. Also plays a system sounds (if settings true).
150150
*/
151151
fun showAlarmDisableDialog(activity: AppCompatActivity, alarmCodeListener: AlarmDisableView.ViewListener,
152-
code: Int, beep: Boolean, timeRemaining: Int, systemSounds: Boolean,
152+
code: Int, timeRemaining: Int, systemSounds: Boolean,
153153
useFingerprint: Boolean) {
154154
clearDialogs()
155155
val inflater = activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
@@ -160,9 +160,27 @@ class DialogUtils(base: Context?) : ContextWrapper(base), LifecycleObserver {
160160
alarmCodeView.setUseSound(systemSounds)
161161
alarmCodeView.setUseFingerPrint(useFingerprint)
162162
alarmCodeView.startCountDown(timeRemaining)
163-
if (beep) {
164-
alarmCodeView.playContinuousAlarm()
165-
}
163+
alarmCodeView.playContinuousAlarm()
164+
dialog = buildImmersiveDialog(activity, true, view, false)
165+
dialog!!.setOnDismissListener { alarmCodeView.destroySoundUtils() }
166+
}
167+
168+
/**
169+
* Shows the disable alarm dialog with countdown. It is important that this
170+
* dialog only be shown once and not relaunched when already displayed as
171+
* it resets the timer.
172+
*/
173+
fun showAlarmDisableDialog(activity: AppCompatActivity, alarmCodeListener: AlarmDisableView.ViewListener,
174+
code: Int, timeRemaining: Int, useFingerprint: Boolean) {
175+
clearDialogs()
176+
val inflater = activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
177+
val view = inflater.inflate(R.layout.dialog_alarm_disable, null, false)
178+
val alarmCodeView = view.findViewById<AlarmDisableView>(R.id.alarmDisableView)
179+
alarmCodeView.setListener(alarmCodeListener)
180+
alarmCodeView.setCode(code)
181+
alarmCodeView.setUseSound(false)
182+
alarmCodeView.setUseFingerPrint(useFingerprint)
183+
alarmCodeView.startCountDown(timeRemaining)
166184
dialog = buildImmersiveDialog(activity, true, view, false)
167185
dialog!!.setOnDismissListener { alarmCodeView.destroySoundUtils() }
168186
}

0 commit comments

Comments
 (0)