Merge branch 'feature/chooseAntifeaturesToShow' into 'master'

Allow choosing which antifeatures to show

Closes #564

See merge request fdroid/fdroidclient!1053
This commit is contained in:
Sylvia van Os
2021-10-14 09:25:25 +00:00
15 changed files with 258 additions and 142 deletions

View File

@@ -76,11 +76,13 @@
android:title="@string/show_incompat_versions"
android:defaultValue="false"
android:key="incompatibleVersions"/>
<SwitchPreferenceCompat
android:title="@string/show_anti_feature_apps"
android:defaultValue="false"
android:key="showAntiFeatureApps"/>
<SwitchPreferenceCompat
<MultiSelectListPreference
android:title="@string/show_anti_feature_apps"
android:defaultValue="@array/antifeaturesValues"
android:key="showAntiFeatures"
android:entries="@array/antifeaturesNames"
android:entryValues="@array/antifeaturesValues"/>
<SwitchPreference
android:title="@string/force_touch_apps"
android:defaultValue="false"
android:key="ignoreTouchscreen"/>

View File

@@ -80,6 +80,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
PrivilegedInstaller.isExtensionInstalledCorrectly(context)
!= PrivilegedInstaller.IS_EXTENSION_INSTALLED_YES);
}
editor.apply();
}
@@ -91,7 +92,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
public static final String PREF_THEME = "theme";
public static final String PREF_USE_PURE_BLACK_DARK_THEME = "usePureBlackDarkTheme";
public static final String PREF_SHOW_INCOMPAT_VERSIONS = "incompatibleVersions";
public static final String PREF_SHOW_ANTI_FEATURE_APPS = "showAntiFeatureApps";
public static final String PREF_SHOW_ANTI_FEATURES = "showAntiFeatures";
public static final String PREF_FORCE_TOUCH_APPS = "ignoreTouchscreen";
public static final String PREF_PROMPT_TO_SEND_CRASH_REPORTS = "promptToSendCrashReports";
public static final String PREF_KEEP_CACHE_TIME = "keepCacheFor";
@@ -170,7 +171,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
DateUtils.HOUR_IN_MILLIS,
};
private boolean showAppsWithAntiFeatures;
private Set<String> showAppsWithAntiFeatures;
private final Map<String, Boolean> initialized = new HashMap<>();
@@ -585,18 +586,15 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
* This is cached as it is called several times inside app list adapters.
* Providing it here means the shared preferences file only needs to be
* read once, and we will keep our copy up to date by listening to changes
* in PREF_SHOW_ANTI_FEATURE_APPS.
* in PREF_SHOW_ANTI_FEATURES.
*/
public boolean showAppsWithAntiFeatures() {
// migrate old preference to new key
if (isInitialized("hideAntiFeatureApps")) {
boolean oldPreference = preferences.getBoolean("hideAntiFeatureApps", false);
preferences.edit().putBoolean(PREF_SHOW_ANTI_FEATURE_APPS, !oldPreference).apply();
}
if (!isInitialized(PREF_SHOW_ANTI_FEATURE_APPS)) {
initialize(PREF_SHOW_ANTI_FEATURE_APPS);
showAppsWithAntiFeatures = preferences.getBoolean(PREF_SHOW_ANTI_FEATURE_APPS, IGNORED_B);
public Set<String> showAppsWithAntiFeatures() {
if (!isInitialized(PREF_SHOW_ANTI_FEATURES)) {
initialize(PREF_SHOW_ANTI_FEATURES);
showAppsWithAntiFeatures = preferences.getStringSet(
PREF_SHOW_ANTI_FEATURES, null);
}
return showAppsWithAntiFeatures;
}
@@ -622,7 +620,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
uninitialize(key);
switch (key) {
case PREF_SHOW_ANTI_FEATURE_APPS:
case PREF_SHOW_ANTI_FEATURES:
for (ChangeListener listener : showAppsRequiringAntiFeaturesListeners) {
listener.onPreferenceChange();
}

View File

@@ -1139,12 +1139,22 @@ public class App extends ValueObject implements Comparable<App>, Parcelable {
/**
* @return if the given app should be filtered out based on the
* {@link Preferences#PREF_SHOW_ANTI_FEATURE_APPS Show Anti-Features Setting}
* {@link Preferences#PREF_SHOW_ANTI_FEATURES Show Anti-Features Setting}
*/
public boolean isDisabledByAntiFeatures() {
return this.antiFeatures != null
&& this.antiFeatures.length > 0
&& !Preferences.get().showAppsWithAntiFeatures();
if (this.antiFeatures == null) {
return false;
}
Set<String> shownAntiFeatures = Preferences.get().showAppsWithAntiFeatures();
for (String antiFeature : this.antiFeatures) {
if (!shownAntiFeatures.contains(antiFeature)) {
return true;
}
}
return false;
}
@Nullable

View File

@@ -79,7 +79,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat
Preferences.PREF_OVER_DATA,
Preferences.PREF_UPDATE_INTERVAL,
Preferences.PREF_UPDATE_NOTIFICATION_ENABLED,
Preferences.PREF_SHOW_ANTI_FEATURE_APPS,
Preferences.PREF_SHOW_ANTI_FEATURES,
Preferences.PREF_SHOW_INCOMPAT_VERSIONS,
Preferences.PREF_THEME,
Preferences.PREF_USE_PURE_BLACK_DARK_THEME,
@@ -306,7 +306,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat
checkSummary(key, R.string.show_incompat_versions_on);
break;
case Preferences.PREF_SHOW_ANTI_FEATURE_APPS:
case Preferences.PREF_SHOW_ANTI_FEATURES:
checkSummary(key, R.string.show_anti_feature_apps_on);
break;

View File

@@ -38,10 +38,103 @@ import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.HashMap;
public class AntiFeaturesListingView extends RecyclerView {
static HashMap<String, String> antiFeatureDescriptions;
static HashMap<String, Integer> antiFeatureIcons;
public AntiFeaturesListingView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
if (antiFeatureDescriptions == null) {
antiFeatureDescriptions = new HashMap<>();
antiFeatureDescriptions.put(
context.getString(R.string.antiads_key),
context.getString(R.string.antiadslist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antitrack_key),
context.getString(R.string.antitracklist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antinonfreenet_key),
context.getString(R.string.antinonfreenetlist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antinonfreead_key),
context.getString(R.string.antinonfreeadlist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antinonfreedep_key),
context.getString(R.string.antinonfreedeplist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antiupstreamnonfree_key),
context.getString(R.string.antiupstreamnonfreelist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antinonfreeassets_key),
context.getString(R.string.antinonfreeassetslist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antidisabledalgorithm_key),
context.getString(R.string.antidisabledalgorithmlist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antiknownvuln_key),
context.getString(R.string.antiknownvulnlist)
);
antiFeatureDescriptions.put(
context.getString(R.string.antinosource_key),
context.getString(R.string.antinosourcesince)
);
}
if (antiFeatureIcons == null) {
antiFeatureIcons = new HashMap<>();
antiFeatureIcons.put(
context.getString(R.string.antiads_key),
R.drawable.ic_antifeature_ads
);
antiFeatureIcons.put(
context.getString(R.string.antitrack_key),
R.drawable.ic_antifeature_tracking
);
antiFeatureIcons.put(
context.getString(R.string.antinonfreenet_key),
R.drawable.ic_antifeature_nonfreenet
);
antiFeatureIcons.put(
context.getString(R.string.antinonfreead_key),
R.drawable.ic_antifeature_nonfreeadd
);
antiFeatureIcons.put(
context.getString(R.string.antinonfreedep_key),
R.drawable.ic_antifeature_nonfreedep
);
antiFeatureIcons.put(
context.getString(R.string.antiupstreamnonfree_key),
R.drawable.ic_antifeature_upstreamnonfree
);
antiFeatureIcons.put(
context.getString(R.string.antinonfreeassets_key),
R.drawable.ic_antifeature_nonfreeassets
);
antiFeatureIcons.put(
context.getString(R.string.antidisabledalgorithm_key),
R.drawable.ic_antifeature_disabledalgorithm
);
antiFeatureIcons.put(
context.getString(R.string.antiknownvuln_key),
R.drawable.ic_antifeature_knownvuln
);
antiFeatureIcons.put(
context.getString(R.string.antinosource_key),
R.drawable.ic_antifeature_nosourcesince
);
}
}
public void setApp(final App app) {
@@ -67,7 +160,7 @@ public class AntiFeaturesListingView extends RecyclerView {
holder.antiFeatureIcon.setBackgroundDrawable(
ContextCompat.getDrawable(getContext(), antiFeatureIcon(antiFeatureName)));
holder.antiFeatureText.setText(
getAntiFeatureDescriptionText(holder.antiFeatureText.getContext(), antiFeatureName));
getAntiFeatureDescriptionText(antiFeatureName));
holder.entireView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -105,57 +198,21 @@ public class AntiFeaturesListingView extends RecyclerView {
}
public static String getAntiFeatureDescriptionText(Context context, String antiFeatureName) {
switch (antiFeatureName) {
case "Ads":
return context.getString(R.string.antiadslist);
case "Tracking":
return context.getString(R.string.antitracklist);
case "NonFreeNet":
return context.getString(R.string.antinonfreenetlist);
case "NonFreeAdd":
return context.getString(R.string.antinonfreeadlist);
case "NonFreeDep":
return context.getString(R.string.antinonfreedeplist);
case "UpstreamNonFree":
return context.getString(R.string.antiupstreamnonfreelist);
case "NonFreeAssets":
return context.getString(R.string.antinonfreeassetslist);
case "DisabledAlgorithm":
return context.getString(R.string.antidisabledalgorithmlist);
case "KnownVuln":
return context.getString(R.string.antiknownvulnlist);
case "NoSourceSince":
return context.getString(R.string.antinosourcesince);
default:
return antiFeatureName;
public static String getAntiFeatureDescriptionText(String antiFeatureName) {
String description = antiFeatureDescriptions.get(antiFeatureName);
if (description == null) {
return antiFeatureName;
}
return description;
}
public static @DrawableRes int antiFeatureIcon(String antiFeatureName) {
switch (antiFeatureName) {
case "Ads":
return R.drawable.ic_antifeature_ads;
case "Tracking":
return R.drawable.ic_antifeature_tracking;
case "NonFreeNet":
return R.drawable.ic_antifeature_nonfreenet;
case "NonFreeAdd":
return R.drawable.ic_antifeature_nonfreeadd;
case "NonFreeDep":
return R.drawable.ic_antifeature_nonfreedep;
case "UpstreamNonFree":
return R.drawable.ic_antifeature_upstreamnonfree;
case "NonFreeAssets":
return R.drawable.ic_antifeature_nonfreeassets;
case "DisabledAlgorithm":
return R.drawable.ic_antifeature_disabledalgorithm;
case "KnownVuln":
return R.drawable.ic_antifeature_knownvuln;
case "NoSourceSince":
return R.drawable.ic_antifeature_nosourcesince;
default:
return R.drawable.ic_cancel;
Integer icon = antiFeatureIcons.get(antiFeatureName);
if (icon == null) {
return R.drawable.ic_cancel;
}
return icon;
}
}

View File

@@ -46,6 +46,7 @@ import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.Schema.AppMetadataTable;
import org.fdroid.fdroid.data.Schema.AppMetadataTable.Cols;
import org.fdroid.fdroid.views.main.MainActivity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -83,6 +84,7 @@ public class AppListActivity extends AppCompatActivity implements LoaderManager.
private TextView emptyState;
private EditText searchInput;
private ImageView sortImage;
private View hiddenAppNotice;
private Utils.KeyboardStateMonitor keyboardStateMonitor;
private interface SortClause {
@@ -152,6 +154,15 @@ public class AppListActivity extends AppCompatActivity implements LoaderManager.
}
});
hiddenAppNotice = findViewById(R.id.hiddenAppNotice);
hiddenAppNotice.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra(MainActivity.EXTRA_VIEW_SETTINGS, true);
getApplicationContext().startActivity(intent);
}
});
emptyState = (TextView) findViewById(R.id.empty_state);
View backButton = findViewById(R.id.back);
@@ -225,6 +236,10 @@ public class AppListActivity extends AppCompatActivity implements LoaderManager.
return string.toString();
}
private void setShowHiddenAppsNotice(boolean show) {
hiddenAppNotice.setVisibility(show ? View.VISIBLE : View.GONE);
}
@NonNull
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
@@ -240,6 +255,8 @@ public class AppListActivity extends AppCompatActivity implements LoaderManager.
@Override
public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor cursor) {
setShowHiddenAppsNotice(false);
appAdapter.setHasHiddenAppsCallback(() -> setShowHiddenAppsNotice(true));
appAdapter.setAppCursor(cursor);
if (cursor.getCount() > 0) {
emptyState.setVisibility(View.GONE);

View File

@@ -1,6 +1,7 @@
package org.fdroid.fdroid.views.apps;
import android.database.Cursor;
import android.view.View;
import android.view.ViewGroup;
import org.fdroid.fdroid.R;
@@ -14,12 +15,11 @@ import androidx.recyclerview.widget.RecyclerView;
class AppListAdapter extends RecyclerView.Adapter<StandardAppListItemController> {
private Cursor cursor;
private Runnable hasHiddenAppsCallback;
private final AppCompatActivity activity;
private final AppListItemDivider divider;
AppListAdapter(AppCompatActivity activity) {
this.activity = activity;
divider = new AppListItemDivider(activity);
setHasStableIds(true);
}
@@ -28,6 +28,10 @@ class AppListAdapter extends RecyclerView.Adapter<StandardAppListItemController>
notifyDataSetChanged();
}
public void setHasHiddenAppsCallback(Runnable callback) {
hasHiddenAppsCallback = callback;
}
@NonNull
@Override
public StandardAppListItemController onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@@ -40,6 +44,28 @@ class AppListAdapter extends RecyclerView.Adapter<StandardAppListItemController>
cursor.moveToPosition(position);
final App app = new App(cursor);
holder.bindModel(app);
if (app.isDisabledByAntiFeatures()) {
holder.itemView.setVisibility(View.GONE);
holder.itemView.setLayoutParams(
new RecyclerView.LayoutParams(
0,
0
)
);
if (this.hasHiddenAppsCallback != null) {
this.hasHiddenAppsCallback.run();
}
} else {
holder.itemView.setVisibility(View.VISIBLE);
holder.itemView.setLayoutParams(
new RecyclerView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
);
}
}
@Override
@@ -52,16 +78,4 @@ class AppListAdapter extends RecyclerView.Adapter<StandardAppListItemController>
public int getItemCount() {
return cursor == null ? 0 : cursor.getCount();
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
recyclerView.addItemDecoration(divider);
}
@Override
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
recyclerView.removeItemDecoration(divider);
super.onDetachedFromRecyclerView(recyclerView);
}
}

