Broadcast Receiver in Application class android - android

I am registering BroadcastReceiver in application class and its register method is getting called and completed successfully without issue during application start. I am sending a broadcast from the module. I can print the action, it is there. But the app is not catching the broadcast. I don't know where I am doing wrong.
Below is the method to register receiver.
fun registerRecordingDataReceiver () {
info("AppReceiver register called=>${CommonsDataVars.TEMPERATURE.action()}")
val temperatureCompleted = CommonsDataVars.TEMPERATURE.action()
val temperatureCompletedIntentFilter = IntentFilter(temperatureCompleted)
val broadcastManager = LocalBroadcastManager.getInstance(this)
broadcastManager.registerReceiver(appReceiver,temperatureCompletedIntentFilter)
info("AppREceiver register completed")
}
Part of Broadcast Receiver
override fun onReceive(context: Context?, intent: Intent?) {
val action = intent?.getAction()
debug("Action in App Receiver =>"+action)
if (action == CommonsDataVars.TEMPERATURE.action()) {
info("AppReceiver****************************************")
sendBroadcast part:
info("TEMPERATURE register called=>${CommonsDataVars.TEMPERATURE.action()}")
val intent = Intent()
intent.setAction(CommonsDataVars.TEMPERATURE.action())
//intent.putExtra(CommonsDataVars.TEMPERATURE.name, temperatureData)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)

Related

check if bluetooth is connected to any device with broadcast receiver

I need to check if the device is connected to any device via Bluetooth.
This is my activity where I launch activity for Bluetooth settings. ``
receiver = BluetoothModeReceiver()
IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED).also {
registerReceiver(receiver, it)
val settingsIntent = Intent(Settings.ACTION_BLUETOOTH_SETTINGS)
startActivity(settingsIntent)
}
And this is the broadcast receiver:
class BluetoothModeReceiver :BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isDeviceConnected = intent?.getBooleanExtra("state",false) ?: return
if(isDeviceConnected){
Log.i("Broadcast", "Happened ")
}
}
}
I also tried to use intents like BluetoothDevice.ACTION_ACL_CONNECTED and ACTION_ACL_DISCONNECTED but none of them work. When I connect the phone to any device that log in receiver doesn't get printed in the logcat. Any ideas why it doesn't work? They would be appreciated.

Android Dynamic BroadcastReceiver not receiving broadcast

I am trying to set an alarm for a 15 minute reminder (Testing with 5 seconds first). When I register the receiver in my Manifest, it works perfect. When I try to set it as a dynamic broadcast receiver, I can't get it to work. The onReceive() method doesn't get called at all. I can see this by putting in Log.d() entries
The reason I need to convert it to a dynamic broadcast receiver is because I can't figure out how to access my MainActivity from inside the onReceive() method, as I need to perform some UI tasks like show a notification etc.
I am setting up the AlarmManager like this:
fun snoozeTask(context: Context, taskId: String, snoozeTime: Long) {
alarmIntent = Intent(context, AlarmReceiver::class.java).let { intent ->
intent.putExtra("taskId", taskId)
intent.action = AlarmReceiver.SNOOZE_TASK
PendingIntent.getActivity(context, ALARM_REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
(context.getSystemService(Context.ALARM_SERVICE) as? AlarmManager)?.let { alarmManager ->
val hasPermissions = alarmManager.canScheduleExactAlarms()
AlarmManagerCompat.setExactAndAllowWhileIdle(alarmManager, AlarmManager.ELAPSED_REALTIME_WAKEUP, snoozeTime, alarmIntent)
}
}
and then my onReceive method:
class AlarmReceiver : BroadcastReceiver() {
companion object {
const val SNOOZE_TASK = "com.my.app.SNOOZE_TASK"
}
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
AlarmManager.ACTION_SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED -> {
// reschedule all the exact alarms
//TODO: When the user revokes permission for
// <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
}
SNOOZE_TASK -> {
val taskId = intent.extras?.getString("taskId")
val snoozeTime = intent.extras?.getLong("snoozeTime")
}
else -> Log.d("TAG", "AlarmReceiver::onReceive::ELSE")
}
}
}
Then in my MainActivity I have this:
private var alarmReceiver: AlarmReceiver = AlarmReceiver()
and then in MainActivity onCreate:
registerReceiver(alarmReceiver, IntentFilter(AlarmReceiver.SNOOZE_TASK))
With the same code, this works when I register it in the Manifest. When I try to register in MainActivity, it doesn't work.
Eventually I want to pass some MutableLiveData to the constructor of my AlarmReceiver class so when I receive the taskId, it gets passed back to MainActivity this way.
What am I doing wrong?
Thanks

