diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 14c9174..d53a2a5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,47 +1,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/example/oilcheckkotlin/BLEConnectionService.kt b/app/src/main/java/com/example/oilcheckkotlin/BLEConnectionService.kt index 9ced612..cd9369c 100644 --- a/app/src/main/java/com/example/oilcheckkotlin/BLEConnectionService.kt +++ b/app/src/main/java/com/example/oilcheckkotlin/BLEConnectionService.kt @@ -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() + + } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/oilcheckkotlin/BLEController.kt b/app/src/main/java/com/example/oilcheckkotlin/BLEController.kt index 1aa9d88..5fcfbed 100644 --- a/app/src/main/java/com/example/oilcheckkotlin/BLEController.kt +++ b/app/src/main/java/com/example/oilcheckkotlin/BLEController.kt @@ -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() - 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 = ArrayList() - 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?) { - 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() + 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 = ArrayList() + 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 = 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?) { + 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) + } + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/oilcheckkotlin/BLEControllerListener.kt b/app/src/main/java/com/example/oilcheckkotlin/BLEControllerListener.kt index 5f5d16a..54ab836 100644 --- a/app/src/main/java/com/example/oilcheckkotlin/BLEControllerListener.kt +++ b/app/src/main/java/com/example/oilcheckkotlin/BLEControllerListener.kt @@ -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?) } \ No newline at end of file diff --git a/app/src/main/java/com/example/oilcheckkotlin/NLService.kt b/app/src/main/java/com/example/oilcheckkotlin/NLService.kt index f820c9a..1f7b6c5 100644 --- a/app/src/main/java/com/example/oilcheckkotlin/NLService.kt +++ b/app/src/main/java/com/example/oilcheckkotlin/NLService.kt @@ -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" + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/oilcheckkotlin/NotificationCreator.kt b/app/src/main/java/com/example/oilcheckkotlin/NotificationCreator.kt index d74f718..3bed3a7 100644 --- a/app/src/main/java/com/example/oilcheckkotlin/NotificationCreator.kt +++ b/app/src/main/java/com/example/oilcheckkotlin/NotificationCreator.kt @@ -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 + } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 37af76e..d081d00 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,15 +6,6 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - - 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