From ef717437a9e2abf1e4abb7eb72941e69530a837a Mon Sep 17 00:00:00 2001 From: Peter Serwylo <peter@serwylo.com> Date: Tue, 8 Aug 2017 10:01:43 +1000 Subject: [PATCH] Explain multi-sig problems to user in app details. --- .../views/AppDetailsRecyclerViewAdapter.java | 76 ++++++++++++++++++- app/src/main/res/values/strings.xml | 7 ++ 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java index 4af3004d4..61ab2c8d6 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java @@ -12,6 +12,7 @@ import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; import android.support.v4.view.ViewCompat; import android.support.v4.widget.TextViewCompat; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.GridLayout; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -96,6 +97,7 @@ public class AppDetailsRecyclerViewAdapter private RecyclerView recyclerView; private List<Object> items; private List<Apk> versions; + private List<Apk> compatibleVersionsDifferentSig; private boolean showVersions; private HeaderViewHolder headerView; @@ -112,12 +114,16 @@ public class AppDetailsRecyclerViewAdapter // Get versions versions = new ArrayList<>(); + compatibleVersionsDifferentSig = new ArrayList<>(); final List<Apk> apks = ApkProvider.Helper.findByPackageName(context, this.app.packageName); for (final Apk apk : apks) { boolean allowByCompatability = apk.compatible || Preferences.get().showIncompatibleVersions(); boolean allowBySig = this.app.installedSig == null || TextUtils.equals(this.app.installedSig, apk.sig); - if (allowByCompatability && allowBySig) { - versions.add(apk); + if (allowByCompatability) { + compatibleVersionsDifferentSig.add(apk); + if (allowBySig) { + versions.add(apk); + } } } @@ -226,8 +232,12 @@ public class AppDetailsRecyclerViewAdapter View permissions = inflater.inflate(R.layout.app_details2_links, parent, false); return new PermissionsViewHolder(permissions); case VIEWTYPE_VERSIONS: - View versions = inflater.inflate(R.layout.app_details2_links, parent, false); - return new VersionsViewHolder(versions); + View versionsView = inflater.inflate(R.layout.app_details2_links, parent, false); + if (versions.size() == 0) { + return new NoVersionsViewHolder(versionsView); + } else { + return new VersionsViewHolder(versionsView); + } case VIEWTYPE_VERSION: View version = inflater.inflate(R.layout.apklistitem, parent, false); return new VersionViewHolder(version); @@ -690,6 +700,64 @@ public class AppDetailsRecyclerViewAdapter } } + private class NoVersionsViewHolder extends AppDetailsViewHolder { + final TextView headerView; + + NoVersionsViewHolder(View view) { + super(view); + headerView = (TextView) view.findViewById(R.id.information); + TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(headerView, R.drawable.ic_access_time_24dp_grey600, 0, 0, 0); + + itemView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + explainIncompatibleVersions(); + } + }); + } + + @Override + public void bindModel() { + if (hasCompatibleApksDifferentSigs()) { + headerView.setText("No versions with compatible signature"); + } else { + headerView.setText("No versions compatible with device"); + } + } + + /** + * Show a dialog to the user explaining the reaons there are no compatible versions. + * This will either be due to device features (e.g. NFC, API levels, etc) or being signed + * by a different certificate (as is often the case with apps from Google Play signed by + * upstream). + */ + private void explainIncompatibleVersions() { + String preferenceName = context.getString(R.string.show_incompat_versions); + String showIncompatible = context.getString( + R.string.app_details__no_versions__show_incompat_versions, preferenceName); + + String message; + String title; + if (hasCompatibleApksDifferentSigs()) { + title = context.getString(R.string.app_details__no_versions__no_compatible_signatures); + message = context.getString(R.string.app_details__no_versions__explain_incompatible_signatures) + + "\n\n" + showIncompatible; + } else { + title = context.getString(R.string.app_details__no_versions__none_compatible_with_device); + message = showIncompatible; + } + + new AlertDialog.Builder(context) + .setTitle(title) + .setMessage(message) + .show(); + } + + private boolean hasCompatibleApksDifferentSigs() { + return compatibleVersionsDifferentSig != null && compatibleVersionsDifferentSig.size() > 0; + } + } + private class PermissionsViewHolder extends ExpandableLinearLayoutViewHolder { PermissionsViewHolder(View view) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c3e01cc93..6136cb79d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -54,6 +54,13 @@ <string name="app_details_donate_prompt_unknown_author">Buy the developers of %1$s a coffee!</string> <string name="app_details_donate_prompt">%1$s is created by %2$s. Buy them a coffee!</string> + <string name="app_details__no_versions__show_incompat_versions">To show incompatible versions here anyway, enable the \"%1$s\" setting.</string> + <string name="app_details__no_versions__no_compatible_signatures">No versions with compatible signature</string> + <string name="app_details__no_versions__none_compatible_with_device">No versions compatible with device</string> + <string name="app_details__no_versions__explain_incompatible_signatures">The installed version is not compatible with any available versions. Uninstalling the app will enable you to view and install compatible versions. + +This often occurs with apps installed via Google Play or other sources, if they are signed by a different certificate.</string> + <string name="about_title">About F-Droid</string> <string name="about_version">Version</string> <string name="about_site">Website</string>