How to send data from Service to Activity ? Android Kotlin - android

I want to pass data from service to activity from another app. I already did activity to service exactly same as Bound Services using Messenger in developer.android.com. However they didn't do service to activity in Kotlin, and I didn't see similar solution in Kotlin. There are java solutions but they didn't work for me. Probably Messenger or Broadcast should work but I want to know how.
I think activity should have IncomingHandler and service should have onServiceConnected so can send message like mService?.send(msg) , but I didn't find how to bind them.
Update
Service
val intent = Intent("TO_SALE_APP")
intent.putExtra("RESPONSE_CODE", responseCode)
intent.putExtra("STATUS", status)
intent.putExtra("PAYMENT_TYPE", paymentType)
LocalBroadcastManager.getInstance(this.applicationContext).sendBroadcast(intent)
Update
Activity
private val mMessageReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val responseCode = intent.getStringExtra("RESPONSE_CODE")
val status = intent.getIntExtra("STATUS",0)
val paymentType = intent.getIntExtra("PAYMENT_TYPE",0)
Log.d("myTAG","data receive on activity!")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
...
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, IntentFilter("TO_SALE_APP")
)
}

Yes you can send data from Services to Activity
I had done it by sending Location Coordinated from Background Service class to Activity Periodically
In the service, class add this code
val intent = Intent("GPSLocationUpdates")
intent.putExtra("latitude", location.latitude.toString())
intent.putExtra("longitude", location.longitude.toString())
LocalBroadcastManager.getInstance(this#LocationService).sendBroadcast(intent)
In your Activity receives this data by , write this before onCreate
private val mMessageReceiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
// Get extra data included in the Intent
val latitude = intent.getStringExtra("latitude")
val longitude = intent.getStringExtra("longitude")
}
}
and in the onCreate method mention this
LocalBroadcastManager.getInstance(this).registerReceiver(
mMessageReceiver, IntentFilter("GPSLocationUpdates")
);
NOTE: the EventListener GPSLocationUpdates should be the same in Service and Activity

Related

How to receive ACTION.SHUDOWN intent in my activity

I want to receive an Android Shutdown Event in my app to revert a config change when I start the app. For that, I have register a context registered receiver in my main Activity onCreate as shown below
override fun onCreate(..)
{
...
val bootIntentFilter = IntentFilter(Intent.ACTION_SHUTDOWN);
registerReceiver(shutDownReceiver, bootIntentFilter)
}
private val shutDownReceiver = object : BroadcastReceiver()
{
override fun onReceive(context: Context?, intent: Intent?) {
if(Intent.ACTION_SHUTDOWN == intent?.action)
{
Log.e(TAG, "Shutdown Called")
//Run your logic
}
}
}
and I also added the following permission in manifest.xml
I still don't receive the broadcast is there anything I am missing? target API is 29
Any information to help is really appreciated.
Thanks,
Asma

How to send data by Intent from BroadcastReceiver to Fragment in Kotlin

I will send step count:
Foreground Service -> Broadcast Receiver -> Fragment
Since I need to keep tracking step count on background and when app is off, I've created two Broadcast Receiver, one for notification to keep showing step count on background and one for fragment UI which will be unregistered on Destroy.
So this process is for the latter.
Foreground Service
: I send "stepCount" value to broadcast.
Intent().also { intent ->
intent.setAction(ACTION_STEP_COUNTER_NOTIFICATION)
intent.putExtra("stepCount", "$todayTotalStepCount")
sendBroadcast(intent)
}
BroadcastReceiver
open class StepCountBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
if(intent!!.action == ACTION_STEP_COUNTER_NOTIFICATION) {
var intent = Intent()
var stepCount = intent.getStringExtra("stepCount")
var sendMyDiary = Intent(context!!, MyDiaryFragment::class.java)
sendMyDiary.putExtra("stepCount", stepCount)
context.startActivity(sendMyDiary)
}
}
}
when custom Action is triggered, this will get 'stepCount' from Service and here I will send it to Fragment named MyDiaryFragment.
So I send it by using Intent().putExtra.
Fragment
private val stepCountBroadcastReceiver: BroadcastReceiver = StepCountBroadcastReceiver()
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
addAction(ACTION_STEP_COUNTER_NOTIFICATION)
}
LocalBroadcastManager.getInstance(requireActivity()).registerReceiver(stepCountBroadcastReceiver, filter)
Here is my question.
I register this StepCountBroadcastReceiver in onCreate.
But I don't know how to get stepCount coming from broadcast in Fragment whenever Broadcastreceiver is called.
It that same process like just adding this below line at the bottom?
var stepCount = requireActivity().intent.getStringExtra("stepCount")
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
addAction(ACTION_STEP_COUNTER_NOTIFICATION)
}
LocalBroadcastManager.getInstance(requireActivity()).registerReceiver(stepCountBroadcastReceiver, filter)
var stepCount = requireActivity().intent.getStringExtra("stepCount")
In your broadcast receiver, add this.To Send a LocalBroadCast
override fun onReceive(context: Context?, intent: Intent?) {
super.onReceive(context, intent)
if(intent?.action == ACTION_STEP_COUNTER_NOTIFICATION) {
var stepCount = intent.getStringExtra("stepCount")
var localBroadCastIntent = Intent(LOCAL_BROADCAST_KEY)
localBroadCastIntent.putExtra("stepCount",stepCount?:"")
Handler(Looper.getMainLooper()).post {
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
}
}
const val LOCAL_BROADCAST_KEY = "step_counter_local_broadcast"
In your Fragment Call this register function.And in onCreateView and make sure to call unregisterReceiver in ondestroyview of Fragment.
private fun registerBroadCastReceiver() {
LocalBroadcastManager.getInstance(applicationContext).registerReceiver(
receiver,
IntentFilter(LOCAL_BROADCAST_KEY)
)
}
}
Add this BroadCast Receiver,in Fragment Class globally.
private var receiver: BroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
intent?.let {
val stepCount = it.getStringExtra("stepCount")
}
}
}
Note:
Here Flow will be like this.
Service -> BroadCast Receiver -> LocalBroadCastReceiver ->
UpdateFragment UI.
You can also directly call this localbroadcast from service based on your usecase. So it will be like below.
Service-> LocalBroadCastReceiver -> UpdateFragment UI.
So only when fragment is alive, the local broadcast receiver will receive messages and update ui.

