yourealwaysbe / forkyz

Forkyz Crosswords
GNU General Public License v3.0
39 stars 5 forks source link

Fails to write to storage #19

Closed simonpoole1 closed 3 years ago

simonpoole1 commented 3 years ago

Since pulling recent changes, crossword data isn't being written to external storage. This is affecting download of new crosswords and saving of game state.

2021-03-01 09:42:33.880 13322-13322/? E/yourealwaysbe: null
    java.io.FileNotFoundException: /storage/emulated/0/crosswords/temp/2021-1-19-USAToday.puz: open failed: EPERM (Operation not permitted)
        at libcore.io.IoBridge.open(IoBridge.java:492)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
        at app.crossword.yourealwaysbe.io.IO.save(IO.java:390)
        at app.crossword.yourealwaysbe.forkyz.ForkyzApplication.saveBoard(ForkyzApplication.java:75)
        at app.crossword.yourealwaysbe.PuzzleActivity.saveBoard(PuzzleActivity.java:200)
        at app.crossword.yourealwaysbe.PuzzleActivity.onPause(PuzzleActivity.java:113)
        at app.crossword.yourealwaysbe.PlayActivity.onPause(PlayActivity.java:795)
        at android.app.Activity.performPause(Activity.java:8174)
        at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1510)
        at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4735)
        at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4696)
        at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4647)
        at android.app.servertransaction.PauseActivityItem.execute(PauseActivityItem.java:46)
        at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Checking File.canRead()/canWrite() on /storage/emulated/0/crosswords shows that it is not writeable. (Although /storage/emulated/0/crosswords/temp is present and claims to be writeable).

I'm wondering if this is related to [getExternalStorageDirectory() being deprecated](https://developer.android.com/reference/android/os/Environment#getExternalStorageDirectory()). I'm running Android 11 on my phone and in my emulator - haven't tried yet on older versions.

yourealwaysbe commented 3 years ago

Quite possibly it is -- i noticed a similar bug report on OsmAnd this morning.

I'm currently working on updating the file access to the storage access framework which should fix this, though i'm just in a phase of abstracting the current file access into one place at the moment.

Does fadd29ea6d2f18e82e327dd95b351059c99a3ba3 work for you for now?

yourealwaysbe commented 3 years ago

You might want to try out the current file-access branch. It's still experimental at the moment as it's a big overhaul in how files are managed -- so backup your crosswords first. It's been working ok for a couple of days for me, but i haven't tried Android 11.

By default it now stores/looks for files in the app internal storage. To use the traditional "crosswords" folder instead, go to settings, select external storage, and select the crosswords folder.

yourealwaysbe commented 3 years ago

This appears to work well for me, even on Android 11. It's now on master so i'm closing this.

Note: Android 11 file access is slow (at least on LineageOS 18.1 for me). As far as i know i'm using the SAF properly (i.e. not naive use of DocumentFile). I have a plan to optimise the browse list population to try and improve things for large collections -- currently it reads the meta file for every puzzle in the list, which isn't ideal. This should halve the load time according to my experiments.