View File

@@ -1,34 +0,0 @@
package org.fdroid.fdroid.views.apps;
import android.content.Context;
import android.graphics.Rect;
import android.view.View;
import org.fdroid.fdroid.R;
import org.fdroid.fdroid.Utils;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.RecyclerView;
/**
* Draws a faint line between items, to be used with the {@link AppListItemDivider}.
*/
public class AppListItemDivider extends DividerItemDecoration {
private final int itemSpacing;
public AppListItemDivider(Context context) {
super(context, DividerItemDecoration.VERTICAL);
setDrawable(ContextCompat.getDrawable(context, R.drawable.app_list_item_divider));
itemSpacing = Utils.dpToPx(8, context);
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildAdapterPosition(view);
if (position > 0) {
outRect.bottom = itemSpacing;
}
}
}

View File

@@ -38,7 +38,7 @@ public class StandardAppListItemController extends AppListItemController {
private CharSequence getStatusText(@NonNull App app) {
if (!app.compatible) {
return activity.getString(R.string.app_incompatible);
} else if (app.isDisabledByAntiFeatures()) {
} else if (app.antiFeatures != null && app.antiFeatures.length > 0) {
return activity.getString(R.string.antifeatures);
} else if (app.isInstalled(activity.getApplicationContext())) {
if (app.canAndWantToUpdate(activity)) {
@@ -53,7 +53,7 @@ public class StandardAppListItemController extends AppListItemController {
private boolean shouldShowInstall(@NonNull App app) {
boolean installable = app.canAndWantToUpdate(activity) || !app.isInstalled(activity.getApplicationContext());
boolean shouldAllow = app.compatible && !app.isDisabledByAntiFeatures();
boolean shouldAllow = app.compatible && (app.antiFeatures == null || app.antiFeatures.length == 0);
return installable && shouldAllow;
}

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Used to separate two separate R.layout.app_list_item views in a list.
As these are not cards, they don't have their own drop shadow or other features that help
separate different list items.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="#50999999" />
</shape>

View File

@@ -82,6 +82,23 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/search_card"/>
<TextView
android:id="@+id/hiddenAppNotice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_marginLeft="4dp"
android:layout_marginEnd="4dp"
android:layout_marginRight="4dp"
android:padding="4dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/search_card"
android:drawableStart="@drawable/ic_error"
android:drawablePadding="4dp"
android:text="@string/app_list_results_hidden_antifeature_settings"
android:visibility="gone"/>
<!-- Don't center, only show it at the top because a keyboard will usually be shown at the bottom of the screen,
covering most of this layout. -->
<TextView
@@ -90,7 +107,7 @@
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/search_card"
app:layout_constraintTop_toBottomOf="@+id/hiddenAppNotice"
android:visibility="gone"
style="@style/AppListEmptyText"
android:text="@string/empty_search_available_app_list"/>
@@ -103,7 +120,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/search_card"
app:layout_constraintTop_toBottomOf="@+id/hiddenAppNotice"
android:visibility="visible"
android:scrollbars="vertical" />

View File

@@ -15,4 +15,29 @@
<item>@string/theme_follow_system</item>
</string-array>
<string-array name="antifeaturesValues">
<item>@string/antiads_key</item>
<item>@string/antitrack_key</item>
<item>@string/antinonfreead_key</item>
<item>@string/antinonfreenet_key</item>
<item>@string/antinonfreedep_key</item>
<item>@string/antiupstreamnonfree_key</item>
<item>@string/antinonfreeassets_key</item>
<item>@string/antidisabledalgorithm_key</item>
<item>@string/antiknownvuln_key</item>
<item>@string/antinosource_key</item>
</string-array>
<string-array name="antifeaturesNames">
<item>@string/antiads</item>
<item>@string/antitrack</item>
<item>@string/antinonfreead</item>
<item>@string/antinonfreenet</item>
<item>@string/antinonfreedep</item>
<item>@string/antiupstreamnonfree</item>
<item>@string/antinonfreeassets</item>
<item>@string/antidisabledalgorithm</item>
<item>@string/antiknownvuln</item>
<item>@string/antinosource</item>
</string-array>
</resources>

View File

@@ -128,6 +128,7 @@ This often occurs with apps installed via Google Play or other sources, if they
<string name="app_repository">Repository: %1$s</string>
<string name="app_size">Size: %1$s</string>
<string name="app_list_results_hidden_antifeature_settings">Some results were hidden based on your antifeature settings.</string>
<string name="app_list__name__downloading_in_progress">Downloading %1$s</string>
<string name="app_list__name__successfully_installed">%1$s installed</string>
<string name="app_list_download_ready">Downloaded, ready to install</string>
@@ -280,7 +281,27 @@ This often occurs with apps installed via Google Play or other sources, if they
<string name="details_new_in_version">New in version %s</string>
<string name="antifeatureswarning">This app has features you may not like.</string>
<string name="antiads_key" translatable="false">Ads</string>
<string name="antitrack_key" translatable="false">Tracking</string>
<string name="antinonfreenet_key" translatable="false">NonFreeNet</string>
<string name="antinonfreead_key" translatable="false">NonFreeAdd</string>
<string name="antinonfreedep_key" translatable="false">NonFreeDep</string>
<string name="antiupstreamnonfree_key" translatable="false">UpstreamNonFree</string>
<string name="antinonfreeassets_key" translatable="false">NonFreeAssets</string>
<string name="antidisabledalgorithm_key" translatable="false">DisabledAlgorithm</string>
<string name="antiknownvuln_key" translatable="false">KnownVuln</string>
<string name="antinosource_key">NoSourceSince</string>
<string name="antifeatures">Anti-features</string>
<string name="antiads">Ads</string>
<string name="antitrack">Tracking</string>
<string name="antinonfreead">Non-Free Addons</string>
<string name="antinonfreenet">Non-Free Network Services</string>
<string name="antinonfreedep">Non-Free Dependencies</string>
<string name="antiupstreamnonfree">Upstream Non-Free</string>
<string name="antinonfreeassets">Non-Free Assets</string>
<string name="antidisabledalgorithm">Signed Using An Unsafe Algorithm</string>
<string name="antiknownvuln">Known Vulnerability</string>
<string name="antinosource">Source Code No Longer Available</string>
<string name="antiadslist">This app contains advertising</string>
<string name="antitracklist">This app tracks and reports your activity</string>
<string name="antinonfreeadlist">This app promotes non-free add-ons</string>

View File

@@ -84,10 +84,12 @@
android:defaultValue="false"
android:key="incompatibleVersions"
android:title="@string/show_incompat_versions" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="showAntiFeatureApps"
android:title="@string/show_anti_feature_apps" />
<MultiSelectListPreference
android:title="@string/show_anti_feature_apps"
android:defaultValue="@array/antifeaturesValues"
android:key="showAntiFeatures"
android:entries="@array/antifeaturesNames"
android:entryValues="@array/antifeaturesValues"/>
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="ignoreTouchscreen"

View File

@@ -116,7 +116,7 @@ public class PreferencesTest {
preferences.isForceOldIndexEnabled());
assertEquals(defaults.getBoolean(Preferences.PREF_PREVENT_SCREENSHOTS, false),
preferences.preventScreenshots());
assertEquals(defaults.getBoolean(Preferences.PREF_SHOW_ANTI_FEATURE_APPS, false),
assertEquals(defaults.getStringSet(Preferences.PREF_SHOW_ANTI_FEATURES, null),
preferences.showAppsWithAntiFeatures());
assertEquals(defaults.getBoolean(Preferences.PREF_SHOW_INCOMPAT_VERSIONS, false),
preferences.showIncompatibleVersions());