From ab8948eb5acd70aacd4a9b1b5af19ee764dafdef Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 17 Apr 2018 17:52:40 +0200 Subject: [PATCH 1/5] fix "Send F-Droid via Bluetooth" The 'com.mediatek.bluetooth' Bluetooth or android-23 devices were not being granted URI permissions. --- .../fdroid/views/swap/StartSwapView.java | 4 ++- .../java/org/fdroid/fdroid/FDroidApp.java | 6 ++-- .../fdroid/installer/ApkFileProvider.java | 28 +++++++++++-------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/app/src/full/java/org/fdroid/fdroid/views/swap/StartSwapView.java b/app/src/full/java/org/fdroid/fdroid/views/swap/StartSwapView.java index 1891468cd..03aeeb2ac 100644 --- a/app/src/full/java/org/fdroid/fdroid/views/swap/StartSwapView.java +++ b/app/src/full/java/org/fdroid/fdroid/views/swap/StartSwapView.java @@ -257,7 +257,9 @@ public class StartSwapView extends RelativeLayout implements SwapWorkflowActivit textBluetoothVisible.setText(textResource); bluetoothSwitch = (SwitchCompat) findViewById(R.id.switch_bluetooth); - Utils.debugLog(TAG, getManager().isBluetoothDiscoverable() ? "Initially marking switch as checked, because Bluetooth is discoverable." : "Initially marking switch as not-checked, because Bluetooth is not discoverable."); + Utils.debugLog(TAG, getManager().isBluetoothDiscoverable() + ? "Initially marking switch as checked, because Bluetooth is discoverable." + : "Initially marking switch as not-checked, because Bluetooth is not discoverable."); bluetoothSwitch.setOnCheckedChangeListener(onBluetoothSwitchToggled); setBluetoothSwitchState(getManager().isBluetoothDiscoverable(), true); diff --git a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java index 6844d0934..90a673fbd 100644 --- a/app/src/main/java/org/fdroid/fdroid/FDroidApp.java +++ b/app/src/main/java/org/fdroid/fdroid/FDroidApp.java @@ -580,7 +580,6 @@ public class FDroidApp extends Application { String bluetoothPackageName = null; String className = null; - boolean found = false; Intent sendBt = null; try { @@ -599,20 +598,19 @@ public class FDroidApp extends Application { if ("com.android.bluetooth".equals(bluetoothPackageName) || "com.mediatek.bluetooth".equals(bluetoothPackageName)) { className = info.activityInfo.name; - found = true; break; } } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Could not get application info to send via bluetooth", e); - found = false; + className = null; } catch (IOException e) { Exception toLog = new RuntimeException("Error preparing file to send via Bluetooth", e); ACRA.getErrorReporter().handleException(toLog, false); } if (sendBt != null) { - if (found) { + if (className != null) { sendBt.setClassName(bluetoothPackageName, className); activity.startActivity(sendBt); } else { diff --git a/app/src/main/java/org/fdroid/fdroid/installer/ApkFileProvider.java b/app/src/main/java/org/fdroid/fdroid/installer/ApkFileProvider.java index ceb903cf9..c1f9fe615 100644 --- a/app/src/main/java/org/fdroid/fdroid/installer/ApkFileProvider.java +++ b/app/src/main/java/org/fdroid/fdroid/installer/ApkFileProvider.java @@ -37,14 +37,18 @@ import java.io.IOException; * either locally or for sending via bluetooth. *

* APK handling for installations: - * 1. APKs are downloaded into a cache directory that is either created on SD card + *

    + *
  1. APKs are downloaded into a cache directory that is either created on SD card * "/Android/data/[app_package_name]/cache/apks" (if card is mounted and app has - * appropriate permission) or on device's file system depending incoming parameters. - * 2. Before installation, the APK is copied into the private data directory of the F-Droid, - * "/data/data/[app_package_name]/files/install-$random.apk". - * 3. The hash of the file is checked against the expected hash from the repository - * 4. For Android < 7, a file Uri pointing to the File is returned, for Android >= 7, - * a content Uri is returned using support lib's FileProvider. + * appropriate permission) or on device's file system depending incoming parameters
  2. + *
  3. Before installation, the APK is copied into the private data directory of the F-Droid, + * "/data/data/[app_package_name]/files/install-$random.apk"
  4. + *
  5. The hash of the file is checked against the expected hash from the repository
  6. + *
  7. For {@link Build.VERSION_CODES#M < android-23}, a {@code file://} {@link Uri} + * pointing to the {@link File} is returned, for {@link Build.VERSION_CODES#M >= android-23}, + * a {@code content://} {@code Uri} is returned using support lib's + * {@link FileProvider}
  8. + *
*/ public class ApkFileProvider extends FileProvider { @@ -52,7 +56,7 @@ public class ApkFileProvider extends FileProvider { public static Uri getSafeUri(Context context, PackageInfo packageInfo) throws IOException { SanitizedFile tempApkFile = ApkCache.copyInstalledApkToFiles(context, packageInfo); - return getSafeUri(context, tempApkFile, Build.VERSION.SDK_INT >= 24); + return getSafeUri(context, tempApkFile, Build.VERSION.SDK_INT >= 23); } /** @@ -89,12 +93,12 @@ public class ApkFileProvider extends FileProvider { context.grantUriPermission(PrivilegedInstaller.PRIVILEGED_EXTENSION_PACKAGE_NAME, apkUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); context.grantUriPermission("com.android.bluetooth", apkUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); + context.grantUriPermission("com.mediatek.bluetooth", apkUri, Intent.FLAG_GRANT_READ_URI_PERMISSION); return apkUri; + } else { + tempFile.setReadable(true, false); + return Uri.fromFile(tempFile); } - - tempFile.setReadable(true, false); - - return Uri.fromFile(tempFile); } } From 6db0fa63879e2313417d38490dc54ed3e2c5001b Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 9 Aug 2018 23:53:40 +0200 Subject: [PATCH 2/5] add clickable list of APKs to the swap HTML index page This allows for rapid, direct download of APKs. It is sometimes useful, as long as it doesn't get in the way. --- .../fdroid/localrepo/LocalRepoManager.java | 14 +++++++++ app/src/main/assets/index.template.html | 29 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/app/src/full/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java b/app/src/full/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java index 6256b6209..b7a730766 100644 --- a/app/src/full/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java +++ b/app/src/full/java/org/fdroid/fdroid/localrepo/LocalRepoManager.java @@ -147,10 +147,24 @@ public final class LocalRepoManager { BufferedWriter out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(indexHtml))); + StringBuilder builder = new StringBuilder(); + for (App app : apps.values()) { + builder.append("
  • ") + .append(app.name) + .append("
  • \n"); + } + String line; while ((line = in.readLine()) != null) { line = line.replaceAll("\\{\\{REPO_URL\\}\\}", repoAddress); line = line.replaceAll("\\{\\{CLIENT_URL\\}\\}", fdroidClientURL); + line = line.replaceAll("\\{\\{APP_LIST\\}\\}", builder.toString()); out.write(line); } in.close(); diff --git a/app/src/main/assets/index.template.html b/app/src/main/assets/index.template.html index f2f9cee82..5d8d08e11 100644 --- a/app/src/main/assets/index.template.html +++ b/app/src/main/assets/index.template.html @@ -71,6 +71,28 @@ color: #fff; } + details { + margin-left: 1em; + } + + ul { + list-style-type: none; + } + + ul > li { + padding: 1em 0; + } + + ul > li a { + font-size: xx-large; + text-decoration: none; + color: #fff; + } + + ul > li a img { + padding-right: 0.5em; + } + #download-from-web { padding-left: 2em; padding-right: 2em; @@ -105,5 +127,12 @@ Not done +



    +
    + Available Apps +
      + {{APP_LIST}} +
    +
    From 6b6ab02c9cbf6a3fa78777a8e852e9c54cd61496 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 10 Aug 2018 11:30:11 +0200 Subject: [PATCH 3/5] bump to bouncycastle 1.60 --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1e9133f80..a821ba29b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -161,15 +161,15 @@ dependencies { implementation 'com.fasterxml.jackson.core:jackson-annotations:2.8.7' implementation 'com.fasterxml.jackson.core:jackson-databind:2.8.7' - implementation 'org.bouncycastle:bcprov-jdk15on:1.59' - fullImplementation 'org.bouncycastle:bcpkix-jdk15on:1.59' + implementation 'org.bouncycastle:bcprov-jdk15on:1.60' + fullImplementation 'org.bouncycastle:bcpkix-jdk15on:1.60' fullImplementation 'cc.mvdan.accesspoint:library:0.2.0' fullImplementation 'org.jmdns:jmdns:3.5.3' fullImplementation 'org.nanohttpd:nanohttpd:2.3.1' testImplementation 'org.robolectric:robolectric:3.8' testImplementation "com.android.support.test:monitor:1.0.2" - testImplementation 'org.bouncycastle:bcprov-jdk15on:1.59' + testImplementation 'org.bouncycastle:bcprov-jdk15on:1.60' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:2.7.22' From aead26f02caa1b2c182936086c04bd2ad375ece7 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 13 Aug 2018 20:56:51 +0200 Subject: [PATCH 4/5] show "Open" button when media is installed and viewable This checks if there is an app that can view the installed media file, and if so, it shows an "Open" button where the "Run" button is for apps. --- app/src/main/AndroidManifest.xml | 2 +- .../installer/InstallHistoryService.java | 4 +- .../fdroid/fdroid/installer/Installer.java | 3 ++ .../views/AppDetailsRecyclerViewAdapter.java | 39 +++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + .../res/xml/install_history_file_provider.xml | 6 --- .../main/res/xml/installer_file_provider.xml | 5 +++ 7 files changed, 50 insertions(+), 10 deletions(-) delete mode 100644 app/src/main/res/xml/install_history_file_provider.xml create mode 100644 app/src/main/res/xml/installer_file_provider.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d098cdc47..354df5dd0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -129,7 +129,7 @@ android:grantUriPermissions="true"> + android:resource="@xml/installer_file_provider"/> 0) { + buttonPrimaryView.setText(R.string.menu_open); + buttonPrimaryView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + context.startActivity(viewIntent); + } catch (ActivityNotFoundException e) { + e.printStackTrace(); + } + } + }); + } else { + buttonPrimaryView.setVisibility(View.GONE); + } + } else { + buttonPrimaryView.setVisibility(View.GONE); + } } else { buttonPrimaryView.setVisibility(View.GONE); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0ebf4b3b8..0052e632b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -171,6 +171,7 @@ This often occurs with apps installed via Google Play or other sources, if they New Repository Run + Open Share Install Uninstall diff --git a/app/src/main/res/xml/install_history_file_provider.xml b/app/src/main/res/xml/install_history_file_provider.xml deleted file mode 100644 index 06e42c762..000000000 --- a/app/src/main/res/xml/install_history_file_provider.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/xml/installer_file_provider.xml b/app/src/main/res/xml/installer_file_provider.xml new file mode 100644 index 000000000..9b5dfbcd5 --- /dev/null +++ b/app/src/main/res/xml/installer_file_provider.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file From efd577b36b5bdd2e5958f88b9f4eb42b5cfecf43 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 17 Aug 2018 14:48:40 +0200 Subject: [PATCH 5/5] add Share button to "Installed Apps" to export CSV list refs #1484 --- .../installed/InstalledAppListAdapter.java | 10 +++++- .../installed/InstalledAppsActivity.java | 36 ++++++++++++++++++- app/src/main/res/menu/installed_apps.xml | 9 +++++ app/src/main/res/values/strings.xml | 2 ++ 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 app/src/main/res/menu/installed_apps.xml diff --git a/app/src/main/java/org/fdroid/fdroid/views/installed/InstalledAppListAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/installed/InstalledAppListAdapter.java index 9dec761a8..438fdc3f4 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/installed/InstalledAppListAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/installed/InstalledAppListAdapter.java @@ -6,7 +6,6 @@ import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; - import org.fdroid.fdroid.R; import org.fdroid.fdroid.data.App; import org.fdroid.fdroid.data.Schema; @@ -58,4 +57,13 @@ class InstalledAppListAdapter extends RecyclerView.Adapter + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0052e632b..069afd50e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -110,6 +110,8 @@ This often occurs with apps installed via Google Play or other sources, if they Download canceled Installed Apps + Share installed apps + Apps installed by F-Droid as CSV file Updates ignored Updates ignored for Version %1$s