update
This commit is contained in:
@@ -1,47 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.oilcheckkotlin">
|
||||
|
||||
<!-- for Android below 12 start -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
|
||||
android:maxSdkVersion="30" />
|
||||
<!-- for Android below 12 end -->
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
|
||||
<!-- android:icon="@mipmap/ic_launcher"-->
|
||||
<!-- android:roundIcon="@mipmap/ic_launcher_round"-->
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/draw_icon_blue"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.OilCheckKotlin">
|
||||
<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>
|
||||
<service android:name=".BLEConnectionService"></service>
|
||||
<service android:name=".NLService"
|
||||
android:exported="true"
|
||||
android:enabled="true"
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
|
||||
<intent-filter>
|
||||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.oilcheckkotlin">
|
||||
|
||||
<!-- for Android below 12 start -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"
|
||||
android:maxSdkVersion="30" />
|
||||
<!-- for Android below 12 end -->
|
||||
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
|
||||
<!-- android:icon="@mipmap/ic_launcher"-->
|
||||
<!-- android:roundIcon="@mipmap/ic_launcher_round"-->
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@drawable/draw_icon_blue"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.OilCheckKotlin">
|
||||
<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>
|
||||
<service android:name=".BLEConnectionService"></service>
|
||||
<service android:name=".NLService"
|
||||
android:exported="true"
|
||||
android:enabled="true"
|
||||
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" >
|
||||
<intent-filter>
|
||||
<action android:name="android.service.notification.NotificationListenerService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,209 +1,233 @@
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
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.graphics.Color
|
||||
import android.location.LocationManager
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.location.LocationManagerCompat
|
||||
|
||||
class BLEConnectionService : Service() {
|
||||
val CHANNEL_DEFAULT_IMPORTANCE = "1"
|
||||
val ONGOING_NOTIFICATION_ID = 2
|
||||
var bleController: BLEController? = null
|
||||
var deviceAddress: String? = null
|
||||
var nlService = NLService()
|
||||
private val myThread = Thread {
|
||||
while (true){
|
||||
Log.d("Runnable", "Working")
|
||||
if(bleController == null) {
|
||||
|
||||
val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
if (!LocationManagerCompat.isLocationEnabled(lm)) {
|
||||
// Start Location Settings Activity, you should explain to the user why he need to enable location before.
|
||||
startActivity(Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS))
|
||||
}
|
||||
Log.d("Debug", "bleController null")
|
||||
// bleController = BLEController.getInstance(applicationContext)
|
||||
bleController = BLEController(applicationContext)
|
||||
|
||||
} else if(!bleController!!.isConnected()){
|
||||
// not connected
|
||||
Log.d("Debug", "bleController not null but not connected")
|
||||
bleController!!.init()
|
||||
Log.d("Debug", "tried to init ble controller")
|
||||
} else{
|
||||
// controller is connected
|
||||
Log.d("Debug", "BLE device connected")
|
||||
bleController!!.stopScanner()
|
||||
|
||||
|
||||
}
|
||||
Thread.sleep(12000)
|
||||
}
|
||||
}
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
|
||||
if(intent?.action.equals("STARTService")){
|
||||
Log.d("DEBUG", "Startflag set")
|
||||
myThread.start()
|
||||
|
||||
// setup ble connection
|
||||
val channel_id =
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
|
||||
createNotificationChannel("my_service", "My Background Service")
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
val serviceIntent: PendingIntent = Intent(this, BLEConnectionService::class.java).let { notificationIntent ->
|
||||
PendingIntent.getActivity(this, 0, notificationIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE)
|
||||
}
|
||||
val myIntent = Intent(this, MainActivity::class.java).apply {
|
||||
var flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
|
||||
val contentIntent: PendingIntent = PendingIntent.getActivity(this, 0, myIntent, PendingIntent.FLAG_IMMUTABLE)
|
||||
val notification: Notification = Notification.Builder(this, channel_id)
|
||||
.setContentTitle("Oil-Check")
|
||||
.setContentText("running")
|
||||
.setSmallIcon(R.drawable.icon)
|
||||
.setContentIntent(serviceIntent)
|
||||
// .setTicker(getText(R.string.ticker_text))
|
||||
.build()
|
||||
|
||||
startForeground(101, notification)
|
||||
|
||||
// startService(Intent(this, NLService::class.java)
|
||||
// .setAction("StartNLService")
|
||||
// )
|
||||
|
||||
|
||||
val nlServiceIntent: PendingIntent = Intent(this, NLService::class.java).let { notificationIntent ->
|
||||
PendingIntent.getActivity(this, 0, notificationIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE)
|
||||
}
|
||||
|
||||
val nlNotification: Notification = Notification.Builder(this, channel_id)
|
||||
.setContentTitle("Oil-Check")
|
||||
.setContentText("running")
|
||||
.setSmallIcon(R.drawable.icon)
|
||||
.setContentIntent(nlServiceIntent)
|
||||
// .setTicker(getText(R.string.ticker_text))
|
||||
.build()
|
||||
startForeground(101, nlNotification)
|
||||
|
||||
|
||||
|
||||
|
||||
// setup notification listener
|
||||
// val nlServiceIntent: PendingIntent = Intent(this, NLService::class.java).let { notificationIntent ->
|
||||
// PendingIntent.getActivity(this, 0, notificationIntent,
|
||||
// PendingIntent.FLAG_IMMUTABLE)
|
||||
// }
|
||||
//
|
||||
// val nlNotification: Notification = Notification.Builder(this, channel_id)
|
||||
// .setContentTitle("Oil-Check")
|
||||
// .setContentText("running")
|
||||
// .setSmallIcon(R.drawable.icon)
|
||||
// .setContentIntent(nlServiceIntent)
|
||||
//// .setTicker(getText(R.string.ticker_text))
|
||||
// .build()
|
||||
// startForeground(101, nlNotification)
|
||||
|
||||
|
||||
} else if (intent?.action.equals("STOPService")){
|
||||
Log.d("DEBUG", "Stopflag set")
|
||||
stopForeground(true)
|
||||
stopSelfResult(101)
|
||||
stopSelf()
|
||||
|
||||
} else if (intent?.action.equals("StartNLService")) {
|
||||
//
|
||||
}
|
||||
else if(intent?.action.equals("Toggle")){
|
||||
try {
|
||||
bleController!!.sendData("X".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "tried to toggle, but failed")
|
||||
}
|
||||
} else if(intent?.action.equals("X")){
|
||||
try {
|
||||
bleController!!.sendData("X".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send X, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("XX")){
|
||||
try {
|
||||
bleController!!.sendData("XX".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send XX, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("XXX")){
|
||||
try {
|
||||
bleController!!.sendData("XXX".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send XXX, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("XXXX")){
|
||||
try {
|
||||
bleController!!.sendData("XXXX".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send XXXX, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("OTA")) {
|
||||
try {
|
||||
bleController!!.sendData("U".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to update firmware, but connection failed")
|
||||
}
|
||||
}
|
||||
else{
|
||||
Log.d("Debug", "Intent without arguments occured in service")
|
||||
}
|
||||
|
||||
|
||||
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.BLUE
|
||||
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
|
||||
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
service.createNotificationChannel(chan)
|
||||
return channelId
|
||||
}
|
||||
override fun onBind(p0: Intent?): IBinder? {
|
||||
// TODO("Not yet implemented")
|
||||
return null;
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
this.myThread.interrupt()
|
||||
|
||||
}
|
||||
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
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.graphics.Color
|
||||
import android.location.LocationManager
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.annotation.RequiresApi
|
||||
import androidx.core.location.LocationManagerCompat
|
||||
|
||||
class BLEConnectionService : Service() {
|
||||
val CHANNEL_DEFAULT_IMPORTANCE = "1"
|
||||
val ONGOING_NOTIFICATION_ID = 2
|
||||
var bleController: BLEController? = null
|
||||
var deviceAddress: String? = null
|
||||
var nlService = NLService()
|
||||
private val myThread = Thread {
|
||||
while (true){
|
||||
Log.d("Runnable", "Working")
|
||||
if(bleController == null) {
|
||||
|
||||
val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
||||
if (!LocationManagerCompat.isLocationEnabled(lm)) {
|
||||
// Start Location Settings Activity, you should explain to the user why he need to enable location before.
|
||||
startActivity(Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS))
|
||||
}
|
||||
Log.d("Debug", "bleController null")
|
||||
bleController = BLEController(applicationContext)
|
||||
if(!bleController!!.isConnected()){
|
||||
bleController!!.init()
|
||||
}
|
||||
|
||||
} else if(!bleController!!.isConnected()){
|
||||
// not connected
|
||||
Log.d("Debug", "bleController not null but not connected")
|
||||
bleController!!.init()
|
||||
Log.d("Debug", "tried to init ble controller")
|
||||
} else{
|
||||
// controller is connected
|
||||
Log.d("Debug", "BLE device connected")
|
||||
bleController!!.stopScanner()
|
||||
|
||||
|
||||
}
|
||||
Thread.sleep(12000)
|
||||
}
|
||||
}
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Log.d("DEBUG", "onStartCommand of BLE Connection Service")
|
||||
|
||||
if(intent?.action.equals("STARTService")){
|
||||
Log.d("DEBUG", "Startflag set")
|
||||
try {
|
||||
myThread.start()
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("DEBUG", "tried to start Thread, but failed :(")
|
||||
}
|
||||
|
||||
// setup ble connection
|
||||
val channel_id =
|
||||
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
|
||||
createNotificationChannel("my_service", "My Background Service")
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
||||
val serviceIntent: PendingIntent = Intent(this, BLEConnectionService::class.java).let { notificationIntent ->
|
||||
PendingIntent.getActivity(this, 0, notificationIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE)
|
||||
}
|
||||
val myIntent = Intent(this, MainActivity::class.java).apply {
|
||||
var flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
}
|
||||
|
||||
val activityIntent = Intent(this, MainActivity::class.java)
|
||||
|
||||
// val contentIntent: PendingIntent = PendingIntent.getActivity(this, 0, myIntent, PendingIntent.FLAG_IMMUTABLE)
|
||||
|
||||
val contentIntent = PendingIntent.getActivity(this, 0, activityIntent, PendingIntent.FLAG_MUTABLE);
|
||||
// create stop button
|
||||
|
||||
|
||||
// val intent = Intent(this, BLEConnectionService::class.java)
|
||||
// .setAction("STOPService")
|
||||
// val stopIntent = PendingIntent.getBroadcast(this, 0, intent, 0)
|
||||
|
||||
|
||||
|
||||
val notification: Notification = Notification.Builder(this, channel_id)
|
||||
.setContentTitle("Oil-Check")
|
||||
.setContentText("running")
|
||||
.setSmallIcon(R.drawable.icon)
|
||||
.setContentIntent(serviceIntent)
|
||||
// .setContentIntent(contentIntent)
|
||||
// .setTicker(getText(R.string.ticker_text))
|
||||
// .addAction(R.drawable.icon, "Stop", contentIntent)
|
||||
.build()
|
||||
|
||||
startForeground(101, notification)
|
||||
|
||||
// startService(Intent(this, NLService::class.java)
|
||||
// .setAction("StartNLService")
|
||||
// )
|
||||
|
||||
|
||||
val nlServiceIntent: PendingIntent = Intent(this, NLService::class.java).let { notificationIntent ->
|
||||
PendingIntent.getActivity(this, 0, notificationIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE)
|
||||
}
|
||||
|
||||
val nlNotification: Notification = Notification.Builder(this, channel_id)
|
||||
.setContentTitle("Oil-Check")
|
||||
.setContentText("running")
|
||||
.setSmallIcon(R.drawable.icon)
|
||||
.setContentIntent(nlServiceIntent)
|
||||
// .addAction(R.drawable.icon, "Stop", contentIntent)
|
||||
// .setTicker(getText(R.string.ticker_text))
|
||||
.build()
|
||||
startForeground(101, nlNotification)
|
||||
|
||||
|
||||
|
||||
|
||||
// setup notification listener
|
||||
// val nlServiceIntent: PendingIntent = Intent(this, NLService::class.java).let { notificationIntent ->
|
||||
// PendingIntent.getActivity(this, 0, notificationIntent,
|
||||
// PendingIntent.FLAG_IMMUTABLE)
|
||||
// }
|
||||
//
|
||||
// val nlNotification: Notification = Notification.Builder(this, channel_id)
|
||||
// .setContentTitle("Oil-Check")
|
||||
// .setContentText("running")
|
||||
// .setSmallIcon(R.drawable.icon)
|
||||
// .setContentIntent(nlServiceIntent)
|
||||
//// .setTicker(getText(R.string.ticker_text))
|
||||
// .build()
|
||||
// startForeground(101, nlNotification)
|
||||
|
||||
|
||||
} else if (intent?.action.equals("STOPService")){
|
||||
Log.d("DEBUG", "Stopflag set")
|
||||
stopForeground(true)
|
||||
stopSelfResult(101)
|
||||
stopSelf()
|
||||
|
||||
} else if (intent?.action.equals("StartNLService")) {
|
||||
//
|
||||
}
|
||||
else if(intent?.action.equals("Toggle")){
|
||||
try {
|
||||
bleController!!.sendData("XX".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "tried to toggle, but failed")
|
||||
}
|
||||
} else if(intent?.action.equals("X")){
|
||||
try {
|
||||
bleController!!.sendData("X".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send X, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("XX")){
|
||||
try {
|
||||
bleController!!.sendData("XX".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send XX, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("XXX")){
|
||||
try {
|
||||
bleController!!.sendData("XXX".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send XXX, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("XXXX")){
|
||||
try {
|
||||
bleController!!.sendData("XXXX".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to send XXXX, but connection failed")
|
||||
}
|
||||
} else if(intent?.action.equals("OTA")) {
|
||||
try {
|
||||
bleController!!.sendData("U".toByteArray(Charsets.UTF_8))
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Tried to update firmware, but connection failed")
|
||||
}
|
||||
}
|
||||
else{
|
||||
Log.d("Debug", "Intent without arguments occured in service")
|
||||
}
|
||||
|
||||
|
||||
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.BLUE
|
||||
chan.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
|
||||
val service = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||
service.createNotificationChannel(chan)
|
||||
return channelId
|
||||
}
|
||||
override fun onBind(p0: Intent?): IBinder? {
|
||||
// TODO("Not yet implemented")
|
||||
return null;
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
this.myThread.interrupt()
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,338 +1,380 @@
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
import android.Manifest
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCallback
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.bluetooth.le.BluetoothLeScanner
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.app.ActivityCompat
|
||||
import java.util.Locale
|
||||
|
||||
class BLEController(ctx: Context) : BLEControllerListener{
|
||||
companion object{
|
||||
var instance: BLEController? = null
|
||||
fun getInstance(ctx: Context?): BLEController? {
|
||||
Log.d("BLEController", "called")
|
||||
if (null == instance){
|
||||
instance = BLEController(ctx!!)
|
||||
}
|
||||
return instance
|
||||
}
|
||||
}
|
||||
private val SCAN_PERIOD: Long = 10000
|
||||
|
||||
private var deviceAddress: String? = null
|
||||
|
||||
var ctx: Context
|
||||
private var devices = hashMapOf<String, BluetoothDevice>()
|
||||
private var scanner: BluetoothLeScanner? = null
|
||||
var bluetoothManager: BluetoothManager? = null
|
||||
private var btGattChar: BluetoothGattCharacteristic? = null
|
||||
private lateinit var bluetoothGatt: BluetoothGatt
|
||||
private var device: BluetoothDevice? = null
|
||||
private val listeners: ArrayList<BLEControllerListener> = ArrayList<BLEControllerListener>()
|
||||
private var connectionState = false
|
||||
|
||||
fun stopScanner(){
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
try {
|
||||
scanner!!.stopScan(bleCallback)
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Scanner seems to run, stopping")
|
||||
}
|
||||
}
|
||||
|
||||
// constructor
|
||||
init {
|
||||
Log.d("Debug", "constructor called")
|
||||
this.bluetoothManager = ctx.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
this.ctx = ctx
|
||||
}
|
||||
|
||||
fun init(){
|
||||
Log.d("Debug", "init")
|
||||
this.devices?.clear()
|
||||
Log.d("Debug", "get scanner")
|
||||
this.scanner = this.bluetoothManager?.adapter?.bluetoothLeScanner
|
||||
Log.d("Debug", "got scanner")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
||||
// requestBluetooth.launch(enableBtIntent)
|
||||
Log.d("Debug", "permission needed")
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
} else{
|
||||
Log.d("Debug", "permission granted")
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("Debug", "try to scan")
|
||||
|
||||
this.scanner?.startScan(bleCallback)
|
||||
|
||||
}
|
||||
var bleCallback = object: ScanCallback(){
|
||||
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult?) {
|
||||
// Log.d("Debug", "onScanResult called")
|
||||
val device = result?.device
|
||||
// Log.d("Debug", "device result exists")
|
||||
if (!devices?.containsKey(device?.address)!! && isThisTheDevice(device)) {
|
||||
Log.d("Debug", "found the device")
|
||||
deviceFound(device!!)
|
||||
Log.d("Debug", device.address)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBatchScanResults(results: List<ScanResult?>?) {
|
||||
Log.d("Debug", "onBatchScanResults called")
|
||||
for (sr in results!!) {
|
||||
val device = sr?.device
|
||||
if (!devices!!.containsKey(device!!.address) && isThisTheDevice(device)) {
|
||||
deviceFound(device!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScanFailed(errorCode: Int) {
|
||||
Log.i("[BLE]", "scan failed with errorcode: $errorCode")
|
||||
}
|
||||
}
|
||||
private fun isThisTheDevice(device: BluetoothDevice?): Boolean {
|
||||
try {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return false
|
||||
}
|
||||
Log.d("BLE", device!!.name)
|
||||
} catch (e: Exception) {
|
||||
Log.d("BLE", "Device with null-Name found")
|
||||
}
|
||||
return null != device!!.name && device.name.startsWith("OilCheck")
|
||||
}
|
||||
private fun deviceFound(device: BluetoothDevice) {
|
||||
Log.d("Debug", "deviceFound called")
|
||||
// connectToDevice(device.address)
|
||||
devices.put(device.address, device)
|
||||
fireDeviceFound(device)
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
scanner!!.stopScan(bleCallback)
|
||||
}
|
||||
private fun fireDeviceFound(device: BluetoothDevice) {
|
||||
// for (l in listeners) {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
Log.d("Debug", "BLEDeviceFound called")
|
||||
BLEDeviceFound(device.name.trim { it <= ' ' }, device.address)
|
||||
// }
|
||||
}
|
||||
fun connectToDevice(address: String?) {
|
||||
Log.d("Debug", "connectToDevice")
|
||||
this.device = devices[address!!]
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
scanner!!.stopScan(bleCallback)
|
||||
try {
|
||||
Log.i("[BLE]", "connect to device " + device!!.getAddress())
|
||||
} catch (e: java.lang.Exception) {
|
||||
Log.d("Debug", "Connection to device failed :(")
|
||||
}
|
||||
this.bluetoothGatt = device!!.connectGatt(null, true, this.bleConnectCallback)
|
||||
}
|
||||
|
||||
private val bleConnectCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
|
||||
val CHANNEL_ID = "ForegroundServiceChannel"
|
||||
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
connectionState = true
|
||||
Log.d("Debug", "connection state changed to connected")
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
Log.i("[BLE]", "start service discovery " + bluetoothGatt.discoverServices())
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
connectionState = false
|
||||
|
||||
Log.d("Debug", "connection state changed to not connected")
|
||||
btGattChar = null
|
||||
Log.w("[BLE]", "DISCONNECTED with status $status")
|
||||
fireDisconnected()
|
||||
} else {
|
||||
Log.i("[BLE]", "unknown state $newState and status $status")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
|
||||
if (null == btGattChar) {
|
||||
for (service in gatt.services) {
|
||||
if (service.uuid.toString().uppercase(Locale.getDefault())
|
||||
.startsWith("00001811")
|
||||
) {
|
||||
val gattCharacteristics = service.characteristics
|
||||
for (bgc in gattCharacteristics) {
|
||||
if (bgc.uuid.toString().uppercase(Locale.getDefault())
|
||||
.startsWith("00002A46")
|
||||
) {
|
||||
val chprop = bgc.properties
|
||||
if (chprop and BluetoothGattCharacteristic.PROPERTY_WRITE or (chprop and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
|
||||
btGattChar = bgc
|
||||
Log.i("[BLE]", "CONNECTED and ready to send")
|
||||
fireConnected()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun fireDisconnected() {
|
||||
for (l in listeners){
|
||||
l.BLEControllerDisconnected()
|
||||
}
|
||||
device = null
|
||||
}
|
||||
fun isConnected():Boolean {
|
||||
if(!connectionState){
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
fun sendData(data: ByteArray?) {
|
||||
btGattChar!!.value = data
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
bluetoothGatt.writeCharacteristic(btGattChar)
|
||||
}
|
||||
private fun fireConnected() {
|
||||
for (l in listeners) {
|
||||
l.BLEControllerConnected()
|
||||
}
|
||||
}
|
||||
|
||||
override fun BLEControllerConnected() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun BLEControllerDisconnected() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun BLEDeviceFound(name: String?, address: String?) {
|
||||
// log("Device $name found with address $address")
|
||||
deviceAddress = address
|
||||
Log.d("Debug", "connectToDevice called")
|
||||
// btnConnect.setEnabled(true)
|
||||
connectToDevice(deviceAddress)
|
||||
}
|
||||
|
||||
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.bluetooth.BluetoothAdapter.LeScanCallback
|
||||
import android.bluetooth.BluetoothDevice
|
||||
import android.bluetooth.BluetoothGatt
|
||||
import android.bluetooth.BluetoothGattCallback
|
||||
import android.bluetooth.BluetoothGattCharacteristic
|
||||
import android.bluetooth.BluetoothManager
|
||||
import android.bluetooth.BluetoothProfile
|
||||
import android.bluetooth.le.BluetoothLeScanner
|
||||
import android.bluetooth.le.ScanCallback
|
||||
import android.bluetooth.le.ScanFilter
|
||||
import android.bluetooth.le.ScanResult
|
||||
import android.bluetooth.le.ScanSettings
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.Log
|
||||
import androidx.core.app.ActivityCompat
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
class BLEController(ctx: Context) : BLEControllerListener{
|
||||
companion object{
|
||||
var instance: BLEController? = null
|
||||
fun getInstance(ctx: Context?): BLEController? {
|
||||
Log.d("BLEController", "called")
|
||||
if (null == instance){
|
||||
instance = BLEController(ctx!!)
|
||||
}
|
||||
return instance
|
||||
}
|
||||
}
|
||||
private val SCAN_PERIOD: Long = 10000
|
||||
|
||||
private var deviceAddress: String? = null
|
||||
|
||||
var ctx: Context
|
||||
private var devices = hashMapOf<String, BluetoothDevice>()
|
||||
private var scanner: BluetoothLeScanner? = null
|
||||
var bluetoothManager: BluetoothManager? = null
|
||||
private var btGattChar: BluetoothGattCharacteristic? = null
|
||||
private lateinit var bluetoothGatt: BluetoothGatt
|
||||
private var device: BluetoothDevice? = null
|
||||
private val listeners: ArrayList<BLEControllerListener> = ArrayList<BLEControllerListener>()
|
||||
private var connectionState = false
|
||||
private var scanning = false
|
||||
|
||||
|
||||
fun stopScanner(){
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
try {
|
||||
scanner!!.stopScan(bleCallback)
|
||||
}
|
||||
catch (e: Exception){
|
||||
Log.d("Debug", "Scanner seems to run, stopping")
|
||||
}
|
||||
}
|
||||
|
||||
// constructor
|
||||
init {
|
||||
Log.d("Debug", "constructor called")
|
||||
this.bluetoothManager = ctx.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||
this.ctx = ctx
|
||||
}
|
||||
|
||||
fun init(){
|
||||
Log.d("Debug", "init")
|
||||
this.devices?.clear()
|
||||
Log.d("Debug", "get scanner")
|
||||
this.scanner = this.bluetoothManager?.adapter?.bluetoothLeScanner
|
||||
Log.d("Debug", "got scanner")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
||||
// requestBluetooth.launch(enableBtIntent)
|
||||
Log.d("Debug", "permission needed")
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
} else{
|
||||
Log.d("Debug", "permission granted")
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("Debug", "try to scan")
|
||||
|
||||
// this.scanner?.startScan(bleCallback)
|
||||
this.scanForDevice()
|
||||
}
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
fun scanForDevice(){
|
||||
Log.d("DEBUG", "SCAN for Device started")
|
||||
if(!scanning){
|
||||
Handler(Looper.getMainLooper()).postDelayed({
|
||||
scanning = false
|
||||
this.scanner?.stopScan(bleCallback)
|
||||
}, SCAN_PERIOD)
|
||||
Log.d("DEBUG", "nach Haendler")
|
||||
scanning = true
|
||||
|
||||
val bleScanSettings =
|
||||
ScanSettings.Builder().setCallbackType((ScanSettings.CALLBACK_TYPE_FIRST_MATCH or ScanSettings.CALLBACK_TYPE_MATCH_LOST)).build()
|
||||
|
||||
val filter = ScanFilter.Builder().setDeviceName("OilCheck").build()
|
||||
//
|
||||
|
||||
val devFilter: MutableList<ScanFilter> = ArrayList()
|
||||
devFilter.add(filter)
|
||||
|
||||
this.scanner?.startScan(devFilter, bleScanSettings, bleCallback)
|
||||
}
|
||||
else{
|
||||
scanning = false
|
||||
this.scanner?.stopScan(bleCallback)
|
||||
}
|
||||
}
|
||||
|
||||
var bleCallback = object: ScanCallback(){
|
||||
|
||||
override fun onScanResult(callbackType: Int, result: ScanResult?) {
|
||||
Log.d("Debug", "onScanResult called")
|
||||
// val device = result?.device
|
||||
val device = result?.getDevice()
|
||||
// Log.d("Debug", "device result exists")
|
||||
if (!devices?.containsKey(device?.address)!! && isThisTheDevice(device)) {
|
||||
Log.d("Debug", "found the device")
|
||||
deviceFound(device!!)
|
||||
Log.d("Debug", device.address)
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBatchScanResults(results: List<ScanResult?>?) {
|
||||
Log.d("Debug", "onBatchScanResults called")
|
||||
for (sr in results!!) {
|
||||
val device = sr?.device
|
||||
if (!devices!!.containsKey(device!!.address) && isThisTheDevice(device)) {
|
||||
deviceFound(device!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onScanFailed(errorCode: Int) {
|
||||
Log.i("[BLE]", "scan failed with errorcode: $errorCode")
|
||||
}
|
||||
}
|
||||
private fun isThisTheDevice(device: BluetoothDevice?): Boolean {
|
||||
try {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return false
|
||||
}
|
||||
Log.d("BLE", device!!.name)
|
||||
} catch (e: Exception) {
|
||||
Log.d("BLE", "Device with null-Name found")
|
||||
}
|
||||
// return null != device!!.name && device.name.startsWith("OilCheck")
|
||||
// "94:B9:7E:C0:53:FE") debugger
|
||||
// "30:83:98:00:89:86" KTM
|
||||
return null != (device!!.address.startsWith("94:B9:7E:C0:53:FE")
|
||||
or device!!.address.startsWith("30:83:98:00:89:86"))
|
||||
|
||||
}
|
||||
private fun deviceFound(device: BluetoothDevice) {
|
||||
Log.d("Debug", "deviceFound called")
|
||||
// connectToDevice(device.address)
|
||||
devices.put(device.address, device)
|
||||
fireDeviceFound(device)
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
scanner!!.stopScan(bleCallback)
|
||||
}
|
||||
private fun fireDeviceFound(device: BluetoothDevice) {
|
||||
// for (l in listeners) {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
Log.d("Debug", "BLEDeviceFound called")
|
||||
BLEDeviceFound("device.name.trim { it <= ' ' }", device.address)
|
||||
// }
|
||||
}
|
||||
fun connectToDevice(address: String?) {
|
||||
Log.d("Debug", "connectToDevice")
|
||||
this.device = devices[address!!]
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_SCAN
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
scanner!!.stopScan(bleCallback)
|
||||
try {
|
||||
Log.i("[BLE]", "connect to device " + device!!.getAddress())
|
||||
} catch (e: java.lang.Exception) {
|
||||
Log.d("Debug", "Connection to device failed :(")
|
||||
}
|
||||
this.bluetoothGatt = device!!.connectGatt(null, true, this.bleConnectCallback)
|
||||
}
|
||||
|
||||
private val bleConnectCallback: BluetoothGattCallback = object : BluetoothGattCallback() {
|
||||
val CHANNEL_ID = "ForegroundServiceChannel"
|
||||
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
connectionState = true
|
||||
Log.d("Debug", "connection state changed to connected")
|
||||
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
Log.i("[BLE]", "start service discovery " + bluetoothGatt.discoverServices())
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
connectionState = false
|
||||
|
||||
Log.d("Debug", "connection state changed to not connected")
|
||||
btGattChar = null
|
||||
Log.w("[BLE]", "DISCONNECTED with status $status")
|
||||
fireDisconnected()
|
||||
} else {
|
||||
Log.i("[BLE]", "unknown state $newState and status $status")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
|
||||
if (null == btGattChar) {
|
||||
for (service in gatt.services) {
|
||||
if (service.uuid.toString().uppercase(Locale.getDefault())
|
||||
.startsWith("00001811")
|
||||
) {
|
||||
val gattCharacteristics = service.characteristics
|
||||
for (bgc in gattCharacteristics) {
|
||||
if (bgc.uuid.toString().uppercase(Locale.getDefault())
|
||||
.startsWith("00002A46")
|
||||
) {
|
||||
val chprop = bgc.properties
|
||||
if (chprop and BluetoothGattCharacteristic.PROPERTY_WRITE or (chprop and BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
|
||||
btGattChar = bgc
|
||||
Log.i("[BLE]", "CONNECTED and ready to send")
|
||||
fireConnected()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun fireDisconnected() {
|
||||
for (l in listeners){
|
||||
l.BLEControllerDisconnected()
|
||||
}
|
||||
device = null
|
||||
}
|
||||
fun isConnected():Boolean {
|
||||
if(!connectionState){
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
fun sendData(data: ByteArray?) {
|
||||
btGattChar!!.value = data
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
ctx,
|
||||
Manifest.permission.BLUETOOTH_CONNECT
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
// here to request the missing permissions, and then overriding
|
||||
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
|
||||
// int[] grantResults)
|
||||
// to handle the case where the user grants the permission. See the documentation
|
||||
// for ActivityCompat#requestPermissions for more details.
|
||||
return
|
||||
}
|
||||
bluetoothGatt.writeCharacteristic(btGattChar)
|
||||
}
|
||||
private fun fireConnected() {
|
||||
for (l in listeners) {
|
||||
l.BLEControllerConnected()
|
||||
}
|
||||
}
|
||||
|
||||
override fun BLEControllerConnected() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun BLEControllerDisconnected() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun BLEDeviceFound(name: String?, address: String?) {
|
||||
deviceAddress = address
|
||||
Log.d("Debug", "connectToDevice called")
|
||||
// btnConnect.setEnabled(true)
|
||||
connectToDevice(deviceAddress)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
/*
|
||||
* (c) Matey Nenov (https://www.thinker-talk.com)
|
||||
*
|
||||
* Licensed under Creative Commons: By Attribution 3.0
|
||||
* http://creativecommons.org/licenses/by/3.0/
|
||||
*
|
||||
*/
|
||||
interface BLEControllerListener {
|
||||
fun BLEControllerConnected()
|
||||
fun BLEControllerDisconnected()
|
||||
fun BLEDeviceFound(name: String?, address: String?)
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
/*
|
||||
* (c) Matey Nenov (https://www.thinker-talk.com)
|
||||
*
|
||||
* Licensed under Creative Commons: By Attribution 3.0
|
||||
* http://creativecommons.org/licenses/by/3.0/
|
||||
*
|
||||
*/
|
||||
interface BLEControllerListener {
|
||||
fun BLEControllerConnected()
|
||||
fun BLEControllerDisconnected()
|
||||
fun BLEDeviceFound(name: String?, address: String?)
|
||||
}
|
||||
@@ -1,213 +1,213 @@
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
import android.app.Notification
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.service.notification.NotificationListenerService
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.util.Log
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class NLService : NotificationListenerService() {
|
||||
|
||||
// override fun onBind(intent: Intent?): IBinder? {
|
||||
// return super.onBind(intent)
|
||||
// }
|
||||
//
|
||||
// override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||
// // Implement what you want here
|
||||
// }
|
||||
//
|
||||
// override fun onNotificationRemoved(sbn: StatusBarNotification?) {
|
||||
// // Implement what you want here
|
||||
// }
|
||||
//
|
||||
// private final IBinder mBinder = new LocalBinder();
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return super.onBind(intent)
|
||||
}
|
||||
|
||||
//returns the instance of the service
|
||||
// public class LocalBinder extends Binder{
|
||||
// public NLService getServiceInstance(){
|
||||
// return NLService.this;
|
||||
// }
|
||||
// }
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
|
||||
Log.d("Debug: ", "BLE service onStartCommand called")
|
||||
// // String input = intent.getStringExtra("inputExtra");
|
||||
// val input = "Text"
|
||||
// createNotificationChannel()
|
||||
// val notificationIntent = Intent(this, MainActivity::class.java)
|
||||
// val pendingIntent = PendingIntent.getActivity(
|
||||
// this,
|
||||
// 0, notificationIntent, 0
|
||||
// )
|
||||
// val notification = NotificationCompat.Builder(this, CHANNEL_ID)
|
||||
// .setContentTitle("Oil Check")
|
||||
// .setContentText(input) //.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||
// .setSmallIcon(R.drawable.icon)
|
||||
// .setContentIntent(pendingIntent)
|
||||
// .build()
|
||||
// startForeground(1, notification)
|
||||
// // NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
|
||||
//// notificationManager.notify(3, notification);
|
||||
// try {
|
||||
// bleController = BLEController.getInstance(applicationContext)
|
||||
// Log.d("BLE", "bleController instance")
|
||||
// } catch (e: Exception) {
|
||||
// Log.d("BLE", "bleController not available")
|
||||
// }
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
// private fun createNotificationChannel() {
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// val serviceChannel = NotificationChannel(
|
||||
// CHANNEL_ID,
|
||||
// "Foreground Service Channel",
|
||||
// NotificationManager.IMPORTANCE_DEFAULT
|
||||
// )
|
||||
// val manager = getSystemService(
|
||||
// NotificationManager::class.java
|
||||
// )
|
||||
// manager.createNotificationChannel(serviceChannel)
|
||||
// }
|
||||
// }
|
||||
|
||||
override fun onNotificationPosted(sbn: StatusBarNotification) {
|
||||
Log.d("Debug", "NL Notification fired")
|
||||
// Implement what you want here
|
||||
if (sbn.packageName.contains("de.blitzer.plus")) {
|
||||
Log.d(sbn.packageName, "sbn.getTag()")
|
||||
Log.d("MyNotification", sbn.notification.toString())
|
||||
|
||||
// filter for digits
|
||||
try {
|
||||
val notification =
|
||||
sbn.notification.extras.getCharSequence(Notification.EXTRA_TEXT).toString()
|
||||
// check of unit in m or km
|
||||
val unitM = "(.*)[\\d][m][\\s](.*)"
|
||||
val unitKm = "(.*)[\\d][k][m][\\s](.*)"
|
||||
Log.d("Unit", unitM)
|
||||
if (notification.matches(unitM.toRegex())) {
|
||||
Log.d("Notification", "meter")
|
||||
Log.d("Notification", notification)
|
||||
// notification in meters
|
||||
// get digits
|
||||
val pattern = Pattern.compile("[\\d]+[m][\\s]")
|
||||
val matcher = pattern.matcher(notification)
|
||||
while (matcher.find()) {
|
||||
Log.d("Matcher", "Match found")
|
||||
val start = matcher.start()
|
||||
val end = matcher.end()
|
||||
// Log.d("Start", )
|
||||
// end -2 (one for blank and one for unit(m))
|
||||
val digits = notification.substring(start, end - 2)
|
||||
Log.d("Matcher", digits)
|
||||
val distance = digits.toInt()
|
||||
Log.d("Distanz", digits)
|
||||
try {
|
||||
if (distance > 500) {
|
||||
Log.d("Distanz", "groesser 500")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("X")
|
||||
startService(intent)
|
||||
// bleController!!.sendData(String("X").toByteArray())
|
||||
} else if (distance > 300) {
|
||||
Log.d("Distanz", "groesser 300")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("XX")
|
||||
startService(intent)
|
||||
} else if (distance > 150) {
|
||||
Log.d("Distanz", "groesser 150")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("XXX")
|
||||
startService(intent)
|
||||
} else {
|
||||
Log.d("Distanz", "kleiner 100")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("XXXX")
|
||||
startService(intent)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
//
|
||||
Log.d("DEBUG", "Send Data failed :(")
|
||||
}
|
||||
// end while loop after first match
|
||||
break
|
||||
}
|
||||
} else if (notification.matches(unitKm.toRegex())) {
|
||||
// notification in kilometers
|
||||
// no need to differ, to much distance
|
||||
// bleController!!.sendData(String("X").toByteArray())
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("X")
|
||||
startService(intent)
|
||||
}
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("nicht gefunden") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("ungenau")){
|
||||
// bleController.sendData(new String("XXXXX").getBytes());
|
||||
// }
|
||||
// else{
|
||||
// bleController.sendData(new String("XXX").getBytes());
|
||||
// }
|
||||
} // old version not working anymore because of update of Blitzer.de
|
||||
// try {
|
||||
// if (sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("1.0km") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("1000m")) {
|
||||
// bleController.sendData(new String("X").getBytes());
|
||||
// }
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("500m")){
|
||||
// bleController.sendData(new String("XX").getBytes());
|
||||
// }
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("300m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("200m")){
|
||||
// bleController.sendData(new String("XXX").getBytes());
|
||||
// }
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("100m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("90m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("80m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("70m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("50m")){
|
||||
// bleController.sendData(new String("XXXX").getBytes());
|
||||
// }
|
||||
//// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("nicht gefunden") ||
|
||||
//// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("ungenau")){
|
||||
//// bleController.sendData(new String("XXXXX").getBytes());
|
||||
//// }
|
||||
//// else{
|
||||
//// bleController.sendData(new String("XXX").getBytes());
|
||||
//// }
|
||||
// }
|
||||
catch (e: Exception) {
|
||||
Log.d("DEBUG", "Send notification failed :(")
|
||||
}
|
||||
// try {
|
||||
// bleController.sendData(new String("X").getBytes());
|
||||
// }
|
||||
// catch(Exception e){
|
||||
//
|
||||
// }
|
||||
}
|
||||
// Log.d(sbn.getPackageName(), "packagename");
|
||||
}
|
||||
|
||||
override fun onNotificationRemoved(sbn: StatusBarNotification) {
|
||||
// Implement what you want here
|
||||
this.stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
Log.d("BLE:", "Service onDestory called")
|
||||
this.stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
stopForeground(true)
|
||||
// stopSelf();
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "ForegroundServiceChannel"
|
||||
}
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
import android.app.Notification
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import android.service.notification.NotificationListenerService
|
||||
import android.service.notification.StatusBarNotification
|
||||
import android.util.Log
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class NLService : NotificationListenerService() {
|
||||
|
||||
// override fun onBind(intent: Intent?): IBinder? {
|
||||
// return super.onBind(intent)
|
||||
// }
|
||||
//
|
||||
// override fun onNotificationPosted(sbn: StatusBarNotification?) {
|
||||
// // Implement what you want here
|
||||
// }
|
||||
//
|
||||
// override fun onNotificationRemoved(sbn: StatusBarNotification?) {
|
||||
// // Implement what you want here
|
||||
// }
|
||||
//
|
||||
// private final IBinder mBinder = new LocalBinder();
|
||||
override fun onBind(intent: Intent): IBinder? {
|
||||
return super.onBind(intent)
|
||||
}
|
||||
|
||||
//returns the instance of the service
|
||||
// public class LocalBinder extends Binder{
|
||||
// public NLService getServiceInstance(){
|
||||
// return NLService.this;
|
||||
// }
|
||||
// }
|
||||
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
|
||||
|
||||
Log.d("Debug: ", "BLE service onStartCommand called")
|
||||
// // String input = intent.getStringExtra("inputExtra");
|
||||
// val input = "Text"
|
||||
// createNotificationChannel()
|
||||
// val notificationIntent = Intent(this, MainActivity::class.java)
|
||||
// val pendingIntent = PendingIntent.getActivity(
|
||||
// this,
|
||||
// 0, notificationIntent, 0
|
||||
// )
|
||||
// val notification = NotificationCompat.Builder(this, CHANNEL_ID)
|
||||
// .setContentTitle("Oil Check")
|
||||
// .setContentText(input) //.setSmallIcon(R.drawable.ic_launcher_foreground)
|
||||
// .setSmallIcon(R.drawable.icon)
|
||||
// .setContentIntent(pendingIntent)
|
||||
// .build()
|
||||
// startForeground(1, notification)
|
||||
// // NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
|
||||
//// notificationManager.notify(3, notification);
|
||||
// try {
|
||||
// bleController = BLEController.getInstance(applicationContext)
|
||||
// Log.d("BLE", "bleController instance")
|
||||
// } catch (e: Exception) {
|
||||
// Log.d("BLE", "bleController not available")
|
||||
// }
|
||||
return START_NOT_STICKY
|
||||
}
|
||||
|
||||
// private fun createNotificationChannel() {
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// val serviceChannel = NotificationChannel(
|
||||
// CHANNEL_ID,
|
||||
// "Foreground Service Channel",
|
||||
// NotificationManager.IMPORTANCE_DEFAULT
|
||||
// )
|
||||
// val manager = getSystemService(
|
||||
// NotificationManager::class.java
|
||||
// )
|
||||
// manager.createNotificationChannel(serviceChannel)
|
||||
// }
|
||||
// }
|
||||
|
||||
override fun onNotificationPosted(sbn: StatusBarNotification) {
|
||||
Log.d("Debug", "NL Notification fired")
|
||||
// Implement what you want here
|
||||
if (sbn.packageName.contains("de.blitzer.plus")) {
|
||||
Log.d(sbn.packageName, "sbn.getTag()")
|
||||
Log.d("MyNotification", sbn.notification.toString())
|
||||
|
||||
// filter for digits
|
||||
try {
|
||||
val notification =
|
||||
sbn.notification.extras.getCharSequence(Notification.EXTRA_TEXT).toString()
|
||||
// check of unit in m or km
|
||||
val unitM = "(.*)[\\d][m][\\s](.*)"
|
||||
val unitKm = "(.*)[\\d][k][m][\\s](.*)"
|
||||
Log.d("Unit", unitM)
|
||||
if (notification.matches(unitM.toRegex())) {
|
||||
Log.d("Notification", "meter")
|
||||
Log.d("Notification", notification)
|
||||
// notification in meters
|
||||
// get digits
|
||||
val pattern = Pattern.compile("[\\d]+[m][\\s]")
|
||||
val matcher = pattern.matcher(notification)
|
||||
while (matcher.find()) {
|
||||
Log.d("Matcher", "Match found")
|
||||
val start = matcher.start()
|
||||
val end = matcher.end()
|
||||
// Log.d("Start", )
|
||||
// end -2 (one for blank and one for unit(m))
|
||||
val digits = notification.substring(start, end - 2)
|
||||
Log.d("Matcher", digits)
|
||||
val distance = digits.toInt()
|
||||
Log.d("Distanz", digits)
|
||||
try {
|
||||
if (distance > 500) {
|
||||
Log.d("Distanz", "groesser 500")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("X")
|
||||
startService(intent)
|
||||
// bleController!!.sendData(String("X").toByteArray())
|
||||
} else if (distance > 300) {
|
||||
Log.d("Distanz", "groesser 300")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("XX")
|
||||
startService(intent)
|
||||
} else if (distance > 150) {
|
||||
Log.d("Distanz", "groesser 150")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("XXX")
|
||||
startService(intent)
|
||||
} else {
|
||||
Log.d("Distanz", "kleiner 100")
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("XXXX")
|
||||
startService(intent)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
//
|
||||
Log.d("DEBUG", "Send Data failed :(")
|
||||
}
|
||||
// end while loop after first match
|
||||
break
|
||||
}
|
||||
} else if (notification.matches(unitKm.toRegex())) {
|
||||
// notification in kilometers
|
||||
// no need to differ, to much distance
|
||||
// bleController!!.sendData(String("X").toByteArray())
|
||||
val intent = Intent(this, BLEConnectionService::class.java)
|
||||
.setAction("X")
|
||||
startService(intent)
|
||||
}
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("nicht gefunden") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("ungenau")){
|
||||
// bleController.sendData(new String("XXXXX").getBytes());
|
||||
// }
|
||||
// else{
|
||||
// bleController.sendData(new String("XXX").getBytes());
|
||||
// }
|
||||
} // old version not working anymore because of update of Blitzer.de
|
||||
// try {
|
||||
// if (sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("1.0km") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("1000m")) {
|
||||
// bleController.sendData(new String("X").getBytes());
|
||||
// }
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("500m")){
|
||||
// bleController.sendData(new String("XX").getBytes());
|
||||
// }
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("300m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("200m")){
|
||||
// bleController.sendData(new String("XXX").getBytes());
|
||||
// }
|
||||
// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("100m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("90m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("80m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("70m") ||
|
||||
// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("50m")){
|
||||
// bleController.sendData(new String("XXXX").getBytes());
|
||||
// }
|
||||
//// else if(sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("nicht gefunden") ||
|
||||
//// sbn.getNotification().extras.getCharSequence(Notification.EXTRA_TEXT).toString().contains("ungenau")){
|
||||
//// bleController.sendData(new String("XXXXX").getBytes());
|
||||
//// }
|
||||
//// else{
|
||||
//// bleController.sendData(new String("XXX").getBytes());
|
||||
//// }
|
||||
// }
|
||||
catch (e: Exception) {
|
||||
Log.d("DEBUG", "Send notification failed :(")
|
||||
}
|
||||
// try {
|
||||
// bleController.sendData(new String("X").getBytes());
|
||||
// }
|
||||
// catch(Exception e){
|
||||
//
|
||||
// }
|
||||
}
|
||||
// Log.d(sbn.getPackageName(), "packagename");
|
||||
}
|
||||
|
||||
override fun onNotificationRemoved(sbn: StatusBarNotification) {
|
||||
// Implement what you want here
|
||||
this.stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
Log.d("BLE:", "Service onDestory called")
|
||||
this.stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
stopForeground(true)
|
||||
// stopSelf();
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val CHANNEL_ID = "ForegroundServiceChannel"
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,32 @@
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
import android.R
|
||||
import android.app.Notification
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.app.NotificationCompat
|
||||
|
||||
|
||||
class NotificationCreator {
|
||||
private val NOTIFICATION_ID = 1094
|
||||
private val CHANNEL_ID = "Foreground Service Channel"
|
||||
private var notification: Notification? = null
|
||||
|
||||
fun getNotification(context: Context?, intent: PendingIntent): Notification? {
|
||||
if (notification == null) {
|
||||
|
||||
notification = NotificationCompat.Builder(context!!, CHANNEL_ID)
|
||||
.setContentTitle("Oil-Check")
|
||||
.setContentText("running")
|
||||
.setSmallIcon(com.example.oilcheckkotlin.R.drawable.icon)
|
||||
.setContentIntent(intent)
|
||||
.build()
|
||||
}
|
||||
return notification
|
||||
}
|
||||
|
||||
fun getNotificationId(): Int {
|
||||
return NOTIFICATION_ID
|
||||
}
|
||||
package com.example.oilcheckkotlin
|
||||
|
||||
import android.R
|
||||
import android.app.Notification
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.app.NotificationCompat
|
||||
|
||||
|
||||
class NotificationCreator {
|
||||
private val NOTIFICATION_ID = 1094
|
||||
private val CHANNEL_ID = "Foreground Service Channel"
|
||||
private var notification: Notification? = null
|
||||
|
||||
fun getNotification(context: Context?, intent: PendingIntent): Notification? {
|
||||
if (notification == null) {
|
||||
|
||||
notification = NotificationCompat.Builder(context!!, CHANNEL_ID)
|
||||
.setContentTitle("Oil-Check")
|
||||
.setContentText("running")
|
||||
.setSmallIcon(com.example.oilcheckkotlin.R.drawable.icon)
|
||||
.setContentIntent(intent)
|
||||
.build()
|
||||
}
|
||||
return notification
|
||||
}
|
||||
|
||||
fun getNotificationId(): Int {
|
||||
return NOTIFICATION_ID
|
||||
}
|
||||
}
|
||||
@@ -6,15 +6,6 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<TextView
|
||||
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" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="400dp"
|
||||
android:layout_height="257dp"
|
||||
|
||||
12
gradle/wrapper/gradle-wrapper.properties
vendored
12
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
||||
#Thu Aug 31 20:53:30 CEST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
#Thu Aug 31 20:53:30 CEST 2023
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
178
gradlew.bat
vendored
178
gradlew.bat
vendored
@@ -1,89 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
||||
Reference in New Issue
Block a user