final things
This commit is contained in:
parent
e1d79d2faa
commit
7bc5f72309
|
|
@ -4,7 +4,7 @@
|
||||||
<selectionStates>
|
<selectionStates>
|
||||||
<SelectionState runConfigName="app">
|
<SelectionState runConfigName="app">
|
||||||
<option name="selectionMode" value="DROPDOWN" />
|
<option name="selectionMode" value="DROPDOWN" />
|
||||||
<DropdownSelection timestamp="2025-05-29T12:15:47.909492410Z">
|
<DropdownSelection timestamp="2025-06-01T19:10:27.800446242Z">
|
||||||
<Target type="DEFAULT_BOOT">
|
<Target type="DEFAULT_BOOT">
|
||||||
<handle>
|
<handle>
|
||||||
<DeviceId pluginId="PhysicalDevice" identifier="serial=c3a188c5" />
|
<DeviceId pluginId="PhysicalDevice" identifier="serial=c3a188c5" />
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings" defaultProject="true" />
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="" vcs="Git" />
|
||||||
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -53,6 +53,7 @@ dependencies {
|
||||||
implementation(libs.material)
|
implementation(libs.material)
|
||||||
implementation(libs.androidx.activity)
|
implementation(libs.androidx.activity)
|
||||||
implementation(libs.androidx.constraintlayout)
|
implementation(libs.androidx.constraintlayout)
|
||||||
|
implementation(libs.socket.socket.io.client)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
android:name="android.hardware.location.network"
|
android:name="android.hardware.location.network"
|
||||||
android:required="false" />
|
android:required="false" />
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.SEND_SMS" />
|
<uses-permission android:name="android.permission.SEND_SMS" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
<uses-permission android:name="android.permission.RECEIVE_SMS" />
|
||||||
<uses-permission android:name="android.permission.READ_SMS" />
|
<uses-permission android:name="android.permission.READ_SMS" />
|
||||||
|
|
@ -28,6 +29,7 @@
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||||
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
|
||||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
|
|
@ -77,18 +79,34 @@
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".services.WebSocketService"
|
||||||
|
android:directBootAware="true"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="true"
|
||||||
|
android:foregroundServiceType="specialUse">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
</intent-filter>
|
||||||
|
</service>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".receivers.SmsReceiver"
|
android:name=".receivers.SmsReceiver"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:directBootAware="true">
|
android:directBootAware="true"
|
||||||
|
android:permission="android.permission.BROADCAST_SMS">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
|
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".receivers.FmdBootReceiver"
|
android:name=".receivers.FmdBootReceiver"
|
||||||
android:directBootAware="true"
|
android:directBootAware="true"
|
||||||
android:exported="false">
|
android:exported="true"
|
||||||
|
android:enabled="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||||
<!-- Handle direct boot actions -->
|
<!-- Handle direct boot actions -->
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ class CommandHandler(val context: Context, val lockIntent: Intent, val ringInten
|
||||||
reply("https://www.openstreetmap.org/#map=18/${loc.latitude}/${loc.longitude}")
|
reply("https://www.openstreetmap.org/#map=18/${loc.latitude}/${loc.longitude}")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
} else if (args[2].contentEquals("battery")) {
|
||||||
|
reply("${Utils.getBatteryLevel(context)}% ${if (Utils.getBatteryCharging(context)) "charging" else "discharging"}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package ru.officialdakari.fmd
|
package ru.officialdakari.fmd
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
|
@ -27,6 +28,8 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import ru.officialdakari.fmd.dialogs.NewPinDialog
|
import ru.officialdakari.fmd.dialogs.NewPinDialog
|
||||||
import ru.officialdakari.fmd.dialogs.SelectAppsDialog
|
import ru.officialdakari.fmd.dialogs.SelectAppsDialog
|
||||||
|
import ru.officialdakari.fmd.dialogs.ServerSetupDialog
|
||||||
|
import ru.officialdakari.fmd.services.WebSocketService
|
||||||
import ru.officialdakari.fmd.ui.theme.FindMyDeviceTheme
|
import ru.officialdakari.fmd.ui.theme.FindMyDeviceTheme
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
|
|
@ -48,10 +51,13 @@ class MainActivity : ComponentActivity() {
|
||||||
) {
|
) {
|
||||||
SetPinButton(context = this@MainActivity)
|
SetPinButton(context = this@MainActivity)
|
||||||
SetAppsButton(context = this@MainActivity)
|
SetAppsButton(context = this@MainActivity)
|
||||||
|
ServerSetupDialog(context = this@MainActivity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val intent = Intent(this, WebSocketService::class.java)
|
||||||
|
startService(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,6 +92,37 @@ fun SetPinButton(context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ServerSetupDialog(context: Context) {
|
||||||
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
if (showDialog) {
|
||||||
|
ServerSetupDialog(
|
||||||
|
context = context,
|
||||||
|
initialState = Utils.getServerData(context),
|
||||||
|
onDismissRequest = {
|
||||||
|
showDialog = false
|
||||||
|
},
|
||||||
|
onConfirm = {
|
||||||
|
Utils.setServerData(context, it.first, it.second)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Setup controlling FMA via website.",
|
||||||
|
modifier = Modifier.padding(10.dp)
|
||||||
|
)
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
showDialog = true
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(10.dp)
|
||||||
|
) {
|
||||||
|
Text("Setup server")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SetAppsButton(context: Context) {
|
fun SetAppsButton(context: Context) {
|
||||||
var showDialog by remember { mutableStateOf(false) }
|
var showDialog by remember { mutableStateOf(false) }
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.app.admin.DevicePolicyManager
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import kotlin.jvm.java
|
import kotlin.jvm.java
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.os.BatteryManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
|
@ -12,8 +13,10 @@ import kotlinx.coroutines.launch
|
||||||
import ru.officialdakari.fmd.receivers.FmdDeviceAdminReceiver
|
import ru.officialdakari.fmd.receivers.FmdDeviceAdminReceiver
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
|
import java.io.FileNotFoundException
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
class Utils {
|
class Utils {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
@ -61,11 +64,50 @@ class Utils {
|
||||||
writer.write(buff)
|
writer.write(buff)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setServerData(context: Context, url: String, devKey: String) {
|
||||||
|
val ctx: Context = context.createDeviceProtectedStorageContext()
|
||||||
|
val writer = ctx.openFileOutput("server.txt", Context.MODE_PRIVATE)
|
||||||
|
val buff = "$url\n$devKey".toByteArray(Charsets.UTF_8)
|
||||||
|
writer.write(buff)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getServerData(context: Context): Pair<String, String>? {
|
||||||
|
try {
|
||||||
|
val ctx: Context = context.createDeviceProtectedStorageContext()
|
||||||
|
val reader = ctx.openFileInput("server.txt")
|
||||||
|
val data = reader.readAllBytes().toString(Charsets.UTF_8).split("\n")
|
||||||
|
return Pair(data[0], data[1])
|
||||||
|
} catch (ex: FileNotFoundException) {
|
||||||
|
Log.w("FMD", ex.stackTraceToString())
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun sleep(ms: Long, onComplete: () -> Unit) {
|
fun sleep(ms: Long, onComplete: () -> Unit) {
|
||||||
GlobalScope.launch(Dispatchers.Main) {
|
GlobalScope.launch(Dispatchers.Main) {
|
||||||
delay(ms)
|
delay(ms)
|
||||||
onComplete()
|
onComplete()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getBatteryLevel(context: Context): Int {
|
||||||
|
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
|
||||||
|
return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBatteryCharging(context: Context): Boolean {
|
||||||
|
val batteryManager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager
|
||||||
|
return batteryManager.isCharging
|
||||||
|
}
|
||||||
|
|
||||||
|
fun randomDevKey(): String {
|
||||||
|
var devKey = ""
|
||||||
|
for (i in 0..18) {
|
||||||
|
devKey += ALPHABET[Random.nextInt(0, ALPHABET.length)];
|
||||||
|
}
|
||||||
|
return devKey
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const val ALPHABET: String = "ABCDEF1234567890"
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package ru.officialdakari.fmd.dialogs
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.material3.AlertDialog
|
||||||
|
import androidx.compose.material3.Button
|
||||||
|
import androidx.compose.material3.Checkbox
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
|
import androidx.compose.material3.OutlinedTextField
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import ru.officialdakari.fmd.Utils
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ServerSetupDialog(
|
||||||
|
context: Context,
|
||||||
|
initialState: Pair<String, String>?,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
onConfirm: (Pair<String, String>) -> Unit
|
||||||
|
) {
|
||||||
|
var serverUrl by remember { mutableStateOf(if (initialState != null) initialState!!.first else "https://fma.officialdakari.ru/") }
|
||||||
|
var devKey by remember { mutableStateOf(if (initialState != null) initialState!!.second else Utils.randomDevKey() ) }
|
||||||
|
|
||||||
|
AlertDialog(
|
||||||
|
onDismissRequest = onDismissRequest,
|
||||||
|
title = { Text(text = "Server connection") },
|
||||||
|
text = {
|
||||||
|
Column {
|
||||||
|
Text(text = "Choose FMA Server instance and device key.")
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
OutlinedTextField(
|
||||||
|
value = serverUrl,
|
||||||
|
onValueChange = { it ->
|
||||||
|
serverUrl = it
|
||||||
|
},
|
||||||
|
label = {
|
||||||
|
Text("Server URL")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
OutlinedTextField(
|
||||||
|
value = devKey,
|
||||||
|
onValueChange = {},
|
||||||
|
readOnly = true,
|
||||||
|
label = {
|
||||||
|
Text("Device key")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Text(text = "Disclaimer: Device key grants full FMA access, treat it like a password.")
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = {
|
||||||
|
devKey = Utils.randomDevKey()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Random key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmButton = {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
onConfirm(Pair(serverUrl, devKey))
|
||||||
|
onDismissRequest()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Text("Save")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dismissButton = {
|
||||||
|
Button(onClick = onDismissRequest) {
|
||||||
|
Text("Cancel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -3,13 +3,16 @@ package ru.officialdakari.fmd.receivers
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
import ru.officialdakari.fmd.services.FmdNotificationListenerService
|
import ru.officialdakari.fmd.services.FmdNotificationListenerService
|
||||||
|
import ru.officialdakari.fmd.services.WebSocketService
|
||||||
|
|
||||||
class FmdBootReceiver: BroadcastReceiver() {
|
class FmdBootReceiver: BroadcastReceiver() {
|
||||||
override fun onReceive(ctx: Context, intent: Intent) {
|
override fun onReceive(ctx: Context, intent: Intent) {
|
||||||
|
Log.w("FMD BootReceiver", "Received ${intent.action}")
|
||||||
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
|
if (intent.action == Intent.ACTION_LOCKED_BOOT_COMPLETED) {
|
||||||
|
val intent = Intent(ctx, WebSocketService::class.java)
|
||||||
|
ctx.startService(intent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ class SmsReceiver: BroadcastReceiver() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("Exception caught",e.stackTraceToString());
|
Log.d("Exception caught FMD",e.stackTraceToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
package ru.officialdakari.fmd.services
|
||||||
|
|
||||||
|
import android.app.Service
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.IBinder
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.Toast
|
||||||
|
|
||||||
|
import ru.officialdakari.fmd.LockActivity
|
||||||
|
import ru.officialdakari.fmd.RingActivity
|
||||||
|
import ru.officialdakari.fmd.Utils
|
||||||
|
|
||||||
|
import io.socket.client.IO
|
||||||
|
import io.socket.client.Socket
|
||||||
|
import io.socket.engineio.client.transports.PollingXHR
|
||||||
|
import io.socket.engineio.client.transports.WebSocket
|
||||||
|
import ru.officialdakari.fmd.LocationUtils
|
||||||
|
|
||||||
|
class WebSocketService: Service() {
|
||||||
|
var ringIntent: Intent? = null
|
||||||
|
var lockIntent: Intent? = null
|
||||||
|
var loc: LocationUtils = LocationUtils(this)
|
||||||
|
|
||||||
|
var mSocket: Socket? = null
|
||||||
|
|
||||||
|
private fun initIntents(context: Context) {
|
||||||
|
ringIntent = Intent(context, RingActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
|
||||||
|
addFlags(Intent.FLAG_FROM_BACKGROUND)
|
||||||
|
}
|
||||||
|
lockIntent = Intent(context, LockActivity::class.java).apply {
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
|
||||||
|
addFlags(Intent.FLAG_FROM_BACKGROUND)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startWebsocket(context: Context) {
|
||||||
|
try {
|
||||||
|
val connData = Utils.getServerData(context)
|
||||||
|
Log.w("FMD Service", "Connecting IO")
|
||||||
|
if (connData == null) {
|
||||||
|
Log.w("FMD Service", "connData == null, returning")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val opts = IO.Options()
|
||||||
|
opts.transports = arrayOf(WebSocket.NAME, PollingXHR.NAME)
|
||||||
|
mSocket = IO.socket(connData.first, opts)
|
||||||
|
Log.w("FMD Service", "Connecting to ${connData.first}")
|
||||||
|
mSocket!!.on(Socket.EVENT_CONNECT) {
|
||||||
|
Log.d("FMD Service", "Connected to server")
|
||||||
|
mSocket!!.emit("auth", connData.second, "${Build.BRAND} ${Build.MODEL}")
|
||||||
|
}.on(Socket.EVENT_CONNECT_ERROR) { args ->
|
||||||
|
Log.e("FMD Service", "Connection Error: ${(args[0] as Throwable).stackTraceToString()}")
|
||||||
|
}.on(Socket.EVENT_DISCONNECT) {
|
||||||
|
Log.d("FMD Service", "Disconnected from server")
|
||||||
|
Utils.sleep(15000) {
|
||||||
|
startWebsocket(context)
|
||||||
|
}
|
||||||
|
}.on("ring") {
|
||||||
|
ring(context)
|
||||||
|
}.on("lock") {
|
||||||
|
val message = it[0] as String
|
||||||
|
lock(context, message)
|
||||||
|
}.on("locate") {
|
||||||
|
loc.getLocation({
|
||||||
|
mSocket!!.emit("location", it.latitude, it.longitude)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
mSocket!!.connect()
|
||||||
|
} catch (ex: Throwable) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
Toast.makeText(this, "Failed to connect to server, see logcat", Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ring(context: Context) {
|
||||||
|
if (ringIntent != null) {
|
||||||
|
context.startActivity(ringIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun lock(context: Context, message: String) {
|
||||||
|
if (lockIntent != null) {
|
||||||
|
Utils.lockMessage = message
|
||||||
|
Utils.lockDevice(context)
|
||||||
|
Utils.sleep(1000) {
|
||||||
|
startActivity(lockIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
if (!loc.isStarted()) loc.start()
|
||||||
|
if (lockIntent == null || ringIntent == null) {
|
||||||
|
initIntents(this)
|
||||||
|
}
|
||||||
|
startWebsocket(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBind(p0: Intent?): IBinder? {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
// if (intent.action == "android.intent.action.LOCKED_BOOT_COMPLETED"
|
||||||
|
// || intent.action == "android.intent.action.BOOT_COMPLETED") {
|
||||||
|
// if (lockIntent == null || ringIntent == null) {
|
||||||
|
// initIntents(context)
|
||||||
|
// }
|
||||||
|
// startWebsocket(context)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,8 @@ appcompat = "1.6.1"
|
||||||
material = "1.10.0"
|
material = "1.10.0"
|
||||||
activity = "1.10.1"
|
activity = "1.10.1"
|
||||||
constraintlayout = "2.1.4"
|
constraintlayout = "2.1.4"
|
||||||
|
socketIoClient = "0.6.0"
|
||||||
|
socketIoClientVersion = "2.1.2"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||||
|
|
@ -32,6 +34,8 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version
|
||||||
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
|
||||||
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
|
||||||
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
|
||||||
|
socket-io-client = { group = "com.github.nkzawa", name = "socket.io-client", version.ref = "socketIoClient" }
|
||||||
|
socket-socket-io-client = { group = "io.socket", name = "socket.io-client", version.ref = "socketIoClientVersion" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue