forked from upstream-mirrors/OpenTracks
Import: replaced async task with thread.
Extracted directory chooser into a separate activity.
This commit is contained in:
+2
-1
@@ -47,6 +47,7 @@ MarkerDetailActivity --> CoordinateOnMapIntent : URI
|
|||||||
SettingsActivity --> AboutActivity
|
SettingsActivity --> AboutActivity
|
||||||
SettingsActivity --> HelpActivity
|
SettingsActivity --> HelpActivity
|
||||||
SettingsActivity --> ExportActivity
|
SettingsActivity --> ExportActivity
|
||||||
SettingsActivity --> ImportActivity
|
SettingsActivity --> DirectoryChooserActivity
|
||||||
|
DirectoryChooserActivity --> ImportActivity
|
||||||
|
|
||||||
@enduml
|
@enduml
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ limitations under the License.
|
|||||||
android:name=".HelpActivity"
|
android:name=".HelpActivity"
|
||||||
android:label="@string/menu_help" />
|
android:label="@string/menu_help" />
|
||||||
|
|
||||||
|
<activity android:name=".io.file.importer.DirectoryChooserActivity" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".io.file.importer.ImportActivity"
|
android:name=".io.file.importer.ImportActivity"
|
||||||
android:theme="@style/ThemeCustomTransparentActivity">
|
android:theme="@style/ThemeCustomTransparentActivity">
|
||||||
|
|||||||
+15
-2
@@ -31,6 +31,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
import javax.xml.parsers.SAXParser;
|
import javax.xml.parsers.SAXParser;
|
||||||
@@ -72,6 +73,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
// The current element content
|
// The current element content
|
||||||
//TODO Should be made private and getter be used by child classes.
|
//TODO Should be made private and getter be used by child classes.
|
||||||
protected String content;
|
protected String content;
|
||||||
|
|
||||||
protected String icon;
|
protected String icon;
|
||||||
protected String name;
|
protected String name;
|
||||||
protected String description;
|
protected String description;
|
||||||
@@ -83,6 +85,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
protected String speed;
|
protected String speed;
|
||||||
protected String waypointType;
|
protected String waypointType;
|
||||||
protected String photoUrl;
|
protected String photoUrl;
|
||||||
|
protected String uuid;
|
||||||
|
|
||||||
// The current track data
|
// The current track data
|
||||||
private TrackData trackData;
|
private TrackData trackData;
|
||||||
@@ -91,11 +94,11 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
private Locator locator;
|
private Locator locator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param context the context
|
* @param context the context
|
||||||
* @param importTrackId the track id to import to. -1L to import to a new track.
|
* @param importTrackId the track id to import to. -1L to import to a new track.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
|
// Remove importTrackId
|
||||||
AbstractFileTrackImporter(Context context, long importTrackId, ContentProviderUtils contentProviderUtils) {
|
AbstractFileTrackImporter(Context context, long importTrackId, ContentProviderUtils contentProviderUtils) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.importTrackId = importTrackId;
|
this.importTrackId = importTrackId;
|
||||||
@@ -244,6 +247,16 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track
|
|||||||
if (name != null) {
|
if (name != null) {
|
||||||
trackData.track.setName(name);
|
trackData.track.setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UUID uuidParsed;
|
||||||
|
try {
|
||||||
|
uuidParsed = UUID.fromString(uuid);
|
||||||
|
} catch (IllegalArgumentException | NullPointerException e) {
|
||||||
|
Log.w(TAG, "could not parse Track UUID, generating a new one.");
|
||||||
|
uuidParsed = UUID.randomUUID();
|
||||||
|
}
|
||||||
|
trackData.track.setUuid(uuidParsed);
|
||||||
|
|
||||||
if (description != null) {
|
if (description != null) {
|
||||||
trackData.track.setDescription(description);
|
trackData.track.setDescription(description);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package de.dennisguse.opentracks.io.file.importer;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import de.dennisguse.opentracks.util.IntentUtils;
|
||||||
|
|
||||||
|
public class DirectoryChooserActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
private static final int DIRECTORY_PICKER_REQUEST_CODE = 6;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||||
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
|
|
||||||
|
startActivityForResult(intent, DIRECTORY_PICKER_REQUEST_CODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent resultData) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, resultData);
|
||||||
|
if (requestCode == DIRECTORY_PICKER_REQUEST_CODE) {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
Uri directoryUri = resultData.getData();
|
||||||
|
|
||||||
|
Intent intent = IntentUtils.newIntent(this, ImportActivity.class);
|
||||||
|
intent.putExtra(ImportActivity.EXTRA_DIRECTORY_URI_KEY, directoryUri);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,24 +16,24 @@
|
|||||||
|
|
||||||
package de.dennisguse.opentracks.io.file.importer;
|
package de.dennisguse.opentracks.io.file.importer;
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.documentfile.provider.DocumentFile;
|
import androidx.documentfile.provider.DocumentFile;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.R;
|
import de.dennisguse.opentracks.R;
|
||||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||||
import de.dennisguse.opentracks.util.DialogUtils;
|
import de.dennisguse.opentracks.util.DialogUtils;
|
||||||
import de.dennisguse.opentracks.util.FileUtils;
|
import de.dennisguse.opentracks.util.FileUtils;
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An activity to import files from the external storage.
|
* An activity to import files from the external storage.
|
||||||
@@ -42,14 +42,18 @@ import de.dennisguse.opentracks.util.PreferencesUtils;
|
|||||||
*/
|
*/
|
||||||
public class ImportActivity extends FragmentActivity {
|
public class ImportActivity extends FragmentActivity {
|
||||||
|
|
||||||
private static final int DIRECTORY_PICKER_REQUEST_CODE = 6;
|
private static final String TAG = ImportActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
public static final String EXTRA_DIRECTORY_URI_KEY = "directory_uri";
|
||||||
|
|
||||||
private static final int DIALOG_PROGRESS_ID = 0;
|
private static final int DIALOG_PROGRESS_ID = 0;
|
||||||
private static final int DIALOG_RESULT_ID = 1;
|
private static final int DIALOG_RESULT_ID = 1;
|
||||||
|
|
||||||
|
private DocumentFile pickedDirectory;
|
||||||
private String directoryDisplayName;
|
private String directoryDisplayName;
|
||||||
|
|
||||||
private ImportAsyncTask importAsyncTask;
|
|
||||||
|
private Thread importTask = new ImportThread();
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
|
|
||||||
private int importedTrackCount;
|
private int importedTrackCount;
|
||||||
@@ -59,29 +63,22 @@ public class ImportActivity extends FragmentActivity {
|
|||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
Uri directoryUri = getIntent().getParcelableExtra(EXTRA_DIRECTORY_URI_KEY);
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
pickedDirectory = DocumentFile.fromTreeUri(this, directoryUri);
|
||||||
|
directoryDisplayName = FileUtils.getPath(pickedDirectory);
|
||||||
startActivityForResult(intent, DIRECTORY_PICKER_REQUEST_CODE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent resultData) {
|
protected void onStart() {
|
||||||
super.onActivityResult(requestCode, resultCode, resultData);
|
super.onStart();
|
||||||
if (requestCode == DIRECTORY_PICKER_REQUEST_CODE) {
|
showDialog(DIALOG_PROGRESS_ID);
|
||||||
if (resultCode == Activity.RESULT_OK) {
|
importTask.start();
|
||||||
Uri directoryUri = resultData.getData();
|
}
|
||||||
DocumentFile pickedDirectory = DocumentFile.fromTreeUri(this, directoryUri);
|
|
||||||
|
|
||||||
directoryDisplayName = FileUtils.getPath(pickedDirectory);
|
@Override
|
||||||
TrackFileFormat trackFileFormat = PreferencesUtils.getExportTrackFileFormat(this);
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
importAsyncTask = new ImportAsyncTask(this, trackFileFormat, pickedDirectory);
|
importTask.interrupt();
|
||||||
importAsyncTask.execute();
|
|
||||||
} else {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -89,13 +86,10 @@ public class ImportActivity extends FragmentActivity {
|
|||||||
switch (id) {
|
switch (id) {
|
||||||
case DIALOG_PROGRESS_ID:
|
case DIALOG_PROGRESS_ID:
|
||||||
progressDialog = DialogUtils.createHorizontalProgressDialog(
|
progressDialog = DialogUtils.createHorizontalProgressDialog(
|
||||||
this, R.string.import_progress_message, new DialogInterface.OnCancelListener() {
|
this, R.string.import_progress_message, dialog -> {
|
||||||
@Override
|
importTask.interrupt();
|
||||||
public void onCancel(DialogInterface dialog) {
|
dialog.dismiss();
|
||||||
importAsyncTask.cancel(true);
|
finish();
|
||||||
dialog.dismiss();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}, directoryDisplayName);
|
}, directoryDisplayName);
|
||||||
return progressDialog;
|
return progressDialog;
|
||||||
case DIALOG_RESULT_ID:
|
case DIALOG_RESULT_ID:
|
||||||
@@ -120,18 +114,12 @@ public class ImportActivity extends FragmentActivity {
|
|||||||
message = getString(R.string.import_error, importedTrackCount, totalFiles, directoryDisplayName);
|
message = getString(R.string.import_error, importedTrackCount, totalFiles, directoryDisplayName);
|
||||||
}
|
}
|
||||||
return new AlertDialog.Builder(this).setCancelable(true).setIcon(iconId)
|
return new AlertDialog.Builder(this).setCancelable(true).setIcon(iconId)
|
||||||
.setMessage(message).setOnCancelListener(new DialogInterface.OnCancelListener() {
|
.setMessage(message).setOnCancelListener(dialogInterface -> {
|
||||||
@Override
|
dialogInterface.dismiss();
|
||||||
public void onCancel(DialogInterface dialogInterface) {
|
finish();
|
||||||
dialogInterface.dismiss();
|
}).setPositiveButton(R.string.generic_ok, (dialogInterface, which) -> {
|
||||||
finish();
|
dialogInterface.dismiss();
|
||||||
}
|
finish();
|
||||||
}).setPositiveButton(R.string.generic_ok, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialogInterface, int which) {
|
|
||||||
dialogInterface.dismiss();
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}).setTitle(titleId).create();
|
}).setTitle(titleId).create();
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
@@ -145,17 +133,12 @@ public class ImportActivity extends FragmentActivity {
|
|||||||
* @param aTotalCount the number of files to import
|
* @param aTotalCount the number of files to import
|
||||||
*/
|
*/
|
||||||
public void onAsyncTaskCompleted(int aSuccessCount, int aTotalCount) {
|
public void onAsyncTaskCompleted(int aSuccessCount, int aTotalCount) {
|
||||||
importedTrackCount = aSuccessCount;
|
runOnUiThread(() -> {
|
||||||
totalTrackCount = aTotalCount;
|
importedTrackCount = aSuccessCount;
|
||||||
removeDialog(DIALOG_PROGRESS_ID);
|
totalTrackCount = aTotalCount;
|
||||||
showDialog(DIALOG_RESULT_ID);
|
removeDialog(DIALOG_PROGRESS_ID);
|
||||||
}
|
showDialog(DIALOG_RESULT_ID);
|
||||||
|
});
|
||||||
/**
|
|
||||||
* Shows the progress dialog.
|
|
||||||
*/
|
|
||||||
public void showProgressDialog() {
|
|
||||||
showDialog(DIALOG_PROGRESS_ID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,4 +154,54 @@ public class ImportActivity extends FragmentActivity {
|
|||||||
progressDialog.setProgress(Math.min(number, max));
|
progressDialog.setProgress(Math.min(number, max));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ImportThread extends Thread {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<DocumentFile> files = FileUtils.getFiles(pickedDirectory);
|
||||||
|
int totalTrackCount = files.size();
|
||||||
|
int importedTrackCount = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < totalTrackCount; i++) {
|
||||||
|
if (Thread.interrupted()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (importFile(files.get(i))) {
|
||||||
|
importedTrackCount++;
|
||||||
|
}
|
||||||
|
setProgressDialogValue(i + 1, totalTrackCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
onAsyncTaskCompleted(importedTrackCount, totalTrackCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports a file.
|
||||||
|
*
|
||||||
|
* @param file the file
|
||||||
|
*/
|
||||||
|
private boolean importFile(final DocumentFile file) {
|
||||||
|
TrackImporter trackImporter;
|
||||||
|
String fileExtension = FileUtils.getExtension(file);
|
||||||
|
|
||||||
|
if (TrackFileFormat.GPX.getExtension().equals(fileExtension)) {
|
||||||
|
trackImporter = new GpxFileTrackImporter(ImportActivity.this);
|
||||||
|
} else if (TrackFileFormat.KML_WITH_TRACKDETAIL_AND_SENSORDATA.getExtension().equals(fileExtension)) {
|
||||||
|
trackImporter = new KmlFileTrackImporter(ImportActivity.this, -1L);
|
||||||
|
} else if (TrackFileFormat.KMZ_WITH_TRACKDETAIL_AND_SENSORDATA_AND_PICTURES.getExtension().equals(fileExtension)) {
|
||||||
|
trackImporter = new KmzTrackImporter(ImportActivity.this, -1L, file.getUri());
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "Unsupported file format.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (InputStream inputStream = ImportActivity.this.getContentResolver().openInputStream(file.getUri())) {
|
||||||
|
return trackImporter.importFile(inputStream) != -1L;
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Unable to import file", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,179 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2012 Google Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
||||||
* use this file except in compliance with the License. You may obtain a copy of
|
|
||||||
* the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations under
|
|
||||||
* the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.dennisguse.opentracks.io.file.importer;
|
|
||||||
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.AsyncTask;
|
|
||||||
import android.os.PowerManager.WakeLock;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.documentfile.provider.DocumentFile;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import de.dennisguse.opentracks.content.data.Track;
|
|
||||||
import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
|
|
||||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
|
||||||
import de.dennisguse.opentracks.util.FileUtils;
|
|
||||||
import de.dennisguse.opentracks.util.PreferencesUtils;
|
|
||||||
import de.dennisguse.opentracks.util.SystemUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AsyncTask to import files from the external storage.
|
|
||||||
*
|
|
||||||
* @author Jimmy Shih
|
|
||||||
*/
|
|
||||||
class ImportAsyncTask extends AsyncTask<Void, Integer, Boolean> {
|
|
||||||
|
|
||||||
private static final String TAG = ImportAsyncTask.class.getSimpleName();
|
|
||||||
private final TrackFileFormat trackFileFormat;
|
|
||||||
private final DocumentFile directory;
|
|
||||||
|
|
||||||
// TODO Use weak reference
|
|
||||||
private ImportActivity importActivity;
|
|
||||||
private WakeLock wakeLock;
|
|
||||||
|
|
||||||
private int importTrackCount;
|
|
||||||
private int totalTrackCount;
|
|
||||||
private long lastSuccessfulTrackId;
|
|
||||||
|
|
||||||
public ImportAsyncTask(ImportActivity importActivity, TrackFileFormat trackFileFormat, DocumentFile directory) {
|
|
||||||
this.importActivity = importActivity;
|
|
||||||
this.trackFileFormat = trackFileFormat;
|
|
||||||
this.directory = directory;
|
|
||||||
|
|
||||||
importTrackCount = 0;
|
|
||||||
totalTrackCount = 0;
|
|
||||||
lastSuccessfulTrackId = -1L;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPreExecute() {
|
|
||||||
if (importActivity != null) {
|
|
||||||
importActivity.showProgressDialog();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of files.
|
|
||||||
*/
|
|
||||||
private static List<DocumentFile> getFiles(DocumentFile file, TrackFileFormat trackFileFormat) {
|
|
||||||
List<DocumentFile> files = new ArrayList<>();
|
|
||||||
|
|
||||||
for (DocumentFile candidate : file.listFiles()) {
|
|
||||||
if (!candidate.isDirectory()) {
|
|
||||||
String extension = FileUtils.getExtension(candidate.getName());
|
|
||||||
if (extension != null && trackFileFormat.getExtension().equals(extension)) {
|
|
||||||
files.add(candidate);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
files.addAll(getFiles(candidate, trackFileFormat));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onProgressUpdate(Integer... values) {
|
|
||||||
if (importActivity != null) {
|
|
||||||
importActivity.setProgressDialogValue(values[0], values[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPostExecute(Boolean result) {
|
|
||||||
if (importActivity != null) {
|
|
||||||
importActivity.onAsyncTaskCompleted(importTrackCount, totalTrackCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCancelled() {
|
|
||||||
if (importActivity != null) {
|
|
||||||
importActivity.onAsyncTaskCompleted(importTrackCount, totalTrackCount);
|
|
||||||
importActivity = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Boolean doInBackground(Void... params) {
|
|
||||||
try {
|
|
||||||
Thread.currentThread().setPriority(Thread.MAX_PRIORITY); // TODO Should be set to previous level at the end of this method.
|
|
||||||
// Get the wake lock if not recording or paused
|
|
||||||
boolean isRecording = PreferencesUtils.isRecording(importActivity);
|
|
||||||
boolean isPaused = PreferencesUtils.isRecordingTrackPaused(importActivity);
|
|
||||||
if (!isRecording || isPaused) {
|
|
||||||
wakeLock = SystemUtils.acquireWakeLock(importActivity, wakeLock);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<DocumentFile> files = getFiles(directory, trackFileFormat);
|
|
||||||
totalTrackCount = files.size();
|
|
||||||
|
|
||||||
for (int i = 0; i < totalTrackCount; i++) {
|
|
||||||
if (isCancelled()) {
|
|
||||||
// If cancelled, return true to show the number of files imported
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (importFile(files.get(i))) {
|
|
||||||
importTrackCount++;
|
|
||||||
}
|
|
||||||
publishProgress(i + 1, totalTrackCount);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} finally {
|
|
||||||
if (wakeLock != null && wakeLock.isHeld()) {
|
|
||||||
wakeLock.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imports a file.
|
|
||||||
*
|
|
||||||
* @param file the file
|
|
||||||
*/
|
|
||||||
private boolean importFile(final DocumentFile file) {
|
|
||||||
TrackImporter trackImporter;
|
|
||||||
if (trackFileFormat == TrackFileFormat.GPX) {
|
|
||||||
trackImporter = new GpxFileTrackImporter(importActivity);
|
|
||||||
} else {
|
|
||||||
//KML or KMZ
|
|
||||||
String extension = FileUtils.getExtension(file.getName());
|
|
||||||
if (TrackFileFormat.KML_ONLY_TRACK.getExtension().equals(extension)) {
|
|
||||||
trackImporter = new KmlFileTrackImporter(importActivity, -1L);
|
|
||||||
} else {
|
|
||||||
ContentProviderUtils contentProviderUtils = new ContentProviderUtils(importActivity);
|
|
||||||
Uri uri = contentProviderUtils.insertTrack(new Track());
|
|
||||||
long newId = Long.parseLong(uri.getLastPathSegment());
|
|
||||||
|
|
||||||
trackImporter = new KmzTrackImporter(importActivity, newId, file.getUri());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try (InputStream inputStream = importActivity.getContentResolver().openInputStream(file.getUri())) {
|
|
||||||
lastSuccessfulTrackId = trackImporter.importFile(inputStream);
|
|
||||||
return lastSuccessfulTrackId != -1L;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Unable to import file", e);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -72,7 +72,6 @@ public class KmlFileTrackImporter extends AbstractFileTrackImporter {
|
|||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param context the context
|
* @param context the context
|
||||||
* @param importTrackId track id to import to. -1L to import to a new track.
|
|
||||||
*/
|
*/
|
||||||
public KmlFileTrackImporter(Context context, long importTrackId) {
|
public KmlFileTrackImporter(Context context, long importTrackId) {
|
||||||
this(context, importTrackId, new ContentProviderUtils(context));
|
this(context, importTrackId, new ContentProviderUtils(context));
|
||||||
|
|||||||
@@ -56,8 +56,6 @@ public class KmzTrackImporter implements TrackImporter {
|
|||||||
private Uri uriKmzFile;
|
private Uri uriKmzFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param context the context
|
* @param context the context
|
||||||
* @param importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported.
|
* @param importTrackId track id to import to. This should not be -1L so that images in the kmz file can be imported.
|
||||||
* @param uriFile URI of the kmz file.
|
* @param uriFile URI of the kmz file.
|
||||||
|
|||||||
@@ -30,5 +30,6 @@ interface TrackImporter {
|
|||||||
* @param inputStream the file's input stream
|
* @param inputStream the file's input stream
|
||||||
* @return the imported track id or RECORDING_TRACK_ID_DEFAULT.
|
* @return the imported track id or RECORDING_TRACK_ID_DEFAULT.
|
||||||
*/
|
*/
|
||||||
|
//TODO Figure out how can make the import an atomic operation (incl. database transaction rollback).
|
||||||
long importFile(InputStream inputStream);
|
long importFile(InputStream inputStream);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import java.io.FileInputStream;
|
|||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.nio.channels.FileChannel;
|
import java.nio.channels.FileChannel;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import de.dennisguse.opentracks.BuildConfig;
|
import de.dennisguse.opentracks.BuildConfig;
|
||||||
@@ -111,6 +112,10 @@ public class FileUtils {
|
|||||||
return fileName.substring(index + 1);
|
return fileName.substring(index + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getExtension(DocumentFile file) {
|
||||||
|
return getExtension(file.getName());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a filename with the given base and the given extension, possibly adding a suffix to ensure the file doesn't exist.
|
* Builds a filename with the given base and the given extension, possibly adding a suffix to ensure the file doesn't exist.
|
||||||
*
|
*
|
||||||
@@ -229,13 +234,13 @@ public class FileUtils {
|
|||||||
return file.getAbsolutePath();
|
return file.getAbsolutePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy a File (src) to a File (dst).
|
* Copy a File (src) to a File (dst).
|
||||||
*
|
*
|
||||||
* @param src source file.
|
* @param src source file.
|
||||||
* @param dst destination file.
|
* @param dst destination file.
|
||||||
*/
|
*/
|
||||||
public static void copy(FileDescriptor src, File dst) {
|
public static void copy(FileDescriptor src, File dst) {
|
||||||
try (FileChannel in = new FileInputStream(src).getChannel();
|
try (FileChannel in = new FileInputStream(src).getChannel();
|
||||||
FileChannel out = new FileOutputStream(dst).getChannel()) {
|
FileChannel out = new FileOutputStream(dst).getChannel()) {
|
||||||
in.transferTo(0, in.size(), out);
|
in.transferTo(0, in.size(), out);
|
||||||
@@ -262,7 +267,7 @@ public class FileUtils {
|
|||||||
* @param context the Context.
|
* @param context the Context.
|
||||||
* @param trackId the id of the Track.
|
* @param trackId the id of the Track.
|
||||||
* @param uri the uri to check.
|
* @param uri the uri to check.
|
||||||
* @return File object or null.
|
* @return File object or null.
|
||||||
*/
|
*/
|
||||||
public static File getPhotoFileIfExists(Context context, long trackId, Uri uri) {
|
public static File getPhotoFileIfExists(Context context, long trackId, Uri uri) {
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
@@ -300,4 +305,18 @@ public class FileUtils {
|
|||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static ArrayList<DocumentFile> getFiles(DocumentFile file) {
|
||||||
|
ArrayList<DocumentFile> files = new ArrayList<>();
|
||||||
|
|
||||||
|
for (DocumentFile candidate : file.listFiles()) {
|
||||||
|
if (!candidate.isDirectory()) {
|
||||||
|
files.add(candidate);
|
||||||
|
} else {
|
||||||
|
files.addAll(getFiles(candidate));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ limitations under the License.
|
|||||||
<PreferenceCategory android:title="@string/generic_tracks">
|
<PreferenceCategory android:title="@string/generic_tracks">
|
||||||
<Preference android:title="@string/menu_import_all">
|
<Preference android:title="@string/menu_import_all">
|
||||||
<intent
|
<intent
|
||||||
android:targetClass="de.dennisguse.opentracks.io.file.importer.ImportActivity"
|
android:targetClass="de.dennisguse.opentracks.io.file.importer.DirectoryChooserActivity"
|
||||||
android:targetPackage="@string/applicationId" />
|
android:targetPackage="@string/applicationId" />
|
||||||
</Preference>
|
</Preference>
|
||||||
<Preference android:title="@string/menu_export_all">
|
<Preference android:title="@string/menu_export_all">
|
||||||
|
|||||||
Reference in New Issue
Block a user