commit
fc22892a66
17 changed files with 552 additions and 142 deletions
|
@ -352,7 +352,7 @@ public class RoutingEngine extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logException(Throwable t) {
|
private void logException(Throwable t) {
|
||||||
errorMessage = t instanceof IllegalArgumentException ? t.getMessage() : t.toString();
|
errorMessage = t instanceof RuntimeException ? t.getMessage() : t.toString();
|
||||||
logInfo("Error (linksProcessed=" + linksProcessed + " open paths: " + openSet.getSize() + "): " + errorMessage);
|
logInfo("Error (linksProcessed=" + linksProcessed + " open paths: " + openSet.getSize() + "): " + errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -187,6 +187,8 @@ public final class NodesCache {
|
||||||
ghostWakeup += segment.getDataSize();
|
ghostWakeup += segment.getDataSize();
|
||||||
}
|
}
|
||||||
return segment;
|
return segment;
|
||||||
|
} catch (IOException re) {
|
||||||
|
throw new RuntimeException(re.getMessage());
|
||||||
} catch (RuntimeException re) {
|
} catch (RuntimeException re) {
|
||||||
throw re;
|
throw re;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -294,14 +296,14 @@ public final class NodesCache {
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
MatchedWaypoint mwp = unmatchedWaypoints.get(i);
|
MatchedWaypoint mwp = unmatchedWaypoints.get(i);
|
||||||
if (mwp.crosspoint == null) {
|
if (mwp.crosspoint == null) {
|
||||||
if (unmatchedWaypoints.size() > 1 && i == unmatchedWaypoints.size()-1 && unmatchedWaypoints.get(i-1).direct) {
|
if (unmatchedWaypoints.size() > 1 && i == unmatchedWaypoints.size() - 1 && unmatchedWaypoints.get(i - 1).direct) {
|
||||||
mwp.crosspoint = new OsmNode(mwp.waypoint.ilon, mwp.waypoint.ilat);
|
mwp.crosspoint = new OsmNode(mwp.waypoint.ilon, mwp.waypoint.ilat);
|
||||||
mwp.direct = true;
|
mwp.direct = true;
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
|
throw new IllegalArgumentException(mwp.name + "-position not mapped in existing datafile");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unmatchedWaypoints.size() > 1 && i == unmatchedWaypoints.size()-1 && unmatchedWaypoints.get(i-1).direct) {
|
if (unmatchedWaypoints.size() > 1 && i == unmatchedWaypoints.size() - 1 && unmatchedWaypoints.get(i - 1).direct) {
|
||||||
mwp.crosspoint = new OsmNode(mwp.waypoint.ilon, mwp.waypoint.ilat);
|
mwp.crosspoint = new OsmNode(mwp.waypoint.ilon, mwp.waypoint.ilat);
|
||||||
mwp.direct = true;
|
mwp.direct = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,27 @@ final public class PhysicalFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int checkVersionIntegrity(File f) {
|
||||||
|
int version = -1;
|
||||||
|
RandomAccessFile raf = null;
|
||||||
|
try {
|
||||||
|
byte[] iobuffer = new byte[200];
|
||||||
|
raf = new RandomAccessFile(f, "r");
|
||||||
|
raf.readFully(iobuffer, 0, 200);
|
||||||
|
ByteDataReader dis = new ByteDataReader(iobuffer);
|
||||||
|
long lv = dis.readLong();
|
||||||
|
version = (int) (lv >> 48);
|
||||||
|
} catch (IOException e) {
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (raf != null) raf.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the integrity of the file using the build-in checksums
|
* Checks the integrity of the file using the build-in checksums
|
||||||
*
|
*
|
||||||
|
@ -81,7 +102,7 @@ final public class PhysicalFile {
|
||||||
short readVersion = (short) (lv >> 48);
|
short readVersion = (short) (lv >> 48);
|
||||||
if (i == 0 && lookupVersion != -1 && readVersion != lookupVersion) {
|
if (i == 0 && lookupVersion != -1 && readVersion != lookupVersion) {
|
||||||
throw new IOException("lookup version mismatch (old rd5?) lookups.dat="
|
throw new IOException("lookup version mismatch (old rd5?) lookups.dat="
|
||||||
+ lookupVersion + " " + f.getAbsolutePath() + "=" + readVersion);
|
+ lookupVersion + " " + f.getName() + "=" + readVersion);
|
||||||
}
|
}
|
||||||
fileIndex[i] = lv & 0xffffffffffffL;
|
fileIndex[i] = lv & 0xffffffffffffL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,10 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 31
|
compileSdkVersion 33
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
namespace 'btools.routingapp'
|
||||||
applicationId "btools.routingapp"
|
applicationId "btools.routingapp"
|
||||||
|
|
||||||
versionCode 45
|
versionCode 45
|
||||||
|
@ -17,7 +18,7 @@ android {
|
||||||
setProperty("archivesBaseName", "BRouterApp." + defaultConfig.versionName)
|
setProperty("archivesBaseName", "BRouterApp." + defaultConfig.versionName)
|
||||||
|
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 30
|
targetSdkVersion 33
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
@ -84,10 +85,10 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||||
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
|
implementation "androidx.constraintlayout:constraintlayout:2.1.4"
|
||||||
implementation 'androidx.work:work-runtime:2.7.1'
|
implementation 'androidx.work:work-runtime:2.8.0'
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'com.google.android.material:material:1.8.0'
|
||||||
|
|
||||||
implementation project(':brouter-mapaccess')
|
implementation project(':brouter-mapaccess')
|
||||||
implementation project(':brouter-core')
|
implementation project(':brouter-core')
|
||||||
|
@ -96,9 +97,13 @@ dependencies {
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
|
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
androidTestImplementation 'androidx.work:work-testing:2.7.1'
|
androidTestImplementation 'androidx.work:work-testing:2.8.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
preBuild.dependsOn(generateProfilesZip, generateReadmesZip)
|
||||||
}
|
}
|
||||||
|
|
||||||
check.dependsOn 'checkstyle'
|
check.dependsOn 'checkstyle'
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="btools.routingapp">
|
>
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
|
|
|
@ -5,22 +5,30 @@ import static btools.routingapp.BInstallerView.MASK_DELETED_RD5;
|
||||||
import static btools.routingapp.BInstallerView.MASK_INSTALLED_RD5;
|
import static btools.routingapp.BInstallerView.MASK_INSTALLED_RD5;
|
||||||
import static btools.routingapp.BInstallerView.MASK_SELECTED_RD5;
|
import static btools.routingapp.BInstallerView.MASK_SELECTED_RD5;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.StatFs;
|
import android.os.StatFs;
|
||||||
import android.text.format.Formatter;
|
import android.text.format.Formatter;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.work.Constraints;
|
import androidx.work.Constraints;
|
||||||
import androidx.work.Data;
|
import androidx.work.Data;
|
||||||
|
import androidx.work.ExistingWorkPolicy;
|
||||||
import androidx.work.NetworkType;
|
import androidx.work.NetworkType;
|
||||||
import androidx.work.OneTimeWorkRequest;
|
import androidx.work.OneTimeWorkRequest;
|
||||||
import androidx.work.WorkInfo;
|
import androidx.work.WorkInfo;
|
||||||
|
@ -28,23 +36,36 @@ import androidx.work.WorkManager;
|
||||||
import androidx.work.WorkRequest;
|
import androidx.work.WorkRequest;
|
||||||
|
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import btools.router.RoutingHelper;
|
import btools.router.RoutingHelper;
|
||||||
|
|
||||||
public class BInstallerActivity extends AppCompatActivity {
|
public class BInstallerActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private static final int DIALOG_CONFIRM_DELETE_ID = 1;
|
private static final int DIALOG_CONFIRM_DELETE_ID = 1;
|
||||||
|
private static final int DIALOG_CONFIRM_NEXTSTEPS_ID = 2;
|
||||||
|
private static final int DIALOG_CONFIRM_GETDIFFS_ID = 3;
|
||||||
|
|
||||||
|
public static final int MY_PERMISSIONS_REQUEST_NITIFICATION = 100;
|
||||||
|
|
||||||
public static boolean downloadCanceled = false;
|
public static boolean downloadCanceled = false;
|
||||||
private File mBaseDir;
|
private File mBaseDir;
|
||||||
private BInstallerView mBInstallerView;
|
private BInstallerView mBInstallerView;
|
||||||
private Button mButtonDownload;
|
private Button mButtonDownload;
|
||||||
private TextView mSummaryInfo;
|
private TextView mSummaryInfo;
|
||||||
|
private TextView mDownloadSummaryInfo;
|
||||||
private LinearProgressIndicator mProgressIndicator;
|
private LinearProgressIndicator mProgressIndicator;
|
||||||
|
private ArrayList<Integer> selectedTiles;
|
||||||
|
|
||||||
|
BInstallerView.OnSelectListener onSelectListener;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static long getAvailableSpace(String baseDir) {
|
public static long getAvailableSpace(String baseDir) {
|
||||||
StatFs stat = new StatFs(baseDir);
|
StatFs stat = new StatFs(baseDir);
|
||||||
|
|
||||||
|
@ -60,32 +81,78 @@ public class BInstallerActivity extends AppCompatActivity {
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
boolean running = isDownloadRunning(DownloadWorker.class);
|
||||||
|
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
|
|
||||||
setContentView(R.layout.activity_binstaller);
|
setContentView(R.layout.activity_binstaller);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
if (shouldShowRequestPermissionRationale(Manifest.permission.POST_NOTIFICATIONS)) {
|
||||||
|
//
|
||||||
|
} else {
|
||||||
|
// You can directly ask for the permission.
|
||||||
|
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.POST_NOTIFICATIONS}, MY_PERMISSIONS_REQUEST_NITIFICATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mSummaryInfo = findViewById(R.id.textViewSegmentSummary);
|
mSummaryInfo = findViewById(R.id.textViewSegmentSummary);
|
||||||
mBInstallerView = findViewById(R.id.BInstallerView);
|
mBInstallerView = findViewById(R.id.BInstallerView);
|
||||||
mBInstallerView.setOnSelectListener(
|
onSelectListener = new BInstallerView.OnSelectListener() {
|
||||||
() -> {
|
@Override
|
||||||
|
public void onSelect() {
|
||||||
|
//if (!isDownloadRunning(DownloadWorker.class))
|
||||||
updateDownloadButton();
|
updateDownloadButton();
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
|
|
||||||
|
mBInstallerView.setOnSelectListener(onSelectListener);
|
||||||
|
|
||||||
mButtonDownload = findViewById(R.id.buttonDownload);
|
mButtonDownload = findViewById(R.id.buttonDownload);
|
||||||
mButtonDownload.setOnClickListener(
|
mButtonDownload.setOnClickListener(
|
||||||
view -> {
|
view -> {
|
||||||
if (mBInstallerView.getSelectedTiles(MASK_DELETED_RD5).size() > 0) {
|
if (isDownloadRunning(DownloadWorker.class)) {
|
||||||
|
stopDownload();
|
||||||
|
} else if (mBInstallerView.getSelectedTiles(MASK_DELETED_RD5).size() > 0) {
|
||||||
showConfirmDelete();
|
showConfirmDelete();
|
||||||
} else if (mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5).size() > 0) {
|
} else if (mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5).size() > 0) {
|
||||||
|
mBInstallerView.setOnSelectListener(null);
|
||||||
downloadSelectedTiles();
|
downloadSelectedTiles();
|
||||||
} else {
|
} else {
|
||||||
|
mBInstallerView.setOnSelectListener(null);
|
||||||
downloadInstalledTiles();
|
downloadInstalledTiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
mProgressIndicator = findViewById(R.id.progressDownload);
|
mProgressIndicator = findViewById(R.id.progressDownload);
|
||||||
|
mDownloadSummaryInfo = findViewById(R.id.textViewDownloadSummary);
|
||||||
|
mDownloadSummaryInfo.setVisibility(View.INVISIBLE);
|
||||||
|
|
||||||
mBaseDir = ConfigHelper.getBaseDir(this);
|
mBaseDir = ConfigHelper.getBaseDir(this);
|
||||||
scanExistingFiles();
|
|
||||||
|
if (running) {
|
||||||
|
mProgressIndicator.show();
|
||||||
|
mButtonDownload.setEnabled(false);
|
||||||
|
WorkManager instance = WorkManager.getInstance(getApplicationContext());
|
||||||
|
LiveData<List<WorkInfo>> ld = instance.getWorkInfosForUniqueWorkLiveData(DownloadWorker.WORKER_NAME);
|
||||||
|
ld.observe(this, listOfWorkInfo -> {
|
||||||
|
// If there are no matching work info, do nothing
|
||||||
|
if (listOfWorkInfo == null || listOfWorkInfo.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (WorkInfo workInfo : listOfWorkInfo) {
|
||||||
|
startObserver(workInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
scanExistingFiles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getSegmentsPlural(int count) {
|
private String getSegmentsPlural(int count) {
|
||||||
|
@ -131,19 +198,24 @@ public class BInstallerActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void downloadAll(ArrayList<Integer> downloadList) {
|
public void downloadAll(ArrayList<Integer> downloadList, int all) {
|
||||||
ArrayList<String> urlparts = new ArrayList<>();
|
ArrayList<String> urlparts = new ArrayList<>();
|
||||||
for (Integer i : downloadList) {
|
for (Integer i : downloadList) {
|
||||||
urlparts.add(baseNameForTile(i));
|
urlparts.add(baseNameForTile(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadCanceled = false;
|
downloadCanceled = false;
|
||||||
|
mProgressIndicator.show();
|
||||||
|
mButtonDownload.setEnabled(false);
|
||||||
|
|
||||||
Data inputData = new Data.Builder()
|
Data inputData = new Data.Builder()
|
||||||
.putStringArray(DownloadWorker.KEY_INPUT_SEGMENT_NAMES, urlparts.toArray(new String[0]))
|
.putStringArray(DownloadWorker.KEY_INPUT_SEGMENT_NAMES, urlparts.toArray(new String[0]))
|
||||||
|
.putInt(DownloadWorker.KEY_INPUT_SEGMENT_ALL, all)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
Constraints constraints = new Constraints.Builder()
|
Constraints constraints = new Constraints.Builder()
|
||||||
|
.setRequiresBatteryNotLow(true)
|
||||||
|
.setRequiresStorageNotLow(true)
|
||||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
@ -154,65 +226,112 @@ public class BInstallerActivity extends AppCompatActivity {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
|
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
|
||||||
workManager.enqueue(downloadWorkRequest);
|
workManager.enqueueUniqueWork(DownloadWorker.WORKER_NAME, ExistingWorkPolicy.KEEP, (OneTimeWorkRequest) downloadWorkRequest);
|
||||||
|
|
||||||
|
try {
|
||||||
|
WorkInfo wi = WorkManager.getInstance(getApplicationContext()).getWorkInfoById(downloadWorkRequest.getId()).get();
|
||||||
|
if (wi != null && (wi.getState() == WorkInfo.State.ENQUEUED || wi.getState() == WorkInfo.State.BLOCKED)) {
|
||||||
|
Log.d("worker", "cancel " + wi.getState());
|
||||||
|
//WorkManager.getInstance(getApplicationContext()).cancelWorkById(downloadWorkRequest.getId());
|
||||||
|
}
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.d("worker", "canceled " + e.getMessage());
|
||||||
|
//e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
workManager
|
workManager
|
||||||
.getWorkInfoByIdLiveData(downloadWorkRequest.getId())
|
.getWorkInfoByIdLiveData(downloadWorkRequest.getId())
|
||||||
.observe(this, workInfo -> {
|
.observe(this, workInfo -> {
|
||||||
if (workInfo != null) {
|
startObserver(workInfo);
|
||||||
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
|
|
||||||
Toast.makeText(this, "Download scheduled. Check internet connection if it doesn't start.", Toast.LENGTH_LONG).show();
|
|
||||||
mProgressIndicator.hide();
|
|
||||||
mProgressIndicator.setIndeterminate(true);
|
|
||||||
mProgressIndicator.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workInfo.getState() == WorkInfo.State.RUNNING) {
|
|
||||||
Data progress = workInfo.getProgress();
|
|
||||||
String segmentName = progress.getString(DownloadWorker.PROGRESS_SEGMENT_NAME);
|
|
||||||
int percent = progress.getInt(DownloadWorker.PROGRESS_SEGMENT_PERCENT, 0);
|
|
||||||
if (percent > 0) {
|
|
||||||
mProgressIndicator.setIndeterminate(false);
|
|
||||||
}
|
|
||||||
mProgressIndicator.setProgress(percent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (workInfo.getState().isFinished()) {
|
|
||||||
String result;
|
|
||||||
switch (workInfo.getState()) {
|
|
||||||
case FAILED:
|
|
||||||
result = "Download failed";
|
|
||||||
break;
|
|
||||||
case CANCELLED:
|
|
||||||
result = "Download cancelled";
|
|
||||||
break;
|
|
||||||
case SUCCEEDED:
|
|
||||||
result = "Download succeeded";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
result = "";
|
|
||||||
}
|
|
||||||
if (workInfo.getState() != WorkInfo.State.FAILED) {
|
|
||||||
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
|
|
||||||
} else {
|
|
||||||
String error = workInfo.getOutputData().getString(DownloadWorker.KEY_OUTPUT_ERROR);
|
|
||||||
Toast.makeText(this, result + ": " + error, Toast.LENGTH_LONG).show();
|
|
||||||
}
|
|
||||||
mProgressIndicator.hide();
|
|
||||||
scanExistingFiles();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
deleteRawTracks(); // invalidate raw-tracks after data update
|
deleteRawTracks(); // invalidate raw-tracks after data update
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private void startObserver(WorkInfo workInfo) {
|
||||||
protected Dialog onCreateDialog(int id) {
|
if (workInfo != null) {
|
||||||
|
if (workInfo.getState() == WorkInfo.State.ENQUEUED || workInfo.getState() == WorkInfo.State.BLOCKED) {
|
||||||
|
Log.d("worker", "cancel " + workInfo.getState());
|
||||||
|
//WorkManager.getInstance(getApplicationContext()).cancelWorkById(downloadWorkRequest.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
|
||||||
|
Toast.makeText(this, "Download scheduled. Check internet connection if it doesn't start.", Toast.LENGTH_LONG).show();
|
||||||
|
mProgressIndicator.hide();
|
||||||
|
mProgressIndicator.setIndeterminate(true);
|
||||||
|
mProgressIndicator.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workInfo.getState() == WorkInfo.State.RUNNING) {
|
||||||
|
mDownloadSummaryInfo.setVisibility(View.VISIBLE);
|
||||||
|
Data progress = workInfo.getProgress();
|
||||||
|
String segmentName = progress.getString(DownloadWorker.PROGRESS_SEGMENT_NAME);
|
||||||
|
int percent = progress.getInt(DownloadWorker.PROGRESS_SEGMENT_PERCENT, 0);
|
||||||
|
if (percent > 0) {
|
||||||
|
mDownloadSummaryInfo.setText("Downloading .. " + segmentName);
|
||||||
|
}
|
||||||
|
if (percent > 0) {
|
||||||
|
mProgressIndicator.setIndeterminate(false);
|
||||||
|
}
|
||||||
|
mProgressIndicator.setProgress(percent);
|
||||||
|
|
||||||
|
mButtonDownload.setText(getString(R.string.action_cancel));
|
||||||
|
mButtonDownload.setEnabled(true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workInfo.getState().isFinished()) {
|
||||||
|
String result;
|
||||||
|
switch (workInfo.getState()) {
|
||||||
|
case FAILED:
|
||||||
|
result = "Download failed";
|
||||||
|
break;
|
||||||
|
case CANCELLED:
|
||||||
|
result = "Download cancelled";
|
||||||
|
break;
|
||||||
|
case SUCCEEDED:
|
||||||
|
result = "Download succeeded";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = "";
|
||||||
|
}
|
||||||
|
String error = null;
|
||||||
|
if (workInfo.getState() != WorkInfo.State.FAILED) {
|
||||||
|
Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
|
||||||
|
} else {
|
||||||
|
error = workInfo.getOutputData().getString(DownloadWorker.KEY_OUTPUT_ERROR);
|
||||||
|
if (error != null && !error.startsWith("Version")) {
|
||||||
|
Toast.makeText(this, result + ": " + error, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error != null && error.startsWith("Version error")) {
|
||||||
|
showConfirmNextSteps();
|
||||||
|
} else if (error != null && error.startsWith("Version diffs")) {
|
||||||
|
showConfirmGetDiffs();
|
||||||
|
} else {
|
||||||
|
mBInstallerView.setOnSelectListener(onSelectListener);
|
||||||
|
mBInstallerView.clearAllTilesStatus(MASK_SELECTED_RD5);
|
||||||
|
scanExistingFiles();
|
||||||
|
}
|
||||||
|
mProgressIndicator.hide();
|
||||||
|
mDownloadSummaryInfo.setVisibility(View.INVISIBLE);
|
||||||
|
mButtonDownload.setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected Dialog createADialog(int id) {
|
||||||
AlertDialog.Builder builder;
|
AlertDialog.Builder builder;
|
||||||
|
builder = new AlertDialog.Builder(this);
|
||||||
|
builder.setCancelable(false);
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case DIALOG_CONFIRM_DELETE_ID:
|
case DIALOG_CONFIRM_DELETE_ID:
|
||||||
builder = new AlertDialog.Builder(this);
|
|
||||||
builder
|
builder
|
||||||
.setTitle("Confirm Delete")
|
.setTitle("Confirm Delete")
|
||||||
.setMessage("Really delete?").setPositiveButton("Yes", new DialogInterface.OnClickListener() {
|
.setMessage("Really delete?").setPositiveButton("Yes", new DialogInterface.OnClickListener() {
|
||||||
|
@ -225,15 +344,77 @@ public class BInstallerActivity extends AppCompatActivity {
|
||||||
});
|
});
|
||||||
return builder.create();
|
return builder.create();
|
||||||
|
|
||||||
|
case DIALOG_CONFIRM_NEXTSTEPS_ID:
|
||||||
|
builder
|
||||||
|
.setTitle("Version Problem")
|
||||||
|
.setMessage("The base version for tiles has changed. What to do?")
|
||||||
|
.setPositiveButton("Continue with current download, delete other old data", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
|
||||||
|
ArrayList<Integer> allTiles = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5);
|
||||||
|
for (Integer sel : allTiles) {
|
||||||
|
if (!selectedTiles.contains(sel)) {
|
||||||
|
mBInstallerView.toggleTileStatus(sel, 0);
|
||||||
|
new File(mBaseDir, "brouter/segments4/" + baseNameForTile(sel) + ".rd5").delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
downloadSelectedTiles();
|
||||||
|
}
|
||||||
|
}).setNegativeButton("Select all for download and start", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
downloadInstalledTiles();
|
||||||
|
}
|
||||||
|
}).setNeutralButton("Cancel now, complete on an other day", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
File tmplookupFile = new File(mBaseDir, "brouter/profiles2/lookups.dat.tmp");
|
||||||
|
tmplookupFile.delete();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder.create();
|
||||||
|
|
||||||
|
case DIALOG_CONFIRM_GETDIFFS_ID:
|
||||||
|
builder
|
||||||
|
.setTitle("Version Differences")
|
||||||
|
.setMessage("The base version for some tiles is different. What to do?")
|
||||||
|
.setPositiveButton("Download all different tiles", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
downloadDiffVersionTiles();
|
||||||
|
}
|
||||||
|
}).setNegativeButton("Drop all different tiles", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
dropDiffVersionTiles();
|
||||||
|
}
|
||||||
|
}).setNeutralButton("Cancel now, complete on an other day", new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder.create();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showConfirmDelete() {
|
void showADialog(int id) {
|
||||||
showDialog(DIALOG_CONFIRM_DELETE_ID);
|
Dialog d = createADialog(id);
|
||||||
|
if (d != null) d.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void showConfirmDelete() {
|
||||||
|
showADialog(DIALOG_CONFIRM_DELETE_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showConfirmNextSteps() {
|
||||||
|
showADialog(DIALOG_CONFIRM_NEXTSTEPS_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showConfirmGetDiffs() {
|
||||||
|
showADialog(DIALOG_CONFIRM_GETDIFFS_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void scanExistingFiles() {
|
private void scanExistingFiles() {
|
||||||
mBInstallerView.clearAllTilesStatus(MASK_CURRENT_RD5 | MASK_INSTALLED_RD5 | MASK_DELETED_RD5 | MASK_SELECTED_RD5);
|
mBInstallerView.clearAllTilesStatus(MASK_CURRENT_RD5 | MASK_INSTALLED_RD5 | MASK_DELETED_RD5 | MASK_SELECTED_RD5);
|
||||||
|
|
||||||
|
@ -270,14 +451,51 @@ public class BInstallerActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadSelectedTiles() {
|
private void downloadSelectedTiles() {
|
||||||
ArrayList<Integer> selectedTiles = mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5);
|
selectedTiles = mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5);
|
||||||
downloadAll(selectedTiles);
|
downloadAll(selectedTiles, DownloadWorker.VALUE_SEGMENT_PARTS);
|
||||||
mBInstallerView.clearAllTilesStatus(MASK_SELECTED_RD5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadInstalledTiles() {
|
private void downloadInstalledTiles() {
|
||||||
ArrayList<Integer> selectedTiles = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5);
|
ArrayList<Integer> selectedTiles = mBInstallerView.getSelectedTiles(MASK_INSTALLED_RD5);
|
||||||
downloadAll(selectedTiles);
|
ArrayList<Integer> tmpSelectedTiles = mBInstallerView.getSelectedTiles(MASK_SELECTED_RD5);
|
||||||
|
if (tmpSelectedTiles.size() > 0) {
|
||||||
|
selectedTiles.addAll(tmpSelectedTiles);
|
||||||
|
}
|
||||||
|
downloadAll(selectedTiles, DownloadWorker.VALUE_SEGMENT_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadDiffVersionTiles() {
|
||||||
|
downloadAll(new ArrayList<Integer>(), DownloadWorker.VALUE_SEGMENT_DIFFS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void dropDiffVersionTiles() {
|
||||||
|
downloadAll(new ArrayList<Integer>(), DownloadWorker.VALUE_SEGMENT_DROPDIFFS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isDownloadRunning(Class<?> serviceClass) {
|
||||||
|
WorkManager instance = WorkManager.getInstance(getApplicationContext());
|
||||||
|
|
||||||
|
ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosForUniqueWork(DownloadWorker.WORKER_NAME);
|
||||||
|
try {
|
||||||
|
boolean running = false;
|
||||||
|
List<WorkInfo> workInfoList = statuses.get();
|
||||||
|
for (WorkInfo workInfo : workInfoList) {
|
||||||
|
WorkInfo.State state = workInfo.getState();
|
||||||
|
running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
|
||||||
|
}
|
||||||
|
return running;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stopDownload() {
|
||||||
|
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
|
||||||
|
workManager.cancelAllWork();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int tileForBaseName(String basename) {
|
private int tileForBaseName(String basename) {
|
||||||
|
|
|
@ -75,18 +75,20 @@ public class BInstallerView extends View {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTileStatus(int tileIndex, int tileMask) {
|
public void setTileStatus(int tileIndex, int tileMask) {
|
||||||
tileStatus[tileIndex] |= tileMask;
|
if (mOnSelectListener == null) {
|
||||||
if (mOnSelectListener != null) {
|
return;
|
||||||
mOnSelectListener.onSelect();
|
|
||||||
}
|
}
|
||||||
|
tileStatus[tileIndex] |= tileMask;
|
||||||
|
mOnSelectListener.onSelect();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toggleTileStatus(int tileIndex, int tileMask) {
|
public void toggleTileStatus(int tileIndex, int tileMask) {
|
||||||
tileStatus[tileIndex] ^= tileMask;
|
if (mOnSelectListener == null) {
|
||||||
if (mOnSelectListener != null) {
|
return;
|
||||||
mOnSelectListener.onSelect();
|
|
||||||
}
|
}
|
||||||
|
tileStatus[tileIndex] ^= tileMask;
|
||||||
|
mOnSelectListener.onSelect();
|
||||||
invalidate();
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
|
||||||
setContentView(mBRouterView);
|
setContentView(mBRouterView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected Dialog createADialog(int id) {
|
||||||
protected Dialog onCreateDialog(int id) {
|
|
||||||
AlertDialog.Builder builder;
|
AlertDialog.Builder builder;
|
||||||
builder = new AlertDialog.Builder(this);
|
builder = new AlertDialog.Builder(this);
|
||||||
builder.setCancelable(false);
|
builder.setCancelable(false);
|
||||||
|
@ -103,7 +102,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
|
||||||
if (item == 0)
|
if (item == 0)
|
||||||
startDownloadManager();
|
startDownloadManager();
|
||||||
else
|
else
|
||||||
showDialog(DIALOG_SELECTPROFILE_ID);
|
showADialog(DIALOG_SELECTPROFILE_ID);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNegativeButton("Close", new DialogInterface.OnClickListener() {
|
.setNegativeButton("Close", new DialogInterface.OnClickListener() {
|
||||||
|
@ -214,7 +213,7 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
|
||||||
if (selectedBasedir < availableBasedirs.size()) {
|
if (selectedBasedir < availableBasedirs.size()) {
|
||||||
mBRouterView.startSetup(availableBasedirs.get(selectedBasedir), true);
|
mBRouterView.startSetup(availableBasedirs.get(selectedBasedir), true);
|
||||||
} else {
|
} else {
|
||||||
showDialog(DIALOG_TEXTENTRY_ID);
|
showADialog(DIALOG_TEXTENTRY_ID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -338,17 +337,14 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
|
||||||
Arrays.sort(availableProfiles);
|
Arrays.sort(availableProfiles);
|
||||||
|
|
||||||
// show main dialog
|
// show main dialog
|
||||||
showDialog(DIALOG_MAINACTION_ID);
|
showADialog(DIALOG_MAINACTION_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startDownloadManager() {
|
public void startDownloadManager() {
|
||||||
if (!mBRouterView.hasUpToDateLookups()) {
|
showADialog(DIALOG_SHOW_DM_INFO_ID);
|
||||||
showDialog(DIALOG_OLDDATAHINT_ID);
|
|
||||||
} else {
|
|
||||||
showDialog(DIALOG_SHOW_DM_INFO_ID);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public void selectBasedir(ArrayList<File> items, String message) {
|
public void selectBasedir(ArrayList<File> items, String message) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
availableBasedirs = items;
|
availableBasedirs = items;
|
||||||
|
@ -357,7 +353,11 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
|
||||||
long size = 0L;
|
long size = 0L;
|
||||||
try {
|
try {
|
||||||
StatFs stat = new StatFs(f.getAbsolutePath());
|
StatFs stat = new StatFs(f.getAbsolutePath());
|
||||||
size = (long) stat.getAvailableBlocks() * stat.getBlockSize();
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||||
|
size = stat.getAvailableBlocksLong() * stat.getBlockSizeLong();
|
||||||
|
} else {
|
||||||
|
size = (long) stat.getAvailableBlocks() * stat.getBlockSize();
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
/* ignore */ }
|
/* ignore */ }
|
||||||
dirFreeSizes.add(size);
|
dirFreeSizes.add(size);
|
||||||
|
@ -379,26 +379,26 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
|
||||||
basedirOptions[bdidx] = "Enter path manually";
|
basedirOptions[bdidx] = "Enter path manually";
|
||||||
}
|
}
|
||||||
|
|
||||||
showDialog(DIALOG_SELECTBASEDIR_ID);
|
showADialog(DIALOG_SELECTBASEDIR_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectRoutingModes(String[] modes, boolean[] modesChecked, String message) {
|
public void selectRoutingModes(String[] modes, boolean[] modesChecked, String message) {
|
||||||
routingModes = modes;
|
routingModes = modes;
|
||||||
routingModesChecked = modesChecked;
|
routingModesChecked = modesChecked;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
showDialog(DIALOG_ROUTINGMODES_ID);
|
showADialog(DIALOG_ROUTINGMODES_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showModeConfigOverview(String message) {
|
public void showModeConfigOverview(String message) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
showDialog(DIALOG_MODECONFIGOVERVIEW_ID);
|
showADialog(DIALOG_MODECONFIGOVERVIEW_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectVias(String[] items) {
|
public void selectVias(String[] items) {
|
||||||
availableVias = items;
|
availableVias = items;
|
||||||
selectedVias = new HashSet<>(availableVias.length);
|
selectedVias = new HashSet<>(availableVias.length);
|
||||||
Collections.addAll(selectedVias, items);
|
Collections.addAll(selectedVias, items);
|
||||||
showDialog(DIALOG_VIASELECT_ID);
|
showADialog(DIALOG_VIASELECT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectWaypoint(String[] items) {
|
public void selectWaypoint(String[] items) {
|
||||||
|
@ -412,15 +412,20 @@ public class BRouterActivity extends AppCompatActivity implements ActivityCompat
|
||||||
|
|
||||||
public void selectNogos(List<OsmNodeNamed> nogoList) {
|
public void selectNogos(List<OsmNodeNamed> nogoList) {
|
||||||
this.nogoList = nogoList;
|
this.nogoList = nogoList;
|
||||||
showDialog(DIALOG_NOGOSELECT_ID);
|
showADialog(DIALOG_NOGOSELECT_ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showADialog(int id) {
|
||||||
|
Dialog d = createADialog(id);
|
||||||
|
if (d!=null) d.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showNewDialog(int id) {
|
private void showNewDialog(int id) {
|
||||||
if (dialogIds.contains(id)) {
|
if (dialogIds.contains(id)) {
|
||||||
removeDialog(id);
|
// removeDialog(id);
|
||||||
}
|
}
|
||||||
dialogIds.add(id);
|
dialogIds.add(id);
|
||||||
showDialog(id);
|
showADialog(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void showErrorMessage(String msg) {
|
public void showErrorMessage(String msg) {
|
||||||
|
|
|
@ -279,7 +279,7 @@ public class BRouterService extends Service {
|
||||||
private void logBundle(Bundle params) {
|
private void logBundle(Bundle params) {
|
||||||
if (AppLogger.isLogging()) {
|
if (AppLogger.isLogging()) {
|
||||||
for (String k : params.keySet()) {
|
for (String k : params.keySet()) {
|
||||||
Object val = "remoteProfile".equals(k) ? "<..cut..>" : params.get(k);
|
Object val = "remoteProfile".equals(k) ? "<..cut..>" : params.getString(k);
|
||||||
String desc = "key=" + k + (val == null ? "" : " class=" + val.getClass() + " val=" + val.toString());
|
String desc = "key=" + k + (val == null ? "" : " class=" + val.getClass() + " val=" + val.toString());
|
||||||
AppLogger.log(desc);
|
AppLogger.log(desc);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,9 +5,11 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -740,7 +742,8 @@ public class BRouterView extends View {
|
||||||
paintPosition(n.ilon, n.ilat, color, minradius);
|
paintPosition(n.ilon, n.ilat, color, minradius);
|
||||||
}
|
}
|
||||||
|
|
||||||
canvas.drawBitmap(imgPixels, 0, imgw, (float) 0., (float) 0., imgw, imgh, false, null);
|
Bitmap bmp = Bitmap.createBitmap(imgPixels, imgw, imgh, Bitmap.Config.RGB_565);
|
||||||
|
canvas.drawBitmap(bmp, 0, 0, null);
|
||||||
|
|
||||||
// nogo circles if any
|
// nogo circles if any
|
||||||
for (int ngi = 0; ngi < nogoList.size(); ngi++) {
|
for (int ngi = 0; ngi < nogoList.size(); ngi++) {
|
||||||
|
|
|
@ -17,28 +17,42 @@ import androidx.work.Worker;
|
||||||
import androidx.work.WorkerParameters;
|
import androidx.work.WorkerParameters;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import btools.expressions.BExpressionMetaData;
|
||||||
import btools.mapaccess.PhysicalFile;
|
import btools.mapaccess.PhysicalFile;
|
||||||
import btools.mapaccess.Rd5DiffManager;
|
import btools.mapaccess.Rd5DiffManager;
|
||||||
import btools.mapaccess.Rd5DiffTool;
|
import btools.mapaccess.Rd5DiffTool;
|
||||||
import btools.util.ProgressListener;
|
import btools.util.ProgressListener;
|
||||||
|
|
||||||
public class DownloadWorker extends Worker {
|
public class DownloadWorker extends Worker {
|
||||||
|
public static final String WORKER_NAME = "BRouterWorker";
|
||||||
|
|
||||||
|
private final static boolean DEBUG = false;
|
||||||
|
|
||||||
public static final String KEY_INPUT_SEGMENT_NAMES = "SEGMENT_NAMES";
|
public static final String KEY_INPUT_SEGMENT_NAMES = "SEGMENT_NAMES";
|
||||||
|
public static final String KEY_INPUT_SEGMENT_ALL = "SEGMENT_ALL";
|
||||||
public static final String KEY_OUTPUT_ERROR = "ERROR";
|
public static final String KEY_OUTPUT_ERROR = "ERROR";
|
||||||
|
|
||||||
|
public static final int VALUE_SEGMENT_PARTS = 0;
|
||||||
|
public static final int VALUE_SEGMENT_ALL = 1;
|
||||||
|
public static final int VALUE_SEGMENT_DIFFS = 2;
|
||||||
|
public static final int VALUE_SEGMENT_DROPDIFFS = 3;
|
||||||
|
|
||||||
public static final String PROGRESS_SEGMENT_NAME = "PROGRESS_SEGMENT_NAME";
|
public static final String PROGRESS_SEGMENT_NAME = "PROGRESS_SEGMENT_NAME";
|
||||||
public static final String PROGRESS_SEGMENT_PERCENT = "PROGRESS_SEGMENT_PERCENT";
|
public static final String PROGRESS_SEGMENT_PERCENT = "PROGRESS_SEGMENT_PERCENT";
|
||||||
|
|
||||||
private final static boolean DEBUG = false;
|
|
||||||
private static final int NOTIFICATION_ID = new Random().nextInt();
|
private static final int NOTIFICATION_ID = new Random().nextInt();
|
||||||
private static final String PROFILES_DIR = "profiles2/";
|
public static final String PROFILES_DIR = "profiles2/";
|
||||||
private static final String SEGMENTS_DIR = "segments4/";
|
private static final String SEGMENTS_DIR = "segments4/";
|
||||||
private static final String SEGMENT_DIFF_SUFFIX = ".df5";
|
private static final String SEGMENT_DIFF_SUFFIX = ".df5";
|
||||||
private static final String SEGMENT_SUFFIX = ".rd5";
|
private static final String SEGMENT_SUFFIX = ".rd5";
|
||||||
|
@ -51,6 +65,11 @@ public class DownloadWorker extends Worker {
|
||||||
private final DownloadProgressListener downloadProgressListener;
|
private final DownloadProgressListener downloadProgressListener;
|
||||||
private final Data.Builder progressBuilder = new Data.Builder();
|
private final Data.Builder progressBuilder = new Data.Builder();
|
||||||
private final NotificationCompat.Builder notificationBuilder;
|
private final NotificationCompat.Builder notificationBuilder;
|
||||||
|
private int downloadAll;
|
||||||
|
private boolean versionChanged;
|
||||||
|
private List<URL> done = new ArrayList<>();
|
||||||
|
|
||||||
|
int version = -1;
|
||||||
|
|
||||||
public DownloadWorker(
|
public DownloadWorker(
|
||||||
@NonNull Context context,
|
@NonNull Context context,
|
||||||
|
@ -70,16 +89,21 @@ public class DownloadWorker extends Worker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadStart(String downloadName, DownloadType downloadType) {
|
public void onDownloadStart(String downloadName, DownloadType downloadType) {
|
||||||
|
if (DEBUG) Log.d(LOG_TAG, "onDownloadStart " + downloadName);
|
||||||
currentDownloadName = downloadName;
|
currentDownloadName = downloadName;
|
||||||
currentDownloadType = downloadType;
|
currentDownloadType = downloadType;
|
||||||
if (downloadType == DownloadType.SEGMENT) {
|
if (downloadType == DownloadType.SEGMENT) {
|
||||||
progressBuilder.putString(PROGRESS_SEGMENT_NAME, downloadName);
|
progressBuilder.putString(PROGRESS_SEGMENT_NAME, downloadName);
|
||||||
notificationBuilder.setContentText(downloadName);
|
notificationBuilder.setContentText(downloadName);
|
||||||
|
} else {
|
||||||
|
progressBuilder.putString(PROGRESS_SEGMENT_NAME, "check profiles");
|
||||||
}
|
}
|
||||||
|
setProgressAsync(progressBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadInfo(String info) {
|
public void onDownloadInfo(String info) {
|
||||||
|
if (DEBUG) Log.d(LOG_TAG, "onDownloadInfo " + info);
|
||||||
notificationBuilder.setContentText(currentDownloadName + ": " + info);
|
notificationBuilder.setContentText(currentDownloadName + ": " + info);
|
||||||
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
||||||
}
|
}
|
||||||
|
@ -100,6 +124,7 @@ public class DownloadWorker extends Worker {
|
||||||
notificationBuilder.setProgress(0, 0, true);
|
notificationBuilder.setProgress(0, 0, true);
|
||||||
progressBuilder.putInt(PROGRESS_SEGMENT_PERCENT, -1);
|
progressBuilder.putInt(PROGRESS_SEGMENT_PERCENT, -1);
|
||||||
}
|
}
|
||||||
|
progressBuilder.putString(PROGRESS_SEGMENT_NAME, currentDownloadName);
|
||||||
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
|
||||||
setProgressAsync(progressBuilder.build());
|
setProgressAsync(progressBuilder.build());
|
||||||
|
|
||||||
|
@ -108,12 +133,14 @@ public class DownloadWorker extends Worker {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadFinished() {
|
public void onDownloadFinished() {
|
||||||
|
if (DEBUG) Log.d(LOG_TAG, "onDownloadFinished ");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
diffProgressListener = new ProgressListener() {
|
diffProgressListener = new ProgressListener() {
|
||||||
@Override
|
@Override
|
||||||
public void updateProgress(String task, int progress) {
|
public void updateProgress(String task, int progress) {
|
||||||
|
if (DEBUG) Log.d(LOG_TAG, "updateProgress " + task + " " + progress);
|
||||||
downloadProgressListener.onDownloadInfo(task);
|
downloadProgressListener.onDownloadInfo(task);
|
||||||
downloadProgressListener.onDownloadProgress(100, progress);
|
downloadProgressListener.onDownloadProgress(100, progress);
|
||||||
}
|
}
|
||||||
|
@ -131,6 +158,9 @@ public class DownloadWorker extends Worker {
|
||||||
Data inputData = getInputData();
|
Data inputData = getInputData();
|
||||||
Data.Builder output = new Data.Builder();
|
Data.Builder output = new Data.Builder();
|
||||||
String[] segmentNames = inputData.getStringArray(KEY_INPUT_SEGMENT_NAMES);
|
String[] segmentNames = inputData.getStringArray(KEY_INPUT_SEGMENT_NAMES);
|
||||||
|
downloadAll = inputData.getInt(KEY_INPUT_SEGMENT_ALL, 0);
|
||||||
|
if (DEBUG)
|
||||||
|
Log.d(LOG_TAG, "doWork done " + done.size() + " segs " + segmentNames.length + " " + this);
|
||||||
if (segmentNames == null) {
|
if (segmentNames == null) {
|
||||||
if (DEBUG) Log.d(LOG_TAG, "Failure: no segmentNames");
|
if (DEBUG) Log.d(LOG_TAG, "Failure: no segmentNames");
|
||||||
return Result.failure();
|
return Result.failure();
|
||||||
|
@ -140,49 +170,127 @@ public class DownloadWorker extends Worker {
|
||||||
setForegroundAsync(new ForegroundInfo(NOTIFICATION_ID, notificationBuilder.build()));
|
setForegroundAsync(new ForegroundInfo(NOTIFICATION_ID, notificationBuilder.build()));
|
||||||
try {
|
try {
|
||||||
if (DEBUG) Log.d(LOG_TAG, "Download lookup & profiles");
|
if (DEBUG) Log.d(LOG_TAG, "Download lookup & profiles");
|
||||||
downloadLookupAndProfiles();
|
if (!downloadLookup()) {
|
||||||
|
output.putString(KEY_OUTPUT_ERROR, "Version error");
|
||||||
|
return Result.failure(output.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!versionChanged && downloadAll != VALUE_SEGMENT_ALL) {
|
||||||
|
List<String> tmpSegementNames = new ArrayList<>();
|
||||||
|
File segmentFolder = new File(baseDir, SEGMENTS_DIR);
|
||||||
|
File[] files = segmentFolder.listFiles(new FileFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(File file) {
|
||||||
|
return (file.getPath().endsWith(SEGMENT_SUFFIX));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (File f : files) {
|
||||||
|
int thePFversion = PhysicalFile.checkVersionIntegrity(f);
|
||||||
|
if (DEBUG) Log.d("worker", "check " + f.getName() + " " + thePFversion + "=" + version);
|
||||||
|
if (thePFversion != -1 && thePFversion != version) {
|
||||||
|
tmpSegementNames.add(f.getName().substring(0, f.getName().indexOf(".")));
|
||||||
|
versionChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tmpSegementNames.size() > 0 && (downloadAll != VALUE_SEGMENT_DIFFS && downloadAll != VALUE_SEGMENT_DROPDIFFS)) {
|
||||||
|
output.putString(KEY_OUTPUT_ERROR, "Version diffs");
|
||||||
|
return Result.failure(output.build());
|
||||||
|
}
|
||||||
|
if (downloadAll == VALUE_SEGMENT_DIFFS) {
|
||||||
|
segmentNames = tmpSegementNames.toArray(new String[0]);
|
||||||
|
} else if (downloadAll == VALUE_SEGMENT_DROPDIFFS) {
|
||||||
|
for (String segmentName : tmpSegementNames) {
|
||||||
|
File segmentFile = new File(baseDir, SEGMENTS_DIR + segmentName + SEGMENT_SUFFIX);
|
||||||
|
segmentFile.delete();
|
||||||
|
}
|
||||||
|
return Result.success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadProfiles();
|
||||||
|
|
||||||
for (String segmentName : segmentNames) {
|
for (String segmentName : segmentNames) {
|
||||||
|
if (isStopped()) break;
|
||||||
downloadProgressListener.onDownloadStart(segmentName, DownloadType.SEGMENT);
|
downloadProgressListener.onDownloadStart(segmentName, DownloadType.SEGMENT);
|
||||||
if (DEBUG) Log.d(LOG_TAG, "Download segment " + segmentName);
|
if (DEBUG) Log.d(LOG_TAG, "Download segment " + segmentName);
|
||||||
downloadSegment(mServerConfig.getSegmentUrl(), segmentName + SEGMENT_SUFFIX);
|
downloadSegment(mServerConfig.getSegmentUrl(), segmentName + SEGMENT_SUFFIX);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.w(LOG_TAG, e);
|
output.putString(KEY_OUTPUT_ERROR, e.getMessage());
|
||||||
output.putString(KEY_OUTPUT_ERROR, e.toString());
|
|
||||||
return Result.failure(output.build());
|
return Result.failure(output.build());
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.w(LOG_TAG, e);
|
output.putString(KEY_OUTPUT_ERROR, e.getMessage());
|
||||||
output.putString(KEY_OUTPUT_ERROR, e.toString());
|
|
||||||
return Result.failure(output.build());
|
return Result.failure(output.build());
|
||||||
}
|
}
|
||||||
if (DEBUG) Log.d(LOG_TAG, "doWork finished");
|
if (DEBUG) Log.d(LOG_TAG, "doWork finished");
|
||||||
return Result.success();
|
return Result.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadLookupAndProfiles() throws IOException, InterruptedException {
|
private boolean downloadLookup() throws IOException, InterruptedException {
|
||||||
String[] lookups = mServerConfig.getLookups();
|
String[] lookups = mServerConfig.getLookups();
|
||||||
for (String fileName : lookups) {
|
for (String fileName : lookups) {
|
||||||
if (fileName.length() > 0) {
|
if (fileName.length() > 0) {
|
||||||
File lookupFile = new File(baseDir, PROFILES_DIR + fileName);
|
File lookupFile = new File(baseDir, PROFILES_DIR + fileName);
|
||||||
String lookupLocation = mServerConfig.getLookupUrl() + fileName;
|
BExpressionMetaData meta = new BExpressionMetaData();
|
||||||
URL lookupUrl = new URL(lookupLocation);
|
meta.readMetaData(lookupFile);
|
||||||
downloadProgressListener.onDownloadStart(fileName, DownloadType.LOOKUP);
|
version = meta.lookupVersion;
|
||||||
downloadFile(lookupUrl, lookupFile, false);
|
|
||||||
downloadProgressListener.onDownloadFinished();
|
int size = (int) (lookupFile.exists() ? lookupFile.length() : 0);
|
||||||
|
File tmplookupFile = new File(baseDir, PROFILES_DIR + fileName + ".tmp");
|
||||||
|
boolean changed = false;
|
||||||
|
if (tmplookupFile.exists()) {
|
||||||
|
lookupFile.delete();
|
||||||
|
tmplookupFile.renameTo(lookupFile);
|
||||||
|
versionChanged = true;
|
||||||
|
meta.readMetaData(lookupFile);
|
||||||
|
version = meta.lookupVersion;
|
||||||
|
} else {
|
||||||
|
String lookupLocation = mServerConfig.getLookupUrl() + fileName;
|
||||||
|
URL lookupUrl = new URL(lookupLocation);
|
||||||
|
downloadProgressListener.onDownloadStart(fileName, DownloadType.LOOKUP);
|
||||||
|
changed = downloadFile(lookupUrl, tmplookupFile, size, false, DownloadType.LOOKUP);
|
||||||
|
downloadProgressListener.onDownloadFinished();
|
||||||
|
done.add(lookupUrl);
|
||||||
|
}
|
||||||
|
if (changed && downloadAll == VALUE_SEGMENT_PARTS) {
|
||||||
|
meta = new BExpressionMetaData();
|
||||||
|
meta.readMetaData(tmplookupFile);
|
||||||
|
int newversion = meta.lookupVersion;
|
||||||
|
if (DEBUG) Log.d(LOG_TAG, "version old " + version + " new " + newversion);
|
||||||
|
if (version != newversion) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (changed) {
|
||||||
|
lookupFile.delete();
|
||||||
|
tmplookupFile.renameTo(lookupFile);
|
||||||
|
versionChanged = changed;
|
||||||
|
meta.readMetaData(lookupFile);
|
||||||
|
version = meta.lookupVersion;
|
||||||
|
} else {
|
||||||
|
if (tmplookupFile.exists()) tmplookupFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadProfiles() throws IOException, InterruptedException {
|
||||||
String[] profiles = mServerConfig.getProfiles();
|
String[] profiles = mServerConfig.getProfiles();
|
||||||
for (String fileName : profiles) {
|
for (String fileName : profiles) {
|
||||||
|
if (isStopped()) break;
|
||||||
if (fileName.length() > 0) {
|
if (fileName.length() > 0) {
|
||||||
File profileFile = new File(baseDir, PROFILES_DIR + fileName);
|
File profileFile = new File(baseDir, PROFILES_DIR + fileName);
|
||||||
if (profileFile.exists()) {
|
//if (profileFile.exists())
|
||||||
|
{
|
||||||
String profileLocation = mServerConfig.getProfilesUrl() + fileName;
|
String profileLocation = mServerConfig.getProfilesUrl() + fileName;
|
||||||
URL profileUrl = new URL(profileLocation);
|
URL profileUrl = new URL(profileLocation);
|
||||||
|
int size = (int) (profileFile.exists() ? profileFile.length() : 0);
|
||||||
downloadProgressListener.onDownloadStart(fileName, DownloadType.PROFILE);
|
downloadProgressListener.onDownloadStart(fileName, DownloadType.PROFILE);
|
||||||
downloadFile(profileUrl, profileFile, false);
|
downloadFile(profileUrl, profileFile, size, false, DownloadType.PROFILE);
|
||||||
downloadProgressListener.onDownloadFinished();
|
downloadProgressListener.onDownloadFinished();
|
||||||
|
done.add(profileUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,29 +299,38 @@ public class DownloadWorker extends Worker {
|
||||||
private void downloadSegment(String segmentBaseUrl, String segmentName) throws IOException, InterruptedException {
|
private void downloadSegment(String segmentBaseUrl, String segmentName) throws IOException, InterruptedException {
|
||||||
File segmentFile = new File(baseDir, SEGMENTS_DIR + segmentName);
|
File segmentFile = new File(baseDir, SEGMENTS_DIR + segmentName);
|
||||||
File segmentFileTemp = new File(segmentFile.getAbsolutePath() + "_tmp");
|
File segmentFileTemp = new File(segmentFile.getAbsolutePath() + "_tmp");
|
||||||
|
if (DEBUG) Log.d(LOG_TAG, "Download " + segmentName + " " + version + " " + versionChanged);
|
||||||
try {
|
try {
|
||||||
if (segmentFile.exists()) {
|
if (segmentFile.exists()) {
|
||||||
if (DEBUG) Log.d(LOG_TAG, "Calculating local checksum");
|
if (!versionChanged) { // no diff file on version change
|
||||||
String md5 = Rd5DiffManager.getMD5(segmentFile);
|
String md5 = Rd5DiffManager.getMD5(segmentFile);
|
||||||
String segmentDeltaLocation = segmentBaseUrl + "diff/" + segmentName.replace(SEGMENT_SUFFIX, "/" + md5 + SEGMENT_DIFF_SUFFIX);
|
if (DEBUG) Log.d(LOG_TAG, "Calculating local checksum " + md5);
|
||||||
URL segmentDeltaUrl = new URL(segmentDeltaLocation);
|
String segmentDeltaLocation = segmentBaseUrl + "diff/" + segmentName.replace(SEGMENT_SUFFIX, "/" + md5 + SEGMENT_DIFF_SUFFIX);
|
||||||
if (httpFileExists(segmentDeltaUrl)) {
|
URL segmentDeltaUrl = new URL(segmentDeltaLocation);
|
||||||
File segmentDeltaFile = new File(segmentFile.getAbsolutePath() + "_diff");
|
if (httpFileExists(segmentDeltaUrl)) {
|
||||||
try {
|
File segmentDeltaFile = new File(segmentFile.getAbsolutePath() + "_diff");
|
||||||
downloadFile(segmentDeltaUrl, segmentDeltaFile, true);
|
try {
|
||||||
if (DEBUG) Log.d(LOG_TAG, "Applying delta");
|
downloadFile(segmentDeltaUrl, segmentDeltaFile, 0, true, DownloadType.SEGMENT);
|
||||||
Rd5DiffTool.recoverFromDelta(segmentFile, segmentDeltaFile, segmentFileTemp, diffProgressListener);
|
done.add(segmentDeltaUrl);
|
||||||
} catch (IOException e) {
|
if (DEBUG) Log.d(LOG_TAG, "Applying delta");
|
||||||
throw new IOException("Failed to download & apply delta update", e);
|
Rd5DiffTool.recoverFromDelta(segmentFile, segmentDeltaFile, segmentFileTemp, diffProgressListener);
|
||||||
} finally {
|
} catch (IOException e) {
|
||||||
segmentDeltaFile.delete();
|
throw new IOException("Failed to download & apply delta update", e);
|
||||||
|
} finally {
|
||||||
|
segmentDeltaFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (segmentFileTemp.exists()) {
|
||||||
|
segmentFileTemp.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!segmentFileTemp.exists()) {
|
if (!segmentFileTemp.exists()) {
|
||||||
URL segmentUrl = new URL(segmentBaseUrl + segmentName);
|
URL segmentUrl = new URL(segmentBaseUrl + segmentName);
|
||||||
downloadFile(segmentUrl, segmentFileTemp, true);
|
downloadFile(segmentUrl, segmentFileTemp, 0, true, DownloadType.SEGMENT);
|
||||||
|
done.add(segmentUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalFile.checkFileIntegrity(segmentFileTemp);
|
PhysicalFile.checkFileIntegrity(segmentFileTemp);
|
||||||
|
@ -235,12 +352,14 @@ public class DownloadWorker extends Worker {
|
||||||
HttpURLConnection connection = (HttpURLConnection) downloadUrl.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) downloadUrl.openConnection();
|
||||||
connection.setConnectTimeout(5000);
|
connection.setConnectTimeout(5000);
|
||||||
connection.setRequestMethod("HEAD");
|
connection.setRequestMethod("HEAD");
|
||||||
|
connection.setDoInput(false);
|
||||||
connection.connect();
|
connection.connect();
|
||||||
|
|
||||||
return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
|
return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void downloadFile(URL downloadUrl, File outputFile, boolean limitDownloadSpeed) throws IOException, InterruptedException {
|
private boolean downloadFile(URL downloadUrl, File outputFile, int fileSize, boolean limitDownloadSpeed, DownloadType type) throws IOException, InterruptedException {
|
||||||
|
if (DEBUG) Log.d(LOG_TAG, "download " + outputFile.getAbsolutePath());
|
||||||
HttpURLConnection connection = (HttpURLConnection) downloadUrl.openConnection();
|
HttpURLConnection connection = (HttpURLConnection) downloadUrl.openConnection();
|
||||||
connection.setConnectTimeout(5000);
|
connection.setConnectTimeout(5000);
|
||||||
connection.connect();
|
connection.connect();
|
||||||
|
@ -248,11 +367,25 @@ public class DownloadWorker extends Worker {
|
||||||
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
|
||||||
throw new IOException("HTTP Request failed: " + downloadUrl + " returned " + connection.getResponseCode());
|
throw new IOException("HTTP Request failed: " + downloadUrl + " returned " + connection.getResponseCode());
|
||||||
}
|
}
|
||||||
int fileLength = connection.getContentLength();
|
int dataLength = connection.getContentLength();
|
||||||
try (
|
// no need of download when size equal
|
||||||
InputStream input = connection.getInputStream();
|
// file size not the best coice but easy to handle, date is not available
|
||||||
OutputStream output = new FileOutputStream(outputFile)
|
switch (type) {
|
||||||
) {
|
case LOOKUP:
|
||||||
|
if (fileSize == dataLength) return false;
|
||||||
|
break;
|
||||||
|
case PROFILE:
|
||||||
|
if (fileSize == dataLength) return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
InputStream input = null;
|
||||||
|
OutputStream output = null;
|
||||||
|
try {
|
||||||
|
input = connection.getInputStream();
|
||||||
|
output = new FileOutputStream(outputFile);
|
||||||
|
|
||||||
byte[] buffer = new byte[4096];
|
byte[] buffer = new byte[4096];
|
||||||
int total = 0;
|
int total = 0;
|
||||||
long t0 = System.currentTimeMillis();
|
long t0 = System.currentTimeMillis();
|
||||||
|
@ -264,7 +397,7 @@ public class DownloadWorker extends Worker {
|
||||||
total += count;
|
total += count;
|
||||||
output.write(buffer, 0, count);
|
output.write(buffer, 0, count);
|
||||||
|
|
||||||
downloadProgressListener.onDownloadProgress(fileLength, total);
|
downloadProgressListener.onDownloadProgress(dataLength, total);
|
||||||
|
|
||||||
if (limitDownloadSpeed) {
|
if (limitDownloadSpeed) {
|
||||||
// enforce < 16 Mbit/s
|
// enforce < 16 Mbit/s
|
||||||
|
@ -274,7 +407,12 @@ public class DownloadWorker extends Worker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
if (input != null) input.close();
|
||||||
|
if (output != null) output.close();
|
||||||
|
connection.disconnect();
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -313,7 +451,7 @@ public class DownloadWorker extends Worker {
|
||||||
notificationManager.createNotificationChannel(channel);
|
notificationManager.createNotificationChannel(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DownloadType {
|
public enum DownloadType {
|
||||||
LOOKUP,
|
LOOKUP,
|
||||||
PROFILE,
|
PROFILE,
|
||||||
SEGMENT
|
SEGMENT
|
||||||
|
|
|
@ -42,4 +42,17 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/textViewDownloadSummary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_below="@+id/progressDownload"
|
||||||
|
android:textColor="@android:color/primary_text_light"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
<string name="action_delete">Delete %s</string>
|
<string name="action_delete">Delete %s</string>
|
||||||
<string name="action_update">Update %s</string>
|
<string name="action_update">Update %s</string>
|
||||||
<string name="action_select">Select segments</string>
|
<string name="action_select">Select segments</string>
|
||||||
|
<string name="action_cancel">Stop Download</string>
|
||||||
<string name="summary_segments">Size=%s\nFree=%s</string>
|
<string name="summary_segments">Size=%s\nFree=%s</string>
|
||||||
<string name="notification_channel_id">brouter_download</string>
|
<string name="notification_channel_id">brouter_download</string>
|
||||||
<string name="notification_title">Download Segments</string>
|
<string name="notification_title">Download Segments</string>
|
||||||
|
|
|
@ -13,7 +13,7 @@ application {
|
||||||
attributes "Main-Class": getMainClass(), "Implementation-Version": project.version
|
attributes "Main-Class": getMainClass(), "Implementation-Version": project.version
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task fatJar(type: Jar) {
|
task fatJar(type: Jar) {
|
||||||
archiveFileName = 'brouter-' + project.version + '-all.jar'
|
archiveFileName = 'brouter-' + project.version + '-all.jar'
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ application {
|
||||||
}
|
}
|
||||||
|
|
||||||
distZip {
|
distZip {
|
||||||
dependsOn fatJar
|
dependsOn fatJar, ':brouter-routing-app:packageRelease'
|
||||||
archiveFileName = 'brouter-' + project.version + '.zip'
|
archiveFileName = 'brouter-' + project.version + '.zip'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ buildscript {
|
||||||
google()
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.2'
|
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|
|
@ -16,5 +16,6 @@ org.gradle.jvmargs=-Xmx1536m
|
||||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
# Automatically convert third-party libraries to use AndroidX
|
# Automatically convert third-party libraries to use AndroidX
|
||||||
android.enableJetifier=true
|
android.enableJetifier=false
|
||||||
|
|
||||||
|
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
|
||||||
|
|
Loading…
Reference in a new issue