diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 71f709fe..4dddc0e6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -66,7 +66,9 @@
android:foregroundServiceType="location" />
-
+
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/CellInformation.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/CellInformation.java
index 4f37073d..1eeacfd7 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/CellInformation.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/CellInformation.java
@@ -219,10 +219,10 @@ public Point getPoint(Point point){
public StringBuilder getStringBuilder(){
StringBuilder stringBuilder = new StringBuilder();
- stringBuilder.append(" Type: ").append(this.getCellType());
- if(this.getPci() != -1) stringBuilder.append(" PCI: ").append(this.getPci());
+ stringBuilder.append(" Type: ").append(this.getCellType()).append("\n");
+ if(this.getPci() != -1) stringBuilder.append(" PCI: ").append(this.getPci()).append("\n");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && this.getAlphaLong() != null && !this.getAlphaLong().equals("N/A") && !this.getAlphaLong().isEmpty()){
- stringBuilder.append(" Alpha Long: ").append(this.getAlphaLong());
+ stringBuilder.append(" Alpha Long: ").append(this.getAlphaLong()).append("\n");
}
return stringBuilder;
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/LTEInformation.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/LTEInformation.java
index 373d705a..f3b158cb 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/LTEInformation.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/LTEInformation.java
@@ -235,15 +235,22 @@ public Point getPoint(Point point){
@Override
public StringBuilder getStringBuilder(){
StringBuilder stringBuilder = super.getStringBuilder();
- stringBuilder.append(" RSRQ: ").append(this.getRsrq());
- stringBuilder.append(" RSRP: ").append(this.getRsrp());
- stringBuilder.append(" RSSI: ").append(this.getRssi());
- stringBuilder.append(" RSSNR: ").append(this.getRssnr());
- stringBuilder.append(" CQI: ").append(this.getCqi());
- stringBuilder.append(" Bandwidth: ").append(this.getBandwidth());
- stringBuilder.append(" EARFCN: ").append(this.getEarfcn());
- stringBuilder.append(" TimingAdvance: ").append(this.getTimingAdvance());
+ String max = Integer.MAX_VALUE + "";
+ if(!this.getRsrqString().equals(max)) stringBuilder.append(" RSRQ: ").append(this.getRsrq()).append(" dB").append("\n");
+ if(!this.getRsrpString().equals(max)) stringBuilder.append(" RSRP: ").append(this.getRsrp()).append(" dBm").append("\n");
+
+ if(!this.getRssiString().equals(max)) stringBuilder.append(" RSSI: ").append(this.getRssi()).append(" dBm").append("\n");
+
+ if(!this.getRssnrString().equals(max)) stringBuilder.append(" RSSNR: ").append(this.getRssnr()).append(" dB").append("\n");
+
+ if(!this.getCqiString().equals(max)) stringBuilder.append(" CQI: ").append(this.getCqi()).append("\n");
+
+ if(!this.getBandwidthString().equals(max)) stringBuilder.append(" Bandwidth: ").append(this.getBandwidth()).append(" kHz").append("\n");
+
+ if(!this.getEarfcnString().equals(max)) stringBuilder.append(" EARFCN: ").append(this.getEarfcn()).append("\n");
+
+ if(!this.getTimingAdvanceString().equals(max)) stringBuilder.append(" TimingAdvance: ").append(this.getTimingAdvance()).append(" ns").append("\n");
return stringBuilder;
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java
index a888fc79..110706f7 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/DataProvider/CellInformations/NRInformation.java
@@ -136,6 +136,18 @@ public List getCqis() {
return cqis;
}
+ public int getFirstCqi() {
+ try {
+ return cqis.get(0);
+ } catch (IndexOutOfBoundsException e) {
+ return 0;
+ }
+ }
+
+ public String getFirstCqiString(){
+ return Integer.toString(this.getFirstCqi());
+ }
+
public void setCqis(List cqis) {
this.cqis = cqis;
}
@@ -279,11 +291,20 @@ public Point getPoint(Point point){
@Override
public StringBuilder getStringBuilder(){
- StringBuilder sb = super.getStringBuilder();
- sb.append(" SSRSQ: ").append(this.getSsrsrq());
- sb.append(" SSRSRP: ").append(this.getSsrsrp());
- sb.append(" SSSINR: ").append(this.getSssinr());
- return sb;
- }
+ StringBuilder stringBuilder = super.getStringBuilder();
+ String max = Integer.MAX_VALUE + "";
+ if(!this.getSsrsrqString().equals(max)) stringBuilder.append(" SSRSRQ: ").append(this.getSsrsrqString()).append(" dB").append("\n");
+ if(!this.getSsrsrpString().equals(max)) stringBuilder.append(" SSRSRP: ").append(this.getSsrsrpString()).append(" dBm").append("\n");
+
+ if(!this.getSssinrString().equals(max)) stringBuilder.append(" SSRSRP: ").append(this.getSssinrString()).append(" dBm").append("\n");
+
+ if(!this.getFirstCqiString().equals(max)) stringBuilder.append(" CQI: ").append(this.getFirstCqiString()).append("\n");
+
+ if(!this.getNrarfcnString().equals(max)) stringBuilder.append(" NRARFCN: ").append(this.getNrarfcnString()).append("\n");
+
+ if(!this.getTimingAdvanceString().equals(max)) stringBuilder.append(" TimingAdvance: ").append(this.getTimingAdvance()).append(" ns").append("\n");
+
+ return stringBuilder;
+ }
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java
index 77ea6ba1..23dbf089 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/GlobalVars.java
@@ -25,6 +25,7 @@ public class GlobalVars {
public static final String SSRSRP = "SSRSRP";
public static final String SSRSRQ = "SSRSRQ";
public static final String SSSINR = "SSSINR";
+ public static final String INFLUX_WRITE_STATUS = "influxdb_write_status";
private static GlobalVars instance;
ImageView log_status;
private DataProvider dp;
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/InfluxdbConnection.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/InfluxdbConnection.java
index 4a019198..50b9be6f 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/InfluxdbConnection.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/InfluxdbConnection.java
@@ -69,23 +69,22 @@ public void open_write_api() {
.exponentialBase(4)
.build());
writeApi.listenEvents(BackpressureEvent.class, value -> {
- Log.d(TAG, "Backpressure: Reason: " + value.getReason());
- value.logEvent();
+ Log.d(TAG, "open_write_api: Could not write to InfluxDBv2 due to backpressure");
});
writeApi.listenEvents(WriteSuccessEvent.class, value -> {
+ //Log.d(TAG, "open_write_api: Write to InfluxDBv2 was successful");
if ( spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)) {
gv.getLog_status().setColorFilter(Color.argb(255, 0, 255, 0));
}
});
writeApi.listenEvents(WriteErrorEvent.class, value -> {
- value.logEvent();
+ Log.d(TAG, "open_write_api: Could not write to InfluxDBv2 due to error");
if ( spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)) {
gv.getLog_status().setColorFilter(Color.argb(255, 255, 0, 0));
}
});
-
writeApi.listenEvents(WriteRetriableErrorEvent.class, value -> {
- value.logEvent();
+ Log.d(TAG, "open_write_api: Could not write to InfluxDBv2 due to retriable error");
if ( spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)) {
gv.getLog_status().setColorFilter(Color.argb(255, 255, 0, 0));
}
@@ -109,27 +108,20 @@ public void disconnect() {
writeApi.close();
writeApi = null;
} catch (com.influxdb.exceptions.InfluxException e) {
- Log.d(TAG, "disconnect: Error while closing write API");
- Log.d(TAG,e.toString());
- }
- try {
- Log.d(TAG, "disconnect: Closing influx connection");
- influxDBClient.close();
- influxDBClient = null;
- } catch (com.influxdb.exceptions.InfluxException e) {
- Log.d(TAG, "disconnect: Error while closing influx connection");
+ Log.e(TAG, "disconnect: Error while closing write API");
Log.d(TAG,e.toString());
}
} else {
Log.d(TAG, "disconnect() was called on not existing instance of the influx client");
}
+ Log.d(TAG, "disconnect: InfluxDB connection closed");
}
/**
* Add a point to the message queue
*/
public boolean writePoint(Point point) {
- if (influxDBClient != null && influxDBClient.ping()) {
+ if (influxDBClient != null && ping()) {
try {
writeApi.writePoint(point);
} catch (com.influxdb.exceptions.InfluxException e) {
@@ -153,7 +145,7 @@ public boolean writePoint(Point point) {
public boolean writeRecords(List points) throws IOException {
new Thread(() -> {
try {
- if (influxDBClient != null && influxDBClient.ping()) {
+ if (influxDBClient != null && ping()) {
try {
writeApi.writeRecords(WritePrecision.MS, points);
} catch (com.influxdb.exceptions.InfluxException e) {
@@ -180,18 +172,19 @@ public boolean writeRecords(List points) throws IOException {
public boolean writePoints(List points) throws IOException {
new Thread(() -> {
try {
- if (influxDBClient != null && influxDBClient.ping()) {
+ if (influxDBClient != null && ping()) {
try {
writeApi.writePoints(points);
} catch (com.influxdb.exceptions.InfluxException e) {
- Log.d(TAG, "writePoint: Error while writing points to influx DB");
+ Log.e(TAG, "writePoint: Error while writing points to influx DB");
Log.d(TAG,e.toString());
}
} else {
- Log.d(TAG, "writePoints: InfluxDB not reachable: " + url);
+ Log.e(TAG, "writePoints: InfluxDB not reachable: " + url);
}
}
catch (Exception e) {
+ Log.e(TAG, "writePoints: Error while writing points to influx DB");
Log.d(TAG,e.toString());
}
}).start();
@@ -230,11 +223,12 @@ public boolean onboard() {
public boolean flush() {
new Thread(() -> {
try {
- if (influxDBClient.ping()) {
+ if (ping()) {
writeApi.flush();
}
} catch (Exception e) {
- Log.d(TAG,e.toString());
+ Log.e(TAG, "flush: Error while flushing write API");
+ Log.d(TAG, "flush: \n"+e.toString());
}
}).start();
return true;
@@ -243,6 +237,9 @@ public boolean flush() {
public WriteApi getWriteApi() {
return writeApi;
}
+ public String getUrl() {
+ return this.url;
+ }
public boolean ping() {
return influxDBClient.ping();
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/InfluxdbWriteApiStatus.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/InfluxdbWriteApiStatus.java
new file mode 100644
index 00000000..0dc1af0a
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/InfluxDB2x/InfluxdbWriteApiStatus.java
@@ -0,0 +1,37 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x;
+
+import androidx.annotation.NonNull;
+
+public enum InfluxdbWriteApiStatus {
+ Backpressure,
+ WriteSuccess,
+ WriteErrorEvent,
+ WriteRetriableErrorEvent,
+ Unknown;
+ @NonNull
+ public String toString() {
+ switch(this) {
+ case Backpressure: return "Backpressure";
+ case WriteSuccess: return "WriteSuccess";
+ case WriteErrorEvent: return "WriteErrorEvent";
+ case WriteRetriableErrorEvent: return "WriteRetriableErrorEvent";
+ case Unknown:;
+ default: return "Unknown";
+ }
+ }
+ public static InfluxdbWriteApiStatus fromString(String str) {
+ str = str.toLowerCase();
+ switch(str) {
+ case "backpressure": return Backpressure;
+ case "writesuccess": return WriteSuccess;
+ case "writeerrorevent": return WriteErrorEvent;
+ case "writeeetriableerrorevent": return WriteRetriableErrorEvent;
+ case "unknown": return Unknown;
+ default: return Unknown;
+ }
+ }
+
+ public boolean isEquals(InfluxdbWriteApiStatus status) {
+ return this==status;
+ }
+}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java
index bd6dfcab..5de06761 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/LoggingService.java
@@ -28,8 +28,13 @@
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
+import com.influxdb.client.WriteApi;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
+import com.influxdb.client.write.events.BackpressureEvent;
+import com.influxdb.client.write.events.WriteErrorEvent;
+import com.influxdb.client.write.events.WriteRetriableErrorEvent;
+import com.influxdb.client.write.events.WriteSuccessEvent;
import java.io.File;
import java.io.FileNotFoundException;
@@ -47,6 +52,7 @@
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DataProvider;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.WifiInformation;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnection;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbWriteApiStatus;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.InfluxDB2x.InfluxdbConnections;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
@@ -59,8 +65,6 @@ public class LoggingService extends Service {
InfluxdbConnection lic; // local influxDB
DataProvider dp;
SharedPreferencesGrouper spg;
- private Handler notificationHandler;
- private HandlerThread notificationHandlerThread;
private Handler remoteInfluxHandler;
private HandlerThread remoteInfluxHandlerThread;
private Handler localInfluxHandler;
@@ -70,6 +74,9 @@ public class LoggingService extends Service {
private List logFilePoints;
private FileOutputStream stream;
private int interval;
+ private InfluxdbWriteApiStatus currentInfluxdbWriteApiStatus = InfluxdbWriteApiStatus.Unknown;
+ private boolean influxConnectionStatus = true;
+ private String currentInfluxDbWriteApiStatusMessage = "";
GlobalVars gv;
// Handle local on-device logging to logfile
private final Runnable localFileUpdate = new Runnable() {
@@ -94,21 +101,6 @@ public void run() {
localFileHandler.postDelayed(this, interval);
}
};
- // Handle notification bar update
- private final Runnable notification_updater = new Runnable() {
- @SuppressLint("ObsoleteSdkInt")
- @Override
- public void run() {
- if(dp == null) {
- Log.e(TAG, "run: Data provider is null!");
- return;
- }
- StringBuilder s = dp.getRegisteredCells().get(0).getStringBuilder();
- builder.setContentText(s);
- nm.notify(1, builder.build());
- notificationHandler.postDelayed(this, interval);
- }
- };
// Handle local on-device influxDB
private final Runnable localInfluxUpdate = () -> {
@@ -138,6 +130,8 @@ public void run() {
remoteInfluxHandler.postDelayed(this, interval);*/
};
+
+
// Handle remote on-server influxdb update
private final Runnable RemoteInfluxUpdate = new Runnable() {
@Override
@@ -159,38 +153,161 @@ public void onCreate() {
gv = GlobalVars.getInstance();
}
- @SuppressLint("ObsoleteSdkInt")
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d(TAG, "onStartCommand: Start logging service");
- GlobalVars gv = GlobalVars.getInstance();
- // setup class variables
- dp = gv.get_dp();
- nm = getSystemService(NotificationManager.class);
- spg = SharedPreferencesGrouper.getInstance(this);
- interval = Integer.parseInt(spg.getSharedPreference(SPType.logging_sp).getString("logging_interval", "1000"));
+ private StringBuilder getStringBuilder() {
+ StringBuilder s = new StringBuilder();
+ s.append("Logging to...\n");
+
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_local_file_log", false))
+ s.append("File\n");
+
+ if(ic == null) {
+ // influx not initialized
+ //s.append("InfluxDB: not connected\n");
+ if(s.toString().equals("Logging to...\n")) {
+ s.append("No logging targets enabled\n");
+ }
+ return s;
+ }
+ s.append("InfluxDB: ");
+ if(!influxConnectionStatus){
+ //influx not reachable
+ s.append(ic.getUrl())
+ .append(" not reachable\n");
+ return s;
+ } else {
+ //influx reachable, so showing the writeApi Status
+ s.append(currentInfluxdbWriteApiStatus).append("\n");
+ }
+
+ switch (currentInfluxdbWriteApiStatus) {
+ case Backpressure:
+ case WriteErrorEvent:
+ case WriteRetriableErrorEvent:
+ s.append("\tReason: ").append(currentInfluxDbWriteApiStatusMessage).append("\n");
+ break;
+ case WriteSuccess:
+ case Unknown:
+ default:
+ break;
+ }
+ return s;
+ }
+
+ private void setupNotification() {
// create intent for notifications
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
+ StringBuilder s = getStringBuilder();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// create notification
- builder = new NotificationCompat.Builder(this, "OMNT_notification_channel").setContentTitle(getText(R.string.loggin_notifaction)).setSmallIcon(R.mipmap.ic_launcher_foreground).setColor(Color.WHITE).setContentIntent(pendingIntent)
+ builder = new NotificationCompat.Builder(this, "OMNT_notification_channel")
+ .setContentTitle(getText(R.string.loggin_notifaction))
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setColor(Color.WHITE)
+ .setContentIntent(pendingIntent)
// prevent to swipe the notification away
.setOngoing(true)
+ .setOnlyAlertOnce(true)
+ .setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(s))
// don't wait 10 seconds to show the notification
.setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
} else {
// create notification
- builder = new NotificationCompat.Builder(this, "OMNT_notification_channel").setContentTitle(getText(R.string.loggin_notifaction)).setSmallIcon(R.mipmap.ic_launcher_foreground).setColor(Color.WHITE).setContentIntent(pendingIntent)
+ builder = new NotificationCompat.Builder(this, "OMNT_notification_channel")
+ .setContentTitle(getText(R.string.loggin_notifaction))
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setColor(Color.WHITE)
+ .setContentIntent(pendingIntent)
+ .setOnlyAlertOnce(true)
+ .setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(s))
// prevent to swipe the notification away
.setOngoing(true);
}
+ }
+
+ private void updateNotification(){
+ StringBuilder s = getStringBuilder();
+ builder.setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(s));
+ nm.notify(1, builder.build());
+ }
+ private void getInfluxDBConnectionStatus() {
+ if (ic == null) return;
+ WriteApi writeApi = ic.getWriteApi();
+ if (writeApi == null) return;
+
+ // Listen for different WriteApi events
+ writeApi.listenEvents(BackpressureEvent.class, event ->
+ handleWriteApiEvent(InfluxdbWriteApiStatus.Backpressure, event.getReason().toString()));
+
+ writeApi.listenEvents(WriteSuccessEvent.class, event ->
+ handleWriteApiEvent(InfluxdbWriteApiStatus.WriteSuccess, null));
+
+ writeApi.listenEvents(WriteErrorEvent.class, event ->
+ handleWriteApiEvent(InfluxdbWriteApiStatus.WriteErrorEvent, event.getThrowable().getMessage()));
+
+ writeApi.listenEvents(WriteRetriableErrorEvent.class, event ->
+ handleWriteApiEvent(InfluxdbWriteApiStatus.WriteRetriableErrorEvent, event.getThrowable().getMessage()));
+ }
+
+ private void handleWriteApiEvent(InfluxdbWriteApiStatus status, String message) {
+ if (!spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)) return;
+
+ // Check if status has changed
+ if (currentInfluxdbWriteApiStatus == status &&
+ (message == null || message.equals(currentInfluxDbWriteApiStatusMessage))) return;
+
+ // Update the status and log message
+ currentInfluxdbWriteApiStatus = status;
+ if (message != null) currentInfluxDbWriteApiStatusMessage = message;
+
+ Log.d(TAG, String.format("getInfluxDBConnectionStatus: Could not write to InfluxDBv2 due to %s %s", status.toString(), currentInfluxDbWriteApiStatusMessage));
+
+ updateNotification();
+ }
+
+
+ @SuppressLint("ObsoleteSdkInt")
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(TAG, "onStartCommand: Start logging service");
+ GlobalVars gv = GlobalVars.getInstance();
+
+ // setup class variables
+ dp = gv.get_dp();
+ nm = getSystemService(NotificationManager.class);
+ spg = SharedPreferencesGrouper.getInstance(this);
+ interval = Integer.parseInt(spg.getSharedPreference(SPType.logging_sp).getString("logging_interval", "1000"));
+
+
+
// create preferences listener
spg.setListener((prefs, key) -> {
+ if(Objects.equals(key, "enable_logging")) {
+ if (prefs.getBoolean(key, false)) {
+ Log.d(TAG, "onSharedPreferenceChanged: " + prefs.getBoolean(key, false));
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)) {
+ // enable influx when enable_logging is enabled
+ setupRemoteInfluxDB();
+ }
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_local_file_log", false)){
+ // enable local file log when enable_logging is enabled
+ setupLocalFile();
+ updateNotification();
+ }
+
+
+ } else {
+ updateNotification();
+ this.onDestroy();
+ }
+ } else
if (Objects.equals(key, "enable_influx")) {
if (prefs.getBoolean(key, false)) {
if (prefs.getString("influx_URL", "").isEmpty() || prefs.getString("influx_org", "").isEmpty() || prefs.getString("influx_token", "").isEmpty() || prefs.getString("influx_bucket", "").isEmpty()) {
@@ -198,22 +315,34 @@ public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(getApplicationContext(), "Please fill all Influx Settings", Toast.LENGTH_LONG).show();
prefs.edit().putBoolean("enable_influx", false).apply();
} else {
- setupRemoteInfluxDB();
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_logging", false)) {
+ // only enable influx log, when enable_logging is also enabled
+ setupRemoteInfluxDB();
+ updateNotification();
+ }
+
}
} else {
- stopRemoteInfluxDB();
- }
- } else if (Objects.equals(key, "enable_notification_update")) {
- if (prefs.getBoolean(key, false)) {
- setupNotificationUpdate();
- } else {
- stopNotificationUpdate();
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_logging", false)) {
+ // only stop influx log, when enable_logging is also enabled
+ stopRemoteInfluxDB();
+ updateNotification();
+ }
+
}
} else if (Objects.equals(key, "enable_local_file_log")) {
if (prefs.getBoolean(key, false)) {
- setupLocalFile();
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_logging", false)) {
+ // only enable file log, when enable_logging is also enabled
+ setupLocalFile();
+ updateNotification();
+ }
} else {
- stopLocalFile();
+ if(spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_logging", false)) {
+ // only stop file log, when enable_logging is also enabled
+ stopLocalFile();
+ updateNotification();
+ }
}
} else if (Objects.equals(key, "enable_local_influx_log")) {
if (prefs.getBoolean(key, false)) {
@@ -226,13 +355,6 @@ public int onStartCommand(Intent intent, int flags, int startId) {
}
}, SPType.logging_sp);
- // Start foreground service and setup logging targets
- startForeground(1, builder.build());
-
- if (spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_notification_update", false)) {
- setupNotificationUpdate();
- }
-
if (spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_influx", false)) {
setupRemoteInfluxDB();
}
@@ -244,6 +366,12 @@ public int onStartCommand(Intent intent, int flags, int startId) {
if (spg.getSharedPreference(SPType.logging_sp).getBoolean("enable_local_influx_log", false)) {
setupLocalFile();
}
+
+ setupNotification();
+ // Start foreground service and setup logging targets
+ startForeground(1, builder.build());
+
+
return START_STICKY;
}
@@ -262,6 +390,8 @@ public void onDestroy() {
stopLocalInfluxDB();
}
+ //remove notification
+ nm.cancel(1);
// Stop foreground service and remove the notification.
stopForeground(STOP_FOREGROUND_DETACH);
// Stop the foreground service.
@@ -434,30 +564,6 @@ private void stopLocalFile() {
}
}
- private void setupNotificationUpdate() {
- Log.d(TAG, "setupNotificationUpdate");
- notificationHandlerThread = new HandlerThread("NotificationHandlerThread");
- notificationHandlerThread.start();
- notificationHandler = new Handler(Objects.requireNonNull(notificationHandlerThread.getLooper()));
- notificationHandler.post(notification_updater);
- }
-
- private void stopNotificationUpdate() {
- Log.d(TAG, "stopNotificationUpdate");
- notificationHandler.removeCallbacks(notification_updater);
- builder.setContentText(null);
- nm.notify(1, builder.build());
-
- if (notificationHandlerThread != null) {
- notificationHandlerThread.quitSafely();
- try {
- notificationHandlerThread.join();
- } catch (InterruptedException e) {
- Log.e(TAG, "Exception happened!! "+e, e);
- }
- notificationHandlerThread = null;
- }
- }
private void setupLocalInfluxDB() {
Log.d(TAG, "setupLocalInfluxDB");
@@ -492,6 +598,20 @@ private void stopLocalInfluxDB() {
}
}
+ Runnable monitorInfluxDBConnectionStatus = new Runnable() {
+ @Override
+ public void run() {
+ if (ic == null) return;
+ boolean newInfluxConnectionStatus = ic.ping();
+ Log.d(TAG, "run: monitorInfluxDBConnectionStatus: "+newInfluxConnectionStatus);
+ if(newInfluxConnectionStatus != influxConnectionStatus) {
+ influxConnectionStatus = newInfluxConnectionStatus;
+ updateNotification();
+ };
+ remoteInfluxHandler.postDelayed(this, interval);
+ }
+ };
+
/**
* initialize a new remote influxDB connection
*/
@@ -499,10 +619,12 @@ private void setupRemoteInfluxDB() {
Log.d(TAG, "setupRemoteInfluxDB");
ic = InfluxdbConnections.getRicInstance(getApplicationContext());
Objects.requireNonNull(ic).open_write_api();
+ getInfluxDBConnectionStatus();
remoteInfluxHandlerThread = new HandlerThread("RemoteInfluxHandlerThread");
remoteInfluxHandlerThread.start();
remoteInfluxHandler = new Handler(Objects.requireNonNull(remoteInfluxHandlerThread.getLooper()));
remoteInfluxHandler.post(RemoteInfluxUpdate);
+ remoteInfluxHandler.post(monitorInfluxDBConnectionStatus);
ImageView log_status = gv.getLog_status();
if (log_status != null) {
gv.getLog_status().setColorFilter(Color.argb(255, 255, 0, 0));
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java
index 3062356b..0f940278 100644
--- a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/MainActivity.java
@@ -69,6 +69,7 @@ public class MainActivity extends AppCompatActivity implements PreferenceFragmen
public boolean cp = false;
public boolean feature_telephony = false;
Intent loggingServiceIntent;
+ Intent notificationServiceIntent;
NavController navController;
private Handler requestCellInfoUpdateHandler;
private HandlerThread requestCellInfoUpdateHandlerThread;
@@ -213,6 +214,21 @@ protected void onCreate(Bundle savedInstanceState) {
}
}
}, SPType.logging_sp);
+
+ notificationServiceIntent = new Intent(context, NotificationService.class);
+ if(spg.getSharedPreference(SPType.default_sp).getBoolean("enable_radio_notification", false)){
+ context.startService(notificationServiceIntent);
+ }
+ spg.setListener((prefs, key) -> {
+ if(Objects.equals(key, "enable_radio_notification")){
+ if(prefs.getBoolean(key, false)){
+ context.startService(notificationServiceIntent);
+ } else {
+ context.stopService(notificationServiceIntent);
+ }
+ }
+ }, SPType.default_sp);
+
getAppSignature();
gv.setGit_hash(getString(R.string.git_hash));
}
diff --git a/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/NotificationService.java b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/NotificationService.java
new file mode 100644
index 00000000..894e3f30
--- /dev/null
+++ b/app/src/main/java/de/fraunhofer/fokus/OpenMobileNetworkToolkit/NotificationService.java
@@ -0,0 +1,158 @@
+package de.fraunhofer.fokus.OpenMobileNetworkToolkit;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.core.app.NotificationCompat;
+
+import com.influxdb.client.domain.Run;
+
+import java.util.Objects;
+
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.DataProvider.DataProvider;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SPType;
+import de.fraunhofer.fokus.OpenMobileNetworkToolkit.Preferences.SharedPreferencesGrouper;
+
+public class NotificationService extends Service {
+
+ private static final String TAG = "NotificationService";
+ public NotificationManager nm;
+ NotificationCompat.Builder builder;
+ private Handler notificationHandler;
+ private HandlerThread notificationHandlerThread;
+ private SharedPreferencesGrouper spg;
+
+ private GlobalVars gv;
+ private DataProvider dp;
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private void setupNotificationUpdate() {
+ Log.d(TAG, "setupNotificationUpdate");
+ notificationHandlerThread = new HandlerThread("NotificationHandlerThread");
+ notificationHandlerThread.start();
+ notificationHandler = new Handler(Objects.requireNonNull(notificationHandlerThread.getLooper()));
+ notificationHandler.post(servingCellNotificaiton);
+ }
+
+ private void stopNotificationUpdate() {
+ Log.d(TAG, "stopNotificationUpdate");
+ notificationHandler.removeCallbacks(servingCellNotificaiton);
+ //builder.setContentText(null);
+ //nm.notify(1, builder.build());
+ nm.cancel(4);
+
+ if (notificationHandlerThread != null) {
+ notificationHandlerThread.quitSafely();
+ try {
+ notificationHandlerThread.join();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Exception happened!! "+e, e);
+ }
+ notificationHandlerThread = null;
+ }
+ onDestroy();
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ gv = GlobalVars.getInstance();
+ dp = gv.get_dp();
+ nm = getSystemService(NotificationManager.class);
+ spg = SharedPreferencesGrouper.getInstance(this);
+ spg.setListener((prefs, key) -> {
+ if (prefs.getBoolean("enable_radio_notification", false)) {
+ setupNotificationUpdate();
+ } else {
+ stopNotificationUpdate();
+ }
+
+ }, SPType.default_sp);
+ setupNotification();
+ startForeground(4, builder.build());
+
+ return START_STICKY;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+ private void setupNotification() {
+ // create intent for notifications
+ Intent notificationIntent = new Intent(this, MainActivity.class);
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE);
+
+ StringBuilder s = getStringBuilder();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ // create notification
+ builder = new NotificationCompat.Builder(this, "OMNT_notification_channel")
+ .setContentTitle(getText(R.string.cell_notifcation))
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setColor(Color.WHITE)
+ .setContentIntent(pendingIntent)
+ // prevent to swipe the notification away
+ .setOngoing(true)
+ .setOnlyAlertOnce(true)
+ .setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(s))
+ // don't wait 10 seconds to show the notification
+ .setForegroundServiceBehavior(Notification.FOREGROUND_SERVICE_IMMEDIATE);
+ } else {
+ // create notification
+ builder = new NotificationCompat.Builder(this, "OMNT_notification_channel")
+ .setContentTitle(getText(R.string.cell_notifcation))
+ .setSmallIcon(R.mipmap.ic_launcher_foreground)
+ .setColor(Color.WHITE)
+ .setContentIntent(pendingIntent)
+ .setOnlyAlertOnce(true)
+ .setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(s))
+ // prevent to swipe the notification away
+ .setOngoing(true);
+ }
+ setupNotificationUpdate();
+ }
+ private StringBuilder getStringBuilder(){
+ if(dp == null) return new StringBuilder();
+ if(dp.getRegisteredCells() == null) return new StringBuilder();
+ StringBuilder s = dp.getRegisteredCells().get(0).getStringBuilder();
+ return s;
+ }
+ private void updateNotification(){
+ StringBuilder s = getStringBuilder();
+ builder.setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(s));
+ nm.notify(4, builder.build());
+ }
+
+ Runnable servingCellNotificaiton = new Runnable() {
+ @Override
+ public void run() {
+ updateNotification();
+ notificationHandler.postDelayed(servingCellNotificaiton, 1000);
+
+ }
+ };
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8faa0bd4..c3cf36bf 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -17,7 +17,7 @@
iPerf3
Send
-c 172.17.0.1
- OpenMobileNetworkToolkit logging
+ Logging Service
This app is provided by NGNI a department of Fraunhofer FOKUS. \n\nhttps://www.fokus.fraunhofer.de/go/ngni \n\nThis software is licensed under BSD 3-Clause Clear License https://spdx.org/licenses/BSD-3-Clause-Clear.html \n\nAuthors: \n\nPeter Hasse \nMohsin Nisar \nJohann Hackler
OpenMobileNetworkToolkit
@@ -254,5 +254,8 @@
Standard
Channel Bandwidth
Security Type
+ Serving Cell Parameter: PCI, RSRP...
+ Enable Cell Notification
+ Serving Cell
\ No newline at end of file
diff --git a/app/src/main/res/xml/preference.xml b/app/src/main/res/xml/preference.xml
index dc774fe2..6af95295 100644
--- a/app/src/main/res/xml/preference.xml
+++ b/app/src/main/res/xml/preference.xml
@@ -15,13 +15,19 @@
android:title="@string/home_screen_settings"
app:iconSpaceReserved="false">
-
+
+
-
+