Livebeat is now able to send, store and show beats
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
package de.nicolasklier.livebeat
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the default destination in the navigation.
|
||||
*/
|
||||
class FirstFragment : Fragment() {
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_first, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
view.findViewById<Button>(R.id.button_first).setOnClickListener {
|
||||
findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,202 @@
|
||||
package de.nicolasklier.livebeat
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.util.logging.Logger
|
||||
|
||||
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
companion object {
|
||||
@JvmStatic val API_URL = "http://192.168.178.26:8040"
|
||||
var TOKEN = ""
|
||||
}
|
||||
|
||||
private var broadcastReceiver: BroadcastReceiver? = null
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
fun checkIfPhoneIsRegistered() {
|
||||
if (TOKEN == "") return;
|
||||
Thread(Runnable {
|
||||
val androidId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||
val client = OkHttpClient()
|
||||
val req = Request.Builder()
|
||||
.url("$API_URL/phone/$androidId")
|
||||
.get()
|
||||
.build()
|
||||
val response = client.newCall(req).execute()
|
||||
|
||||
if (response.code != 200) {
|
||||
Snackbar.make(findViewById<FloatingActionButton>(R.id.fab), "Device isn't registered yet.", Snackbar.LENGTH_SHORT)
|
||||
.setBackgroundTint(Color.YELLOW)
|
||||
.setTextColor(Color.BLACK)
|
||||
.show()
|
||||
|
||||
// Register device
|
||||
val phone = Phone(
|
||||
androidId,
|
||||
Build.MODEL,
|
||||
Build.PRODUCT,
|
||||
Build.VERSION.RELEASE,
|
||||
System.getProperty("os.arch")
|
||||
)
|
||||
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
|
||||
val phoneToJson = moshi.adapter(Phone::class.java)
|
||||
val json = phoneToJson.toJson(phone)
|
||||
|
||||
val createPhone = Request.Builder()
|
||||
.url("$API_URL/phone")
|
||||
.post(
|
||||
(json).toRequestBody()
|
||||
)
|
||||
.header("Content-Type", "application/json")
|
||||
.header("token", TOKEN)
|
||||
.build()
|
||||
client.newCall(createPhone).execute()
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
checkPerms()
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
setSupportActionBar(findViewById(R.id.toolbar))
|
||||
startService(Intent(this, TrackerService::class.java))
|
||||
|
||||
// Check authorization
|
||||
val backendChecks = Thread(Runnable {
|
||||
val username = findViewById<TextView>(R.id.username).text
|
||||
val password = findViewById<TextView>(R.id.password).text
|
||||
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
|
||||
val jsonToLogin = moshi.adapter(Login::class.java)
|
||||
|
||||
val client = OkHttpClient()
|
||||
val req = Request.Builder()
|
||||
.url("$API_URL/user/login")
|
||||
.post(
|
||||
("{ \"username\": \"" + username + "\"," +
|
||||
"\"password\": \"" + password + "\" }").toRequestBody()
|
||||
)
|
||||
.header("Content-Type", "application/json")
|
||||
.build()
|
||||
val loginResponse = client.newCall(req).execute()
|
||||
val responseBody = loginResponse.body!!.string()
|
||||
|
||||
if (loginResponse.code == 200) {
|
||||
TOKEN = jsonToLogin.fromJson(responseBody)!!.token
|
||||
|
||||
// Since we are in another thread, we have to get back to the UI thread.
|
||||
this.runOnUiThread(Runnable {
|
||||
findViewById<TextView>(R.id.httpStatus).setTextColor(Color.GREEN)
|
||||
findViewById<TextView>(R.id.httpStatus).text = "CONNECTED"
|
||||
})
|
||||
|
||||
Snackbar.make(findViewById<FloatingActionButton>(R.id.fab), "Login succeeded", Snackbar.LENGTH_SHORT)
|
||||
.setBackgroundTint(Color.GREEN)
|
||||
.setActionTextColor(Color.WHITE)
|
||||
.show()
|
||||
|
||||
checkIfPhoneIsRegistered()
|
||||
} else {
|
||||
// Since we are in another thread, we have to get back to the UI thread.
|
||||
this.runOnUiThread(Runnable {
|
||||
findViewById<TextView>(R.id.httpStatus).setTextColor(Color.RED)
|
||||
findViewById<TextView>(R.id.httpStatus).text = "LOGIN FAILED"
|
||||
})
|
||||
Snackbar.make(findViewById<FloatingActionButton>(R.id.fab), "Login failed", Snackbar.LENGTH_LONG)
|
||||
.setBackgroundTint(Color.RED)
|
||||
.setActionTextColor(Color.WHITE)
|
||||
.show()
|
||||
}
|
||||
})
|
||||
backendChecks.start()
|
||||
|
||||
/**
|
||||
* Here we receive updates from our tracker service.
|
||||
*/
|
||||
this.broadcastReceiver = object : BroadcastReceiver() {
|
||||
@SuppressLint("CutPasteId")
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val statusRabbit = intent.getBooleanExtra("statusRabbit", false)
|
||||
val statusHttp = intent.getIntExtra("statusHttp", 404)
|
||||
|
||||
if (statusRabbit) {
|
||||
findViewById<TextView>(R.id.rabbitStatus).text = "connected"
|
||||
findViewById<TextView>(R.id.rabbitStatus).setTextColor(Color.GREEN)
|
||||
} else {
|
||||
findViewById<TextView>(R.id.rabbitStatus).text = "disconnected"
|
||||
findViewById<TextView>(R.id.rabbitStatus).setTextColor(Color.RED)
|
||||
}
|
||||
|
||||
if (statusHttp == 200) {
|
||||
findViewById<TextView>(R.id.httpStatus).text = "ONLINE (no login)"
|
||||
findViewById<TextView>(R.id.httpStatus).setTextColor(Color.CYAN)
|
||||
findViewById<Button>(R.id.signin).isEnabled = false
|
||||
findViewById<Button>(R.id.signin).text = "Signed in"
|
||||
} else {
|
||||
findViewById<TextView>(R.id.httpStatus).text = "OFFLINE"
|
||||
findViewById<TextView>(R.id.httpStatus).setTextColor(Color.RED)
|
||||
findViewById<Button>(R.id.signin).isEnabled = true
|
||||
findViewById<Button>(R.id.signin).text = "Sign in"
|
||||
}
|
||||
}
|
||||
}
|
||||
registerReceiver(broadcastReceiver, IntentFilter("de.nicolasklier.livebeat"))
|
||||
|
||||
findViewById<FloatingActionButton>(R.id.fab).setOnClickListener { view ->
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show()
|
||||
.setAction("Action", null).show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPerms() {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
this,
|
||||
Manifest.permission.ACCESS_FINE_LOCATION
|
||||
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
|
||||
this,
|
||||
Manifest.permission.ACCESS_COARSE_LOCATION
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
|
||||
if (broadcastReceiver != null) {
|
||||
unregisterReceiver(broadcastReceiver)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,4 +215,28 @@ class MainActivity : AppCompatActivity() {
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRequestPermissionsResult(
|
||||
requestCode: Int,
|
||||
permissions: Array<out String>,
|
||||
grantResults: IntArray
|
||||
) {
|
||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
|
||||
if (requestCode == 1) {
|
||||
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||
Snackbar.make(findViewById<FloatingActionButton>(R.id.fab), "Location access is allowed", Snackbar.LENGTH_SHORT)
|
||||
.setBackgroundTint(Color.GREEN)
|
||||
.setAction("Action", null).show()
|
||||
}
|
||||
} else {
|
||||
Snackbar.make(findViewById<FloatingActionButton>(R.id.fab), "Location access is required.", Snackbar.LENGTH_INDEFINITE)
|
||||
.setBackgroundTint(Color.RED)
|
||||
.setActionTextColor(Color.WHITE)
|
||||
.setAction("Grant", View.OnClickListener {
|
||||
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), 1)
|
||||
}).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
26
android/app/src/main/java/de/nicolasklier/livebeat/Models.kt
Normal file
26
android/app/src/main/java/de/nicolasklier/livebeat/Models.kt
Normal file
@@ -0,0 +1,26 @@
|
||||
package de.nicolasklier.livebeat
|
||||
|
||||
import com.squareup.moshi.JsonClass
|
||||
import com.squareup.moshi.ToJson
|
||||
|
||||
/**
|
||||
* This class represents one singe beat that will be send to the database.
|
||||
*/
|
||||
class Beat(
|
||||
final val token: String, // Token of this phone
|
||||
final val gpsLocation: Array<Double>,
|
||||
final val battery: Int?,
|
||||
final val timestamp: Long
|
||||
) {}
|
||||
|
||||
class Phone(
|
||||
final val androidId: String,
|
||||
final val modelName: String,
|
||||
final val displayName: String,
|
||||
final val operatingSystem: String,
|
||||
final val architecture: String
|
||||
) {}
|
||||
|
||||
class Login(
|
||||
final val token: String
|
||||
) {}
|
||||
@@ -1,31 +0,0 @@
|
||||
package de.nicolasklier.livebeat
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass as the second destination in the navigation.
|
||||
*/
|
||||
class SecondFragment : Fragment() {
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_second, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
view.findViewById<Button>(R.id.button_second).setOnClickListener {
|
||||
findNavController().navigate(R.id.action_SecondFragment_to_FirstFragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package de.nicolasklier.livebeat;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.Color;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import com.rabbitmq.client.Channel;
|
||||
import com.rabbitmq.client.Connection;
|
||||
import com.rabbitmq.client.ConnectionFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class TrackerService extends Service {
|
||||
|
||||
private static final int NOTIF_ID = 1;
|
||||
private static final String NOTIF_CHANNEL_ID = "LiveTracker";
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
final Connection[] conn = new Connection[1];
|
||||
|
||||
// This thread only connects to RabbitMQ
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ConnectionFactory factory = new ConnectionFactory();
|
||||
factory.setUsername("lineage");
|
||||
factory.setPassword("ZSo$X97GQ547JXL7nGq");
|
||||
factory.setVirtualHost("/");
|
||||
factory.setHost("192.168.178.26");
|
||||
factory.setPort(5672);
|
||||
|
||||
try {
|
||||
conn[0] = factory.newConnection();
|
||||
Channel channel = conn[0].createChannel();
|
||||
channel.queueDeclare("Tracker", false, false, false, null);
|
||||
channel.basicPublish("", "Tracker", null, "Test message!!!!!!!!!!!!!!!!!".getBytes());
|
||||
Log.i("RabbitMQ", "run: Published test message");
|
||||
} catch (IOException | TimeoutException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
thread.start();
|
||||
startForeground();
|
||||
|
||||
return super.onStartCommand(intent, flags, startId);
|
||||
}
|
||||
|
||||
private void startForeground() {
|
||||
Intent noticicationIntent = new Intent(this, MainActivity.class);
|
||||
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, noticicationIntent, 0);
|
||||
|
||||
NotificationChannel chan = new NotificationChannel(
|
||||
NOTIF_CHANNEL_ID,
|
||||
"Tracker",
|
||||
NotificationManager.IMPORTANCE_LOW);
|
||||
chan.setLightColor(Color.BLACK);
|
||||
chan.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
|
||||
|
||||
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
assert manager != null;
|
||||
manager.createNotificationChannel(chan);
|
||||
|
||||
startForeground(NOTIF_ID, new NotificationCompat.Builder(this, NOTIF_CHANNEL_ID)
|
||||
.setOngoing(true)
|
||||
.setContentTitle("Livebeat")
|
||||
.setContentText("Tracker is running")
|
||||
.setContentIntent(pendingIntent)
|
||||
.setCategory(Notification.CATEGORY_SERVICE)
|
||||
.setPriority(NotificationManager.IMPORTANCE_LOW)
|
||||
.setChannelId(NOTIF_CHANNEL_ID)
|
||||
.setColor(Color.BLACK)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package de.nicolasklier.livebeat
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.*
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.graphics.Color
|
||||
import android.location.LocationManager
|
||||
import android.os.BatteryManager
|
||||
import android.os.Bundle
|
||||
import android.os.IBinder
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import com.rabbitmq.client.Channel
|
||||
import com.rabbitmq.client.Connection
|
||||
import com.rabbitmq.client.ConnectionFactory
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.Moshi
|
||||
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import java.io.IOException
|
||||
import java.util.concurrent.TimeoutException
|
||||
|
||||
class TrackerService : Service() {
|
||||
|
||||
val conn = arrayOfNulls<Connection>(1)
|
||||
val channel = arrayOfNulls<Channel>(1)
|
||||
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun connectWithBroker() {
|
||||
// This thread only connects to RabbitMQ
|
||||
val connectionThread = Thread(Runnable {
|
||||
val client = OkHttpClient()
|
||||
val req = Request.Builder()
|
||||
.url(MainActivity.API_URL)
|
||||
.get()
|
||||
.build()
|
||||
|
||||
val factory = ConnectionFactory()
|
||||
factory.username = "lineage"
|
||||
factory.password = "ZSo\$X97GQ547JXL7nGq"
|
||||
factory.virtualHost = "/"
|
||||
factory.host = "nk-home.ddns.net"
|
||||
factory.port = 5672
|
||||
factory.isAutomaticRecoveryEnabled = true
|
||||
try {
|
||||
conn[0] = factory.newConnection()
|
||||
channel[0] = conn[0]?.createChannel()
|
||||
|
||||
val intent = Intent("de.nicolasklier.livebeat")
|
||||
val bundle = Bundle()
|
||||
bundle.putBoolean("statusRabbit", true)
|
||||
bundle.putInt("statusHttp", client.newCall(req).execute().code)
|
||||
intent.putExtras(bundle)
|
||||
this.sendBroadcast(intent)
|
||||
|
||||
channel[0]?.queueDeclare("tracker", true, false, false, null)
|
||||
//channel[0]?.basicPublish("", "Tracker", null, "Test message".toByteArray())
|
||||
Log.i("RabbitMQ", "run: Published test message")
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
} catch (e: TimeoutException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
})
|
||||
connectionThread.start()
|
||||
}
|
||||
|
||||
@SuppressLint("HardwareIds")
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
|
||||
// Android id as unique identifier
|
||||
val androidId = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||
locationManager.requestLocationUpdates("gps", 5000, 0f
|
||||
) { location ->
|
||||
Log.i("Location", "Location is: " + location.latitude + " | " + location.longitude)
|
||||
|
||||
/* Get battery */
|
||||
val batteryStatus: Intent? = IntentFilter(Intent.ACTION_BATTERY_CHANGED).let { ifilter ->
|
||||
this@TrackerService.registerReceiver(null, ifilter)
|
||||
}
|
||||
val batteryPct: Float? = batteryStatus?.let { intent ->
|
||||
val level: Int = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
|
||||
val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1)
|
||||
level * 100 / scale.toFloat()
|
||||
}
|
||||
|
||||
val beat = Beat(androidId, arrayOf(location.latitude, location.longitude, location.accuracy.toDouble(), location.speed.toDouble()), batteryPct?.toInt(), location.time)
|
||||
val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
|
||||
val jsonAdapter: JsonAdapter<Beat> = moshi.adapter(Beat::class.java)
|
||||
|
||||
Thread(Runnable {
|
||||
channel[0]?.basicPublish("", "tracker", null, jsonAdapter.toJson(beat).toByteArray())
|
||||
}).start()
|
||||
}
|
||||
}
|
||||
|
||||
connectWithBroker()
|
||||
startForeground()
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
private fun startForeground() {
|
||||
val noticicationIntent = Intent(this, MainActivity::class.java)
|
||||
val pendingIntent = PendingIntent.getActivity(this, 0, noticicationIntent, 0)
|
||||
val chan = NotificationChannel(
|
||||
NOTIF_CHANNEL_ID,
|
||||
"Tracker",
|
||||
NotificationManager.IMPORTANCE_LOW)
|
||||
chan.lightColor = Color.BLACK
|
||||
chan.lockscreenVisibility = Notification.VISIBILITY_SECRET
|
||||
val manager = (getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager)
|
||||
manager.createNotificationChannel(chan)
|
||||
startForeground(NOTIF_ID, NotificationCompat.Builder(this, NOTIF_CHANNEL_ID)
|
||||
.setOngoing(true)
|
||||
.setContentTitle("Livebeat")
|
||||
.setContentText("Tracker is running")
|
||||
.setContentIntent(pendingIntent)
|
||||
.setCategory(Notification.CATEGORY_SERVICE)
|
||||
.setPriority(NotificationManager.IMPORTANCE_LOW)
|
||||
.setChannelId(NOTIF_CHANNEL_ID)
|
||||
.setColorized(true)
|
||||
.setColor(Color.BLACK)
|
||||
.build())
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NOTIF_ID = 1
|
||||
private const val NOTIF_CHANNEL_ID = "LiveTracker"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user