Added "Installed Apps" activity to top of settings.
This is as per the mockup in issue #840, and does the following: * Adds a new `PreferencesCategory` of "My Apps" at the top of the preferences screen. * Adds a "Manage Installed Apps" preference, and moves the "Repositories" preference into this category. * Repeals an existing change which prevented "updateable" apps from appearing in the list of "installed" apps. This is because the two lists of apps are no longer displayed alongside eachother. * Enhances the `AppListItemController` to also be able to display whether or not the currently installed version is the recommended version or not. * Also adds option to display whether the user has asked to ignore any updates for any specific apps.
This commit is contained in:
		
							parent
							
								
									92943ebdf3
								
							
						
					
					
						commit
						a1a7427cd2
					
				@ -517,6 +517,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <activity android:name=".views.apps.AppListActivity" />
 | 
					        <activity android:name=".views.apps.AppListActivity" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <activity android:name=".views.installed.InstalledAppsActivity"
 | 
				
			||||||
 | 
					            android:parentActivityName=".views.main.MainActivity">
 | 
				
			||||||
 | 
					            <meta-data
 | 
				
			||||||
 | 
					                android:name="android.support.PARENT_ACTIVITY"
 | 
				
			||||||
 | 
					                android:value=".views.main.MainActivity" />
 | 
				
			||||||
 | 
					        </activity>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    </application>
 | 
					    </application>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</manifest>
 | 
					</manifest>
 | 
				
			||||||
 | 
				
			|||||||
