I am making a project where I read in sensor data and send them to a CSV file. The problem is, as soon as the application is not open anymore in the front, the application doesn't work anymore. I have read that I need some kind of service. The question is, which service should I use, and how exactly, so that my sensor acquisition and writing to a CSV file works also when the application is not open, but is also able to show some of these sensor data on the user interface?
If the application is fully closed, it doesn't needs to run anymore and i want to start and stop that all with a button as it can be seen in the code-snippet. I am not sure if then foreground service is the right one.
Code-snippet where you can see how the application is built:
private SensorEventListener OrientSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
OrientX = (int) sensorEvent.values[0];
OrientY = (int) sensorEvent.values[1];
OrientZ = (int) sensorEvent.values[2];
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//User Interface
time = findViewById(R.id.Time1);
//Steps UI
Stepstxt = findViewById(R.id.Stepstxt);
Walkingtxt = findViewById(R.id.Walkingtxt);
FastStepstxt = findViewById(R.id.FastStepstxt);
//Orientation UI
OrientXtxt = findViewById(R.id.OrientXtxt);
OrientYtxt = findViewById(R.id.OrientYtxt);
OrientZtxt = findViewById(R.id.OrientZtxt);
// Set Date for CSV File name and User Interface
Date currentTime = Calendar.getInstance().getTime();
String formattedDate = DateFormat.getDateInstance(DateFormat.FULL).format(currentTime);
time.setText(formattedDate);
// Initializing
SensorSwitch = findViewById(R.id.SensorSwitch);
//Sensor Initializing
//Acceleration
AccSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = AccSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//Amb Light
AmbLightSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAmbLight = AmbLightSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
//Orientation
OrientSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mOrientation = OrientSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
// Record Data to CSV and SwitchFlag
SensorSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b == true) {
// CSV Raw Data Open
Log.d(TAG, "Writing to " getStorageDir());
try {
writer = new FileWriter(new File(getStorageDir(), "RawSensors_" formattedDate ".csv"));
} catch (
IOException e) {
e.printStackTrace();
}
//CSV Feature Data Open
Log.d(TAG, "Writing to " getStorageDir());
try {
fwriter = new FileWriter(new File(getStorageDir(), "FeatureSensors_" formattedDate ".csv"));
} catch (
IOException e) {
e.printStackTrace();
}
SwitchFlag = true;
} else {
//CSV Raw Data Close
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
//CSV Feature Data Close
try {
fwriter.close();
} catch (IOException e) {
e.printStackTrace();
}
SwitchFlag = false;
}
}
});
}
// Next Activity
public void openMainActivity2(){
Intent intentMain2 = new Intent(this, MainActivity2.class);
startActivity(intentMain2);
}
// Start Sensor Events
protected void onResume() {
super.onResume();
AccSensorManager.registerListener(AccSensorEventListener, mAccelerometer, 1000000, 1000000);
AmbLightSensorManager.registerListener(AmbLightSensorEventListener, mAmbLight, 1000000, 1000000);
OrientSensorManager.registerListener(OrientSensorEventListener, mOrientation,1000000, 1000000);
}
protected void onPause() {
super.onPause();
AccSensorManager.unregisterListener(AccSensorEventListener);
AmbLightSensorManager.unregisterListener(AmbLightSensorEventListener);
OrientSensorManager.unregisterListener(OrientSensorEventListener);
}
// CSV File Creation
private String getStorageDir() {
return Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
}
// CSV Write Function
private void CsvWrite(){
try {
writer.write(String.format("DateTime; %s;AccX; %f; AccY; %f; AccZ; %f; AccSum; %f; AmbLight; %d; OrientX; %d; OrientY; %d; OrientZ; %d \n", dateTime, AccX, AccY, AccZ , AccSum, AmbLight, OrientX, OrientY, OrientZ));
}catch (IOException e) {
e.printStackTrace();
}
}
private void FeatureCsv(){
try {
fwriter.write(String.format("DateTime; %s; GoSteps; %d; RunSteps; %d; StepSum; %d; Position; %s; Location; %s \n", dateTime, stepCount, RunCount, StepSum, position, location));
}catch (IOException e) {
e.printStackTrace();
}
}
private void FeatureCalc(){
// Step Calculation
if (AccChange > 40 && AccChange < 150){
stepCount ;
StepSum ;
} else if (AccChange > 150){
RunCount ;
StepSum ;
}
//Display Steps on UI
Stepstxt.setText("You have currently made: " StepSum " Steps");
Walkingtxt.setText("Thereof: " stepCount " Walking Steps");
FastStepstxt.setText("And: " RunCount " Faster Walking or Running Steps");
// Phone Orientation Feature
if(OrientY <= -5 && OrientY > -25){
position = "Standing";
}else if(OrientY <= -25 && OrientY >= - 90){
position = "Sitting";
}else if (OrientY <= -90 && OrientY >= -180 && AmbLight > 13){
position = "Laying";
}
else{
position = "None/NotUsed";
}
//Display Orientation on UI
OrientXtxt.setText("Azimuth: " OrientX "°");
OrientYtxt.setText("Pitch: " OrientY "°");
OrientZtxt.setText("Roll: " OrientZ "°");
// Location Feature
AbsOrient = Math.abs(OrientY);
if(AmbLight <= 13 && AbsOrient >= 60 && AbsOrient <= 120){
location = "Pocket";
}else if((AmbLight <= 13 && OrientY <= -170 && OrientY >= -190) || (OrientY > -5 && OrientY < 5)){
location = "Table";
}else if(AmbLight <= 25){
location = "Night/Indoor";
}else if(AmbLight > 25 && AmbLight <= 800){
location = "Day/Indoor";
}else if(AmbLight > 800){
location = "Day/Outside";
}else{
location = "None/Unknown";
}
}
}
CodePudding user response:
For any kind of service, you can communicate between your activity and the service using intents or binding. More about it here
Foreground service
A foreground service performs some operation that is noticeable to the user.
A foreground service will display a notification to the user, showing that something is happening, here your measurements. Learn more about it here.
You could for instance, allowing the user to stop the measurements from the notification.
Background service
A background service performs an operation that isn't directly noticed by the user.
If you do not want your user to know that you are making measurements, then a background service could be used.
However, since Android 8.0 serious restrictions are made on the usage of Background services, making it hard to use.
WorkManager Tasks
A more recent approach would be to create a task, which can be periodic if you need to repeat your measurements, or one time only using the WorkManager. More about it here.
CodePudding user response:
I reccomend you to create REST and UI app, so you app will read data from REST and your senzor can send data to REST service.