Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit fca28687 authored by Francesco Saltori's avatar Francesco Saltori Committed by GitHub
Browse files

Various permission-related fixes (#114)

* Do not unnecessarily ask for storage write permission on Android 11

* Fix download PDF not working via HTTP on recent Android versions

* Add missing READ_EXTERNAL_STORAGE permission to manifest

* Reword storage permission request message in intro

* Fix strings wrongly marked as non-translatable

* Handle missing READ_EXTERNAL_STORAGE permission when opening file

* Tweak action_about Italian string to better distinguish it from settings

* Use correct icon for document info dialog

* Remove non-existing WRITE_INTERNAL_STORAGE permission from manifest
parent f7ddc0f3
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -2,8 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gsnathan.pdfviewer">

    <uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
@@ -14,6 +14,7 @@
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:requestLegacyExternalStorage="true"
        android:usesCleartextTraffic="true"
        android:theme="@style/Theme.Cyanea.Light.DarkActionBar">

        <activity
+32 −3
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
@@ -72,8 +71,11 @@ import com.shockwave.pdfium.PdfPasswordException;
import org.jetbrains.annotations.NotNull;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;

import static android.content.pm.PackageManager.PERMISSION_GRANTED;

public class MainActivity extends CyaneaAppCompatActivity {

    private static final String TAG = "MainActivity";
@@ -102,6 +104,11 @@ public class MainActivity extends CyaneaAppCompatActivity {
        this::saveDownloadedFileAfterPermissionRequest
    );

    private final ActivityResultLauncher<String> readFileErrorPermissionLauncher = registerForActivityResult(
        new RequestPermission(),
        this::restartAppIfGranted
    );

    private final ActivityResultLauncher<Intent> settingsLauncher = registerForActivityResult(
        new StartActivityForResult(),
        result -> displayFromUri(uri)
@@ -274,12 +281,34 @@ public class MainActivity extends CyaneaAppCompatActivity {
                pdfPassword = null;  // prevent the toast from being shown again if the user rotates the screen
            }
            askForPdfPassword();
        } else if (couldNotOpenFileDueToMissingPermission(exception)) {
            readFileErrorPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE);
        } else {
            Toast.makeText(this, R.string.file_opening_error, Toast.LENGTH_LONG).show();
            Log.e(TAG, "Error when opening file", exception);
        }
    }

    private boolean couldNotOpenFileDueToMissingPermission(Throwable e) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PERMISSION_GRANTED)
            return false;

        String exceptionMessage = e.getMessage();
        return e instanceof FileNotFoundException &&
            exceptionMessage != null && exceptionMessage.contains("Permission denied");
    }

    private void restartAppIfGranted(boolean isPermissionGranted) {
        if (isPermissionGranted) {
            // This is a quick and dirty way to make the system restart the current activity *and the current app process*.
            // This is needed because on Android 6 storage permission grants do not take effect until
            // the app process is restarted.
            System.exit(0);
        } else {
            Toast.makeText(this, R.string.file_opening_error, Toast.LENGTH_LONG).show();
        }
    }

    private void toggleBottomNavigationAccordingToPosition(int page, float positionOffset) {
        if (positionOffset == 0) {
            showBottomNavigationView();
@@ -359,7 +388,7 @@ public class MainActivity extends CyaneaAppCompatActivity {
    }

    private void saveToDownloadFolderIfAllowed(byte[] fileContent) {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
        if (Utils.canWriteToDownloadFolder(this)) {
            trySaveToDownloadFolder(fileContent, false);
        } else {
            saveToDownloadPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE);
@@ -486,7 +515,7 @@ public class MainActivity extends CyaneaAppCompatActivity {
                            getString(R.string.pdf_author, getArguments().getString(AUTHOR_ARGUMENT)) + "\n" +
                            getString(R.string.pdf_creation_date, getArguments().getString(CREATION_DATE_ARGUMENT)))
                    .setPositiveButton(R.string.ok, (dialog, which) -> {})
                    .setIcon(R.drawable.alert_icon)
                    .setIcon(R.drawable.info_icon)
                    .create();
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ public class MainIntroActivity extends AppIntro {
            third.setImageDrawable(R.drawable.patterns_permissions);
            third.setBgColor(bg);
            addSlide(AppIntroFragment.newInstance(third));
            askForPermissions(new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }, 3);
            askForPermissions(new String[]{ Manifest.permission.READ_EXTERNAL_STORAGE }, 3);
        }

        showSkipButton(false);
+11 −0
Original line number Diff line number Diff line
@@ -25,10 +25,13 @@
package com.gsnathan.pdfviewer;

import android.content.ClipData;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
@@ -100,6 +103,14 @@ public class Utils {
        return BuildConfig.VERSION_NAME;
    }

    static boolean canWriteToDownloadFolder(Context context) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
            return true;

        return ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                == PackageManager.PERMISSION_GRANTED;
    }

    static byte[] readBytesToEnd(InputStream inputStream) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        byte[] buffer = new byte[8 * 1024];
Loading