How to Make a Floating Window Application in Android? (original) (raw)
Last Updated : 23 Jul, 2025
Well, on our desktop computers we can easily restore down windows, do something in the background, and maximize the window whenever we want. But we don't see this feature in android apps that much. Nowadays we can see android is offering Split Screen, but that's a feature provided by OS, not the app's individual feature. Let's make an app that can minimize and maximize itself on just a button click. This feature can help users, in a lot of ways. Suppose you are reading some pdf document with some mathematical calculations and then a minimized calculator over the pdf viewer app will be very helpful. There are a lot of apps that use this feature like Clipboard, MI Calculator, and many more. Here's a demo of the final app of this article. Note that we are going to implement this project using the **Java & Kotlin language.
Step by Step Implementation
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.
Step 2: Add permission in manifest file
Navigate to **app > manifests > AndroidManifest.xml and add the following permission
Step 3: Create an object class
Navigate to **app > java > {package-name}, right click on the folder and select, **New > Java/Kotlin Class/File and name it as **Common. Create two public String variables, one is **currentDesc and another is **savedDesc. Both are initiated with empty Strings.
Common.java `
package org.geeksforgeeks.demo;
public class Common { // The EditText String will be // stored in this variable // when MINIMIZE or MAXIMIZE // button is pressed public static String currentDesc = "";
// The EditText String will be
// stored in this variable
// when SAVE button is pressed
public static String savedDesc = "";}
Common.kt
package org.geeksforgeeks.demo
object Common { // The EditText String will be // stored in this variable // when MINIMIZE or MAXIMIZE // button is pressed var currentDesc: String = ""
// The EditText String will be
// stored in this variable
// when SAVE button is pressed
var savedDesc: String = ""}
`
Step 4: Working with layouts
Create a new layout and name it as **floating_layout.xml and navigate to **activity_main.xml and add the following code in the two files.
activity_main.xml `
<Button
android:id="@+id/buttonMinimize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Minimize"
android:textSize="24sp" />
<TextView
android:id="@+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="GeeksforGeeks"
android:textSize="32sp"
android:textStyle="bold" />
<EditText
android:id="@+id/descEditText"
android:layout_width="match_parent"
android:layout_height="350dp"
android:gravity="start"
android:hint="Description"
android:padding="16dp"
android:textColor="@color/black"
android:textSize="24sp" />
<Button
android:id="@+id/saveBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save"
android:textColor="@android:color/white"
android:textSize="24sp" />
floating\_layout.xml
<Button
android:id="@+id/buttonMaximize"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="Maximize" />
<TextView
android:id="@+id/titleText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="GeeksforGeeks"
android:textSize="24sp"
android:textStyle="bold" />
<EditText
android:id="@+id/descEditText"
android:layout_width="match_parent"
android:layout_height="250dp"
android:gravity="start"
android:hint="Description"
android:textColor="@color/black" />
<Button
android:id="@+id/saveBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="Save" />
`
**Design UI:

