From 19df05950cd6224a048bfc66a2d903435854aae8 Mon Sep 17 00:00:00 2001 From: Matt LaPaglia Date: Thu, 14 Dec 2023 19:33:06 -0500 Subject: [PATCH] more icons --- .../bluetooth/ConnectionEventListener.kt | 2 +- .../bluetooth/ConnectionManager.kt | 42 +++++++++++--- .../cameralink/MyCameraLinkService.kt | 53 ++++++++++++------ .../drawable-anydpi/ic_bluetooth_disabled.xml | 15 +++++ .../drawable-anydpi/ic_device_connecting.xml | 16 ++++++ .../drawable-hdpi/ic_bluetooth_disabled.png | Bin 0 -> 474 bytes .../drawable-hdpi/ic_device_connecting.png | Bin 0 -> 572 bytes .../drawable-mdpi/ic_bluetooth_disabled.png | Bin 0 -> 312 bytes .../drawable-mdpi/ic_device_connecting.png | Bin 0 -> 369 bytes .../drawable-xhdpi/ic_bluetooth_disabled.png | Bin 0 -> 691 bytes .../drawable-xhdpi/ic_device_connecting.png | Bin 0 -> 721 bytes .../drawable-xxhdpi/ic_bluetooth_disabled.png | Bin 0 -> 969 bytes .../drawable-xxhdpi/ic_device_connecting.png | Bin 0 -> 1145 bytes 13 files changed, 103 insertions(+), 25 deletions(-) create mode 100644 app/src/main/res/drawable-anydpi/ic_bluetooth_disabled.xml create mode 100644 app/src/main/res/drawable-anydpi/ic_device_connecting.xml create mode 100644 app/src/main/res/drawable-hdpi/ic_bluetooth_disabled.png create mode 100644 app/src/main/res/drawable-hdpi/ic_device_connecting.png create mode 100644 app/src/main/res/drawable-mdpi/ic_bluetooth_disabled.png create mode 100644 app/src/main/res/drawable-mdpi/ic_device_connecting.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_bluetooth_disabled.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_device_connecting.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_bluetooth_disabled.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_device_connecting.png diff --git a/app/src/main/java/com.alphasync/bluetooth/ConnectionEventListener.kt b/app/src/main/java/com.alphasync/bluetooth/ConnectionEventListener.kt index 80dc66d..e5712d7 100644 --- a/app/src/main/java/com.alphasync/bluetooth/ConnectionEventListener.kt +++ b/app/src/main/java/com.alphasync/bluetooth/ConnectionEventListener.kt @@ -8,5 +8,5 @@ class ConnectionEventListener { var onConnectionSetupComplete: ((BluetoothGatt) -> Unit)? = null var onDisconnect: (() -> Unit)? = null var onCharacteristicWrite: ((BluetoothDevice, BluetoothGattCharacteristic) -> Unit)? = null - + var onBluetoothStatusChange: ((Boolean) -> Unit)? = null } diff --git a/app/src/main/java/com.alphasync/bluetooth/ConnectionManager.kt b/app/src/main/java/com.alphasync/bluetooth/ConnectionManager.kt index 7938187..35b1d08 100644 --- a/app/src/main/java/com.alphasync/bluetooth/ConnectionManager.kt +++ b/app/src/main/java/com.alphasync/bluetooth/ConnectionManager.kt @@ -7,8 +7,13 @@ import android.bluetooth.BluetoothGattCallback import android.bluetooth.BluetoothGattCharacteristic import android.bluetooth.BluetoothManager import android.bluetooth.BluetoothProfile +import android.content.BroadcastReceiver import android.content.Context +import android.content.Intent +import android.content.IntentFilter import android.util.Log +import androidx.core.content.ContextCompat +import androidx.core.content.ContextCompat.RECEIVER_EXPORTED import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import java.lang.ref.WeakReference @@ -21,6 +26,7 @@ class ConnectionManager(context: Context) { context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager } private var btAdapter: BluetoothAdapter = btManager.adapter + private val btAdapterFilter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED) private var btGatt: BluetoothGatt? = null private var btGattIsConnecting: Boolean = false private lateinit var callerContext: Context @@ -58,6 +64,7 @@ class ConnectionManager(context: Context) { btAddress = address callerContext = context + ContextCompat.registerReceiver(context, bluetoothStateReceiver, btAdapterFilter, RECEIVER_EXPORTED) val btDevice = btAdapter.getRemoteDevice(address) if (btGattIsConnecting) { Log.d(logTag, "Device is currently connecting.") @@ -77,20 +84,25 @@ class ConnectionManager(context: Context) { listeners.forEach { it.get()?.onDisconnect?.invoke() } } - btGattIsConnecting = false - btGatt?.close() - btGatt = null + disconnect() connect(btAddress, callerContext) } + @SuppressLint("MissingPermission") + private fun disconnect() { + btGattIsConnecting = false + btGatt?.disconnect() + btGatt = null + } + @SuppressLint("MissingPermission") fun writeCharacteristic( - characteristic: BluetoothGattCharacteristic, - payload: ByteArray - ) { + characteristicId: UUID, + payload: ByteArray) + { if (isConnected) { - btGatt?.findCharacteristic(characteristic.uuid)?.let { characteristic -> + btGatt?.findCharacteristic(characteristicId)?.let { characteristic -> characteristic.value = payload val initialSuccess = btGatt?.writeCharacteristic(characteristic) if(initialSuccess!!) { @@ -117,6 +129,21 @@ class ConnectionManager(context: Context) { return null } + private val bluetoothStateReceiver = object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + if (intent?.action == BluetoothAdapter.ACTION_STATE_CHANGED) { + val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) + if(state == BluetoothAdapter.STATE_OFF) { + disconnect() + listeners.forEach { it.get()?.onBluetoothStatusChange?.invoke(false) } + } else if (state == BluetoothAdapter.STATE_ON) { + reconnect() + listeners.forEach { it.get()?.onBluetoothStatusChange?.invoke(true) } + } + } + } + } + private val callback = object : BluetoothGattCallback() { @SuppressLint("MissingPermission") override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) { @@ -142,6 +169,7 @@ class ConnectionManager(context: Context) { Log.d(logTag,"onConnectionStateChange: status $status encountered for $deviceAddress!") reconnect() } + } @SuppressLint("MissingPermission") diff --git a/app/src/main/java/com.alphasync/cameralink/MyCameraLinkService.kt b/app/src/main/java/com.alphasync/cameralink/MyCameraLinkService.kt index 4a14bbf..ae987a8 100644 --- a/app/src/main/java/com.alphasync/cameralink/MyCameraLinkService.kt +++ b/app/src/main/java/com.alphasync/cameralink/MyCameraLinkService.kt @@ -31,7 +31,7 @@ class MyCameraLinkService: Service() { private var cameraName: String = "" private lateinit var notificationManager: NotificationManagerCompat private val notificationChannel: String = "MyCameraLinkNotificationChannel" - private val notificationConnectDisconnectId: Int = 1 + private val notificationServiceStatusId: Int = 1 private val notificationGpsLostFoundId: Int = 2 fun isPairedToCamera(): Boolean { @@ -92,7 +92,7 @@ class MyCameraLinkService: Service() { .setContentText("Sending GPS to $cameraName") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() - notificationManager.notify(notificationConnectDisconnectId, notificationBuilder) + notificationManager.notify(notificationServiceStatusId, notificationBuilder) } onGpsSignalLost = { notificationManager.cancel(notificationGpsLostFoundId) @@ -102,12 +102,12 @@ class MyCameraLinkService: Service() { .setContentText("Sending GPS to $cameraName paused") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() - notificationManager.notify(notificationConnectDisconnectId, notificationBuilder) + notificationManager.notify(notificationServiceStatusId, notificationBuilder) } onLocationReady = { location -> val characteristic = connectionManager.characteristics.find { it.uuid.toString().contains("0000dd11")} Log.d(logTag, "Writing to ${characteristic!!.uuid}: ${location.toHexString()}") - connectionManager.writeCharacteristic(characteristic, location) + connectionManager.writeCharacteristic(characteristic.uuid, location) } } } @@ -115,38 +115,36 @@ class MyCameraLinkService: Service() { private val connectionEventListener by lazy { ConnectionEventListener().apply { onConnectionSetupComplete = { _ -> - notificationManager.cancel(notificationConnectDisconnectId) + notificationManager.cancel(notificationServiceStatusId) val notificationBuilder = NotificationCompat.Builder(applicationContext, notificationChannel) .setSmallIcon(R.drawable.ic_stat_name) .setContentTitle("$cameraName connected!") .setContentText("Sending GPS coordinates") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() - notificationManager.notify(notificationConnectDisconnectId, notificationBuilder) + notificationManager.notify(notificationServiceStatusId, notificationBuilder) sendEnableGpsCommands() } - onDisconnect = { sonyCommandGenerator.stopLocationReporting(myCameraLinkEventListener) - notificationManager.cancel(notificationConnectDisconnectId) + notificationManager.cancel(notificationServiceStatusId) val notificationBuilder = NotificationCompat.Builder(applicationContext, notificationChannel) .setSmallIcon(R.drawable.ic_camera_disconnected) .setContentTitle("$cameraName disconnected!") .setContentText("GPS coordinates paused") .setPriority(NotificationCompat.PRIORITY_DEFAULT) .build() - notificationManager.notify(notificationConnectDisconnectId, notificationBuilder) + notificationManager.notify(notificationServiceStatusId, notificationBuilder) tryReconnect() } - onCharacteristicWrite = { _, sentCharacteristic: BluetoothGattCharacteristic -> if (sentCharacteristic.uuid.toString().contains("0000dd30")) { val characteristic = connectionManager.characteristics.find { it.uuid.toString().contains("0000dd31")} if (characteristic != null) { Log.d(logTag, "GPS Enable command: ${characteristic.uuid}") - connectionManager.writeCharacteristic(characteristic, "01".hexToBytes()) + connectionManager.writeCharacteristic(characteristic.uuid, "01".hexToBytes()) } else { Log.d(logTag, "GPS Enable command: Cannot find characteristic containing 0000dd31") } @@ -155,6 +153,28 @@ class MyCameraLinkService: Service() { startSendingCoordinatesToDevice() } } + onBluetoothStatusChange = { isEnabled: Boolean -> + if(!isEnabled) { + sonyCommandGenerator.stopLocationReporting(myCameraLinkEventListener) + notificationManager.cancel(notificationServiceStatusId) + val notificationBuilder = NotificationCompat.Builder(applicationContext, notificationChannel) + .setSmallIcon(R.drawable.ic_bluetooth_disabled) + .setContentTitle("Bluetooth disabled") + .setContentText("GPS coordinates paused") + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .build() + notificationManager.notify(notificationServiceStatusId, notificationBuilder) + } else { + notificationManager.cancel(notificationServiceStatusId) + val notificationBuilder = NotificationCompat.Builder(applicationContext, notificationChannel) + .setSmallIcon(R.drawable.ic_camera_disconnected) + .setContentTitle("$cameraName disconnected!") + .setContentText("GPS coordinates paused") + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .build() + notificationManager.notify(notificationServiceStatusId, notificationBuilder) + } + } } } @@ -166,14 +186,13 @@ class MyCameraLinkService: Service() { createNotificationChannel() val notification = NotificationCompat.Builder(this, notificationChannel) - .setContentTitle("Camera GPS link running") - .setContentText("Paired to $cameraName") - .setSmallIcon(R.drawable.ic_camera_back) + .setContentTitle("Connecting to $cameraName") + .setSmallIcon(R.drawable.ic_device_connecting) .build() ServiceCompat.startForeground( this, - 100, + notificationServiceStatusId, notification, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION or ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE @@ -186,7 +205,7 @@ class MyCameraLinkService: Service() { val characteristic = connectionManager.characteristics.find { it.uuid.toString().contains("0000dd30")} if (characteristic != null) { Log.d(logTag, "GPS Enable command: ${characteristic.uuid}") - connectionManager.writeCharacteristic(characteristic, "01".hexToBytes()) + connectionManager.writeCharacteristic(characteristic.uuid, "01".hexToBytes()) } else { Log.d(logTag, "GPS Enable command: Cannot find characteristic containing 0000dd31") } @@ -218,7 +237,7 @@ class MyCameraLinkService: Service() { } override fun onBind(intent: Intent?): IBinder? { - Log.d("MyService","Service being bound") + Log.d(logTag,"Service is being bound") return binder } } \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_bluetooth_disabled.xml b/app/src/main/res/drawable-anydpi/ic_bluetooth_disabled.xml new file mode 100644 index 0000000..a9f04bc --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_bluetooth_disabled.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi/ic_device_connecting.xml b/app/src/main/res/drawable-anydpi/ic_device_connecting.xml new file mode 100644 index 0000000..ba8e65b --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_device_connecting.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/drawable-hdpi/ic_bluetooth_disabled.png b/app/src/main/res/drawable-hdpi/ic_bluetooth_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..a0999a6880c09030903cc7a33c09be899d93cec5 GIT binary patch literal 474 zcmV<00VV#4P)J5QbCHA<=UHDkKVO6j6Xs?tny*gont3CV`fk7E#i011LBF4aeXVNbob0ePs3@ zLqWXWW~X9SjF7U)@#K(@(&e0}NP#D510F932r0Xq z7X@T81yhbI2n&5l+vePrkx2(sXcEY=Lhq)p>~sFg$fQ#$QjtPcs3+~wJS(-lDVDl6 zu{CL*`FJlMyI-a*mM{LEf|n{cy7V`YNfkoJ)l|%vGerbm>dM5{r5#E;rJNf(M|9vf z`i$bm@+o5*s|_i1VTvjv6DyXl-Z#TY!FkmQmz&Bn)B^mW_hS05rmqb7_fbLMV1&QR&djq?&+^H{Ln^d5^gu#?FytA=_t`KF{$l@XO{z z_!IV9+K$PYnAo%ZeRL2Oa{tkgeI?W@qreLta86Q4Xp7^?F+y&cT3VXm2jQ^jUtOd5 Q1ONa407*qoM6N<$f}{}C_5c6? literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-hdpi/ic_device_connecting.png b/app/src/main/res/drawable-hdpi/ic_device_connecting.png new file mode 100644 index 0000000000000000000000000000000000000000..9b54ef12f95353ca85b358c1f95a158f55bc7eb6 GIT binary patch literal 572 zcmV-C0>k}@P)Kvkvdl3<+yxn1?5!G_{KTIm<{L9s~4y)=EOWl|o+N`bpal^e=gQ4%OCukF8`2>m?!HnZkqaBJj(# zzo_jH`gXJA=m2YZP(mh6-f2Jn0kJmlccZ^-G|>no&5O^vj>a0_T#Qs$FKy?SJn%;@YT_aS|p^vuNHSf z;}A1KpSBuX(DuObqKLOmd0z(--m(ek8~f--REu*g5<2kIPyXo8u%K7CHg?%xH8lAO z#|+8;37dCiYKpiE+GbzfkZ?hJ?5QhM&@t$G_k#a}^0GdK2C z$gptZS+LMF5VLIEToNqMvekjOX5;3g;KC`}5h4}aMCB}ZJeRsQ35W|PLKFA||BC#& zUm1yrT0y2lOup_6-xT?g&wFR~PpzfC*fkK3jp0leD=7yC|_Kr~!XvOT1b!dJx&&lSc9 z-8s=ZgYe)o5YxPFR5EMQ>akgb#1W65`4AA#zd=92;&V6l`#b@(n&0k95AX2+0000< KMNUMnLSTY)IgD5U literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_device_connecting.png b/app/src/main/res/drawable-mdpi/ic_device_connecting.png new file mode 100644 index 0000000000000000000000000000000000000000..48a33e3cd315c6eae10a6127723301643a7479fc GIT binary patch literal 369 zcmV-%0gnEOP)I@y%2PKWs)_dW=ZL@0q87k0JpS_!%PLB^9zG? zCNs9p7AztA>tM1$oQ>o&@q7uFMs~~6V!Nl#FvA&0z9fpyCcAX_c4_NVf1v&tW;g)? zh744S3N)xU!wdzW^Mpa3G)siO&rGNrYMVT8ws@0Q>hQLsNIvq7>>txHeg2-0GPO1;2}NMKk1p@@Ewu)z-0gUr6#7ElZL z<$f2qu)B)bwDMP+_+#a^+7i?PzFK+e>V>}PgcJ!CK^_LSUcgyyd+FK=w7a6$kA@Al zYvs2%L8?et{Ru9_o(stBJe_qCD57g5ZU#;;ovJlq^~c%H3%HwYJ*;o~Yexse=~V4b zR)3C*6xu`V{5^k7H*DZ-#Obspc86B3sS(n(E6NRD&ncYNREAWo5HmXXrws&AVOh!-g%@jz{7i#fZ4c41S*Jo0@NNc+4B zAZ)AF#O$DhXj913>`t=*X%YX=`2s~$=fvb-^~@{ti3C#4NBnfZf4JYCY1f1~a0Bgv zJx>wH<8*G*!;aTZvpdG1C`o= za=5Oa)BBE3^7@jzmqf}>@(`b!*e791VuFV-7_ zcvqE)Pjvj9jsvA>IAJkYU3^%{*EpsXpr=z6*_}sxVBb*PDyCESS+BPW^n>Un5R|Zg?=RIl)ZTSG9`zh4^T9AOw^9uD47bb+}cd{F-w*ux*quDMNaXP)F zx;0Fv(bHaU4C1u;>KaIVreifa$63g(yZC+98w1_>vaN(#C$f?7nEu+ueqp^4(9>qt zW=^Hp?3qYVoZNEH4Pr;slqm8%gaN1VJ}EG3JH5+#ZJ<--qF!jyI&qh^xj}iJ&!zx` z0n~q`+~T@gK)=*yyUGA^1Kq#W2hi?kmCJnIQb7E$CGUI!xdBgiAGVGQstr`m`Cb5R zV9+0T2mg6}7a_F300000NkvXXu0mjf DQx;kf literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_bluetooth_disabled.png b/app/src/main/res/drawable-xxhdpi/ic_bluetooth_disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..e4f855f49df424af874a91dc4c24693db47a26e6 GIT binary patch literal 969 zcmV;)12+7LP)&|q#NPEMSx55B>>2;E$KJDh#>N_rMx)VaG#WbwfXC9_*mjWZgGWSphu>^V zJHkGLh6HjnksJsMWM)!ZZU%$}GJKVGiv0%%;sP1IOFP6dRUre|l(x$Kxgaf&!7R7> zM3SV(rM>qCGRHnSKo`hhX3_-577e=MIBv6_2J!?le3N#VjMLPIA`78pnh{SfIDko^Yp!IRYHxYZZqi zxy+dpGaSPpT!Xf(ZG#OSrY4={>lKG2Im4L~OB~~agh1B*oQ)o4cRT7|uSlSaw8$|I zvE5~7cmi3USM1REg zTW;&tXPIriLI!x*6C}h6$2i1xmiu~%40MTAA)-fs!GI=`4n{a94Fc%54~A&r?lm&- z1y&+K^a#*P@OR=kh9MI2mQ{>?FE{8vsO8Yl!Yu=v<&lm+zm5RV#W7DOm{6ZjKSYAQ ztjtYp=((8b(}b=2z6^Rn{`DLmiN`+Be=wWuerqK_-^v#}->5*=uFa%*=UWBP#p%=! zC<0j@Z8p{+67+%mu}vdVg93iqW1q5@8}x!a%P|II%pmKRdb;W;vv5PN6E`@#{fkjq+ec$QHDs8$S%%|nBo`)i5euI&)DE$-t0(G#tp6{a)C3m++yDl zhzKO@DR+8&l(t9OA{&S@3b!OOL5XGG3Lq?y_6puUFJAj)vWz2uBy!#+bcJmx5Edwg znK}Cd*GN6Tf5HAch9t9_`!tX*&=+ZYIo^TrG2;XKRR_Ym7?bsmG`h>pyvIGxKGgwT zpifB597cRsrEPM5wID5!nK{|w^b*7c+C~j;u>NZh7U(kqyVW2;SfKWALkGG7nXO#i rtp)|Ue+xgr_C}-8Xfzs)#{cIhIB6?Elm7OO00000NkvXXu0mjf6nV9G literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_device_connecting.png b/app/src/main/res/drawable-xxhdpi/ic_device_connecting.png new file mode 100644 index 0000000000000000000000000000000000000000..640c320e0766ec225e4da00233149857afc11ec1 GIT binary patch literal 1145 zcmV-<1cv*GP)mr4b`V>=$E9s^X&Sdz|=ieuivry*6rb~SP_XtB9TZW5-A-3Tcka2 zwHq97JYvdrWVyqdMq@EZxz4)A0=q%VZPqptxD8Tnvc7S^Z;&#=V;Tj*1}V+WNhoHJ za)rk>0u(n$>Fm=@zQ8kSlhS%P<^t^*q+I1WmOXONUDBqFFY!xSH|uP`ZO~utFu2I` zENkR|U-CB)##mx}bj+c&nXs@&%#z8Qj zEMp28)Y6(er48#URU~$Z#ljHlN(YHazLk`zlTg4Q`FEeR&nz(bAZ=x;w;}NX9wf}L zt}>A9U_R#mw-GQ1$tEz%L4(4l3hX=LM%GmVlEm#h-RA2gcnm^fj;;T<9v>#hop7AW7^lCiwG0$e4bfM3`e;r64iMw~|~nl+PT+myn&S ziYHN6Q#lCNN$sE;fU`Q6*dBORg~T3br<-Rl>uLf1-K_}IJg14o_ZixC99N|Ou%Ssg z&$?PbxK0X@D>PG(e2cUh;vo~U22u67Wv zlTtz#yXI+S@`SYtl6=U#WnJwcTqh}7J^K>!0pwRs$}83@NN(;iQ>?2U6f;P7KA%DR z;Wp?s>r+^W1=LifgQYvg%qw)0r>s?^zlVjw8`jkZ7M7&P;ZM>>kzYyoSf@z;TGA<2 zGb;y+-{yU%+Y!>bw)st@Q|_~_7SR66VJ3M_6NwKQ+J25J$Q!AgVqK-6+Dnb&D&qbW z35{lEOR$<*2?$@Tx?+pDSlz^ZDLje7n#w@bd30Pet_aF4mO_!gbC)+bPUvFOYY@tLd0{p8l?Lj4{pAwRw=9AE1*&(fvjMk3=5>{g&Us%E`B(7t zS(i2EFmM~>qqAPYOF{Ay=L9Ufl?$|QP-nb)w^X1#gRb%T{~i=KD85MUA^sG>L+9*P zWdOfH@#j!*8x(&~r@(Gdb8`-Zyg|2E(`XQX79NR2B9TZW(lPu4