@ -569,6 +569,10 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
 | 
				
			|||||||
        return TextUtils.isEmpty(flattrID) ? null : "https://flattr.com/thing/" + flattrID;
 | 
					        return TextUtils.isEmpty(flattrID) ? null : "https://flattr.com/thing/" + flattrID;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * @see App#suggestedVersionName for why this uses a getter while other member variables are
 | 
				
			||||||
 | 
					     * publicly accessible.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    public String getSuggestedVersionName() {
 | 
					    public String getSuggestedVersionName() {
 | 
				
			||||||
        return suggestedVersionName;
 | 
					        return suggestedVersionName;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -199,26 +199,16 @@ public class AppProvider extends FDroidProvider {
 | 
				
			|||||||
        public AppQuerySelection add(AppQuerySelection query) {
 | 
					        public AppQuerySelection add(AppQuerySelection query) {
 | 
				
			||||||
            QuerySelection both = super.add(query);
 | 
					            QuerySelection both = super.add(query);
 | 
				
			||||||
            AppQuerySelection bothWithJoin = new AppQuerySelection(both.getSelection(), both.getArgs());
 | 
					            AppQuerySelection bothWithJoin = new AppQuerySelection(both.getSelection(), both.getArgs());
 | 
				
			||||||
            ensureJoinsCopied(query, bothWithJoin);
 | 
					            if (this.naturalJoinToInstalled() || query.naturalJoinToInstalled()) {
 | 
				
			||||||
 | 
					                bothWithJoin.requireNaturalInstalledTable();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (this.leftJoinToPrefs() || query.leftJoinToPrefs()) {
 | 
				
			||||||
 | 
					                bothWithJoin.requireLeftJoinPrefs();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            return bothWithJoin;
 | 
					            return bothWithJoin;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public AppQuerySelection not(AppQuerySelection query) {
 | 
					 | 
				
			||||||
            QuerySelection both = super.not(query);
 | 
					 | 
				
			||||||
            AppQuerySelection bothWithJoin = new AppQuerySelection(both.getSelection(), both.getArgs());
 | 
					 | 
				
			||||||
            ensureJoinsCopied(query, bothWithJoin);
 | 
					 | 
				
			||||||
            return bothWithJoin;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        private void ensureJoinsCopied(AppQuerySelection toAdd, AppQuerySelection newlyCreated) {
 | 
					 | 
				
			||||||
            if (this.naturalJoinToInstalled() || toAdd.naturalJoinToInstalled()) {
 | 
					 | 
				
			||||||
                newlyCreated.requireNaturalInstalledTable();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (this.leftJoinToPrefs() || toAdd.leftJoinToPrefs()) {
 | 
					 | 
				
			||||||
                newlyCreated.requireLeftJoinPrefs();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected class Query extends QueryBuilder {
 | 
					    protected class Query extends QueryBuilder {
 | 
				
			||||||
@ -574,8 +564,7 @@ public class AppProvider extends FDroidProvider {
 | 
				
			|||||||
        final String ignoreAll = "COALESCE(prefs." + AppPrefsTable.Cols.IGNORE_ALL_UPDATES + ", 0) != 1";
 | 
					        final String ignoreAll = "COALESCE(prefs." + AppPrefsTable.Cols.IGNORE_ALL_UPDATES + ", 0) != 1";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        final String ignore = " (" + ignoreCurrent + " AND " + ignoreAll + ") ";
 | 
					        final String ignore = " (" + ignoreCurrent + " AND " + ignoreAll + ") ";
 | 
				
			||||||
        final String nullChecks = app + "." + Cols.SUGGESTED_VERSION_CODE + " IS NOT NULL AND installed." + InstalledAppTable.Cols.VERSION_CODE + " IS NOT NULL ";
 | 
					        final String where = ignore + " AND " + app + "." + Cols.SUGGESTED_VERSION_CODE + " > installed." + InstalledAppTable.Cols.VERSION_CODE;
 | 
				
			||||||
        final String where = nullChecks + " AND " + ignore + " AND " + app + "." + Cols.SUGGESTED_VERSION_CODE + " > installed." + InstalledAppTable.Cols.VERSION_CODE;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return new AppQuerySelection(where).requireNaturalInstalledTable().requireLeftJoinPrefs();
 | 
					        return new AppQuerySelection(where).requireNaturalInstalledTable().requireLeftJoinPrefs();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -587,7 +576,7 @@ public class AppProvider extends FDroidProvider {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private AppQuerySelection queryInstalled() {
 | 
					    private AppQuerySelection queryInstalled() {
 | 
				
			||||||
        return new AppQuerySelection().requireNaturalInstalledTable().not(queryCanUpdate());
 | 
					        return new AppQuerySelection().requireNaturalInstalledTable();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private AppQuerySelection querySearch(String query) {
 | 
					    private AppQuerySelection querySearch(String query) {
 | 
				
			||||||
 | 
				
			|||||||
@ -78,8 +78,4 @@ public class QuerySelection {
 | 
				
			|||||||
        return new QuerySelection(s, a);
 | 
					        return new QuerySelection(s, a);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public QuerySelection not(QuerySelection querySelection) {
 | 
					 | 
				
			||||||
        String where = " NOT (" + querySelection.getSelection() + ") ";
 | 
					 | 
				
			||||||
        return add(where, querySelection.getArgs());
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ import android.net.Uri;
 | 
				
			|||||||
import android.os.Build;
 | 
					import android.os.Build;
 | 
				
			||||||
import android.os.Bundle;
 | 
					import android.os.Bundle;
 | 
				
			||||||
import android.support.annotation.NonNull;
 | 
					import android.support.annotation.NonNull;
 | 
				
			||||||
 | 
					import android.support.annotation.Nullable;
 | 
				
			||||||
import android.support.v4.app.ActivityOptionsCompat;
 | 
					import android.support.v4.app.ActivityOptionsCompat;
 | 
				
			||||||
import android.support.v4.content.ContextCompat;
 | 
					import android.support.v4.content.ContextCompat;
 | 
				
			||||||
import android.support.v4.content.LocalBroadcastManager;
 | 
					import android.support.v4.content.LocalBroadcastManager;
 | 
				
			||||||
@ -33,6 +34,7 @@ import org.fdroid.fdroid.Utils;
 | 
				
			|||||||
import org.fdroid.fdroid.data.Apk;
 | 
					import org.fdroid.fdroid.data.Apk;
 | 
				
			||||||
import org.fdroid.fdroid.data.ApkProvider;
 | 
					import org.fdroid.fdroid.data.ApkProvider;
 | 
				
			||||||
import org.fdroid.fdroid.data.App;
 | 
					import org.fdroid.fdroid.data.App;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.data.AppPrefs;
 | 
				
			||||||
import org.fdroid.fdroid.installer.ApkCache;
 | 
					import org.fdroid.fdroid.installer.ApkCache;
 | 
				
			||||||
import org.fdroid.fdroid.installer.InstallManagerService;
 | 
					import org.fdroid.fdroid.installer.InstallManagerService;
 | 
				
			||||||
import org.fdroid.fdroid.installer.Installer;
 | 
					import org.fdroid.fdroid.installer.Installer;
 | 
				
			||||||
@ -50,10 +52,24 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private final Activity activity;
 | 
					    private final Activity activity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final ImageView installButton;
 | 
					    @NonNull
 | 
				
			||||||
    private final ImageView icon;
 | 
					    private final ImageView icon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @NonNull
 | 
				
			||||||
    private final TextView name;
 | 
					    private final TextView name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    private final ImageView installButton;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
    private final TextView status;
 | 
					    private final TextView status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    private final TextView installedVersion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Nullable
 | 
				
			||||||
 | 
					    private final TextView ignoredStatus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private final DisplayImageOptions displayImageOptions;
 | 
					    private final DisplayImageOptions displayImageOptions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private App currentApp;
 | 
					    private App currentApp;
 | 
				
			||||||
@ -65,28 +81,32 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
        this.activity = activity;
 | 
					        this.activity = activity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        installButton = (ImageView) itemView.findViewById(R.id.install);
 | 
					        installButton = (ImageView) itemView.findViewById(R.id.install);
 | 
				
			||||||
        installButton.setOnClickListener(onInstallClicked);
 | 
					        if (installButton != null) {
 | 
				
			||||||
 | 
					            installButton.setOnClickListener(onInstallClicked);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (Build.VERSION.SDK_INT >= 21) {
 | 
					            if (Build.VERSION.SDK_INT >= 21) {
 | 
				
			||||||
            installButton.setOutlineProvider(new ViewOutlineProvider() {
 | 
					                installButton.setOutlineProvider(new ViewOutlineProvider() {
 | 
				
			||||||
                @Override
 | 
					                    @Override
 | 
				
			||||||
                public void getOutline(View view, Outline outline) {
 | 
					                    public void getOutline(View view, Outline outline) {
 | 
				
			||||||
                    float density = activity.getResources().getDisplayMetrics().density;
 | 
					                        float density = activity.getResources().getDisplayMetrics().density;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // TODO: This is a bit hacky/hardcoded/too-specific to the particular icons we're using.
 | 
					                        // TODO: This is a bit hacky/hardcoded/too-specific to the particular icons we're using.
 | 
				
			||||||
                    // This is because the default "download & install" and "downloaded & ready to install"
 | 
					                        // This is because the default "download & install" and "downloaded & ready to install"
 | 
				
			||||||
                    // icons are smaller than the "downloading progress" button. Hence, we can't just use
 | 
					                        // icons are smaller than the "downloading progress" button. Hence, we can't just use
 | 
				
			||||||
                    // the width/height of the view to calculate the outline size.
 | 
					                        // the width/height of the view to calculate the outline size.
 | 
				
			||||||
                    int xPadding = (int) (8 * density);
 | 
					                        int xPadding = (int) (8 * density);
 | 
				
			||||||
                    int yPadding = (int) (9 * density);
 | 
					                        int yPadding = (int) (9 * density);
 | 
				
			||||||
                    outline.setOval(xPadding, yPadding, installButton.getWidth() - xPadding, installButton.getHeight() - yPadding);
 | 
					                        outline.setOval(xPadding, yPadding, installButton.getWidth() - xPadding, installButton.getHeight() - yPadding);
 | 
				
			||||||
                }
 | 
					                    }
 | 
				
			||||||
            });
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        icon = (ImageView) itemView.findViewById(R.id.icon);
 | 
					        icon = (ImageView) itemView.findViewById(R.id.icon);
 | 
				
			||||||
        name = (TextView) itemView.findViewById(R.id.app_name);
 | 
					        name = (TextView) itemView.findViewById(R.id.app_name);
 | 
				
			||||||
        status = (TextView) itemView.findViewById(R.id.status);
 | 
					        status = (TextView) itemView.findViewById(R.id.status);
 | 
				
			||||||
 | 
					        installedVersion = (TextView) itemView.findViewById(R.id.installed_version);
 | 
				
			||||||
 | 
					        ignoredStatus = (TextView) itemView.findViewById(R.id.ignored_status);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        displayImageOptions = Utils.getImageLoadingOptions().build();
 | 
					        displayImageOptions = Utils.getImageLoadingOptions().build();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,6 +130,8 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
        broadcastManager.registerReceiver(onInstallAction, Installer.getInstallIntentFilter(Uri.parse(currentAppDownloadUrl)));
 | 
					        broadcastManager.registerReceiver(onInstallAction, Installer.getInstallIntentFilter(Uri.parse(currentAppDownloadUrl)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        configureStatusText(app);
 | 
					        configureStatusText(app);
 | 
				
			||||||
 | 
					        configureInstalledVersion(app);
 | 
				
			||||||
 | 
					        configureIgnoredStatus(app);
 | 
				
			||||||
        configureInstallButton(app);
 | 
					        configureInstallButton(app);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -145,6 +167,42 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Shows the currently installed version name, and whether or not it is the recommended version.
 | 
				
			||||||
 | 
					     * Binds to the {@link R.id#installed_version} {@link TextView}.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void configureInstalledVersion(@NonNull App app) {
 | 
				
			||||||
 | 
					        if (installedVersion == null) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        int res = (app.suggestedVersionCode == app.installedVersionCode)
 | 
				
			||||||
 | 
					                ? R.string.app_recommended_version_installed : R.string.app_version_x_installed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        installedVersion.setText(activity.getString(res, app.installedVersionName));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Shows whether the user has previously asked to ignore updates for this app entirely, or for a
 | 
				
			||||||
 | 
					     * specific version of this app. Binds to the {@link R.id#ignored_status} {@link TextView}.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void configureIgnoredStatus(@NonNull App app) {
 | 
				
			||||||
 | 
					        if (ignoredStatus == null) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        AppPrefs prefs = app.getPrefs(activity);
 | 
				
			||||||
 | 
					        if (prefs.ignoreAllUpdates) {
 | 
				
			||||||
 | 
					            ignoredStatus.setText(activity.getString(R.string.installed_app__updates_ignored));
 | 
				
			||||||
 | 
					            ignoredStatus.setVisibility(View.VISIBLE);
 | 
				
			||||||
 | 
					        } else if (prefs.ignoreThisUpdate > 0 && prefs.ignoreThisUpdate == app.suggestedVersionCode) {
 | 
				
			||||||
 | 
					            ignoredStatus.setText(activity.getString(R.string.installed_app__updates_ignored_for_suggested_version, app.getSuggestedVersionName()));
 | 
				
			||||||
 | 
					            ignoredStatus.setVisibility(View.VISIBLE);
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            ignoredStatus.setVisibility(View.GONE);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private boolean isReadyToInstall(@NonNull App app) {
 | 
					    private boolean isReadyToInstall(@NonNull App app) {
 | 
				
			||||||
        for (AppUpdateStatusManager.AppUpdateStatus appStatus : AppUpdateStatusManager.getInstance(activity).getByPackageName(app.packageName)) {
 | 
					        for (AppUpdateStatusManager.AppUpdateStatus appStatus : AppUpdateStatusManager.getInstance(activity).getByPackageName(app.packageName)) {
 | 
				
			||||||
            if (appStatus.status == AppUpdateStatusManager.Status.ReadyToInstall) {
 | 
					            if (appStatus.status == AppUpdateStatusManager.Status.ReadyToInstall) {
 | 
				
			||||||
@ -184,6 +242,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressWarnings("FieldCanBeLocal")
 | 
				
			||||||
    private final View.OnClickListener onAppClicked = new View.OnClickListener() {
 | 
					    private final View.OnClickListener onAppClicked = new View.OnClickListener() {
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public void onClick(View v) {
 | 
					        public void onClick(View v) {
 | 
				
			||||||
@ -206,7 +265,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
    private final BroadcastReceiver onDownloadProgress = new BroadcastReceiver() {
 | 
					    private final BroadcastReceiver onDownloadProgress = new BroadcastReceiver() {
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public void onReceive(Context context, Intent intent) {
 | 
					        public void onReceive(Context context, Intent intent) {
 | 
				
			||||||
            if (currentApp == null || !TextUtils.equals(currentAppDownloadUrl, intent.getDataString())) {
 | 
					            if (installButton == null || currentApp == null || !TextUtils.equals(currentAppDownloadUrl, intent.getDataString())) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -226,7 +285,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
    private final BroadcastReceiver onInstallAction = new BroadcastReceiver() {
 | 
					    private final BroadcastReceiver onInstallAction = new BroadcastReceiver() {
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public void onReceive(Context context, Intent intent) {
 | 
					        public void onReceive(Context context, Intent intent) {
 | 
				
			||||||
            if (currentApp == null) {
 | 
					            if (currentApp == null || installButton == null) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -248,6 +307,7 @@ public class AppListItemController extends RecyclerView.ViewHolder {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @SuppressWarnings("FieldCanBeLocal")
 | 
				
			||||||
    private final View.OnClickListener onInstallClicked = new View.OnClickListener() {
 | 
					    private final View.OnClickListener onInstallClicked = new View.OnClickListener() {
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public void onClick(View v) {
 | 
					        public void onClick(View v) {
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,143 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (C) 2010-12  Ciaran Gultnieks, ciaran@ciarang.com
 | 
				
			||||||
 | 
					 * Copyright (C) 2009  Roberto Jacinto, roberto.jacinto@caixamagica.pt
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is free software; you can redistribute it and/or
 | 
				
			||||||
 | 
					 * modify it under the terms of the GNU General Public License
 | 
				
			||||||
 | 
					 * as published by the Free Software Foundation; either version 3
 | 
				
			||||||
 | 
					 * of the License, or (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with this program; if not, write to the Free Software
 | 
				
			||||||
 | 
					 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package org.fdroid.fdroid.views.installed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.app.Activity;
 | 
				
			||||||
 | 
					import android.database.Cursor;
 | 
				
			||||||
 | 
					import android.os.Bundle;
 | 
				
			||||||
 | 
					import android.support.annotation.Nullable;
 | 
				
			||||||
 | 
					import android.support.v4.app.LoaderManager;
 | 
				
			||||||
 | 
					import android.support.v4.content.CursorLoader;
 | 
				
			||||||
 | 
					import android.support.v4.content.Loader;
 | 
				
			||||||
 | 
					import android.support.v7.app.AppCompatActivity;
 | 
				
			||||||
 | 
					import android.support.v7.widget.LinearLayoutManager;
 | 
				
			||||||
 | 
					import android.support.v7.widget.RecyclerView;
 | 
				
			||||||
 | 
					import android.support.v7.widget.Toolbar;
 | 
				
			||||||
 | 
					import android.view.View;
 | 
				
			||||||
 | 
					import android.view.ViewGroup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.FDroidApp;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.R;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.data.App;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.data.AppProvider;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.data.Schema;
 | 
				
			||||||
 | 
					import org.fdroid.fdroid.views.apps.AppListItemController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class InstalledAppsActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private InstalledAppListAdapter adapter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected void onCreate(Bundle savedInstanceState) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        ((FDroidApp) getApplication()).applyTheme(this);
 | 
				
			||||||
 | 
					        super.onCreate(savedInstanceState);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        setContentView(R.layout.installed_apps_layout);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 | 
				
			||||||
 | 
					        toolbar.setTitle(getString(R.string.installed_apps__activity_title));
 | 
				
			||||||
 | 
					        setSupportActionBar(toolbar);
 | 
				
			||||||
 | 
					        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        adapter = new InstalledAppListAdapter(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        RecyclerView appList = (RecyclerView) findViewById(R.id.app_list);
 | 
				
			||||||
 | 
					        appList.setHasFixedSize(true);
 | 
				
			||||||
 | 
					        appList.setLayoutManager(new LinearLayoutManager(this));
 | 
				
			||||||
 | 
					        appList.setAdapter(adapter);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    protected void onResume() {
 | 
				
			||||||
 | 
					        super.onResume();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Starts a new or restarts an existing Loader in this manager
 | 
				
			||||||
 | 
					        getSupportLoaderManager().restartLoader(0, null, this);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
 | 
				
			||||||
 | 
					        return new CursorLoader(
 | 
				
			||||||
 | 
					                this,
 | 
				
			||||||
 | 
					                AppProvider.getInstalledUri(),
 | 
				
			||||||
 | 
					                Schema.AppMetadataTable.Cols.ALL,
 | 
				
			||||||
 | 
					                null, null, null);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
 | 
				
			||||||
 | 
					        adapter.setApps(cursor);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Override
 | 
				
			||||||
 | 
					    public void onLoaderReset(Loader<Cursor> loader) {
 | 
				
			||||||
 | 
					        adapter.setApps(null);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static class InstalledAppListAdapter extends RecyclerView.Adapter<AppListItemController> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private final Activity activity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Nullable
 | 
				
			||||||
 | 
					        private Cursor cursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        InstalledAppListAdapter(Activity activity) {
 | 
				
			||||||
 | 
					            this.activity = activity;
 | 
				
			||||||
 | 
					            setHasStableIds(true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public long getItemId(int position) {
 | 
				
			||||||
 | 
					            if (cursor == null) {
 | 
				
			||||||
 | 
					                return 0;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cursor.moveToPosition(position);
 | 
				
			||||||
 | 
					            return cursor.getLong(cursor.getColumnIndex(Schema.AppMetadataTable.Cols.ROW_ID));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public AppListItemController onCreateViewHolder(ViewGroup parent, int viewType) {
 | 
				
			||||||
 | 
					            View view = activity.getLayoutInflater().inflate(R.layout.installed_app_list_item, parent, false);
 | 
				
			||||||
 | 
					            return new AppListItemController(activity, view);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public void onBindViewHolder(AppListItemController holder, int position) {
 | 
				
			||||||
 | 
					            if (cursor == null) {
 | 
				
			||||||
 | 
					                return;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cursor.moveToPosition(position);
 | 
				
			||||||
 | 
					            holder.bindModel(new App(cursor));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public int getItemCount() {
 | 
				
			||||||
 | 
					            return cursor == null ? 0 : cursor.getCount();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public void setApps(@Nullable Cursor cursor) {
 | 
				
			||||||
 | 
					            this.cursor = cursor;
 | 
				
			||||||
 | 
					            notifyDataSetChanged();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										75
									
								
								app/src/main/res/layout/installed_app_list_item.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								app/src/main/res/layout/installed_app_list_item.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,75 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<android.support.constraint.ConstraintLayout
 | 
				
			||||||
 | 
					    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
				
			||||||
 | 
					    xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
 | 
					    android:layout_width="match_parent"
 | 
				
			||||||
 | 
					    android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					    android:padding="4dp"
 | 
				
			||||||
 | 
					    android:paddingTop="8dp"
 | 
				
			||||||
 | 
					    android:paddingBottom="8dp">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!-- Ignore ContentDescription because it is kind of meaningless to have TTS read out "App icon"
 | 
				
			||||||
 | 
					         when it will inevitably read out the name of the app straight after. -->
 | 
				
			||||||
 | 
					    <ImageView
 | 
				
			||||||
 | 
					        android:id="@+id/icon"
 | 
				
			||||||
 | 
					        app:layout_constraintStart_toStartOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toTopOf="parent"
 | 
				
			||||||
 | 
					        android:layout_width="48dp"
 | 
				
			||||||
 | 
					        android:layout_height="48dp"
 | 
				
			||||||
 | 
					        tools:src="@drawable/ic_launcher"
 | 
				
			||||||
 | 
					        android:scaleType="fitCenter"
 | 
				
			||||||
 | 
					        android:layout_marginStart="16dp"
 | 
				
			||||||
 | 
					        android:layout_marginLeft="16dp"
 | 
				
			||||||
 | 
					        android:layout_marginTop="8dp"
 | 
				
			||||||
 | 
					        tools:ignore="ContentDescription" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <TextView
 | 
				
			||||||
 | 
					        android:id="@+id/app_name"
 | 
				
			||||||
 | 
					        android:layout_width="0dp"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        tools:text="F-Droid Application manager with a long name that will wrap and then ellipsize"
 | 
				
			||||||
 | 
					        android:textSize="18sp"
 | 
				
			||||||
 | 
					        android:textColor="#424242"
 | 
				
			||||||
 | 
					        android:maxLines="2"
 | 
				
			||||||
 | 
					        android:ellipsize="end"
 | 
				
			||||||
 | 
					        app:layout_constraintStart_toEndOf="@+id/icon"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toTopOf="@+id/icon"
 | 
				
			||||||
 | 
					        android:layout_marginLeft="8dp"
 | 
				
			||||||
 | 
					        android:layout_marginStart="8dp"
 | 
				
			||||||
 | 
					        app:layout_constraintEnd_toEndOf="parent"
 | 
				
			||||||
 | 
					        android:layout_marginEnd="8dp"
 | 
				
			||||||
 | 
					        android:layout_marginRight="8dp" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <TextView
 | 
				
			||||||
 | 
					        android:id="@+id/installed_version"
 | 
				
			||||||
 | 
					        android:layout_width="wrap_content"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        android:layout_marginTop="4dp"
 | 
				
			||||||
 | 
					        tools:text="Version 4.7.3 (recommended)"
 | 
				
			||||||
 | 
					        android:textStyle="italic"
 | 
				
			||||||
 | 
					        android:textSize="14sp"
 | 
				
			||||||
 | 
					        android:textColor="#424242"
 | 
				
			||||||
 | 
					        android:maxLines="1"
 | 
				
			||||||
 | 
					        android:ellipsize="end"
 | 
				
			||||||
 | 
					        android:fontFamily="sans-serif-light"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toBottomOf="@+id/app_name"
 | 
				
			||||||
 | 
					        app:layout_constraintStart_toEndOf="@+id/icon"
 | 
				
			||||||
 | 
					        android:layout_marginStart="8dp"
 | 
				
			||||||
 | 
					        android:layout_marginLeft="8dp" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <TextView
 | 
				
			||||||
 | 
					        android:id="@+id/ignored_status"
 | 
				
			||||||
 | 
					        android:layout_width="wrap_content"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        android:layout_marginTop="4dp"
 | 
				
			||||||
 | 
					        tools:text="Updates ignored"
 | 
				
			||||||
 | 
					        android:textSize="14sp"
 | 
				
			||||||
 | 
					        android:maxLines="1"
 | 
				
			||||||
 | 
					        android:ellipsize="end"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toBottomOf="@+id/installed_version"
 | 
				
			||||||
 | 
					        app:layout_constraintStart_toEndOf="@+id/icon"
 | 
				
			||||||
 | 
					        android:layout_marginStart="8dp"
 | 
				
			||||||
 | 
					        android:layout_marginLeft="8dp" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</android.support.constraint.ConstraintLayout>
 | 
				
			||||||
							
								
								
									
										47
									
								
								app/src/main/res/layout/installed_apps_layout.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/src/main/res/layout/installed_apps_layout.xml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
 | 
					<android.support.constraint.ConstraintLayout
 | 
				
			||||||
 | 
					    xmlns:android="http://schemas.android.com/apk/res/android"
 | 
				
			||||||
 | 
					    xmlns:app="http://schemas.android.com/apk/res-auto"
 | 
				
			||||||
 | 
					    xmlns:tools="http://schemas.android.com/tools"
 | 
				
			||||||
 | 
					    android:layout_width="match_parent"
 | 
				
			||||||
 | 
					    android:layout_height="match_parent">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <android.support.v7.widget.Toolbar
 | 
				
			||||||
 | 
					        android:id="@+id/toolbar"
 | 
				
			||||||
 | 
					        android:layout_width="368dp"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toTopOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintLeft_toLeftOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintRight_toRightOf="parent"
 | 
				
			||||||
 | 
					        app:theme="?attr/actionBarTheme"
 | 
				
			||||||
 | 
					        app:popupTheme="?attr/actionBarPopupTheme" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <android.support.v7.widget.RecyclerView
 | 
				
			||||||
 | 
					        android:id="@+id/app_list"
 | 
				
			||||||
 | 
					        android:layout_width="match_parent"
 | 
				
			||||||
 | 
					        android:layout_height="match_parent"
 | 
				
			||||||
 | 
					        tools:listitem="@layout/installed_app_list_item"
 | 
				
			||||||
 | 
					        app:layout_constraintBottom_toBottomOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintLeft_toLeftOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintRight_toRightOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintTop_toBottomOf="@+id/toolbar"
 | 
				
			||||||
 | 
					        android:scrollbars="vertical" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <!--
 | 
				
			||||||
 | 
					    Commented out until the long press functionality is implemented.
 | 
				
			||||||
 | 
					    <TextView
 | 
				
			||||||
 | 
					        android:id="@+id/helpText"
 | 
				
			||||||
 | 
					        android:layout_width="0dp"
 | 
				
			||||||
 | 
					        android:layout_height="wrap_content"
 | 
				
			||||||
 | 
					        app:layout_constraintBottom_toBottomOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintLeft_toLeftOf="parent"
 | 
				
			||||||
 | 
					        app:layout_constraintRight_toRightOf="parent"
 | 
				
			||||||
 | 
					        android:padding="16dp"
 | 
				
			||||||
 | 
					        android:textAlignment="center"
 | 
				
			||||||
 | 
					        android:textColor="#424242"
 | 
				
			||||||
 | 
					        android:textSize="14sp"
 | 
				
			||||||
 | 
					        android:text="Tap and hold on an app for more options"
 | 
				
			||||||
 | 
					        app:layout_constraintHorizontal_bias="0.0"
 | 
				
			||||||
 | 
					        android:layout_marginBottom="-1dp" />-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</android.support.constraint.ConstraintLayout>
 | 
				
			||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
        app:showAsAction="ifRoom|withText"
 | 
					        app:showAsAction="ifRoom|withText"
 | 
				
			||||||
        android:id="@+id/nearby" />
 | 
					        android:id="@+id/nearby" />
 | 
				
			||||||
    <item
 | 
					    <item
 | 
				
			||||||
        android:title="@string/main_menu__my_apps"
 | 
					        android:title="@string/preference_category__my_apps"
 | 
				
			||||||
        android:icon="@drawable/ic_my_apps"
 | 
					        android:icon="@drawable/ic_my_apps"
 | 
				
			||||||
        app:showAsAction="ifRoom|withText"
 | 
					        app:showAsAction="ifRoom|withText"
 | 
				
			||||||
        android:id="@+id/my_apps" />
 | 
					        android:id="@+id/my_apps" />
 | 
				
			||||||
 | 
				
			|||||||
@ -65,6 +65,11 @@
 | 
				
			|||||||
    <string name="app_inst_unknown_source">Installed (from unknown source)</string>
 | 
					    <string name="app_inst_unknown_source">Installed (from unknown source)</string>
 | 
				
			||||||
    <string name="app_version_x_available">Version %1$s available</string>
 | 
					    <string name="app_version_x_available">Version %1$s available</string>
 | 
				
			||||||
    <string name="app_version_x_installed">Version %1$s</string>
 | 
					    <string name="app_version_x_installed">Version %1$s</string>
 | 
				
			||||||
 | 
					    <string name="app_recommended_version_installed">Version %1$s (Recommended)</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <string name="installed_apps__activity_title">Installed Apps</string>
 | 
				
			||||||
 | 
					    <string name="installed_app__updates_ignored">Updates ignored</string>
 | 
				
			||||||
 | 
					    <string name="installed_app__updates_ignored_for_suggested_version">Updates ignored for Version %1$s</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <string name="added_on">Added on %s</string>
 | 
					    <string name="added_on">Added on %s</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -142,7 +147,9 @@
 | 
				
			|||||||
    <string name="main_menu__latest_apps">Latest</string>
 | 
					    <string name="main_menu__latest_apps">Latest</string>
 | 
				
			||||||
    <string name="main_menu__categories">Categories</string>
 | 
					    <string name="main_menu__categories">Categories</string>
 | 
				
			||||||
    <string name="main_menu__swap_nearby">Nearby</string>
 | 
					    <string name="main_menu__swap_nearby">Nearby</string>
 | 
				
			||||||
    <string name="main_menu__my_apps">My Apps</string>
 | 
					
 | 
				
			||||||
 | 
					    <string name="preference_category__my_apps">My Apps</string>
 | 
				
			||||||
 | 
					    <string name="preference_manage_installed_apps">Manage Installed Apps</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <string name="details_installed">Version %s installed</string>
 | 
					    <string name="details_installed">Version %s installed</string>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,12 @@
 | 
				
			|||||||
<?xml version="1.0" encoding="utf-8"?>
 | 
					<?xml version="1.0" encoding="utf-8"?>
 | 
				
			||||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
 | 
					<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
 | 
				
			||||||
    <PreferenceCategory android:title="@string/updates">
 | 
					    <PreferenceCategory android:title="@string/preference_category__my_apps">
 | 
				
			||||||
 | 
					        <PreferenceScreen android:title="@string/preference_manage_installed_apps">
 | 
				
			||||||
 | 
					            <intent
 | 
				
			||||||
 | 
					                android:action="android.intent.action.MAIN"
 | 
				
			||||||
 | 
					                android:targetPackage="org.fdroid.fdroid"
 | 
				
			||||||
 | 
					                android:targetClass="org.fdroid.fdroid.views.installed.InstalledAppsActivity" />
 | 
				
			||||||
 | 
					        </PreferenceScreen>
 | 
				
			||||||
        <PreferenceScreen
 | 
					        <PreferenceScreen
 | 
				
			||||||
            android:title="@string/menu_manage"
 | 
					            android:title="@string/menu_manage"
 | 
				
			||||||
            android:summary="@string/repositories_summary">
 | 
					            android:summary="@string/repositories_summary">
 | 
				
			||||||
@ -9,6 +15,8 @@
 | 
				
			|||||||
                android:targetPackage="org.fdroid.fdroid"
 | 
					                android:targetPackage="org.fdroid.fdroid"
 | 
				
			||||||
                android:targetClass="org.fdroid.fdroid.views.ManageReposActivity" />
 | 
					                android:targetClass="org.fdroid.fdroid.views.ManageReposActivity" />
 | 
				
			||||||
        </PreferenceScreen>
 | 
					        </PreferenceScreen>
 | 
				
			||||||
 | 
					    </PreferenceCategory>
 | 
				
			||||||
 | 
					    <PreferenceCategory android:title="@string/updates">
 | 
				
			||||||
        <com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/update_interval"
 | 
					        <com.geecko.QuickLyric.view.AppCompatListPreference android:title="@string/update_interval"
 | 
				
			||||||
            android:key="updateInterval"
 | 
					            android:key="updateInterval"
 | 
				
			||||||
            android:defaultValue="24"
 | 
					            android:defaultValue="24"
 | 
				
			||||||
 | 
				
			|||||||
@ -115,7 +115,7 @@ public class AppProviderTest extends FDroidProviderTest {
 | 
				
			|||||||
        assertFalse(notInstalled.canAndWantToUpdate(context));
 | 
					        assertFalse(notInstalled.canAndWantToUpdate(context));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assertResultCount(contentResolver, 2, AppProvider.getCanUpdateUri(), PROJ);
 | 
					        assertResultCount(contentResolver, 2, AppProvider.getCanUpdateUri(), PROJ);
 | 
				
			||||||
        assertResultCount(contentResolver, 7, AppProvider.getInstalledUri(), PROJ);
 | 
					        assertResultCount(contentResolver, 9, AppProvider.getInstalledUri(), PROJ);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        App installedOnlyOneVersionAvailable   = AppProvider.Helper.findSpecificApp(r, "installed, only one version available", 1, Cols.ALL);
 | 
					        App installedOnlyOneVersionAvailable   = AppProvider.Helper.findSpecificApp(r, "installed, only one version available", 1, Cols.ALL);
 | 
				
			||||||
        App installedAlreadyLatestNoIgnore     = AppProvider.Helper.findSpecificApp(r, "installed, already latest, no ignore", 1, Cols.ALL);
 | 
					        App installedAlreadyLatestNoIgnore     = AppProvider.Helper.findSpecificApp(r, "installed, already latest, no ignore", 1, Cols.ALL);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user