milosev.com
  • Home
    • List all categories
    • Sitemap
  • Downloads
    • WebSphere
    • Hitachi902
    • Hospital
    • Kryptonite
    • OCR
    • APK
  • About me
    • Gallery
      • Italy2022
      • Côte d'Azur 2024
    • Curriculum vitae
      • Resume
      • Lebenslauf
    • Social networks
      • Facebook
      • Twitter
      • LinkedIn
      • Xing
      • GitHub
      • Google Maps
      • Sports tracker
    • Adventures planning
  1. You are here:  
  2. Home

Send broadcast from separate service and update UI

Details
Written by: Stanko Milosev
Category: Android
Published: 14 May 2022
Last Updated: 01 November 2025
Hits: 1369
  • kotlin
UPDATE: 2025-10-26 LocalBroadcastManager is deprecated

Please refer to this article for BroadcastReceiver in a separate class

This time I needed to add android:process to my manifest, in order to have a separate never-ending process, and to update UI.

I have started an empty project, then I have added Service: File -> New -> Service - Service, then I have added Broadcast: File -> New -> Other -> Broadcast receiver.

In AndroidManifest.xml I have added FOREGROUND_SERVICE permission and android:process. Now my manifest looks like:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.milosev.sendbroadcastfromanotherprocess">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.SendBroadcastFromAnotherProcess">
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true" />

        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"
            android:process=":MyService" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
In gradle I have added coroutines:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
My gradle looks like:
plugins {
    id 'com.android.application'
    id 'org.jetbrains.kotlin.android'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.milosev.sendbroadcastfromanotherprocess"
        minSdk 21
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {

    implementation 'androidx.core:core-ktx:1.7.0'
    implementation 'androidx.appcompat:appcompat:1.4.1'
    implementation 'com.google.android.material:material:1.5.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'

    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1"
}
MyService.kt:

*2023-04-04 UPDATE: * To debug MyService you will have to attach to this process with debugger.

package com.milosev.sendbroadcastfromanotherprocess

import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.IBinder
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import kotlinx.coroutines.*

class MyService : Service(), CoroutineScope by MainScope() {

    private var job: Job? = null

    override fun onBind(intent: Intent): IBinder {
        TODO("Return the communication channel to the service.")
    }

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        when (intent?.action) {
            "startForeground" -> {

                val channelId = createNotificationChannel("my_service", "My Background Service")
                val notificationBuilder = NotificationCompat.Builder(this, channelId)
                val notification = notificationBuilder.setOngoing(true)
                    .setContentTitle("test")
                    .setContentText("test")
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setPriority(1)
                    .setCategory(Notification.CATEGORY_SERVICE)
                    .build()

                startForeground(101, notification)
                val context = this

                job = launch {
                    while(true) {
                        val myIntent = Intent(context, MyReceiver::class.java).setAction("MyAction")
                        myIntent.putExtra("message", "test")
                        sendBroadcast(myIntent);
                        delay(1_000)
                    }
                }
            }
        }
        if (intent?.action.equals("stopForeground")) {
            job?.cancel()
            stopForeground(true)
            stopSelfResult(startId)
        }
        return START_STICKY;
    }

    @RequiresApi(Build.VERSION_CODES.O)
    private fun createNotificationChannel(channelId: String, channelName: String): String {
        val chan = NotificationChannel(
            channelId,
            channelName, NotificationManager.IMPORTANCE_NONE
        )
        chan.lightColor = Color.RED
        chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
        val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        service.createNotificationChannel(chan)
        return channelId
    }
}
MyReceiver.kt:
package com.milosev.sendbroadcastfromanotherprocess

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import androidx.localbroadcastmanager.content.LocalBroadcastManager

class MyReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        val myIntent = Intent(context, MainActivity::class.java).setAction("MyAction")
        myIntent.putExtra("message", "test")
        LocalBroadcastManager.getInstance(context).sendBroadcast(myIntent)
    }
}
MainActivity.kt:
package com.milosev.sendbroadcastfromanotherprocess

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.TextView
import androidx.annotation.RequiresApi
import androidx.localbroadcastmanager.content.LocalBroadcastManager

class MainActivity : AppCompatActivity() {

