Compare commits

..

No commits in common. "699c533789968421ed83b06dc0cecf3693d011d9" and "046d1d3a26b1cb1f81757a38a026dd07bb329921" have entirely different histories.

4 changed files with 26 additions and 110 deletions

View file

@ -26,8 +26,8 @@ android {
} }
} }
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_1_8
} }
} }
@ -50,9 +50,4 @@ dependencies {
// optional - Guava support for Room, including Optional and ListenableFuture // optional - Guava support for Room, including Optional and ListenableFuture
implementation("androidx.room:room-guava:$room_version") implementation("androidx.room:room-guava:$room_version")
implementation("io.jenetics:jpx:3.1.0")
// https://mvnrepository.com/artifact/org.codehaus.woodstox/woodstox-core-asl
implementation("org.codehaus.woodstox:woodstox-core-asl:4.4.1")
} }

View file

@ -9,7 +9,6 @@ import android.location.LocationListener;
import android.os.Bundle; import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.util.Log; import android.util.Log;
import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import androidx.activity.EdgeToEdge; import androidx.activity.EdgeToEdge;
@ -19,27 +18,13 @@ import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat; import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsCompat;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.Writer;
import io.jenetics.jpx.GPX;
import io.jenetics.jpx.WayPoint;
public class MainActivity extends AppCompatActivity implements LocationListener, ServiceConnection { public class MainActivity extends AppCompatActivity implements LocationListener, ServiceConnection {
private final String TAG = MainActivity.class.getName(); private final String TAG = MainActivity.class.getName();
private Button exportButton;
private WriteToFile writeToFile;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
writeToFile = new WriteToFile(this,"application/gpx");
Intent serviceIntent = new Intent(this, LocationLoggingService.class); Intent serviceIntent = new Intent(this, LocationLoggingService.class);
startForegroundService(serviceIntent); startForegroundService(serviceIntent);
@ -50,8 +35,6 @@ public class MainActivity extends AppCompatActivity implements LocationListener,
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets; return insets;
}); });
exportButton = findViewById(R.id.buttonExport);
} }
@Override @Override
@ -86,73 +69,6 @@ public class MainActivity extends AppCompatActivity implements LocationListener,
LocationLoggingServiceBinder binder = (LocationLoggingServiceBinder) iBinder; LocationLoggingServiceBinder binder = (LocationLoggingServiceBinder) iBinder;
binder.subscribeToLocationUpdates(this); binder.subscribeToLocationUpdates(this);
if(exportButton != null){
exportButton.setOnClickListener(v -> {
Log.d(TAG, "Export button clicked.");
new Thread(() -> {
GPX gpx = GPX.builder().addTrack(track -> track.addSegment(segment -> {
for(LocationEntity location : binder.allLocations()){
segment.addPoint(locationToWayPoint(location));
}
})).build();
Log.d(TAG, "Built GPX.");
writeToFile.write("output.gpx", outputStream -> {
try {
GPX.Writer.of(GPX.Writer.Indent.SPACE4).write(gpx, outputStream);
} catch (IOException e) {
Log.e(TAG, "Failed to write.");
}
});
}).start();
});
}
}
private static WayPoint locationToWayPoint(LocationEntity location) {
WayPoint.Builder builder = WayPoint.builder()
.lat(location.latitude)
.lon(location.longitude)
.time(location.unixTime);
if(location.speed != null){
builder.speed(location.speed);
}
if(location.bearing != null){
builder.course(location.bearing);
}
if(location.altitude != null){
builder.ele(location.altitude);
}
StringBuilder commentBuilder = new StringBuilder();
if(location.isMock){
commentBuilder.append("Location is mock.\n");
}
if(location.accuracy != null){
commentBuilder.append(String.format("Accuracy is expected to be within %s meters.\n", location.accuracy));
}
if(location.altitudeAccuracy != null){
commentBuilder.append(String.format("Altitude accuracy is expected to be within %s meters.\n", location.altitudeAccuracy));
}
if(location.bearingAccuracy != null){
commentBuilder.append(String.format("Bearing accuracy is expected to be within %s degrees.\n", location.bearingAccuracy));
}
if(location.speedAccuracy != null){
commentBuilder.append(String.format("Speed accuracy is expected to be within %s meters per second.\n", location.speedAccuracy));
}
builder.cmt(commentBuilder.toString());
return builder.build();
} }
@Override @Override

View file

@ -1,5 +1,6 @@
package com.proculite.logmylocation; package com.proculite.logmylocation;
import android.content.Context;
import android.net.Uri; import android.net.Uri;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.util.Log; import android.util.Log;
@ -8,22 +9,30 @@ import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher; import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts; import androidx.activity.result.contract.ActivityResultContracts;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.function.Consumer; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class WriteToFile implements ActivityResultCallback<Uri> { public class WriteToFile implements ActivityResultCallback<Uri> {
private final String TAG = WriteToFile.class.getName(); private final String TAG = WriteToFile.class.getName();
private Consumer<OutputStream> fileConsumer; private final InputStream fileContents;
private final AppCompatActivity activityCompat; private final AppCompatActivity activityCompat;
private final ActivityResultLauncher<String> launcher;
public WriteToFile(AppCompatActivity activity, String fileMimeType) public WriteToFile(AppCompatActivity activity, String fileName, String fileMimeType, InputStream fileContents)
{ {
this.fileContents = fileContents;
this.activityCompat = activity; this.activityCompat = activity;
this.launcher = activity.registerForActivityResult( ActivityResultLauncher<String> launcher =
new ActivityResultContracts.CreateDocument(fileMimeType), this); activity.registerForActivityResult(new ActivityResultContracts.CreateDocument(fileMimeType), this);
launcher.launch(fileName);
} }
@Override @Override
@ -43,7 +52,9 @@ public class WriteToFile implements ActivityResultCallback<Uri> {
return; return;
} }
try (FileOutputStream fileOutputStream = new FileOutputStream(fileDescriptor.getFileDescriptor())) { try (FileOutputStream fileOutputStream = new FileOutputStream(fileDescriptor.getFileDescriptor())) {
fileConsumer.accept(fileOutputStream); while (fileContents.available() > 0) {
fileOutputStream.write(fileContents.read());
}
} }
} }
} catch (IOException e) { } catch (IOException e) {
@ -51,8 +62,11 @@ public class WriteToFile implements ActivityResultCallback<Uri> {
} }
} }
public void write(String fileName, Consumer<OutputStream> fileConsumer){ public static WriteToFile WriteBytes(AppCompatActivity activity, String fileName, String fileMimeType, byte[] fileContents){
this.fileConsumer = fileConsumer; return new WriteToFile(activity, fileName, fileMimeType, new ByteArrayInputStream(fileContents));
launcher.launch(fileName); }
public static WriteToFile WriteString(AppCompatActivity activity, String fileName, String fileMimeType, String fileContents){
return WriteBytes(activity, fileName, fileMimeType, fileContents.getBytes(StandardCharsets.UTF_8));
} }
} }

View file

@ -18,13 +18,4 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/buttonExport"
app:layout_constraintTop_toBottomOf="@+id/textViewMain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="Export"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>