Merge branch 'big-install-process-event-overhaul' into 'master'
Big install process event overhaul Closes #1357 See merge request fdroid/fdroidclient!717
This commit is contained in:
commit
6876088ede
@ -362,7 +362,7 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
if (resultCode == Activity.RESULT_OK) {
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
Uri uri = data.getData();
|
Uri uri = data.getData();
|
||||||
Apk apk = ApkProvider.Helper.findByUri(this, uri, Schema.ApkTable.Cols.ALL);
|
Apk apk = ApkProvider.Helper.findByUri(this, uri, Schema.ApkTable.Cols.ALL);
|
||||||
startInstall(apk);
|
InstallManagerService.queue(this, app, apk);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REQUEST_UNINSTALL_DIALOG:
|
case REQUEST_UNINSTALL_DIALOG:
|
||||||
@ -373,6 +373,12 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void installApk() {
|
||||||
|
Apk apkToInstall = ApkProvider.Helper.findSuggestedApk(this, app);
|
||||||
|
installApk(apkToInstall);
|
||||||
|
}
|
||||||
|
|
||||||
// Install the version of this app denoted by 'app.curApk'.
|
// Install the version of this app denoted by 'app.curApk'.
|
||||||
@Override
|
@Override
|
||||||
public void installApk(final Apk apk) {
|
public void installApk(final Apk apk) {
|
||||||
@ -426,12 +432,6 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initiateInstall(Apk apk) {
|
private void initiateInstall(Apk apk) {
|
||||||
if (isAppDownloading()) {
|
|
||||||
Log.i(TAG, "Ignoring request to install " + apk.packageName + " version " + apk.versionName
|
|
||||||
+ ", as we are already downloading (either that or a different version).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Installer installer = InstallerFactory.create(this, apk);
|
Installer installer = InstallerFactory.create(this, apk);
|
||||||
Intent intent = installer.getPermissionScreen();
|
Intent intent = installer.getPermissionScreen();
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
@ -441,10 +441,6 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
startInstall(apk);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startInstall(Apk apk) {
|
|
||||||
InstallManagerService.queue(this, app, apk);
|
InstallManagerService.queue(this, app, apk);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -485,6 +481,7 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (newStatus.status) {
|
switch (newStatus.status) {
|
||||||
|
case PendingInstall:
|
||||||
case Downloading:
|
case Downloading:
|
||||||
if (newStatus.progressMax == 0) {
|
if (newStatus.progressMax == 0) {
|
||||||
// The first progress notification we get telling us our status is "Downloading"
|
// The first progress notification we get telling us our status is "Downloading"
|
||||||
@ -708,11 +705,6 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAppDownloading() {
|
|
||||||
return currentStatus != null && currentStatus.status == AppUpdateStatusManager.Status.Downloading;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableAndroidBeam() {
|
public void enableAndroidBeam() {
|
||||||
NfcHelper.setAndroidBeam(this, app.packageName);
|
NfcHelper.setAndroidBeam(this, app.packageName);
|
||||||
@ -737,7 +729,7 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void installCancel() {
|
public void installCancel() {
|
||||||
if (isAppDownloading()) {
|
if (currentStatus != null) {
|
||||||
InstallManagerService.cancel(this, currentStatus.getUniqueKey());
|
InstallManagerService.cancel(this, currentStatus.getUniqueKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -753,18 +745,6 @@ public class AppDetails2 extends AppCompatActivity
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void installApk() {
|
|
||||||
Apk apkToInstall = ApkProvider.Helper.findSuggestedApk(this, app);
|
|
||||||
installApk(apkToInstall);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void upgradeApk() {
|
|
||||||
Apk apkToInstall = ApkProvider.Helper.findSuggestedApk(this, app);
|
|
||||||
installApk(apkToInstall);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uninstall the app from the current screen. Since there are many ways
|
* Uninstall the app from the current screen. Since there are many ways
|
||||||
* to uninstall an app, including from Google Play, {@code adb uninstall},
|
* to uninstall an app, including from Google Play, {@code adb uninstall},
|
||||||
|
@ -91,13 +91,14 @@ public final class AppUpdateStatusManager {
|
|||||||
private static final String LOGTAG = "AppUpdateStatusManager";
|
private static final String LOGTAG = "AppUpdateStatusManager";
|
||||||
|
|
||||||
public enum Status {
|
public enum Status {
|
||||||
|
PendingInstall,
|
||||||
DownloadInterrupted,
|
DownloadInterrupted,
|
||||||
UpdateAvailable,
|
UpdateAvailable,
|
||||||
Downloading,
|
Downloading,
|
||||||
ReadyToInstall,
|
ReadyToInstall,
|
||||||
Installing,
|
Installing,
|
||||||
Installed,
|
Installed,
|
||||||
InstallError
|
InstallError,
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AppUpdateStatusManager getInstance(Context context) {
|
public static AppUpdateStatusManager getInstance(Context context) {
|
||||||
@ -426,6 +427,7 @@ public final class AppUpdateStatusManager {
|
|||||||
entry.errorText = errorText;
|
entry.errorText = errorText;
|
||||||
entry.intent = null;
|
entry.intent = null;
|
||||||
notifyChange(entry, true);
|
notifyChange(entry, true);
|
||||||
|
removeApk(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,6 +230,7 @@ class NotificationHelper {
|
|||||||
case UpdateAvailable:
|
case UpdateAvailable:
|
||||||
return new NotificationCompat.Action(R.drawable.ic_file_download, context.getString(R.string.notification_action_update), entry.intent);
|
return new NotificationCompat.Action(R.drawable.ic_file_download, context.getString(R.string.notification_action_update), entry.intent);
|
||||||
|
|
||||||
|
case PendingInstall:
|
||||||
case Downloading:
|
case Downloading:
|
||||||
case Installing:
|
case Installing:
|
||||||
return new NotificationCompat.Action(R.drawable.ic_cancel, context.getString(R.string.notification_action_cancel), entry.intent);
|
return new NotificationCompat.Action(R.drawable.ic_cancel, context.getString(R.string.notification_action_cancel), entry.intent);
|
||||||
@ -245,6 +246,7 @@ class NotificationHelper {
|
|||||||
switch (status) {
|
switch (status) {
|
||||||
case UpdateAvailable:
|
case UpdateAvailable:
|
||||||
return context.getString(R.string.notification_title_single_update_available);
|
return context.getString(R.string.notification_title_single_update_available);
|
||||||
|
case PendingInstall:
|
||||||
case Downloading:
|
case Downloading:
|
||||||
return app.name;
|
return app.name;
|
||||||
case ReadyToInstall:
|
case ReadyToInstall:
|
||||||
@ -263,6 +265,7 @@ class NotificationHelper {
|
|||||||
switch (status) {
|
switch (status) {
|
||||||
case UpdateAvailable:
|
case UpdateAvailable:
|
||||||
return app.name;
|
return app.name;
|
||||||
|
case PendingInstall:
|
||||||
case Downloading:
|
case Downloading:
|
||||||
return context.getString(app.isInstalled(context) ? R.string.notification_content_single_downloading_update : R.string.notification_content_single_downloading, app.name);
|
return context.getString(app.isInstalled(context) ? R.string.notification_content_single_downloading_update : R.string.notification_content_single_downloading, app.name);
|
||||||
case ReadyToInstall:
|
case ReadyToInstall:
|
||||||
@ -281,6 +284,7 @@ class NotificationHelper {
|
|||||||
switch (status) {
|
switch (status) {
|
||||||
case UpdateAvailable:
|
case UpdateAvailable:
|
||||||
return context.getString(R.string.notification_title_summary_update_available);
|
return context.getString(R.string.notification_title_summary_update_available);
|
||||||
|
case PendingInstall:
|
||||||
case Downloading:
|
case Downloading:
|
||||||
return context.getString(app.isInstalled(context) ? R.string.notification_title_summary_downloading_update : R.string.notification_title_summary_downloading);
|
return context.getString(app.isInstalled(context) ? R.string.notification_title_summary_downloading_update : R.string.notification_title_summary_downloading);
|
||||||
case ReadyToInstall:
|
case ReadyToInstall:
|
||||||
|
@ -145,7 +145,6 @@ public class FileInstallerActivity extends FragmentActivity {
|
|||||||
|
|
||||||
private void installPackage(Uri localApkUri, Uri downloadUri, Apk apk) {
|
private void installPackage(Uri localApkUri, Uri downloadUri, Apk apk) {
|
||||||
Utils.debugLog(TAG, "Installing: " + localApkUri.getPath());
|
Utils.debugLog(TAG, "Installing: " + localApkUri.getPath());
|
||||||
installer.sendBroadcastInstall(downloadUri, Installer.ACTION_INSTALL_STARTED);
|
|
||||||
File path = apk.getMediaInstallPath(activity.getApplicationContext());
|
File path = apk.getMediaInstallPath(activity.getApplicationContext());
|
||||||
path.mkdirs();
|
path.mkdirs();
|
||||||
try {
|
try {
|
||||||
|
@ -34,7 +34,13 @@ import java.io.IOException;
|
|||||||
/**
|
/**
|
||||||
* Manages the whole process when a background update triggers an install or the user
|
* Manages the whole process when a background update triggers an install or the user
|
||||||
* requests an APK to be installed. It handles checking whether the APK is cached,
|
* requests an APK to be installed. It handles checking whether the APK is cached,
|
||||||
* downloading it, putting up and maintaining a {@link Notification}, and more.
|
* downloading it, putting up and maintaining a {@link Notification}, and more. This
|
||||||
|
* {@code Service} tracks packages that are in the process as "Pending Installs".
|
||||||
|
* Then {@link DownloaderService} and {@link InstallerService} individually track
|
||||||
|
* packages for those phases of the whole install process. Each of those
|
||||||
|
* {@code Services} have their own related events. For tracking status during the
|
||||||
|
* whole process, {@link AppUpdateStatusManager} tracks the status as represented by
|
||||||
|
* {@link AppUpdateStatusManager.AppUpdateStatus}.
|
||||||
* <p>
|
* <p>
|
||||||
* The {@link App} and {@link Apk} instances are sent via
|
* The {@link App} and {@link Apk} instances are sent via
|
||||||
* {@link Intent#putExtra(String, android.os.Bundle)}
|
* {@link Intent#putExtra(String, android.os.Bundle)}
|
||||||
@ -103,7 +109,6 @@ public class InstallManagerService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
Utils.debugLog(TAG, "creating Service");
|
|
||||||
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
localBroadcastManager = LocalBroadcastManager.getInstance(this);
|
||||||
appUpdateStatusManager = AppUpdateStatusManager.getInstance(this);
|
appUpdateStatusManager = AppUpdateStatusManager.getInstance(this);
|
||||||
|
|
||||||
@ -171,7 +176,6 @@ public class InstallManagerService extends Service {
|
|||||||
DownloaderService.cancel(this, apk.getPatchObbUrl());
|
DownloaderService.cancel(this, apk.getPatchObbUrl());
|
||||||
DownloaderService.cancel(this, apk.getMainObbUrl());
|
DownloaderService.cancel(this, apk.getMainObbUrl());
|
||||||
}
|
}
|
||||||
appUpdateStatusManager.removeApk(urlString);
|
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
} else if (ACTION_INSTALL.equals(action)) {
|
} else if (ACTION_INSTALL.equals(action)) {
|
||||||
if (!isPendingInstall(urlString)) {
|
if (!isPendingInstall(urlString)) {
|
||||||
@ -455,14 +459,12 @@ public class InstallManagerService extends Service {
|
|||||||
*/
|
*/
|
||||||
public static void queue(Context context, App app, @NonNull Apk apk) {
|
public static void queue(Context context, App app, @NonNull Apk apk) {
|
||||||
String urlString = apk.getUrl();
|
String urlString = apk.getUrl();
|
||||||
|
AppUpdateStatusManager.getInstance(context).addApk(apk, AppUpdateStatusManager.Status.PendingInstall, null);
|
||||||
putPendingInstall(context, urlString, apk.packageName);
|
putPendingInstall(context, urlString, apk.packageName);
|
||||||
Uri downloadUri = Uri.parse(urlString);
|
|
||||||
Installer.sendBroadcastInstall(context, downloadUri, Installer.ACTION_INSTALL_STARTED, apk,
|
|
||||||
null, null);
|
|
||||||
Utils.debugLog(TAG, "queue " + app.packageName + " " + apk.versionCode + " from " + urlString);
|
Utils.debugLog(TAG, "queue " + app.packageName + " " + apk.versionCode + " from " + urlString);
|
||||||
Intent intent = new Intent(context, InstallManagerService.class);
|
Intent intent = new Intent(context, InstallManagerService.class);
|
||||||
intent.setAction(ACTION_INSTALL);
|
intent.setAction(ACTION_INSTALL);
|
||||||
intent.setData(downloadUri);
|
intent.setData(Uri.parse(urlString));
|
||||||
intent.putExtra(EXTRA_APP, app);
|
intent.putExtra(EXTRA_APP, app);
|
||||||
intent.putExtra(EXTRA_APK, apk);
|
intent.putExtra(EXTRA_APK, apk);
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
@ -487,12 +489,25 @@ public class InstallManagerService extends Service {
|
|||||||
return pendingInstalls.contains(urlString);
|
return pendingInstalls.contains(urlString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Look up by {@code packageName} whether it is a Pending Install.
|
||||||
|
*
|
||||||
|
* @see #isPendingInstall(String)
|
||||||
|
*/
|
||||||
|
public static boolean isPendingInstall(Context context, String packageName) {
|
||||||
|
if (pendingInstalls == null) {
|
||||||
|
pendingInstalls = getPendingInstalls(context);
|
||||||
|
}
|
||||||
|
return pendingInstalls.getAll().values().contains(packageName);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mark a given APK as in the process of being installed, with
|
* Mark a given APK as in the process of being installed, with
|
||||||
* the {@code urlString} of the download used as the unique ID,
|
* the {@code urlString} of the download used as the unique ID,
|
||||||
* and the file hash used to verify that things are the same.
|
* and the file hash used to verify that things are the same.
|
||||||
*
|
*
|
||||||
* @see #isPendingInstall(String)
|
* @see #isPendingInstall(String)
|
||||||
|
* @see #isPendingInstall(Context, String)
|
||||||
*/
|
*/
|
||||||
public static void putPendingInstall(Context context, String urlString, String packageName) {
|
public static void putPendingInstall(Context context, String urlString, String packageName) {
|
||||||
if (pendingInstalls == null) {
|
if (pendingInstalls == null) {
|
||||||
|
@ -115,6 +115,8 @@ public class InstallerService extends JobIntentService {
|
|||||||
* @see #uninstall(Context, Apk)
|
* @see #uninstall(Context, Apk)
|
||||||
*/
|
*/
|
||||||
public static void install(Context context, Uri localApkUri, Uri downloadUri, Apk apk) {
|
public static void install(Context context, Uri localApkUri, Uri downloadUri, Apk apk) {
|
||||||
|
Installer.sendBroadcastInstall(context, downloadUri, Installer.ACTION_INSTALL_STARTED, apk,
|
||||||
|
null, null);
|
||||||
Intent intent = new Intent(context, InstallerService.class);
|
Intent intent = new Intent(context, InstallerService.class);
|
||||||
intent.setAction(ACTION_INSTALL);
|
intent.setAction(ACTION_INSTALL);
|
||||||
intent.setData(localApkUri);
|
intent.setData(localApkUri);
|
||||||
|
@ -43,6 +43,7 @@ import org.fdroid.fdroid.data.ApkProvider;
|
|||||||
import org.fdroid.fdroid.data.App;
|
import org.fdroid.fdroid.data.App;
|
||||||
import org.fdroid.fdroid.data.InstalledAppProvider;
|
import org.fdroid.fdroid.data.InstalledAppProvider;
|
||||||
import org.fdroid.fdroid.data.RepoProvider;
|
import org.fdroid.fdroid.data.RepoProvider;
|
||||||
|
import org.fdroid.fdroid.installer.InstallManagerService;
|
||||||
import org.fdroid.fdroid.privileged.views.AppDiff;
|
import org.fdroid.fdroid.privileged.views.AppDiff;
|
||||||
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
|
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
|
||||||
import org.fdroid.fdroid.views.main.MainActivity;
|
import org.fdroid.fdroid.views.main.MainActivity;
|
||||||
@ -57,8 +58,6 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
|
|
||||||
public interface AppDetailsRecyclerViewAdapterCallbacks {
|
public interface AppDetailsRecyclerViewAdapterCallbacks {
|
||||||
|
|
||||||
boolean isAppDownloading();
|
|
||||||
|
|
||||||
void enableAndroidBeam();
|
void enableAndroidBeam();
|
||||||
|
|
||||||
void disableAndroidBeam();
|
void disableAndroidBeam();
|
||||||
@ -69,8 +68,6 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
|
|
||||||
void installApk(Apk apk);
|
void installApk(Apk apk);
|
||||||
|
|
||||||
void upgradeApk();
|
|
||||||
|
|
||||||
void uninstallApk();
|
void uninstallApk();
|
||||||
|
|
||||||
void installCancel();
|
void installCancel();
|
||||||
@ -378,11 +375,17 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
progressLabel.setText(resIdString);
|
progressLabel.setText(resIdString);
|
||||||
progressLabel.setContentDescription(context.getString(R.string.downloading));
|
progressLabel.setContentDescription(context.getString(R.string.downloading));
|
||||||
progressPercent.setText("");
|
progressPercent.setText("");
|
||||||
|
if (resIdString == R.string.installing || resIdString == R.string.uninstalling) {
|
||||||
|
progressCancel.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
progressCancel.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setProgress(long bytesDownloaded, long totalBytes) {
|
public void setProgress(long bytesDownloaded, long totalBytes) {
|
||||||
progressLayout.setVisibility(View.VISIBLE);
|
progressLayout.setVisibility(View.VISIBLE);
|
||||||
buttonLayout.setVisibility(View.GONE);
|
buttonLayout.setVisibility(View.GONE);
|
||||||
|
progressCancel.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
progressBar.setMax(Utils.bytesToKb(totalBytes));
|
progressBar.setMax(Utils.bytesToKb(totalBytes));
|
||||||
progressBar.setProgress(Utils.bytesToKb(bytesDownloaded));
|
progressBar.setProgress(Utils.bytesToKb(bytesDownloaded));
|
||||||
@ -484,9 +487,11 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
buttonSecondaryView.setOnClickListener(onUnInstallClickListener);
|
buttonSecondaryView.setOnClickListener(onUnInstallClickListener);
|
||||||
buttonPrimaryView.setText(R.string.menu_install);
|
buttonPrimaryView.setText(R.string.menu_install);
|
||||||
buttonPrimaryView.setVisibility(versions.size() > 0 ? View.VISIBLE : View.GONE);
|
buttonPrimaryView.setVisibility(versions.size() > 0 ? View.VISIBLE : View.GONE);
|
||||||
if (callbacks.isAppDownloading()) {
|
if (InstallManagerService.isPendingInstall(context, app.packageName)) {
|
||||||
buttonPrimaryView.setText(R.string.downloading);
|
buttonPrimaryView.setText(R.string.downloading);
|
||||||
buttonPrimaryView.setEnabled(false);
|
buttonPrimaryView.setEnabled(false);
|
||||||
|
buttonLayout.setVisibility(View.GONE);
|
||||||
|
progressLayout.setVisibility(View.VISIBLE);
|
||||||
} else if (!app.isInstalled(context) && suggestedApk != null) {
|
} else if (!app.isInstalled(context) && suggestedApk != null) {
|
||||||
// Check count > 0 due to incompatible apps resulting in an empty list.
|
// Check count > 0 due to incompatible apps resulting in an empty list.
|
||||||
callbacks.disableAndroidBeam();
|
callbacks.disableAndroidBeam();
|
||||||
@ -494,6 +499,8 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
buttonPrimaryView.setText(R.string.menu_install);
|
buttonPrimaryView.setText(R.string.menu_install);
|
||||||
buttonPrimaryView.setOnClickListener(onInstallClickListener);
|
buttonPrimaryView.setOnClickListener(onInstallClickListener);
|
||||||
buttonPrimaryView.setEnabled(true);
|
buttonPrimaryView.setEnabled(true);
|
||||||
|
buttonLayout.setVisibility(View.VISIBLE);
|
||||||
|
progressLayout.setVisibility(View.GONE);
|
||||||
} else if (app.isInstalled(context)) {
|
} else if (app.isInstalled(context)) {
|
||||||
callbacks.enableAndroidBeam();
|
callbacks.enableAndroidBeam();
|
||||||
if (app.canAndWantToUpdate(context) && suggestedApk != null) {
|
if (app.canAndWantToUpdate(context) && suggestedApk != null) {
|
||||||
@ -508,10 +515,8 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
buttonPrimaryView.setEnabled(true);
|
buttonPrimaryView.setEnabled(true);
|
||||||
}
|
buttonLayout.setVisibility(View.VISIBLE);
|
||||||
if (callbacks.isAppDownloading()) {
|
progressLayout.setVisibility(View.GONE);
|
||||||
buttonLayout.setVisibility(View.GONE);
|
|
||||||
progressLayout.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
} else {
|
||||||
buttonLayout.setVisibility(View.VISIBLE);
|
buttonLayout.setVisibility(View.VISIBLE);
|
||||||
progressLayout.setVisibility(View.GONE);
|
progressLayout.setVisibility(View.GONE);
|
||||||
@ -1097,7 +1102,7 @@ public class AppDetailsRecyclerViewAdapter
|
|||||||
private final View.OnClickListener onUpgradeClickListener = new View.OnClickListener() {
|
private final View.OnClickListener onUpgradeClickListener = new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
callbacks.upgradeApk();
|
callbacks.installApk();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ import java.util.Iterator;
|
|||||||
* </ul>
|
* </ul>
|
||||||
* <p>
|
* <p>
|
||||||
* The state of the UI is defined in a dumb {@link AppListItemState} class, then applied to the UI
|
* The state of the UI is defined in a dumb {@link AppListItemState} class, then applied to the UI
|
||||||
* in the {@link #refreshView(App, AppUpdateStatus)} method.
|
* in the {@link #updateAppStatus(App, AppUpdateStatus)} method.
|
||||||
*/
|
*/
|
||||||
public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
@ -220,15 +220,10 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates both the progress bar and the circular install button (which shows progress around the outside of
|
* Updates both the progress bar and the circular install button (which
|
||||||
* the circle). Also updates the app label to indicate that the app is being downloaded.
|
* shows progress around the outside of the circle). Also updates the app
|
||||||
*/
|
* label to indicate that the app is being downloaded.
|
||||||
private void updateAppStatus(@NonNull App app, @Nullable AppUpdateStatus status) {
|
* <p>
|
||||||
currentStatus = status;
|
|
||||||
refreshView(app, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Queries the current state via {@link #getCurrentViewState(App, AppUpdateStatus)}
|
* Queries the current state via {@link #getCurrentViewState(App, AppUpdateStatus)}
|
||||||
* and then updates the relevant widgets depending on that state.
|
* and then updates the relevant widgets depending on that state.
|
||||||
* <p>
|
* <p>
|
||||||
@ -238,7 +233,8 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
* @see AppListItemState
|
* @see AppListItemState
|
||||||
* @see #getCurrentViewState(App, AppUpdateStatus)
|
* @see #getCurrentViewState(App, AppUpdateStatus)
|
||||||
*/
|
*/
|
||||||
private void refreshView(@NonNull App app, @Nullable AppUpdateStatus appStatus) {
|
private void updateAppStatus(@NonNull App app, @Nullable AppUpdateStatus appStatus) {
|
||||||
|
currentStatus = appStatus;
|
||||||
|
|
||||||
AppListItemState viewState = getCurrentViewState(app, appStatus);
|
AppListItemState viewState = getCurrentViewState(app, appStatus);
|
||||||
|
|
||||||
@ -289,12 +285,14 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
if (viewState.shouldShowActionButton()) {
|
if (viewState.shouldShowActionButton()) {
|
||||||
installButton.setVisibility(View.GONE);
|
installButton.setVisibility(View.GONE);
|
||||||
} else if (viewState.showProgress()) {
|
} else if (viewState.showProgress()) {
|
||||||
|
installButton.setEnabled(false);
|
||||||
installButton.setVisibility(View.VISIBLE);
|
installButton.setVisibility(View.VISIBLE);
|
||||||
installButton.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_download_progress));
|
installButton.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_download_progress));
|
||||||
int progressAsDegrees = viewState.getProgressMax() <= 0 ? 0 :
|
int progressAsDegrees = viewState.getProgressMax() <= 0 ? 0 :
|
||||||
(int) (((float) viewState.getProgressCurrent() / viewState.getProgressMax()) * 360);
|
(int) (((float) viewState.getProgressCurrent() / viewState.getProgressMax()) * 360);
|
||||||
installButton.setImageLevel(progressAsDegrees);
|
installButton.setImageLevel(progressAsDegrees);
|
||||||
} else if (viewState.shouldShowInstall()) {
|
} else if (viewState.shouldShowInstall()) {
|
||||||
|
installButton.setEnabled(true);
|
||||||
installButton.setVisibility(View.VISIBLE);
|
installButton.setVisibility(View.VISIBLE);
|
||||||
installButton.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_download));
|
installButton.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.ic_download));
|
||||||
} else {
|
} else {
|
||||||
@ -332,9 +330,13 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
case ReadyToInstall:
|
case ReadyToInstall:
|
||||||
return getViewStateReadyToInstall(app);
|
return getViewStateReadyToInstall(app);
|
||||||
|
|
||||||
|
case PendingInstall:
|
||||||
case Downloading:
|
case Downloading:
|
||||||
return getViewStateDownloading(app, appStatus);
|
return getViewStateDownloading(app, appStatus);
|
||||||
|
|
||||||
|
case Installing:
|
||||||
|
return getViewStateInstalling(app);
|
||||||
|
|
||||||
case Installed:
|
case Installed:
|
||||||
return getViewStateInstalled(app);
|
return getViewStateInstalled(app);
|
||||||
|
|
||||||
@ -344,6 +346,16 @@ public abstract class AppListItemController extends RecyclerView.ViewHolder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected AppListItemState getViewStateInstalling(@NonNull App app) {
|
||||||
|
CharSequence mainText = activity.getString(
|
||||||
|
R.string.app_list__name__downloading_in_progress, app.name);
|
||||||
|
|
||||||
|
return new AppListItemState(app)
|
||||||
|
.setMainText(mainText)
|
||||||
|
.showActionButton(null)
|
||||||
|
.setStatusText(activity.getString(R.string.notification_content_single_installing, app.name));
|
||||||
|
}
|
||||||
|
|
||||||
protected AppListItemState getViewStateInstalled(@NonNull App app) {
|
protected AppListItemState getViewStateInstalled(@NonNull App app) {
|
||||||
CharSequence mainText = activity.getString(
|
CharSequence mainText = activity.getString(
|
||||||
R.string.app_list__name__successfully_installed, app.name);
|
R.string.app_list__name__successfully_installed, app.name);
|
||||||
|
@ -101,10 +101,6 @@ public class AppDetailsAdapterTest extends FDroidProviderTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final AppDetailsRecyclerViewAdapter.AppDetailsRecyclerViewAdapterCallbacks dummyCallbacks = new AppDetailsRecyclerViewAdapter.AppDetailsRecyclerViewAdapterCallbacks() { // NOCHECKSTYLE LineLength
|
private final AppDetailsRecyclerViewAdapter.AppDetailsRecyclerViewAdapterCallbacks dummyCallbacks = new AppDetailsRecyclerViewAdapter.AppDetailsRecyclerViewAdapterCallbacks() { // NOCHECKSTYLE LineLength
|
||||||
@Override
|
|
||||||
public boolean isAppDownloading() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enableAndroidBeam() {
|
public void enableAndroidBeam() {
|
||||||
@ -131,11 +127,6 @@ public class AppDetailsAdapterTest extends FDroidProviderTest {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void upgradeApk() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void uninstallApk() {
|
public void uninstallApk() {
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user