1

In my app i want to get user permission to read and write data on external storage, i have put permission tag in my manifest as below. When installing the app for the first time it works. It asks for permission and the save of the files is working. If I unistall the app and reinstall it without any changes on the code the saving does not work! The files that I want to be saved from the app to the device are on the Assets folder. On a few questions here I read about runtime permissions! I was not able to find a way to add this on my code. Can anyone help me on how to add it on my code in order to make it functionable?

My manisfest is the below:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.hcghelp">

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission
        android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="28" />
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

    <application

        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.HCGHelp">
        <activity android:name=".NP_all"></activity>
        
        <activity android:name=".GKL18_pre" />
        <activity android:name=".GKL17_in" />
        <activity android:name=".GKL17_pre" />
        <activity android:name=".GKL16_in" />
        <activity android:name=".GKL14_in" />
        <activity android:name=".GKL10_in" />
        <activity android:name=".GKL16_pre" />
        <activity android:name=".GKL14_pre" />
        <activity android:name=".GKL10_pre" />
        <activity android:name=".GKL07_in" />
        <activity android:name=".GKL07_pre" />
        <activity android:name=".GKL02_in" />
        <activity android:name=".GKL02_pre" />
        <activity android:name=".GKL01_pre" />
        <activity android:name=".GKL01_in" />
        <activity android:name=".GKL_all" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

My code is the below:

public class GKL10_pre extends AppCompatActivity {


    private Button button1;
    private Button button; 


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_gkl10_pre);



        button1 = (Button) findViewById(R.id.B_GKL10_KEIMENO);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) { opengkl10_pk();
            }
        });


        button = (Button) findViewById(R.id.B_GKL10_FILES);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                copyAsset("file1.pdf");
                copyAsset("file2.pdf");
                copyAsset("file3.pdf");
                copyAsset("file4.pdf");

            }
        });
    }

    private void copyAsset(String filename){
        String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download";
        File dir = new File(dirPath);
        if(!dir.exists()) {
            dir.mkdirs();
        }
        AssetManager assetManager = getAssets();
        InputStream in = null;
        OutputStream out = null;
        try {
            in = assetManager.open(filename);
            File outFile = new File(dirPath, filename);
            out = new FileOutputStream(outFile);
            copyFile(in, out);
            Toast.makeText(this, "Saved!", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, "Failed!", Toast.LENGTH_SHORT).show();
        } finally {
            if(in != null){
                try {
                    in.close();
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
            if(out != null){
                try {
                    out.close();
                } catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    private void copyFile(InputStream in, OutputStream out) throws IOException{
        byte[] buffer = new byte[1024];
        int read;
        while ((read = in.read(buffer)) != -1) {
            out.write(buffer, 0, read);
        }
    }

When I run the debug I am getting the below for every file

W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:492)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
W/System.err:     at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
W/System.err:     at com.example.hcghelp.GKL10_pre.copyAsset(GKL10_pre.java:84)
W/System.err:     at com.example.hcghelp.GKL10_pre.access$000(GKL10_pre.java:28)
W/System.err:     at com.example.hcghelp.GKL10_pre$2.onClick(GKL10_pre.java:56)
W/System.err:     at android.view.View.performClick(View.java:7448)
W/System.err:     at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:992)
W/System.err:     at android.view.View.performClickInternal(View.java:7425)
W/System.err:     at android.view.View.access$3600(View.java:810)
W/System.err:     at android.view.View$PerformClick.run(View.java:28305)
W/System.err:     at android.os.Handler.handleCallback(Handler.java:938)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
W/System.err:     at android.os.Looper.loop(Looper.java:223)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7656)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
W/System.err:     at libcore.io.Linux.open(Native Method)
W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
W/System.err:     at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
W/System.err:     at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
W/System.err:     at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7542)
W/System.err:     at libcore.io.IoBridge.open(IoBridge.java:478)
W/System.err:   ... 17 more
D/CompatibilityChangeReporter: Compat change id reported: 147798919; UID 10157; state: ENABLED```
W8ForMe247
  • 33
  • 1
  • 5
  • Check this out https://stackoverflow.com/a/23529376/13533028 – Narendra_Nath Aug 11 '22 at 18:49
  • Permission is ok but the file to overwrite does not belong to your app. You have been told this. For that file no permission. Not even if you get permissions at runtime. https://stackoverflow.com/questions/73308158/saving-files-from-assets-folder-to-device-storage-working-only-the-first-time-a – blackapps Aug 11 '22 at 19:13
  • `android:name="android.permission.MANAGE_EXTERNAL_STORAGE` If you would execute the necessary code to obtain this permission at runtime you could overwrite the file after reinstall. – blackapps Aug 11 '22 at 19:21
  • `Environment.getExternalStorageDirectory()` If you changed that to getExternalFilesDir(null) you would not need any permission and you could reinstall as often as you want. – blackapps Aug 11 '22 at 19:25
  • My friend @blackapps your help is appreciated, but the problem is still unsolved! I changed the `String dirPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download";` to -> `String dirPath = getExternalFilesDir(null).getAbsolutePath() + "/Download";` as you suggested me. This time I am getting the pop-up message "Saved!" but any file is saved!! It seems that it is getting inside the ''Try'' loop but with no real result. What am I missing here? I did a lot of uninstalls - installs and I having the same outcome everytime. Any file is saved to the device storage! – W8ForMe247 Aug 13 '22 at 15:49
  • I have no idea what problem you have. The files are always saved. Well wonderfull. What is the problem? – blackapps Aug 13 '22 at 21:18
  • That's the problem! The files are not saved! It is getting inside the 'TRY' loop, it is giving me the Toast "Saved!" but any file is saved! The save is never done.. how is that possible? – W8ForMe247 Aug 14 '22 at 07:46
  • How did you check that? – blackapps Aug 14 '22 at 17:34
  • I Uninstall the app. I did the change on android studio. I export the .apk file from android studio. I install the app on my phone. I press the button on the app and then I checked on Download folder where the files should be.. but they did not.. that was what I did.. – W8ForMe247 Aug 14 '22 at 19:03
  • Could you help me my friend? @blackapps – W8ForMe247 Aug 16 '22 at 14:57
  • It is unclear which of the two getExternal.... functions you used. If it is the one in your code block then you knoe why as i told you already long ago what caused this. – blackapps Aug 16 '22 at 17:41
  • `String dirPath = getExternalFilesDir(null).getAbsolutePath() + "/Download";` this is what I used.. it is the getExternal that you suggested.. – W8ForMe247 Aug 17 '22 at 07:56

1 Answers1

0

Below android 11, you can use

                    ActivityCompat.requestPermissions(
                        this,
                        arrayOf(WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE),
                        REQUEST_CODE
                    )

to request runtime permissison

Don't forget add this line into AndroidManifest if you using android 10

android:requestLegacyExternalStorage="true"

And from android 11, you must have MANAGE_EXTERNAL_STORAGE permission to write your file. Check this:

    val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
    intent.addCategory("android.intent.category.DEFAULT")
    intent.data = Uri.parse(String.format("package:%s",applicationContext.packageName))
    startActivity(intent)
ninhnau19
  • 695
  • 1
  • 3
  • 16
  • using given permission google will reject your app i have done same permission but google has rejected app – MARSH Dec 08 '22 at 04:51
  • you will have to explain to gg about using this permission. If it passes, there won't be any problem – ninhnau19 Dec 09 '22 at 02:33