Step 5: Create a new Service
Create a new **Java or **Kotlin class file with the name **FloatingWindowService and add the following code. Now as this class is inherited from the Service class, then this class can be used as a service in the Manifest file. So in the **AndroidManifest.xml add this line after the activity block and before the application block ends.
FloatingWindowService.java `
package org.geeksforgeeks.demo;
import android.annotation.SuppressLint; import android.app.Service; import android.content.Intent; import android.graphics.PixelFormat; import android.os.IBinder; import android.text.Editable; import android.text.TextWatcher; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.Toast;
public class FloatingWindowService extends Service {
// Declare variables for views and WindowManager
private ViewGroup floatView;
private WindowManager.LayoutParams floatWindowLayoutParam;
private WindowManager windowManager;
private Button maximizeBtn;
private EditText descEditArea;
private Button saveBtn;
// This method is required but not used in this Service
@Override
public IBinder onBind(Intent intent) {
return null;
}
// Service is created
@SuppressLint("ClickableViewAccessibility")
@Override
public void onCreate() {
super.onCreate();
// Get screen width and height in pixels
float width = getResources().getDisplayMetrics().widthPixels;
float height = getResources().getDisplayMetrics().heightPixels;
// Get the WindowManager system service for handling windows on the screen
windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
// Inflate the floating window layout using the LayoutInflater system service
LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
floatView = (ViewGroup) inflater.inflate(R.layout.floating_layout, null);
// Initialize the views from the layout file
maximizeBtn = floatView.findViewById(R.id.buttonMaximize);
descEditArea = floatView.findViewById(R.id.descEditText);
saveBtn = floatView.findViewById(R.id.saveBtn);
// Set the initial text in the EditText and place the cursor at the end
descEditArea.setText(Common.currentDesc);
descEditArea.setSelection(descEditArea.getText().length());
// Hide the cursor initially
descEditArea.setCursorVisible(false);
// Set up the parameters for the floating window (size, position, etc.)
floatWindowLayoutParam = new WindowManager.LayoutParams(
// Set width to 60% of screen width
(int) (width * 0.6f),
// Set height to 50% of screen height
(int) (height * 0.5f),
// Type for overlay window
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
// Make it not focusable
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
// Set transparent background for the window
PixelFormat.TRANSLUCENT
);
floatWindowLayoutParam.gravity = Gravity.CENTER;
floatWindowLayoutParam.x = 0;
floatWindowLayoutParam.y = 0;
// Add the floating view to the window using the WindowManager
windowManager.addView(floatView, floatWindowLayoutParam);
// Set up a listener for the maximize button to stop the service and navigate to MainActivity
maximizeBtn.setOnClickListener(view -> {
stopSelf(); // Stop the service
windowManager.removeView(floatView); // Remove the floating window
Intent backToHome = new Intent(this, MainActivity.class);
backToHome.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(backToHome);
});
// Set up a TextWatcher to update the current description when the text changes
descEditArea.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// Update the current description with the text in the EditText
Common.currentDesc = descEditArea.getText().toString();
}
@Override
public void afterTextChanged(Editable editable) {}
});
// Set up the touch listener for the floating window to allow dragging it around
setupFloatingWindowMovement();
// Set up a listener for the EditText to make the cursor visible when clicked
descEditArea.setOnTouchListener((v, event) -> {
descEditArea.setCursorVisible(true); // Make the cursor visible when touched
floatWindowLayoutParam.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
windowManager.updateViewLayout(floatView, floatWindowLayoutParam); // Update the layout
return false;
});
// Set up a listener for the save button to save the text and hide the soft keyboard
saveBtn.setOnClickListener(view -> {
// Save the text in the EditText to the Common object
Common.savedDesc = descEditArea.getText().toString();
// Hide the cursor after saving
descEditArea.setCursorVisible(false);
// Make the window non-interactive
floatWindowLayoutParam.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
windowManager.updateViewLayout(floatView, floatWindowLayoutParam);
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(floatView.getWindowToken(), 0);
Toast.makeText(this, "Text Saved!", Toast.LENGTH_SHORT).show();
});
}
// This method is responsible for handling the movement of the floating window
@SuppressLint("ClickableViewAccessibility")
private void setupFloatingWindowMovement() {
double initialX = 0.0;
double initialY = 0.0;
double initialTouchX = 0.0;
double initialTouchY = 0.0;
// Set a touch listener to detect dragging
floatView.setOnTouchListener((view, event) -> {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// Record the initial position and touch points when the touch starts
initialX = floatWindowLayoutParam.x;
initialY = floatWindowLayoutParam.y;
initialTouchX = event.getRawX();
initialTouchY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
// Calculate the new position of the window based on the movement of the touch
floatWindowLayoutParam.x = (int) ((initialX + event.getRawX()) - initialTouchX);
floatWindowLayoutParam.y = (int) ((initialY + event.getRawY()) - initialTouchY);
// Update the layout
windowManager.updateViewLayout(floatView, floatWindowLayoutParam);
break;
}
return false;
});
}
// This method is called when the service is destroyed
@Override
public void onDestroy() {
super.onDestroy();
try {
// Remove the floating window from the screen
windowManager.removeView(floatView);
} catch (Exception e) {
// Handle any potential errors
e.printStackTrace();
}
}}
FloatingWindowService.kt
package org.geeksforgeeks.demo
import android.annotation.SuppressLint import android.app.Service import android.content.Intent import android.graphics.PixelFormat import android.os.IBinder import android.text.Editable import android.text.TextWatcher import android.view.* import android.view.inputmethod.InputMethodManager import android.widget.Button import android.widget.EditText import android.widget.Toast
class FloatingWindowService : Service() {
// Declare variables for views and WindowManager
private lateinit var floatView: ViewGroup
private lateinit var floatWindowLayoutParam: WindowManager.LayoutParams
private lateinit var windowManager: WindowManager
private lateinit var maximizeBtn: Button
private lateinit var descEditArea: EditText
private lateinit var saveBtn: Button
// This method is required but not used in this Service
override fun onBind(intent: Intent?): IBinder? = null
// Service is created
@SuppressLint("ClickableViewAccessibility")
override fun onCreate() {
super.onCreate()
// Get screen width and height in pixels
val metrics = resources.displayMetrics
val width = metrics.widthPixels
val height = metrics.heightPixels
// Get the WindowManager system service for handling windows on the screen
windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
// Inflate the floating window layout using the LayoutInflater system service
val inflater = getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater
floatView = inflater.inflate(R.layout.floating_layout, null) as ViewGroup
// Initialize the views from the layout file
maximizeBtn = floatView.findViewById(R.id.buttonMaximize)
descEditArea = floatView.findViewById(R.id.descEditText)
saveBtn = floatView.findViewById(R.id.saveBtn)
// Set the initial text in the EditText and place the cursor at the end
descEditArea.apply {
setText(Common.currentDesc)
setSelection(text.length)
// Hide the cursor initially
isCursorVisible = false
}
// Set up the parameters for the floating window (size, position, etc.)
floatWindowLayoutParam = WindowManager.LayoutParams(
// Set width to 60% of screen width
(width * 0.6f).toInt(),
// Set height to 50% of screen height
(height * 0.5f).toInt(),
// Type for overlay window
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
// Make it not focusable
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
// Set transparent background for the window
PixelFormat.TRANSLUCENT
).apply {
// Position the window at the center of the screen
gravity = Gravity.CENTER
x = 0
y = 0
}
// Add the floating view to the window using the WindowManager
windowManager.addView(floatView, floatWindowLayoutParam)
// Set up a listener for the maximize button to stop the service and navigate to MainActivity
maximizeBtn.setOnClickListener {
stopSelf() // Stop the service
windowManager.removeView(floatView) // Remove the floating window
val backToHome = Intent(this, MainActivity::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
startActivity(backToHome)
}
// Set up a TextWatcher to update the current description when the text changes
descEditArea.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
// Update the current description with the text in the EditText
Common.currentDesc = descEditArea.text.toString()
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun afterTextChanged(s: Editable?) {}
})
// Set up the touch listener for the floating window to allow dragging it around
setupFloatingWindowMovement()
// Set up a listener for the EditText to make the cursor visible when clicked
descEditArea.setOnTouchListener { _, _ ->
descEditArea.isCursorVisible = true // Make the cursor visible when touched
floatWindowLayoutParam.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
windowManager.updateViewLayout(floatView, floatWindowLayoutParam) // Update the layout
false
}
// Set up a listener for the save button to save the text and hide the soft keyboard
saveBtn.setOnClickListener {
// Save the text in the EditText to the Common object
Common.savedDesc = descEditArea.text.toString()
// Hide the cursor after saving
descEditArea.isCursorVisible = false
// Make the window non-interactive
floatWindowLayoutParam.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
windowManager.updateViewLayout(floatView, floatWindowLayoutParam)
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
inputMethodManager.hideSoftInputFromWindow(floatView.windowToken, 0)
Toast.makeText(this, "Text Saved!", Toast.LENGTH_SHORT).show()
}
}
// This method is responsible for handling the movement of the floating window
@SuppressLint("ClickableViewAccessibility")
private fun setupFloatingWindowMovement() {
var initialX = 0.0
var initialY = 0.0
var initialTouchX = 0.0
var initialTouchY = 0.0
// Set a touch listener to detect dragging
floatView.setOnTouchListener { _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
// Record the initial position and touch points when the touch starts
initialX = floatWindowLayoutParam.x.toDouble()
initialY = floatWindowLayoutParam.y.toDouble()
initialTouchX = event.rawX.toDouble()
initialTouchY = event.rawY.toDouble()
}
MotionEvent.ACTION_MOVE -> {
// Calculate the new position of the window based on the movement of the touch
floatWindowLayoutParam.x = ((initialX + event.rawX) - initialTouchX).toInt()
floatWindowLayoutParam.y = ((initialY + event.rawY) - initialTouchY).toInt()
// Update the layout
windowManager.updateViewLayout(floatView, floatWindowLayoutParam)
}
}
false
}
}
// This method is called when the service is destroyed
override fun onDestroy() {
super.onDestroy()
try {
// Remove the floating window from the screen
windowManager.removeView(floatView)
} catch (e: Exception) {
// Handle any potential errors
e.printStackTrace()
}
}}
`
Step 6: Working with MainActivity file
Navigate to the **MainActivity file and make the following changes.
MainActivity.java `
package org.geeksforgeeks.demo;
import android.app.ActivityManager; import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.text.Editable; import android.text.TextWatcher; import android.widget.Button; import android.widget.EditText; import android.widget.Toast;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
// Declare the UI components (buttons and edit text)
private Button minimizeBtn;
private EditText descEditArea;
private Button save;
// Register for result to handle overlay permission
private final ActivityResultContracts.StartActivityForResult overlayPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (checkOverlayDisplayPermission()) {
// If permission is granted, start the floating window service
startService(new Intent(MainActivity.this, FloatingWindowService.class));
finish(); // Close the current activity
} else {
// If permission is not granted, show a toast message
Toast.makeText(MainActivity.this, "Permission not granted", Toast.LENGTH_SHORT).show();
}
});
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize the UI components
minimizeBtn = findViewById(R.id.buttonMinimize);
descEditArea = findViewById(R.id.descEditText);
save = findViewById(R.id.saveBtn);
// Check if the floating window service is already running, and stop it if it is
if (isServiceRunning(FloatingWindowService.class)) {
stopService(new Intent(this, FloatingWindowService.class));
}
// Set the text of the description edit text field from the Common.currentDesc variable
descEditArea.setText(Common.currentDesc);
// Move the cursor to the end of the text
descEditArea.setSelection(descEditArea.getText().length());
// Add a TextWatcher to update Common.currentDesc whenever the text in the edit area changes
descEditArea.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Common.currentDesc = descEditArea.getText().toString(); // Update the currentDesc variable
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void afterTextChanged(Editable s) {}
});
// Set an OnClickListener for the save button
save.setOnClickListener(v -> {
// Save the text from the edit area to the savedDesc variable
Common.savedDesc = descEditArea.getText().toString();
// Remove focus from the edit text field and hide the cursor
descEditArea.clearFocus();
descEditArea.setCursorVisible(false);
// Show a toast message to notify the user that the text has been saved
Toast.makeText(MainActivity.this, "Text Saved!", Toast.LENGTH_SHORT).show();
});
// Set an OnClickListener for the minimize button
minimizeBtn.setOnClickListener(v -> {
// Check if overlay permission is granted
if (checkOverlayDisplayPermission()) {
// If permission is granted, start the floating window service and finish the activity
startService(new Intent(MainActivity.this, FloatingWindowService.class));
finish();
} else {
// If permission is not granted, request overlay permission
requestOverlayDisplayPermission();
}
});
}
// Check if a service is currently running
private boolean isServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
// Check if the service is running using the deprecated method (for compatibility)
@SuppressWarnings("deprecation")
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (service.service.getClassName().equals(serviceClass.getName())) {
return true;
}
}
return false;
}
// Request the user to enable the "Display over other apps" permission from system settings
private void requestOverlayDisplayPermission() {
new AlertDialog.Builder(this)
.setTitle("Screen Overlay Permission Needed") // Title of the dialog
.setMessage("Enable 'Display over other apps' from System Settings.") // Message in the dialog
.setCancelable(true) // Allow the dialog to be canceled
.setPositiveButton("Open Settings", (dialog, which) -> {
// If the user clicks "Open Settings", open the system settings for overlay permission
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
overlayPermissionLauncher.launch(intent); // Launch the settings activity
})
.show(); // Show the dialog
}
// Check if the app has the overlay permission
private boolean checkOverlayDisplayPermission() {
// If the SDK version is below Marshmallow (API 23), overlay permission is not needed
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this);
}}
MainActivity.kt
package org.geeksforgeeks.demo
import android.app.ActivityManager import android.content.Intent import android.net.Uri import android.os.Build import android.os.Bundle import android.provider.Settings import android.text.Editable import android.text.TextWatcher import android.widget.Button import android.widget.EditText import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
// Declare the UI components (buttons and edit text)
private lateinit var minimizeBtn: Button
private lateinit var descEditArea: EditText
private lateinit var save: Button
// Register for result to handle overlay permission
private val overlayPermissionLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
if (checkOverlayDisplayPermission()) {
// If permission is granted, start the floating window service
startService(Intent(this, FloatingWindowService::class.java))
finish() // Close the current activity
} else {
// If permission is not granted, show a toast message
Toast.makeText(this, "Permission not granted", Toast.LENGTH_SHORT).show()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Initialize the UI components
minimizeBtn = findViewById(R.id.buttonMinimize)
descEditArea = findViewById(R.id.descEditText)
save = findViewById(R.id.saveBtn)
// Check if the floating window service is already running, and stop it if it is
if (isServiceRunning(FloatingWindowService::class.java)) {
stopService(Intent(this, FloatingWindowService::class.java))
}
// Set the text of the description edit text field from the Common.currentDesc variable
descEditArea.setText(Common.currentDesc)
// Move the cursor to the end of the text
descEditArea.setSelection(descEditArea.text.length)
// Add a TextWatcher to update Common.currentDesc whenever the text in the edit area changes
descEditArea.addTextChangedListener(object : TextWatcher {
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
Common.currentDesc = descEditArea.text.toString() // Update the currentDesc variable
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun afterTextChanged(s: Editable?) {}
})
// Set an OnClickListener for the save button
save.setOnClickListener {
// Save the text from the edit area to the savedDesc variable
Common.savedDesc = descEditArea.text.toString()
// Remove focus from the edit text field and hide the cursor
descEditArea.apply {
clearFocus()
isCursorVisible = false
}
// Show a toast message to notify the user that the text has been saved
Toast.makeText(this, "Text Saved!", Toast.LENGTH_SHORT).show()
}
// Set an OnClickListener for the minimize button
minimizeBtn.setOnClickListener {
// Check if overlay permission is granted
if (checkOverlayDisplayPermission()) {
// If permission is granted, start the floating window service and finish the activity
startService(Intent(this, FloatingWindowService::class.java))
finish()
} else {
// If permission is not granted, request overlay permission
requestOverlayDisplayPermission()
}
}
}
// Check if a service is currently running
private fun isServiceRunning(serviceClass: Class<*>): Boolean {
val manager = getSystemService(ACTIVITY_SERVICE) as ActivityManager
@Suppress("DEPRECATION")
return manager.getRunningServices(Int.MAX_VALUE)
.any { it.service.className == serviceClass.name }
}
// Request the user to enable the "Display over other apps" permission from system settings
private fun requestOverlayDisplayPermission() {
AlertDialog.Builder(this)
.setTitle("Screen Overlay Permission Needed") // Title of the dialog
.setMessage("Enable 'Display over other apps' from System Settings.") // Message in the dialog
.setCancelable(true) // Allow the dialog to be canceled
.setPositiveButton("Open Settings") { _, _ ->
// If the user clicks "Open Settings", open the system settings for overlay permission
val intent = Intent(
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:$packageName")
)
overlayPermissionLauncher.launch(intent) // Launch the settings activity
}
.show() // Show the dialog
}
// Check if the app has the overlay permission
private fun checkOverlayDisplayPermission(): Boolean {
// If the SDK version is below Marshmallow (API 23), overlay permission is not needed
return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(this)
}}
`