This commit is contained in:
TheUnrealDragon 2026-04-16 17:18:02 +05:30
commit 69086d8093
3 changed files with 370 additions and 134 deletions

View file

@ -29,7 +29,9 @@
<service android:name=".WaterLevelService"
android:foregroundServiceType="connectedDevice"
android:exported="true">
android:exported="true"
android:process=":water_service"
android:stopWithTask="false">
<!-- <property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="Monitoring water levels via local network UDP packets for real-time sensor alerts." />-->
<meta-data android:name="android.app.lib_name" android:value="service"/>

View file

@ -32,22 +32,49 @@ public class WaterLevelService extends Service {
private boolean bits_flipped = false;
private String mode = "";
private String url = "";
private Thread udpThread;
private Thread cmdThread;
private boolean resetBinds = false;
public synchronized boolean checkBound() {
return resetBinds;
}
public synchronized void setBound(boolean value) {
resetBinds = value;
}
public class UDPCommandClient implements Runnable {
private DatagramSocket socket_cmd_recv;
private DatagramSocket socket_cmd_send;
private boolean received_cmd_first = false;
@Override
public void run() {
Log.d("UDP Service", "Command thread initialising");
try {
socket_cmd_recv = new DatagramSocket(8178, InetAddress.getByName("localhost"));
socket_cmd_send = new DatagramSocket(8179);
socket_cmd_recv = new DatagramSocket(null);
socket_cmd_send = new DatagramSocket(null);
socket_cmd_recv.setSoTimeout(4000);
socket_cmd_recv.setReuseAddress(true);
socket_cmd_send.setReuseAddress(true);
socket_cmd_recv.bind(new InetSocketAddress(8178));
socket_cmd_send.bind(new InetSocketAddress(8179));
Log.d("UDP Service", "Created command thread sockets");
while (!Thread.currentThread().isInterrupted()) {
if(socket_cmd_recv.isClosed()) {
socket_cmd_recv.bind(new InetSocketAddress(8178));
}
if(socket_cmd_send.isClosed()) {
socket_cmd_send.bind(new InetSocketAddress(8179));
}
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket_cmd_recv.receive(packet);
try {
socket_cmd_recv.receive(packet);
} catch(java.net.SocketTimeoutException e) {
continue;
}
String str = new String(buffer, StandardCharsets.UTF_8);
Log.d("UDP Service ", "Received command packet " + str);
if(str.startsWith("<SET NAME=ALERT VALUE=")) {
@ -55,6 +82,17 @@ public class WaterLevelService extends Service {
str = str.replace("=", "");
str = str.replace(">", "");
alert_thres_distance = Float.parseFloat(str);
{
if(!checkBound())
{
setBound(true);
Log.d("UDP Service ", "Set Bound to True");
}
else {
Log.d("UDP Service ", "Set Bound is False");
}
}
}
else if(str.startsWith("<SET NAME=BITS_FLIPPED VALUE=")) {
str = str.replace("<SET NAME=BITS_FLIPPED VALUE=", "");
@ -121,10 +159,14 @@ public class WaterLevelService extends Service {
multicastLock.acquire();
wakeLock.acquire();
wifiLock.acquire();
socket_recv = new DatagramSocket(8176, InetAddress.getByName("0.0.0.0"));
socket_send = new DatagramSocket(8177);
socket_recv = new DatagramSocket(null);
socket_send = new DatagramSocket(null);
socket_recv.setBroadcast(true);
socket_recv.setSoTimeout(4000);
socket_recv.setReuseAddress(true);
socket_send.setReuseAddress(true);
socket_send.bind(new InetSocketAddress(8177));
socket_recv.bind(new InetSocketAddress(8176));
Log.d("UDP Service", "Created Sockets");
int count = 0;
while (!Thread.currentThread().isInterrupted()) {
@ -133,10 +175,57 @@ public class WaterLevelService extends Service {
Log.i("UDP Service", "Thread is running with mode: " + mode);
count = 0;
}
if(checkBound()) {
Log.i("UDP Service", "Reconnecting sockets");
socket_recv.close();
socket_send.close();
socket_recv = null;
socket_send = null;
socket_recv = new DatagramSocket(null);
socket_send = new DatagramSocket(null);
socket_recv.setBroadcast(true);
socket_recv.setSoTimeout(4000);
socket_recv.setReuseAddress(true);
socket_send.setReuseAddress(true);
socket_send.bind(new InetSocketAddress(8177));
socket_recv.bind(new InetSocketAddress(8176));
setBound(false);
Log.i("UDP Service", "Reconnected sockets");
}
// if(checkBound()) {
// Log.i("UDP Service", "Reset socket binds: " + mode);
// socket_recv.close();
// socket_send.close();
// socket_send.bind(new InetSocketAddress(8177));
// socket_recv.bind(new InetSocketAddress(8176));
// setBound(false);
// if(socket_send.isBound()) {
// Log.i("UDP Service", "Rebound socket: " + 8177);
// }
// else {
// Log.i("UDP Service", "Failed to rebound socket: " + 8177);
// }
// if(socket_recv.isBound()) {
// Log.i("UDP Service", "Rebound socket: " + 8176);
// }
// else {
// Log.i("UDP Service", "Failed to rebound socket: " + 8176);
// }
// }
// if(checkBound()) {
// Log.i("UDP Service", "Reset socket binds: " + mode);
// }
// else {
// Log.i("UDP Service", "Reset socket binds: " + mode);
// }
byte[] buffer = null;
String updated = "";
if(mode.equals("udp")) {
try {
if(socket_recv.isClosed()) {
socket_recv.bind(new InetSocketAddress(8176));
}
buffer = new byte[4];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket_recv.receive(packet);
@ -227,6 +316,9 @@ public class WaterLevelService extends Service {
started = true;
}
}
if(socket_send.isClosed()) {
socket_send.bind(new InetSocketAddress(8177));
}
DatagramPacket send_packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("localhost"), 8180);
socket_send.send(send_packet);
Log.d("UDP Service ", "Sent packet");
@ -289,14 +381,40 @@ public class WaterLevelService extends Service {
Notification notification = createNotification();
startForeground(1, notification);
if (intent == null) {
Log.w("UDP Service", "Service restarted with null intent. Stopping to avoid crash.");
stopSelf();
return START_NOT_STICKY;
}
new Thread(new
Runnable() {
@Override
public void run() {
try {
// Move your socket and thread starting logic here
if (udpThread == null || !udpThread.isAlive()) {
udpThread = new Thread(new UDPClient());
udpThread.start();
}
if (cmdThread == null || !cmdThread.isAlive()) {
cmdThread = new Thread(new UDPCommandClient());
cmdThread.start();
}
} catch (Exception e) {
Log.e("UDP Service", "Error starting threads", e);
}
}
}).start();
Log.d("UDP Service", "Actually starting the thread");
int ret = super.onStartCommand(intent, flags, startId);
(new Thread(new UDPClient())).start();
(new Thread(new UDPCommandClient())).start();
// (new Thread(new UDPClient())).start();
// (new Thread(new UDPCommandClient())).start();
return START_STICKY;
return START_NOT_STICKY;
}
public void showToast(String str) {

View file

@ -5,15 +5,56 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import org.qtproject.qt.android.bindings.QtActivity;
import android.os.Handler;
import android.os.Looper;
public class WaterLevelServiceStarter {
private static boolean isMyServiceRunning(Class<?> serviceClass, Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
private static int getServicePid(Class<?> serviceClass, Context context) {
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return service.pid;
}
}
return 0;
}
public static void startService(Context context) {
Log.d("UDP Service", "Starting service via QtActivity instance");
// Log.d("UDP Service", "Starting service via QtActivity instance");
Intent intent = new Intent(context, WaterLevelService.class);
// if(!isMyServiceRunning(WaterLevelService.class, context)) {
// Intent intent = new Intent(context, WaterLevelService.class);
// context.startForegroundService(intent);
// }
context.startForegroundService(intent);
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
if (!isMyServiceRunning(WaterLevelService.class, context)) {
Log.d("UDP Service", "Starting service safely on Main Looper");
Intent intent = new Intent(context, WaterLevelService.class);
context.startForegroundService(intent);
}
else {
Log.d("UDP Service", "Service already running");
}
Log.d("UDP Service", "Background service running with pid: " + getServicePid(WaterLevelService.class, context));
}
});
}
}