Commit 4724a329 authored by Bartek Fabiszewski's avatar Bartek Fabiszewski
Browse files

Target API 29

parent 044745b9
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3,11 +3,11 @@ jdk: oraclejdk8
android:
  components:
    - tools
    - build-tools-28.0.3
    - platform-tools
    - build-tools-29.0.0
    - android-29
    - extra-android-m2repository
    - extra-google-android-support
    - android-28
script:
  - ./gradlew build
after_success:
+6 −5
Original line number Diff line number Diff line
@@ -10,12 +10,12 @@
apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    compileSdkVersion 29

    defaultConfig {
        applicationId 'net.fabiszewski.ulogger'
        minSdkVersion 14
        targetSdkVersion 28
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 207
        versionName '2.7'
    }
@@ -26,14 +26,15 @@ android {
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            applicationIdSuffix ".debug"
            versionNameSuffix "-dev"
            applicationIdSuffix '.debug'
            versionNameSuffix '-dev'
        }
    }

    lintOptions {
        disable 'GoogleAppIndexingWarning'
        disable 'MissingTranslation'
        disable 'NotificationIconCompatibility'
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
+2 −3
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <!-- For web sync retries -->
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <!-- For exporting tracks -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <!-- For foreground services API >= 28 -->
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

@@ -51,7 +49,8 @@
        <service
            android:name=".LoggerService"
            android:enabled="true"
            android:exported="false" />
            android:exported="false"
            android:foregroundServiceType="location" />
        <service
            android:name=".WebSyncService"
            android:exported="false" />
+12 −10
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ public class ExternalCommandReceiver extends BroadcastReceiver {
        }
        if (intent != null) {
            String command = intent.getStringExtra("command");
            if (command != null) {
                switch (command) {
                    case START_LOGGER:
                        startLoggerService(context);
@@ -44,6 +45,7 @@ public class ExternalCommandReceiver extends BroadcastReceiver {
                        break;
                }
            }
        }

    }

+70 −124
Original line number Diff line number Diff line
@@ -9,26 +9,20 @@

package net.fabiszewski.ulogger;

import android.Manifest;
import android.app.IntentService;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Environment;
import android.net.Uri;
import android.util.Log;
import android.util.Xml;

import androidx.annotation.NonNull;

import org.xmlpull.v1.XmlSerializer;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.Charset;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import java.io.OutputStream;

/**
 * Export track to GPX format
@@ -37,7 +31,6 @@ public class GpxExportService extends IntentService {

    private static final String TAG = GpxExportService.class.getSimpleName();

    public static final String BROADCAST_WRITE_PERMISSION_DENIED = "net.fabiszewski.ulogger.broadcast.write_permission_denied";
    public static final String BROADCAST_EXPORT_FAILED = "net.fabiszewski.ulogger.broadcast.write_failed";
    public static final String BROADCAST_EXPORT_DONE = "net.fabiszewski.ulogger.broadcast.write_ok";

@@ -47,8 +40,8 @@ public class GpxExportService extends IntentService {
    private static final String schemaLocation = ns_gpx + " http://www.topografix.com/GPX/1/1/gpx.xsd " +
            ns_ulogger + " https://raw.githubusercontent.com/bfabiszewski/ulogger-server/master/scripts/gpx_extensions1.xsd";

    private static final String ULOGGER_DIR = "ulogger_tracks";
    private static final String GPX_EXTENSION = ".gpx";
    public static final String GPX_EXTENSION = ".gpx";
    public static final String GPX_MIME = "application/gpx+xml";

    public GpxExportService() {
        super("GpxExportService");
@@ -84,42 +77,43 @@ public class GpxExportService extends IntentService {
     */
    @Override
    protected void onHandleIntent(Intent intent) {

        if (!hasWritePermission()) {
            // no permission to write
            if (Logger.DEBUG) { Log.d(TAG, "[export gpx no permission]"); }
            sendBroadcast(BROADCAST_WRITE_PERMISSION_DENIED, null);
            return;
        if (intent != null && intent.getData() != null) {
            try {
                write(intent.getData());
                sendBroadcast(BROADCAST_EXPORT_DONE, null);
            } catch (IOException e) {
                sendBroadcast(BROADCAST_EXPORT_FAILED, e.getMessage());
            }
        if (!isExternalStorageWritable()) {
            // no access to external storage
            if (Logger.DEBUG) { Log.d(TAG, "[export gpx not writable]"); }
            sendBroadcast(BROADCAST_EXPORT_FAILED, getString(R.string.e_external_not_writable));
            return;
        }

        String trackName = db.getTrackName();
        if (trackName == null) {
            trackName = getString(R.string.unknown_track);
    }
        File dir = getDir();
        if (dir == null) {
            if (Logger.DEBUG) { Log.d(TAG, "[export gpx failed to create output folder]"); }
            sendBroadcast(BROADCAST_EXPORT_FAILED, getString(R.string.e_output_dir));
            return;

    /**
     * Write serialized track to URI
     * @param uri Target URI
     * @throws IOException Exception
     */
    private void write(@NonNull Uri uri) throws IOException {
        OutputStream stream = getContentResolver().openOutputStream(uri);
        if (stream == null) {
            throw new IOException(getString(R.string.e_open_out_stream));
        }
        try (BufferedOutputStream bufferedStream = new BufferedOutputStream(stream)) {
            serialize(bufferedStream);
            if (Logger.DEBUG) { Log.d(TAG, "[export gpx file written to " + uri); }
        } catch (IOException|IllegalArgumentException|IllegalStateException e) {
            if (Logger.DEBUG) { Log.d(TAG, "[export gpx write exception: " + e + "]"); }
            throw new IOException(e.getMessage());
        }
        File file = getFile(dir, trackName);
        int i = 0;
        while (file.exists()) {
            file = getFile(dir, trackName + "_" + (++i));
    }

        try (FileOutputStream stream = new FileOutputStream(file);
             OutputStreamWriter writer = new OutputStreamWriter(stream, Charset.forName("UTF-8"));
             BufferedWriter bufferedWriter = new BufferedWriter(writer)) {

    /**
     * Serialize and write
     * @param stream Output stream
     * @throws IOException Exception
     */
    private void serialize(@NonNull OutputStream stream) throws IOException {
        XmlSerializer serializer = Xml.newSerializer();
            serializer.setOutput(bufferedWriter);
        serializer.setOutput(stream, "UTF-8");

        // header
        serializer.startDocument("UTF-8", true);
@@ -134,6 +128,10 @@ public class GpxExportService extends IntentService {
        serializer.attribute(null, "creator", creator);

        // metadata
        String trackName = db.getTrackName();
        if (trackName == null) {
            trackName = getString(R.string.unknown_track);
        }
        long trackTimestamp = db.getFirstTimestamp();
        String trackTime = DbAccess.getTimeISO8601(trackTimestamp);
        serializer.startTag(null, "metadata");
@@ -150,14 +148,6 @@ public class GpxExportService extends IntentService {
        serializer.endTag("", "gpx");
        serializer.endDocument();
        serializer.flush();

            if (Logger.DEBUG) { Log.d(TAG, "[export gpx file written to " + file.getPath()); }
            sendBroadcast(BROADCAST_EXPORT_DONE, null);
        } catch (IOException|IllegalArgumentException|IllegalStateException e) {
            if (Logger.DEBUG) { Log.d(TAG, "[export gpx exception: " + e + "]"); }
            sendBroadcast(BROADCAST_EXPORT_FAILED, e.getMessage());
        }

    }

    /**
@@ -238,50 +228,6 @@ public class GpxExportService extends IntentService {
        serializer.endTag(ns, name);
    }

    /**
     * Has user granted write permission?
     *
     * @return True if permission granted, false otherwise
     */
    private boolean hasWritePermission() {
        return (ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
    }

    /**
     * Is there external storage we can write to?
     *
     * @return True if writable, false otherwise
     */
    private boolean isExternalStorageWritable() {
        String state = Environment.getExternalStorageState();
        return Environment.MEDIA_MOUNTED.equals(state);
    }

    /**
     * Set up directory in Downloads folder
     *
     * @return File instance or null in case of failure
     */
    private File getDir() {
        File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), ULOGGER_DIR);
        if (!dir.exists() && !dir.mkdirs()) {
            dir = null;
        }
        return dir;
    }

    /**
     * Set up file instance with given name in given folder
     *
     * @param dir Folder
     * @param trackName File name
     * @return File instance
     */
    private File getFile(@NonNull File dir, @NonNull String trackName) {
        String fileName = trackName.replaceAll("[?:\"'*|/\\\\<>]", "_") + GPX_EXTENSION;
        return new File(dir, fileName);
    }

    /**
     * Send broadcast message
     * @param broadcast Broadcast intent
Loading