How to pass data from BroadcastReceiver to one other class?

I am developing an app for scanning devices with bluetooth.
From the Android studio's documentation I found how scan devices and perform an action when a device is discovered:
override fun onCreate(savedInstanceState: Bundle?) {
...
// Register for broadcasts when a device is discovered.
val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
registerReceiver(receiver, filter)
}
// Create a BroadcastReceiver for ACTION_FOUND.
private val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action: String = intent.action
when(action) {
BluetoothDevice.ACTION_FOUND -> {
// Discovery has found a device. Get the BluetoothDevice
// object and its info from the Intent.
val device: BluetoothDevice =
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
val deviceName = device.name
val deviceHardwareAddress = device.address // MAC address
}
}
}
}
The question is: if I would to create a class for scanning devices, how I can, for each device discovered, pass it to my main class (MainActivity) ?.
I was thinking to use Observer and Observe a specific variable in scanning class, but i dont know if this is a good pratice.
You can use ViewModel class and save all your data here. You can get your ViewModel in any class.
https://developer.android.com/topic/libraries/architecture/viewmodel

BroadcastReceiver not getting updated from ACTION_BATTERY_CHANGED

I've created custom broadcast receiver to listen for battery changes (I would like to monitor the percentage level of the battery)
However I'm not getting any updates. Here is my setup:
class MyService : IntentService("MyService") {
val receiver: PowerConnectionReceiver = PowerConnectionReceiver()
override fun onHandleIntent(intent: Intent?) {
Timber.d("Service started now")
}
override fun onCreate() {
val batteryStatus: Intent? =
IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
registerReceiver(receiver, ifilter)
}
}
class PowerConnectionReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val status: Int = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
Timber.d("Battery changed")
}
}
}
You will receive updates for the < 1 millisecond time that your IntentService is running. Your IntentService shuts down as soon as onHandleIntent() returns. IntentService is designed for short-term transactional sorts of work, not long-term operation.
Switch to a regular Service. Make sure that it is a foreground service (using startForeground()), as otherwise it will only run for 1 minute on Android 8.0+.

Broadcast Receiver in kotlin

How to use register and create a Broadcast Receiver in Android in Kotlin. Any advice...
In Java, you can create it by declaring it as a Broadcast Receiver. But in Kotlin I am not able to find Broadcast Receiver ...well if it is there then how to use it.
you can do it in the following way
Create a broadcast receiver object in your activity class
val broadCastReceiver = object : BroadcastReceiver() {
override fun onReceive(contxt: Context?, intent: Intent?) {
when (intent?.action) {
BROADCAST_DEFAULT_ALBUM_CHANGED -> handleAlbumChanged()
BROADCAST_CHANGE_TYPE_CHANGED -> handleChangeTypeChanged()
}
}
}
Register broadcast receiver in onCreate() function of your activity
LocalBroadcastManager.getInstance(this)
.registerReceiver(broadCastReceiver, IntentFilter(BROADCAST_DEFAULT_ALBUM_CHANGED))
unregister it in ondestroy function of your activity
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(broadCastReceiver)
Anonymous class syntax in Kotlin is like this:
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
}
}
I've created a BroadcastReceiver Kotlin extension, which you can copy/paste anywhere.
It doesn't do much more than what is already mentioned, but it reduces some of the boilerplate. 😀
Using this extension, you should register/unregister like so:
private lateinit var myReceiver: BroadcastReceiver
override fun onStart() {
super.onStart()
myReceiver = registerReceiver(IntentFilter(BROADCAST_SOMETHING_HAPPENED)) { intent ->
when (intent?.action) {
BROADCAST_SOMETHING_HAPPENED -> handleSomethingHappened()
}
}
}
override fun onStop() {
super.onStop()
unregisterReceiver(myReceiver)
}

Categories

Resources