diff --git a/app/build.gradle b/app/build.gradle
index 1712de1..301e1d0 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -56,7 +56,7 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7'
implementation 'androidx.navigation:navigation-ui-ktx:2.7.7'
- implementation 'com.budiyev.android:code-scanner:2.1.0'
+ implementation 'com.github.yuriy-budiyev:code-scanner:2.1.0'
implementation 'com.karumi:dexter:6.2.2'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.madgag.spongycastle:bcpkix-jdk15on:1.58.0.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e618687..f61bab1 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,9 +14,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/com/meshcentral/agent/BootReceiver.kt b/app/src/main/java/com/meshcentral/agent/BootReceiver.kt
new file mode 100644
index 0000000..807c2fc
--- /dev/null
+++ b/app/src/main/java/com/meshcentral/agent/BootReceiver.kt
@@ -0,0 +1,22 @@
+package com.meshcentral.agent
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Build
+import androidx.preference.PreferenceManager
+
+class BootReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent?) {
+ if (intent?.action == Intent.ACTION_BOOT_COMPLETED) {
+ val serviceIntent = Intent(context, BootService::class.java)
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ context.startForegroundService(serviceIntent)
+ } else {
+ context.startService(serviceIntent)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/meshcentral/agent/BootService.kt b/app/src/main/java/com/meshcentral/agent/BootService.kt
new file mode 100644
index 0000000..684b13c
--- /dev/null
+++ b/app/src/main/java/com/meshcentral/agent/BootService.kt
@@ -0,0 +1,89 @@
+package com.meshcentral.agent
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.app.Service
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Build
+import android.os.IBinder
+import androidx.core.app.NotificationCompat
+import androidx.preference.PreferenceManager
+
+class BootService : Service() {
+ private val CHANNEL_ID = "BootServiceChannel"
+
+ override fun onCreate() {
+ super.onCreate()
+ createNotificationChannel()
+
+ val notification: Notification = NotificationCompat.Builder(this, CHANNEL_ID)
+ .setContentTitle(getString(R.string.starting_meshcentral_bootservice))
+ .setContentText("")
+ .setSmallIcon(android.R.drawable.ic_dialog_info)
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
+ .build()
+
+ startForeground(1, notification)
+ }
+
+ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
+ performStartupTasks()
+
+ return START_STICKY
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ }
+
+ override fun onBind(intent: Intent?): IBinder? {
+ return null
+ }
+
+ private fun createNotificationChannel() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ val channel = NotificationChannel(
+ CHANNEL_ID,
+ "Boot Service Channel",
+ NotificationManager.IMPORTANCE_HIGH
+ ).apply {
+ description = "Notification channel for BootService"
+ }
+
+ val manager = getSystemService(NotificationManager::class.java)
+ manager?.createNotificationChannel(channel)
+ }
+ }
+
+ private fun performStartupTasks() {
+ val pm: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
+ g_autoStart = pm.getBoolean("pref_autostart", false)
+ if (g_autoStart == true) {
+ Thread {
+ try {
+ Thread.sleep(5000)
+ val launchIntent = Intent(this, MainActivity::class.java).apply {
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ val pendingIntent = PendingIntent.getActivity(
+ this,
+ 0,
+ launchIntent,
+ PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ )
+ pendingIntent.send()
+ } else {
+ startActivity(launchIntent)
+ }
+
+ } catch (e: Exception) {
+ }
+ }.start()
+ }
+ }
+}
diff --git a/app/src/main/java/com/meshcentral/agent/MainActivity.kt b/app/src/main/java/com/meshcentral/agent/MainActivity.kt
index aca1448..1951a8a 100644
--- a/app/src/main/java/com/meshcentral/agent/MainActivity.kt
+++ b/app/src/main/java/com/meshcentral/agent/MainActivity.kt
@@ -20,6 +20,7 @@ import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.CountDownTimer
+import android.os.PowerManager
import android.provider.Settings
import android.text.InputType
import android.util.Base64
@@ -61,6 +62,7 @@ import kotlin.math.absoluteValue
val hardCodedServerLink : String? = null
//val hardCodedServerLink : String? = "mc://central.mesh.meshcentral.com,2ZNi1e2Lrqi\$nnQ7NLJCJWNwxGD9ZstiNzxs\$LIE1tcHQD45bPDvbcKzpC9zUTX9,7b4b43cdad850135f36ab31124b52e47c167fba055ce800267a4dc89fe0e581c"
+
// User interface values
var g_mainActivity : MainActivity? = null
var mainFragment : MainFragment? = null
@@ -79,6 +81,7 @@ var pageUrl : String? = null
var cameraPresent : Boolean = false
var pendingActivities : ArrayList = ArrayList()
var pushMessagingToken : String? = null
+var g_autoStart : Boolean = false
var g_autoConnect : Boolean = true
var g_autoConsent : Boolean = false
var g_userDisconnect : Boolean = false // Indicate user initiated disconnection
@@ -491,6 +494,34 @@ class MainActivity : AppCompatActivity() {
if (permissions.isNotEmpty()) {
ActivityCompat.requestPermissions(this, permissions.toTypedArray(), REQUEST_ALL_PERMISSIONS)
}
+
+ if (!Settings.canDrawOverlays(this)) {
+ val intent = Intent(
+ Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+ Uri.parse("package:$packageName")
+ )
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ startActivity(intent)
+ }
+
+ // Check and add ignore battery optimization permissions if necessary
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
+ if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
+ val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply {
+ data = Uri.parse("package:$packageName")
+ }
+ startActivity(intent)
+ }
+ }
+
+ // Check and add post notifications permissions if necessary
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.POST_NOTIFICATIONS), 1)
+ }
+ }
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) {
@@ -680,6 +711,7 @@ class MainActivity : AppCompatActivity() {
fun settingsChanged() {
this.runOnUiThread {
val pm: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
+ g_autoStart = pm.getBoolean("pref_autostart", false)
g_autoConnect = pm.getBoolean("pref_autoconnect", false)
g_autoConsent = pm.getBoolean("pref_autoconsent", false)
g_userDisconnect = false
diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml
index dfcf188..b6c1ad7 100644
--- a/app/src/main/res/values-de/strings.xml
+++ b/app/src/main/res/values-de/strings.xml
@@ -58,4 +58,9 @@
Immer Zustimmung für Verbindung anfordern
Verbinden mit: %1$s?
Server-Setup löschen?
+ Server Pairing Link ungültig
+ Autostart
+ Manuell starten
+ Mit System starten
+ Starte MeshCentral BootService...
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e4a6ccd..018ba78 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -61,6 +61,10 @@
Always ask for consent when remote agent connects
Setup to: %1$s?
Clear server setup?
- Server Pairing Link
- Invalid Server Pairing Linbk
+ Server Pairing Link
+ Invalid Server Pairing Link
+ Autostart
+ Start manually
+ Start with system
+ Starting MeshCentral BootService...
\ No newline at end of file
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index 50f85ef..29a4e10 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -3,6 +3,13 @@
+