Android Kotlin Broad Receiever in RecyclerAdapter Won't Communicate to Broadcast Receiever in MainActivity

Context: No receiver is declared in the manifest since I am not declaring a new receiver.
I am a bit confused about why the receiver in MainActivity does not receieve the broadcast sent from the recycler adapter.
RecyclerAdapter
holder.checkBox.setOnClickListener {view ->
item.completed = holder.checkBox.isChecked
Log.i("wow", "is checked: ${holder.checkBox.isChecked}")
val intent = Intent().apply {
addCategory(Intent.CATEGORY_DEFAULT)
setAction(changeCompletedForDeck)
putExtra(changeCompletedForDeckItemID, item)
}
LocalBroadcastManager.getInstance(view.context).sendBroadcast(intent)
MainActivity
private lateinit var broadcastReceiver: BroadcastReceiver
broadcastReceiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
//get deck, if deck != null then update the checkmark response
if (intent?.action == DeckRecyclerAdapter.changeCompletedForDeck) {
val deck = intent?.extras?.getParcelable<Deck>(DeckRecyclerAdapter.changeCompletedForDeckItemID)
Log.i("wow", "${deck?.title}")
deck?.let { deck ->
globalViewModel.update(deck)
}
}
}
}
val filter = IntentFilter(DeckRecyclerAdapter.changeCompletedForDeck)
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, filter)
//Destroy the BroadcastReceiver
override fun onDestroy() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver)
super.onDestroy()
}
Your problem is Intent action . See at the time of register you have not provided any action so receiver will not be identified by the system.
You can define a specific action with IntentFilter and use the same action during register and sendBroadcast.
To identify different conditions you can do two things.
you can set data in Bundle and validate the bundle value inside onReceive()
you can also add multiple actions to IntentFilter and validate the action inside onReceive() See this.
So with the first way have a constant action in MainActivity:-
companion object{
const val BROADCAST_ACTION="LIST_CHECK_ACTION"
}
LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, IntentFilter(BROADCAST_ACTION)).
Then for sending broadcast use the code below addCategory(Intent.CATEGORY_DEFAULT) is not required:-
val intent = Intent().apply {
action = MainAcvity.BROADCAST_ACTION
putExtra("item", item)
}
LocalBroadcastManager.getInstance(view.context).sendBroadcast(intent)
PS- However i don't think you should be using a Broadcastreceiver just to provide a callback from Adapter its purpose is more than that. You should be using a callback listener for it . Since RecyclerView.Adapter will binds to a UI component a callback interface will be fine . I think a broadcastReceiver is overkill in this usecase .

Context-Registered Receiver not being triggered by Custom Action

I have a problem: the Broadcast Receiver in one of my apps isn't having its onReceive callback triggered by a custom action broadcast sent by my service from a separate app.
The broadcast receiver is context-registered, meaning I don't want to declare it in a manifest file anywhere because I don't want broadcasts launching my app. The broadcast is being sent from a service completely separate from the app, so we're dealing with inter-process communication here and a local broadcast won't do.
My suspicion is that i'm not correctly matching the intent action string declared in my broadcast sender (the Service) with my broadcast receiver (the App).
Looking at my code below, what am I doing incorrectly?
ScannerService.kt
Intent().also { intent ->
intent.action = "com.foo.bar.example.package.ScannerService.SCANNER_EVENT"
intent.putExtra("barcode", barcode)
intent.setPackage("com.nu.rms")
sendBroadcast(intent)
Timber.d("Sent broadcast")
}
AppActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
registerBroadcastReceivers()
}
private fun registerBroadcastReceivers() {
val broadcastReceiver = ScannerBroadcastReceiver()
val filter = IntentFilter().apply { addAction("SCANNER_EVENT") }
registerReceiver(broadcastReceiver, filter)
Timber.d("Registered broadcast receiver")
}
class ScannerBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Timber.d("Received broadcast")
StringBuilder().apply {
append("Action: ${intent.action}\n")
append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
toString().also { log -> Timber.d(log) }
}
}
}
Try to use a manifest-declared receiver (eg. in case permissions may have to be added there):
<receiver
android:name=".ScannerBroadcastReceiver"
android:permission="android.permission.INTERNET">
<intent-filter>
<action android:name="com.foo.bar.example.package.ScannerService.SCANNER_EVENT"/>
</intent-filter>
</receiver>
When using a context-registered receiver, the action might be ScannerService.SCANNER_EVENT or verbosely com.foo.bar.example.package.ScannerService.SCANNER_EVENT.

Kotlin: Call a function to update UI from BroadcastReceiver onReceive

