Use LinarProgessIndicator instead of sub-view

This commit is contained in:
Manuel Fuhr 2022-04-02 17:34:41 +02:00
parent 3a2c109ded
commit 952ea803b2
8 changed files with 173 additions and 162 deletions

View file

@ -50,9 +50,8 @@ final public class Rd5DiffTool implements ProgressListener
}
@Override
public void updateProgress( String progress )
{
System.out.println( progress );
public void updateProgress(String task, int progress) {
System.out.println(task + ": " + progress + "%");
}
@Override
@ -342,7 +341,7 @@ final public class Rd5DiffTool implements ProgressListener
int pct = (int)(100. * bytesProcessed / getTileEnd( fileIndex1, 24 ) + 0.5 );
if ( pct != lastPct )
{
progress.updateProgress( "Applying delta: " + pct + "%" );
progress.updateProgress("Applying delta", pct);
lastPct = pct;
}
@ -490,7 +489,7 @@ final public class Rd5DiffTool implements ProgressListener
int pct = (int)( (100. * sizeRead) / (sizeTotal+1) + 0.5 );
if ( pct != lastPct )
{
progress.updateProgress( "Copying: " + pct + "%" );
progress.updateProgress("Copying", pct);
lastPct = pct;
}
int len = dis1.read( buf );

View file

@ -64,7 +64,8 @@ android {
}
lintOptions {
disable 'InvalidPackage'
checkReleaseBuilds false //added this line to the build.gradle under the /android/app/build.gradle
checkReleaseBuilds false
//added this line to the build.gradle under the /android/app/build.gradle
}
compileOptions {
@ -96,6 +97,7 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation "androidx.constraintlayout:constraintlayout:2.1.3"
implementation 'androidx.work:work-runtime:2.7.1'
implementation 'com.google.android.material:material:1.5.0'
implementation project(':brouter-mapaccess')
implementation project(':brouter-core')
@ -116,8 +118,7 @@ task generateProfiles(type: Exec) {
task generateProfilesZip(type: Zip) {
if (DefaultNativePlatform.getCurrentOperatingSystem().isWindows()) {
logger.warn("Note: On Windows run script '../misc/scripts/generate_profile_variants.sh' manually to include all profiles")
}
else {
} else {
dependsOn generateProfiles
}
archiveFileName = "profiles2.zip"

View file

@ -18,7 +18,7 @@
android:label="@string/app_name"
android:preserveLegacyExternalStorage="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
android:theme="@style/Theme.App">
<activity
android:name=".BRouterActivity"
android:exported="true"

View file

@ -14,9 +14,9 @@ import android.os.Build;
import android.os.Bundle;
import android.os.StatFs;
import android.text.format.Formatter;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.work.Constraints;
@ -27,6 +27,8 @@ import androidx.work.WorkInfo;
import androidx.work.WorkManager;
import androidx.work.WorkRequest;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
@ -39,12 +41,9 @@ public class BInstallerActivity extends AppCompatActivity {
public static boolean downloadCanceled = false;
private File mBaseDir;
private BInstallerView mBInstallerView;
private View mDownloadInfo;
private TextView mDownloadInfoText;
private Button mButtonDownloadCancel;
private Button mButtonDownload;
private TextView mSummaryInfo;
private View mSegmentsView;
private LinearProgressIndicator mProgressIndicator;
public static long getAvailableSpace(String baseDir) {
StatFs stat = new StatFs(baseDir);
@ -65,7 +64,6 @@ public class BInstallerActivity extends AppCompatActivity {
setContentView(R.layout.activity_binstaller);
mSummaryInfo = findViewById(R.id.textViewSegmentSummary);
mSegmentsView = findViewById(R.id.view_segments);
mBInstallerView = findViewById(R.id.BInstallerView);
mBInstallerView.setOnSelectListener(
() -> {
@ -84,12 +82,7 @@ public class BInstallerActivity extends AppCompatActivity {
}
}
);
mDownloadInfo = findViewById(R.id.view_download_progress);
mDownloadInfoText = findViewById(R.id.textViewDownloadProgress);
mButtonDownloadCancel = findViewById(R.id.buttonDownloadCancel);
mButtonDownloadCancel.setOnClickListener(view -> {
cancelDownload();
});
mProgressIndicator = findViewById(R.id.progressDownload);
mBaseDir = ConfigHelper.getBaseDir(this);
scanExistingFiles();
@ -138,21 +131,13 @@ public class BInstallerActivity extends AppCompatActivity {
}
}
private void cancelDownload() {
downloadCanceled = true;
mDownloadInfoText.setText(getString(R.string.download_info_cancel));
}
public void downloadAll(ArrayList<Integer> downloadList) {
ArrayList<String> urlparts = new ArrayList<>();
for (Integer i : downloadList) {
urlparts.add(baseNameForTile(i));
}
mSegmentsView.setVisibility(View.GONE);
mDownloadInfo.setVisibility(View.VISIBLE);
downloadCanceled = false;
mDownloadInfoText.setText(R.string.download_info_start);
Data inputData = new Data.Builder()
.putStringArray(DownloadWorker.KEY_INPUT_SEGMENT_NAMES, urlparts.toArray(new String[0]))
@ -171,31 +156,44 @@ public class BInstallerActivity extends AppCompatActivity {
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
workManager.enqueue(downloadWorkRequest);
mButtonDownloadCancel.setOnClickListener(view -> {
mDownloadInfoText.setText("Cancelling...");
workManager.cancelWorkById(downloadWorkRequest.getId());
});
workManager
.getWorkInfoByIdLiveData(downloadWorkRequest.getId())
.observe(this, workInfo -> {
if (workInfo != null) {
if (workInfo.getState() == WorkInfo.State.ENQUEUED) {
mDownloadInfoText.setText("Waiting for download to start. Check internet connection if it takes too long");
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 (segmentName != null) {
mDownloadInfoText.setText(String.format("Download %s - %d%%", segmentName, percent));
if (percent > 0) {
mProgressIndicator.setIndeterminate(false);
}
mProgressIndicator.setProgress(percent);
}
if (workInfo.getState().isFinished()) {
mSegmentsView.setVisibility(View.VISIBLE);
mDownloadInfo.setVisibility(View.GONE);
String result;
switch (workInfo.getState()) {
case FAILED:
result = "failed.";
break;
case CANCELLED:
result = "cancelled";
break;
case SUCCEEDED:
result = "succeeded";
break;
default:
result = "";
}
Toast.makeText(this, "Download " + result + ".", Toast.LENGTH_SHORT).show();
mProgressIndicator.hide();
scanExistingFiles();
}
}

View file

@ -59,10 +59,59 @@ public class DownloadWorker extends Worker {
notificationBuilder = createNotificationBuilder();
downloadProgressListener = new DownloadProgressListener() {
private String currentDownloadName;
private DownloadType currentDownloadType;
private int lastProgressPercent;
@Override
public void onDownloadStart(String downloadName, DownloadType downloadType) {
currentDownloadName = downloadName;
currentDownloadType = downloadType;
if (downloadType == DownloadType.SEGMENT) {
progressBuilder.putString(PROGRESS_SEGMENT_NAME, downloadName);
notificationBuilder.setContentText(downloadName);
}
}
@Override
public void onDownloadInfo(String info) {
notificationBuilder.setContentText(info);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
@Override
public void onDownloadProgress(int max, int progress) {
int progressPercent = (int) (progress * 100L / max);
// Only report segments and update if it changed to avoid hammering NotificationManager
if (currentDownloadType != DownloadType.SEGMENT || progressPercent == lastProgressPercent) {
return;
}
if (max > 0) {
notificationBuilder.setProgress(max, progress, false);
progressBuilder.putInt(PROGRESS_SEGMENT_PERCENT, progressPercent);
} else {
notificationBuilder.setProgress(0, 0, true);
progressBuilder.putInt(PROGRESS_SEGMENT_PERCENT, -1);
}
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
setProgressAsync(progressBuilder.build());
lastProgressPercent = progressPercent;
}
@Override
public void onDownloadFinished() {
}
};
diffProgressListener = new ProgressListener() {
@Override
public void updateProgress(String progress) {
notificationManager.notify(NOTIFICATION_ID, createNotification(progress));
public void updateProgress(String task, int progress) {
downloadProgressListener.onDownloadInfo(task);
downloadProgressListener.onDownloadProgress(100, progress);
}
@Override
@ -70,32 +119,6 @@ public class DownloadWorker extends Worker {
return isStopped();
}
};
downloadProgressListener = new DownloadProgressListener() {
@Override
public void updateProgress(int max, int progress) {
if (max > 0) {
notificationBuilder.setProgress(max, progress, false);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
progressBuilder.putInt(PROGRESS_SEGMENT_PERCENT, progress * 100 / max);
setProgressAsync(progressBuilder.build());
} else {
notificationBuilder.setProgress(0, 0, true);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
progressBuilder.putInt(PROGRESS_SEGMENT_PERCENT, -1);
setProgressAsync(progressBuilder.build());
}
}
@Override
public void updateProgress(String content) {
notificationBuilder.setContentText(content);
notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build());
}
};
progressBuilder.putInt(PROGRESS_SEGMENT_PERCENT, 0);
setProgressAsync(progressBuilder.build());
}
@NonNull
@ -109,14 +132,11 @@ public class DownloadWorker extends Worker {
// Mark the Worker as important
setForegroundAsync(new ForegroundInfo(NOTIFICATION_ID, createNotification("Starting Download")));
try {
notificationManager.notify(NOTIFICATION_ID, createNotification("Updating profiles"));
downloadLookupAndProfiles();
int segmentIndex = 1;
for (String segmentName : segmentNames) {
notificationManager.notify(NOTIFICATION_ID, createNotification(String.format("%s (%d/%d)", segmentName, segmentIndex, segmentNames.length)));
progressBuilder.putString(PROGRESS_SEGMENT_NAME, segmentName);
setProgressAsync(progressBuilder.build());
downloadProgressListener.onDownloadStart(segmentName, DownloadType.SEGMENT);
downloadSegment(mServerConfig.getSegmentUrl(), segmentName + SEGMENT_SUFFIX);
segmentIndex++;
}
@ -135,7 +155,9 @@ public class DownloadWorker extends Worker {
File lookupFile = new File(baseDir, PROFILES_DIR + fileName);
String lookupLocation = mServerConfig.getLookupUrl() + fileName;
URL lookupUrl = new URL(lookupLocation);
downloadProgressListener.onDownloadStart(fileName, DownloadType.LOOKUP);
downloadFile(lookupUrl, lookupFile, false);
downloadProgressListener.onDownloadFinished();
}
}
@ -146,7 +168,9 @@ public class DownloadWorker extends Worker {
if (profileFile.exists()) {
String profileLocation = mServerConfig.getProfilesUrl() + fileName;
URL profileUrl = new URL(profileLocation);
downloadProgressListener.onDownloadStart(fileName, DownloadType.PROFILE);
downloadFile(profileUrl, profileFile, false);
downloadProgressListener.onDownloadFinished();
}
}
}
@ -157,7 +181,7 @@ public class DownloadWorker extends Worker {
File segmentFileTemp = new File(segmentFile.getAbsolutePath() + "_tmp");
try {
if (segmentFile.exists()) {
downloadProgressListener.updateProgress("Calculating local checksum...");
downloadProgressListener.onDownloadInfo("Calculating local checksum...");
String md5 = Rd5DiffManager.getMD5(segmentFile);
String segmentDeltaLocation = segmentBaseUrl + "diff/" + segmentName.replace(SEGMENT_SUFFIX, "/" + md5 + SEGMENT_DIFF_SUFFIX);
URL segmentDeltaUrl = new URL(segmentDeltaLocation);
@ -165,7 +189,7 @@ public class DownloadWorker extends Worker {
File segmentDeltaFile = new File(segmentFile.getAbsolutePath() + "_diff");
try {
downloadFile(segmentDeltaUrl, segmentDeltaFile, true);
downloadProgressListener.updateProgress("Applying delta...");
downloadProgressListener.onDownloadInfo("Applying delta...");
Rd5DiffTool.recoverFromDelta(segmentFile, segmentDeltaFile, segmentFileTemp, diffProgressListener);
} catch (IOException e) {
throw new IOException("Failed to download & apply delta update", e);
@ -205,14 +229,10 @@ public class DownloadWorker extends Worker {
}
private void downloadFile(URL downloadUrl, File outputFile, boolean limitDownloadSpeed) throws IOException, InterruptedException {
// For all those small files the progress reporting is really noisy
boolean reportDownloadProgress = limitDownloadSpeed;
HttpURLConnection connection = (HttpURLConnection) downloadUrl.openConnection();
connection.setConnectTimeout(5000);
connection.connect();
if (reportDownloadProgress) downloadProgressListener.updateProgress("Connecting...");
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("HTTP Request failed");
}
@ -232,8 +252,7 @@ public class DownloadWorker extends Worker {
total += count;
output.write(buffer, 0, count);
// publishing the progress....
downloadProgressListener.updateProgress(fileLength, total);
downloadProgressListener.onDownloadProgress(fileLength, total);
if (limitDownloadSpeed) {
// enforce < 16 Mbit/s
@ -244,8 +263,6 @@ public class DownloadWorker extends Worker {
}
}
}
setProgressAsync(new Data.Builder().putInt(PROGRESS_SEGMENT_PERCENT, 100).build());
}
@NonNull
@ -292,8 +309,19 @@ public class DownloadWorker extends Worker {
notificationManager.createNotificationChannel(channel);
}
enum DownloadType {
LOOKUP,
PROFILE,
SEGMENT
}
interface DownloadProgressListener {
void updateProgress(int max, int progress);
void updateProgress(String content);
void onDownloadStart(String downloadName, DownloadType downloadType);
void onDownloadInfo(String info);
void onDownloadProgress(int max, int progress);
void onDownloadFinished();
}
}

View file

@ -1,19 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/view_segments"
android:layout_width="match_parent"
android:layout_height="match_parent">
<btools.routingapp.BInstallerView
android:id="@+id/BInstallerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@ -38,34 +33,13 @@
android:textColor="@android:color/primary_text_light"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/progressDownload"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="invisible"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<LinearLayout
android:id="@+id/view_download_progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:orientation="vertical"
android:visibility="gone">
<TextView
android:id="@+id/textViewDownloadProgress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp" />
<Space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<Button
android:id="@+id/buttonDownloadCancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:text="@string/cancel_download" />
</LinearLayout>
</LinearLayout>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.App" parent="Theme.AppCompat.Light.NoActionBar">
<item name="linearProgressIndicatorStyle">@style/Widget.App.LinearProgressIndicator</item>
</style>
<style name="Widget.App.LinearProgressIndicator" parent="Widget.MaterialComponents.LinearProgressIndicator">
<item name="trackThickness">20dp</item>
</style>
</resources>

View file

@ -1,8 +1,9 @@
package btools.util;
public interface ProgressListener
{
public void updateProgress( String progress );
public void updateProgress(String task, int progress);
public boolean isCanceled();
}