July 1, 2023

Android - reading files (permissions)

I discovered I can use adb very easily to deposit files onto my Pixel 6 phone, placing them in /sdcard/Tom. I then wrote an android app and it gets an exception
java.io.FileNotFoundException: /sdcard/Tom/green.jpg: open failed: EACCES (Permission denied)
The "file not found" is misleading. The problem is access permission. The chart in the above indicate that the "rules" have changed over time for different Android versions.

the Manifest

Each application can specify the permissions it desires in the file AndroidManifest.xml

You add lines that look like:




Sure enough, I look at android studio and there is a directory "manifests" that contains that file. I can double click on it in the left column and I am editing it.

Someone suggested the following process, which is all but useless. Right click above the "application" tag, and get a pull down that offers lots of options -- including "Generate", which you select. Generate offers me "XML tag" or "Copyright", choose "XML tag". If you then pick "uses-permission" you get this.


But you might as well just type in the following by hand:

What permissions are there?

Some that I may be interested in:
ACCESS_COARSE_LOCATION
ACCESS_FINE_LOCATION
READ_EXTERNAL_STORAGE
WRITE_EXTERNAL_STORAGE
It is useful to clarify what they mean by internal/external storage. Internal seems to mean "specific to the app that wants to access it". External seems to mean "world readable", but may or may not be a removeable

Try it out

I add this line to my AndroidManifest.xml

I can build the application, but it immediately dies with:
/sdcard/Tom/green.jpg: open failed: EACCES (Permission denied)
So all of this has gained me nothing. This "manage files" is an even deeper permission, and more than I should need.

Dig deeper

It turns out when you use android studio to run your application on your phone, it gets installed there. This is handy in any number of ways. Note that exporting the application to an "apk" for anybody to install is a different thing. You have to export it as an "android project". But never mind all that for now. I can pick up my phone and find my app (called "Book1" due to me starting it as some tutorial). I can put my finger on the icon and linger there and get a menu allowing me to look at App info. I had hoped to see the READ_EXTERNAL_STORAGE permission there, along with the ability to turn it on or off. But it has "Permissions" greyed out and says "No permissions requested". Hmmm.

Bad cable

I tried using a longer USB-C cable, which would have been handy, but ...

I would plug the phone in and it would announce on the phone "USB debugging enabled", but my project would never download and run. I switched to the shorter cable I was using previously and it "just works". I have heard various things about different USB-C cables, but apparently my long one is only partially functional.

More digging

I add a request for CAMERA permission, so my AndroidManifest.xml now has two lines:


And now my app-info page on the phone shows the Camera permission (and it is disabled when I first look at it). That page does have the ability to enable it, which I do. I don't need camera permission, but it is a way for me to see if some other permission works as expected. And it does.

It is too bad android programming isn't so much guessing and trial and error.

Some searching seems to indicate that Google made changes to how all of this works around Android 13.

Google has forever been making changes to how applications can access phone data.
Subsequent to and with Android 13, the game seems to be: The code would look like this:
	int permissionCheck = ContextCompat.checkSelfPermission(PlayListActivity.this,
                Manifest.permission.READ_EXTERNAL_STORAGE);

        if (ContextCompat.checkSelfPermission(PlayListActivity.this,
                Manifest.permission.READ_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {


            // OPCIONAL(explicaciones de poque pedimos los permisos)
            if (ActivityCompat.shouldShowRequestPermissionRationale(PlayListActivity.this,
                    Manifest.permission.READ_EXTERNAL_STORAGE)) {

            } else {
                //pedir permisos
                ActivityCompat.requestPermissions(PlayListActivity.this,
                        new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
                        permissionCheck);
They had a compatibility attribute as follows, but got rid of it in Android 11 and following:
add android:requestLegacyExternalStorage="true" to the  element in the manifest.
One fellow says: "READ_EXTERNAL_STORAGE should only be requested for devices with Android 9 and below". I am not so sure about this.

Mother may I ?

After being annoyed by the complexity of all this, I am somewhat reconciled to it. The idea, from Googles point of view, is protecting arbitrary users from badly behaved apps. They have deciding that reading "any" file in external storage is a dangerous permission. And they have decided that "dangerous" permissions must be approved by the user for each application that desires to use them.

A book I have has a whole chapter on this in the context of the latest Android (Android 13). As I understand it, you tell Android you want to ask the user permission. Then once Android is satisfied that the user has agreed, you can do as you like.


Have any comments? Questions? Drop me a line!

Adventures in Computing / tom@mmto.org