sorry for bad english language
hello 2 days ago i have been tried to make my app can query data from database to my android app and it seem like it data not show up in the app
here the list of codes that i tried to show the number to the android app using android studio and failed:
- the codes that make querry from influx possible for android:
InfluxDbApp.java
package com.example.tensiometer.data;
import com.influxdb.v3.client.InfluxDBClient;
import com.influxdb.v3.client.Point;
import java.time.Instant;
import java.util.stream.Stream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
public class InfluxDbApp {
private static String Host_Url;
private static String Database;
private static String Database_2;
private static char[] Token;
public static void main(String[]arg){
loadProperties();
try(InfluxDBClient client= InfluxDBClient.getInstance(Host_Url, Token, Database)) {
queryData(client);
}
catch (Exception e){
System.err.println("An error occurred while connecting to InfluxDB");
e.printStackTrace();
}
}
private static void queryData(InfluxDBClient client){
System.out.println("----------------------------------------------------------");
System.out.printf("|%-20s|%-8s|%-8s|%-8s|%-8s|%-30s|\n", "Device", "Sistol", "Diastol", "BpM", "SPO2", "Time");
System.out.println("----------------------------------------------------------");
String sql = "SELECT \"Device\",\"Sistol\", \"Diastol\", \"BpM\", \"SPO2\", time FROM \"TestMeasurement\" WHERE time >= now() - interval '30 days' AND \"Sistol\" IS NOT NULL OR \"Diastol\" IS NOT NULL OR\"BpM\" IS NOT NULL OR\"SPO2\" IS NOT NULL ORDER BY time ASC";
try (Stream<Object[]> stream = client.query(sql)) {
stream.forEach(row -> {
String Device = (row[0] != null) ? row[0].toString():"";
String Sistol = (row[1] != null) ? row [1].toString() : "";
String Diastol = (row[2] != null) ? row[2].toString() : "";
String BpM = (row[3] != null) ? row[3].toString() : "";
String SPO2 = (row[4] != null) ? row[4].toString() : "";
String time = (row[5] != null) ? row[5].toString() : "";
System.out.printf("|%-20s|%-8s|%-8s|%-8s|%-8s|%-30s|\n", Device, Sistol, Diastol, BpM, SPO2,time);
});
}
catch (Exception e) {
System.err.println("Failed to query data from the bucket");
e.printStackTrace();
}
System.out.println("----------------------------------------------------------");
}
private static void loadProperties(){
Properties properties= new Properties();
try (FileInputStream input = new FileInputStream("localProperties")){
properties.load(input);
Host_Url = properties.getProperty("INFLUXDB_URL");
Database = properties.getProperty("INFLUXDB_BUCKET");
Token = properties.getProperty("INFLUXDB_TOKEN2").toCharArray();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
}
- the load.properties that show specific String and char that make it possible to querry from influx database:
INFLUXDB_URL = MY_URL
INFLUXDB_TESTBUCKET = My_TestingBucket
INFLUXDB_BUCKET = My_Bucket
INFLUXDB_TOKEN = BackUp_token
INFLUXDB_TOKEN2 = Read_token
3.a wrapper so that it can work (i tried convert the 1. code into kotlin it doesn’t work as my intended)
package com.example.tensiometer.data
import java.io.ByteArrayOutputStream
import java.io.PrintStream
object InfluxDbWrapper {
// Capture console output of InfluxDbApp.queryData
fun fetchConsoleOutput(): String {
val outputStream = ByteArrayOutputStream()
val printStream = PrintStream(outputStream)
val originalOut = System.out
try {
// Redirect System.out to our stream
System.setOut(printStream)
// Call the queryData function
InfluxDbApp.main(arrayOf())
} finally {
// Restore original System.out
System.setOut(originalOut)
}
return outputStream.toString()
}
// Parse the captured output into a list of rows
fun parseConsoleOutput(output: String): List<Map<String, String>> {
val rows = mutableListOf<Map<String, String>>()
val lines = output.lines()
// Skip header and separator lines
val dataLines = lines.drop(2).dropLast(2)
for (line in dataLines) {
val columns = line.split("|").map { it.trim() }.filter { it.isNotEmpty() }
if (columns.size == 6) { // Expecting 6 columns
rows.add(
mapOf(
"Device" to columns[0],
"Sistol" to columns[1],
"Diastol" to columns[2],
"BpM" to columns[3],
"SPO2" to columns[4],
"Time" to columns[5]
)
)
}
}
return rows
}
}
and lastly
4. my actual code for UI and place to put and view the data in the UI
Greetings.kt
package com.example.tensiometer.ui
//Screen B
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.tensiometer.data.InfluxDbWrapper
@Composable
fun Greetings(modifier: Modifier = Modifier) {
val rows = remember { mutableStateListOf<Map<String, String>>() }
fun reloadData() {
rows.clear() // Clear existing rows
val output = InfluxDbWrapper.fetchConsoleOutput()
val parsedRows = InfluxDbWrapper.parseConsoleOutput(output)
rows.addAll(parsedRows)
}
// Initial load when the composable is first displayed
LaunchedEffect(Unit) {
reloadData()
}
Column(modifier = modifier.fillMaxSize().padding(16.dp)) {
Text(
text = "InfluxDB Data",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(bottom = 16.dp)
)
// Reload button
Button(
onClick = { reloadData() }, // Call reloadData when button is clicked
modifier = Modifier.padding(bottom = 16.dp)
) {
Text("Reload Data")
}
LazyColumn {
// Table header
item {
Row(modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)) {
Text("Device", modifier = Modifier.weight(1f))
Text("Sistol", modifier = Modifier.weight(1f))
Text("Diastol", modifier = Modifier.weight(1f))
Text("BpM", modifier = Modifier.weight(1f))
Text("SPO2", modifier = Modifier.weight(1f))
Text("Time", modifier = Modifier.weight(2f))
}
}
// Table rows
items(rows) { row ->
Row(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)) {
Text(row["Device"] ?: "", modifier = Modifier.weight(1f))
Text(row["Sistol"] ?: "", modifier = Modifier.weight(1f))
Text(row["Diastol"] ?: "", modifier = Modifier.weight(1f))
Text(row["BpM"] ?: "", modifier = Modifier.weight(1f))
Text(row["SPO2"] ?: "", modifier = Modifier.weight(1f))
Text(row["Time"] ?: "", modifier = Modifier.weight(2f))
}
}
}
}
}
@Preview
@Composable
fun GreetingPreview(){
Greetings()
}
i already add dependency ass per instruction from influxdb javaV3 github. but the first problem (i already use exception to handle it) there like 6 exception before my app can build properly
excludes += "/META-INF/{AL2.0,LGPL2.1}"
excludes += "LICENSE-EDL-1.0.txt"
excludes += "META-INF/DEPENDENCIES"
excludes += "META-INF/io.netty.versions.properties"
excludes += "META-INF/INDEX.LIST"
excludes += "LICENSE-EPL-1.0.txt"
excludes += "arrow-git.properties"
so since i am new to Influxdb javaV3 i hope someone in the community can englight me how to deal with a ghost data (is there but not showing up)