I am new to Kotlin, and it seems awesome! Though today, I've been trying to do something that in Java was super simple, but I've got totally stuck.
I am using a broadcast receiver to determine when the device is connected/ disconnected from a power source. And all I need to do it update my UI accordingly.
My Code
Here's my BroadcastReceiver classs, and it seems to work fine.
class PlugInReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
if (action == Intent.ACTION_POWER_CONNECTED) {
// Do stuff when power connected
}
else if (action == Intent.ACTION_POWER_DISCONNECTED) {
// Do more stuff when power disconnected
}
}
}
Now in my MainActivity (but somewhere else, later on), I want to update my UI when the intent is fired, for example in the function below, the background color changes.
private fun updateBackgroundColor( newBgColorId: Int = R.color.colorAccent){
val mainLayout = findViewById<View>(R.id.mainLayout)
val colorFade = ObjectAnimator.ofObject(
mainLayout, "backgroundColor", ArgbEvaluator(), oldBgColor, newBgColor)
colorFade.start()
}
The Question
How can I call a function on the MainActivity, or update my UI when the BroadcastReceiver fires an event?
What I've tried so far
I looked into having a static variable somewhere, storing the result of the BroadcastReciever, then an observable in my UI class, watching and calling appropriate function accordingly. Though after Googling how to do this, looks like that's not really a good approach in Kotlin.
Considered trying to run the BroadcastReciever on the UI thread, but that sounds like a terrible idea.
Tried mixing a Java implementation with my Kotlin class, but couldn't get it to work.
Frustratingly I found several very similar questions on SO. However their implementations seem to all use Java-specific features:
Android BroadcastReceiver onReceive Update TextView in MainActivity
How to update UI in a BroadcastReceiver
Calling a Activity method from BroadcastReceiver in Android
How to update UI from BroadcastReceiver after screenshot
I'm sure this is a trivial question for most Android developers, but I am lost! Let me know if you need any more details. Thanks very much in advance!
Sharing the info to register BroadcastReceiver in Kotlin
Step 1. Create BroadcastReceiver in MainActivity.kt
private val mPlugInReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
Intent.ACTION_POWER_CONNECTED -> {
//update your main background color
updateBackgroundColor()
}
Intent.ACTION_POWER_DISCONNECTED -> {
//update your main background color
updateBackgroundColor()
}
}
}
}
Step 2. Create IntentFilter
private fun getIntentFilter(): IntentFilter {
val iFilter = IntentFilter()
iFilter.addAction(Intent.ACTION_POWER_CONNECTED)
iFilter.addAction(Intent.ACTION_POWER_DISCONNECTED)
return iFilter
}
Step 3. Register receiver at onStart()
override fun onStart() {
super.onStart()
registerReceiver(mPlugInReceiver, getIntentFilter())
}
Step 4. Unregister receiver at onStop()
override fun onStop() {
super.onStop()
unregisterReceiver(mPlugInReceiver)
}
If you have custom BroadcastReceiver, you can register using LocalBroadcastManager and create your local IntentFilter
private val mLocalBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
AnyService.UPDATE_ANY -> {
}
}
}
}
private fun getLocalIntentFilter(): IntentFilter {
val iFilter = IntentFilter()
iFilter.addAction(AnyService.UPDATE_ANY)
return iFilter
}
Register local receiver
LocalBroadcastManager.getInstance(applicationContext).registerReceiver(mLocalBroadcastReceiver, getLocalIntentFilter())
Unregister local receiver LocalBroadcastManager.getInstance(applicationContext).unregisterReceiver(mLocalBroadcastReceiver)
The best way to achieve that is to create an abstract method in the BroadcastReceiver, and when onReceive() method is called, you can invoke that method that will be implemented by your activity.
BroadcastReceiver example:
abstract class ConnectionBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
//Do the checks or whatever you want
var isConnected = true
broadcastResult(isConnected)
}
protected abstract fun broadcastResult(connected: Boolean)
}
And the code in your activity (in the onCreate or onStart for example). Here you register the broadcast receiver with the method implementation, and here you can update the UI:
var connectionBroadcastReceiver = object : ConnectionBroadcastReceiver() {
override fun broadcastResult(connected: Boolean) {
if(isConnected){
refreshList()
}
}
}
val intentFilter = IntentFilter()
intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
this.registerReceiver(connectionBroadcastReceiver, intentFilter)
Don't forget to unregister the receiver in (onPause||onStop||onDestroy), but it's not strictly necessary.
The onReceive(...) method runs on the main thread. You can register your Activity in onStart() and unregister it in onStop(), which will guarantee that your UI is present when the event is received.

Categories

Resources