Skip to content

Instantly share code, notes, and snippets.

@bewithdhanu
Last active January 12, 2023 11:47
Show Gist options
  • Save bewithdhanu/e8c01c207ba3cfadc4cdc52ea8de58b3 to your computer and use it in GitHub Desktop.
Save bewithdhanu/e8c01c207ba3cfadc4cdc52ea8de58b3 to your computer and use it in GitHub Desktop.
Android check for bluetooth devices using alarm manager

Android check for bluetooth devices using alarm manager

  • This uses AlaramManager to wape for every minute and checks for paired bluetooth devices.
  • To make make AlarmManager to work even after rebooting we have register a BroadcastReceiver to listen reboot event, it is implemented in BootCompletedIntentReceiver

Add this dependency to build.gradle

implementation 'androidx.work:work-runtime:2.7.1'
package com.test.uploadtos3
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import java.util.*
class AlarmActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_alarm)
title = "KotlinApp"
val calendar: Calendar = Calendar.getInstance()
calendar.add(Calendar.SECOND, 30)
val alarmUtility = AlarmUtility()
if (alarmUtility.getPendingIntent(this) != null){
alarmUtility.stopAlarm(this)
}
alarmUtility.setAlarm(this)
}
}
package com.test.uploadtos3
import android.annotation.SuppressLint
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.os.Build
import android.util.Log
import java.lang.reflect.Method
class AlarmReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// This method is called when the BroadcastReceiver is receiving an Intent broadcast.
getDevices(context)
}
@SuppressLint("MissingPermission")
private fun getDevices(context: Context){
val btManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val pairedDevices = btManager.adapter.bondedDevices
if (pairedDevices.size > 0) {
for (device in pairedDevices) {
val deviceName = device.name
val macAddress = device.address
val aliasing = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
device.alias
} else {
device.name
}
Log.d(
" pairedDevices ",
"paired device: $deviceName at $macAddress + $aliasing " + isConnected(device)
)
val preferredDevice = device // TODO change logic to get preferred device
if(isConnected(device) && preferredDevice == device){
val notificationUtils = NotificationUtils(context)
val notification = notificationUtils.getNotificationBuilder().build()
notificationUtils.getManager().notify(150, notification)
}
}
}
}
private fun isConnected(device: BluetoothDevice): Boolean {
return try {
val m: Method = device.javaClass.getMethod("isConnected")
m.invoke(device) as Boolean
} catch (e: Exception) {
throw IllegalStateException(e)
}
}
}
package com.test.uploadtos3
import android.app.AlarmManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
class AlarmUtility {
private val REMINDER_INTENT_REQUEST_CODE: Int = 1001
fun setAlarm(context: Context) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pendingIntent: PendingIntent? = getPendingIntent(context)
alarmManager.setRepeating(
AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + (10 * 1000L),
60*1000L,
pendingIntent
)
}
fun getPendingIntent(context: Context): PendingIntent? {
val intent = Intent(context.applicationContext, AlarmReceiver::class.java)
var pendingIntent: PendingIntent? = null
pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getBroadcast(context, REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_MUTABLE)
} else {
PendingIntent.getBroadcast(context, REMINDER_INTENT_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT)
}
return pendingIntent
}
/*
* Call stopAlarm() during logout or user disables alarms
*/
fun stopAlarm(context: Context) {
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pendingIntent: PendingIntent? = getPendingIntent(context)
alarmManager.cancel(pendingIntent) //important
pendingIntent?.cancel() //important
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.test.uploadtos3">
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.UploadToS3"
tools:targetApi="31">
<activity
android:name=".AlarmActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".AlarmReceiver"
android:enabled="true"/>
<receiver android:name=".BootCompletedIntentReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON"/>
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
</application>
</manifest>
package com.test.uploadtos3
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.util.Log
class BootCompletedIntentReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == "android.intent.action.BOOT_COMPLETED" || intent.action == "android.intent.action.QUICKBOOT_POWERON") {
val alarmUtility = AlarmUtility()
if (alarmUtility.getPendingIntent(context) != null){
alarmUtility.stopAlarm(context)
}
alarmUtility.setAlarm(context)
}
}
}
package com.test.uploadtos3
import android.annotation.TargetApi
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.graphics.Color
import android.media.RingtoneManager
import android.os.Build
import android.widget.Toast
import androidx.core.app.NotificationCompat
class NotificationUtils(base: Context) : ContextWrapper(base) {
val MYCHANNEL_ID = "App Alert Notification ID"
val MYCHANNEL_NAME = "App Alert Notification"
private var manager: NotificationManager? = null
init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannels()
}
Toast.makeText(base, "Alarm triggered", Toast.LENGTH_SHORT).show()
}
// Create channel for Android version 26+
@TargetApi(Build.VERSION_CODES.O)
private fun createChannels() {
val channel =
NotificationChannel(MYCHANNEL_ID, MYCHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH)
channel.enableVibration(true)
getManager().createNotificationChannel(channel)
}
// Get Manager
fun getManager(): NotificationManager {
if (manager == null) manager =
getSystemService(NOTIFICATION_SERVICE) as NotificationManager
return manager as NotificationManager
}
fun getNotificationBuilder(): NotificationCompat.Builder {
val intent = Intent(this, AlarmActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
}
var pendingIntent: PendingIntent? = null
pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)
} else {
PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT)
}
return NotificationCompat.Builder(applicationContext, MYCHANNEL_ID)
.setContentTitle("Alarm!")
.setContentText("Your AlarmManager is working.")
.setSmallIcon(R.drawable.ic_launcher_background)
.setColor(Color.YELLOW)
.setContentIntent(pendingIntent)
.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION))
.setAutoCancel(true)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment