Skip to content

Commit

Permalink
fix: informations disappear on restart app (#16)
Browse files Browse the repository at this point in the history
* fix: informations disappear on restart app

* fix: patch the update view after restarting app

* fix: add callback after restart app to continue to receive location update
  • Loading branch information
pioupia authored Aug 13, 2022
1 parent 64d8260 commit 6c33cd8
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 90 deletions.
33 changes: 31 additions & 2 deletions app/src/main/java/fr/pioupia/courserecorder/BackgroundService.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Locale;

import fr.pioupia.courserecorder.Managers.DirectionManager;
Expand All @@ -30,6 +31,13 @@ public class BackgroundService extends Service {

private final IBinder binder = new LocalBinder();

/* General Data */
public boolean isRecording = true;
public double[] startPoint = new double[2];
public long startingTime = 0;
public Array pauses = new Array(1);
public int index = 0;

/* Files stream */
public FileOutputStream speeds = null;
public FileOutputStream cords = null;
Expand All @@ -43,6 +51,7 @@ public class BackgroundService extends Service {
public double lastAlt = 0;
public int speedCount = 1;
public int speed = 0;
public float actualSpeed = 0;
public float maxSpeed = 0;

private static final int LOCATION_REFRESH_TIME = 5 * 1000;
Expand Down Expand Up @@ -99,7 +108,12 @@ BackgroundService getService() {
}
}

public void setEssentialData(ServiceCallback callback, FileOutputStream speeds, FileOutputStream cords, FileOutputStream alt) {
public void setCallback(ServiceCallback callback) {
this.serviceCallback = callback;
isCallbackDeclared = true;
}

public void setEssentialData(ServiceCallback callback, FileOutputStream speeds, FileOutputStream cords, FileOutputStream alt, int index) {
if (isCallbackDeclared) return;

this.serviceCallback = callback;
Expand All @@ -108,10 +122,16 @@ public void setEssentialData(ServiceCallback callback, FileOutputStream speeds,
this.speeds = speeds;
this.cords = cords;
this.alt = alt;
this.index = index;
}

public void setPauses(Array pauses) {
this.pauses = pauses;
}

public void stopListener() {
mLocationManager.removeUpdates(mLocationListener);
isRecording = false;
}

@SuppressLint("MissingPermission")
Expand All @@ -121,6 +141,7 @@ public void startListener() {
LOCATION_REFRESH_DISTANCE,
mLocationListener,
Looper.getMainLooper());
isRecording = true;
}


Expand All @@ -134,7 +155,9 @@ public void onLocationChanged(final Location location) {
double longitude = location.getLongitude();
double bearing = location.getBearing();
double slope = 0;
float actualSpeed = location.getSpeed();
actualSpeed = location.getSpeed();



altMetric = location.getAltitude();
speed += actualSpeed;
Expand All @@ -156,6 +179,12 @@ public void onLocationChanged(final Location location) {
if (slope > 100 || slope < -100) {
slope = 0;
}
} else {
startPoint[0] = longitude;
startPoint[1] = latitude;

Date date = new Date();
startingTime = date.getTime();
}

lastAlt = altMetric;
Expand Down
243 changes: 155 additions & 88 deletions app/src/main/java/fr/pioupia/courserecorder/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.transition.Visibility;

import android.Manifest;
import android.app.ActivityManager;
Expand Down Expand Up @@ -36,7 +37,7 @@


public class MainActivity extends AppCompatActivity implements BackgroundService.ServiceCallback {
private int index = 0;
public int index = 0;

public Timer timer = new Timer();

Expand Down Expand Up @@ -77,88 +78,6 @@ protected void onCreate(Bundle savedInstanceState) {

rootDir = getApplicationInfo().dataDir + "/records";

File file = new File(rootDir);

if (!file.exists()) {
file.mkdir();
}

file = new File(rootDir + "/index");
if (!file.exists()) {
try {
file.createNewFile();
if (file.canWrite()) {
FileOutputStream outputStream = new FileOutputStream(rootDir + "/index");

/**
* On peut garder en mémoire jusqu'à 127 trajets maximum.
* Ensuite, on upload ça sur le serveur
* Le serveur traite les données
* il renvoie les données en JSON / autre
* On met 30 records / fichier (ou moins, tout dépend de la taille finale du fichier)
* Le nom des fichiers est un index
* Donc en gros, le fichier indexes contiendra :
* numéro du dernier fichier utilisé nombre d'enregistrements
* On a en gros l'architecture suivante :
* /records (dossier des données de trajets)
* /records/index (stockage du dernier index en cache)
* /records/_temp/{index} (dossier de stockage d'un trajet en cache à l'index {index})
* - /speeds (fichier contenant les vitesses)
* - /cords (fichier contenant les coordonnées ; long lat long lat)
* - /alt (fichier content les données altimétriques)
* - /infos (fichier contenant les informations générales en JSON.
* - Date de début (date), date de fin (date)
* - (liste des pauses (ms)), durée (ms)
* - Distance (m), vitesse moyenne (km/h), // vitesse max (km/h)
* - Point de départ, point d'arrivé
* /records/data (dossier qui stock tous les trajets parse)
* /records/data/index (stockage du dernier index sous la forme : "index du dossier numéro du record")
* /records/data/{index}/ (speeds/cords/alt/infos - sous forme de tableau), exemple avec speeds :
* index ...speeds
* 0 12 15.00 12.53 88.12 25.32 46.58
* 1 12 15.00 12.53 88.12 25.32 46.58
* 2 12 15.00 12.53 88.12 25.32 46.58
* 3 12 15.00 12.53 88.12 25.32 46.58
* 4 12 15.00 12.53 88.12 25.32 46.58
*
* Quand on lance l'enregistrement, les 3 derniers trajets s'en vont de la manière suivante :
* - Le premier pars avec un fondu de l'opacité vers la droite (~50px)
* - Le second pars avec ~50ms/100 de retard, avec un fondu de l'opacité, vers la droite (~50px) & vers le haut (~20px)
* - Le troisième pars avec ~100/200ms de retard, avec un fondu de l'opacité, vers la droite (~50px) & vers le haut (~40px)
*/

outputStream.write((byte) index);
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
RandomAccessFile f = new RandomAccessFile(file, "r");
byte[] b = new byte[(int) f.length()];
f.readFully(b);

index = b[0];
} catch (IOException e) {
e.printStackTrace();
}
}

havePermissions = this.permissions.verifyPermissions(MainActivity.this);

if (!havePermissions) {
ActivityCompat.requestPermissions(
MainActivity.this,
new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
},
1
);

havePermissions = this.permissions.verifyPermissions(MainActivity.this);
}

RelativeLayout buttonContainer = findViewById(R.id.buttonsContainer);
ImageView startRecording = findViewById(R.id.startRecording);
ImageView stopRecording = findViewById(R.id.stopRecording);
Expand All @@ -171,6 +90,150 @@ protected void onCreate(Bundle savedInstanceState) {
altitudeView = findViewById(R.id.altitude);
penteView = findViewById(R.id.slop);

if (this.foregroundServiceRunning()) {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (ActivityManager.RunningServiceInfo service : activityManager.getRunningServices(Integer.MAX_VALUE)) {
if (BackgroundService.class.getName().equals(service.service.getClassName())) {
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

timer.schedule(new TimerTask() {
@Override
public void run() {
if (isServiceBounded) {
backgroundService.setCallback(MainActivity.this);

// restore data
isRecording = backgroundService.isRecording;
startPoint = backgroundService.startPoint;
startingTime = backgroundService.startingTime;
pauses = backgroundService.pauses;
index = backgroundService.index;

MainActivity.this.runOnUiThread(() -> {
buttonContainer.setVisibility(View.VISIBLE);
stopRecording.setVisibility(View.VISIBLE);

startRecording.setVisibility(View.GONE);

if (!isRecording) {
resumeRecording.setVisibility(View.VISIBLE);
pauseRecording.setVisibility(View.GONE);
} else {
resumeRecording.setVisibility(View.GONE);
pauseRecording.setVisibility(View.VISIBLE);
}

String duration = new DurationManager().getDuration(startingTime);
durationView.setText("Durée d'enregistrement :" + duration);
altitudeView.setText("Altitude : " + (int) backgroundService.altMetric + "m");

speedView.setText(
String.format(Locale.FRANCE, "Vitesse : %d km/h", (int) backgroundService.actualSpeed)
);

if (backgroundService.distance > 1000) {
double d = (double) backgroundService.distance / 1000;
distanceView.setText(
String.format(Locale.FRANCE, "Distance parcourue : %.2f km", d)
);
} else {
distanceView.setText(
String.format(Locale.FRANCE, "Distance parcourue : %d m", (int) backgroundService.distance)
);
}
});

timer.cancel();
timer.purge();
}
}
}, 300, 100);
}
}
} else {
File file = new File(rootDir);

if (!file.exists()) {
file.mkdir();
}

file = new File(rootDir + "/index");
if (!file.exists()) {
try {
file.createNewFile();
if (file.canWrite()) {
FileOutputStream outputStream = new FileOutputStream(rootDir + "/index");

/**
* On peut garder en mémoire jusqu'à 127 trajets maximum.
* Ensuite, on upload ça sur le serveur
* Le serveur traite les données
* il renvoie les données en JSON / autre
* On met 30 records / fichier (ou moins, tout dépend de la taille finale du fichier)
* Le nom des fichiers est un index
* Donc en gros, le fichier indexes contiendra :
* numéro du dernier fichier utilisé nombre d'enregistrements
* On a en gros l'architecture suivante :
* /records (dossier des données de trajets)
* /records/index (stockage du dernier index en cache)
* /records/_temp/{index} (dossier de stockage d'un trajet en cache à l'index {index})
* - /speeds (fichier contenant les vitesses)
* - /cords (fichier contenant les coordonnées ; long lat long lat)
* - /alt (fichier content les données altimétriques)
* - /infos (fichier contenant les informations générales en JSON.
* - Date de début (date), date de fin (date)
* - (liste des pauses (ms)), durée (ms)
* - Distance (m), vitesse moyenne (km/h), // vitesse max (km/h)
* - Point de départ, point d'arrivé
* /records/data (dossier qui stock tous les trajets parse)
* /records/data/index (stockage du dernier index sous la forme : "index du dossier numéro du record")
* /records/data/{index}/ (speeds/cords/alt/infos - sous forme de tableau), exemple avec speeds :
* index ...speeds
* 0 12 15.00 12.53 88.12 25.32 46.58
* 1 12 15.00 12.53 88.12 25.32 46.58
* 2 12 15.00 12.53 88.12 25.32 46.58
* 3 12 15.00 12.53 88.12 25.32 46.58
* 4 12 15.00 12.53 88.12 25.32 46.58
*
* Quand on lance l'enregistrement, les 3 derniers trajets s'en vont de la manière suivante :
* - Le premier pars avec un fondu de l'opacité vers la droite (~50px)
* - Le second pars avec ~50ms/100 de retard, avec un fondu de l'opacité, vers la droite (~50px) & vers le haut (~20px)
* - Le troisième pars avec ~100/200ms de retard, avec un fondu de l'opacité, vers la droite (~50px) & vers le haut (~40px)
*/

outputStream.write((byte) index);
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
RandomAccessFile f = new RandomAccessFile(file, "r");
byte[] b = new byte[(int) f.length()];
f.readFully(b);

index = b[0];
} catch (IOException e) {
e.printStackTrace();
}
}

havePermissions = this.permissions.verifyPermissions(MainActivity.this);

if (!havePermissions) {
ActivityCompat.requestPermissions(
MainActivity.this,
new String[]{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
},
1
);

havePermissions = this.permissions.verifyPermissions(MainActivity.this);
}
}


startRecording.setOnClickListener(v -> {
havePermissions = permissions.askPermissions(MainActivity.this, MainActivity.this, havePermissions);
Expand Down Expand Up @@ -216,7 +279,7 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void run() {
if (isServiceBounded) {
backgroundService.setEssentialData(MainActivity.this, speeds, cords, alt);
backgroundService.setEssentialData(MainActivity.this, speeds, cords, alt, index);
timer.cancel();
timer.purge();
}
Expand Down Expand Up @@ -315,7 +378,7 @@ public void run() {

try {
FileOutputStream outputStream = new FileOutputStream(rootDir + "/index");
outputStream.write((byte) index+1);
outputStream.write((byte) index + 1);
} catch (IOException e) {
e.printStackTrace();
}
Expand All @@ -342,6 +405,8 @@ public void run() {

long date = new Date().getTime();
pauses.push(date);

backgroundService.setPauses(pauses);
});

resumeRecording.setOnClickListener(view -> {
Expand Down Expand Up @@ -374,6 +439,8 @@ public void run() {
);

pauses.push(date);

backgroundService.setPauses(pauses);
});
}

Expand All @@ -391,10 +458,10 @@ public void onServiceDisconnected(ComponentName componentName) {
}
};

public boolean foregroundServiceRunning(){
public boolean foregroundServiceRunning() {
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for(ActivityManager.RunningServiceInfo service: activityManager.getRunningServices(Integer.MAX_VALUE)) {
if(BackgroundService.class.getName().equals(service.service.getClassName())) {
for (ActivityManager.RunningServiceInfo service : activityManager.getRunningServices(Integer.MAX_VALUE)) {
if (BackgroundService.class.getName().equals(service.service.getClassName())) {
return true;
}
}
Expand Down

0 comments on commit 6c33cd8

Please sign in to comment.