    val myReceiver: BroadcastReceiver = MyReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val filter = IntentFilter("MyAction")
        registerReceiver(myReceiver, filter)

        var textView = findViewById(R.id.myText) as TextView
        val broadCastReceiver = object : BroadcastReceiver() {
            override fun onReceive(contxt: Context?, intent: Intent?) {
                when (intent?.action) {
                    "MyAction" -> {
                        textView = findViewById(R.id.myText) as TextView
                        textView.text = intent.getStringExtra("message")
                    }
                }
            }
        }

        LocalBroadcastManager.getInstance(this)
            .registerReceiver(broadCastReceiver, IntentFilter("MyAction"))

    }

    @RequiresApi(Build.VERSION_CODES.O)
    fun onClick(view: View) {
        val intent = Intent(this, MyService::class.java)
        intent.action = "startForeground"
        startForegroundService(intent)
    }
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/myText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClick"
        android:text="Button"
        tools:layout_editor_absoluteX="106dp"
        tools:layout_editor_absoluteY="110dp" />

</androidx.constraintlayout.widget.ConstraintLayout>
Example download from here.

android:process=":MyService"

Details
Written by: Stanko Milosev
Category: Android
Published: 12 May 2022
Last Updated: 12 May 2022
Hits: 1331
  • kotlin
In order to create never ending foreground service in manifest I have added android:process=":MyService" so it looks like:
<?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.example.broadcasts">

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

    <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.Broadcasts"
        tools:targetApi="31">
        <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true"
            android:process=":MyService"/>

        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.AIRPLANE_MODE" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Few more examples of broadcast receiver declared in manifest

Details
Written by: Stanko Milosev
Category: Android
Published: 12 May 2022
Last Updated: 12 May 2022
Hits: 1255
  • kotlin
In File -> New -> Other -> BroadCastReceiver I have added BroadCastReceiver receiver class, and in manifest I have added for example:
<action android:name="android.intent.action.AIRPLANE_MODE"/>
Now my AndroidManifest.xml looks like:
<?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.example.broadcasts">

    <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.Broadcasts"
        tools:targetApi="31">
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true" />

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="android.intent.action.AIRPLANE_MODE"/>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Where MyReceiver.kt looks like:
package com.example.broadcasts

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class MyReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent) {
        // This method is called when the BroadcastReceiver is receiving an Intent broadcast.
        TODO("MyReceiver.onReceive() is not implemented")
    }
}
MainActivity.kt looks like:

package com.example.broadcasts

import android.content.BroadcastReceiver
import android.content.Intent
import android.content.IntentFilter
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    val br: BroadcastReceiver = MyReceiver()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val filter = IntentFilter("android.intent.action.AIRPLANE_MODE").apply {
            addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
        }
        registerReceiver(br, filter)
    }

    fun onClick(view: View) {
        sendBroadcast(Intent(this, MyReceiver::class.java).setAction("MyAction"))
    }
}
With code:
    fun onClick(view: View) {
        sendBroadcast(Intent(this, MyReceiver::class.java).setAction("MyAction"))
    }
I am sending my own "MyAction"

SharedPreferences

Details
Written by: Stanko Milosev
Category: Android
Published: 09 May 2022
Last Updated: 11 May 2022
Hits: 1231
  • kotlin
Here is my example of SharedPreferences:
package com.milosev.myapplication

import android.content.SharedPreferences
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    private lateinit var sharedPreferences: SharedPreferences

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        sharedPreferences = getSharedPreferences("userdetails", MODE_PRIVATE)
    }

    override fun onStart() {
        super.onStart()
        val username = sharedPreferences.getString("username", "")
        System.out.println(username)
    }

    override fun onStop() {
        super.onStop()
        val edit: SharedPreferences.Editor = sharedPreferences.edit()
        edit.putString("username", "test")
        edit.commit()
    }
}
  1. stopForeground
  2. startForegroundService and BroadcastReceiver
  3. Request location updates
  4. Write file on internal storage

Subcategories

C#

Azure

ASP.NET

JavaScript

Software Development Philosophy

MS SQL

IBM WebSphere MQ

MySQL

Joomla

Delphi

PHP

Windows

Life

Lazarus

Downloads

Android

CSS

Chrome

HTML

Linux

Eclipse

Page 144 of 165

  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148