# Unauthorized file access although \`MLPermission.ReadExternalStorage\` was requested and granted

**URL:** <https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383>\
**Category:** Unity Development\
**Tags:** development, unity\
**Created:** [January 12, 2023, 3:10pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383 "2023-01-12T15:10:29Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![julian.schlenker](https://avatars.discourse-cdn.com/v4/letter/j/e495f1/32.png) [@julian.schlenker](https://forum.magicleap.cloud/u/julian.schlenker)\
**Post date:** [January 12, 2023, 3:10pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383/1 "2023-01-12T15:10:29Z")

</div>

Hello there Magic Leap community,

I'm currently trying to host a small web server within my Unity App to allow accessing a debug interface by directly connecting to the ML via a web browser.  
I'm running into an issue where I can't seem to figure out how get the required permissions for accessing a folder previously copied to the device.

Things I have done so far:

- add `<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />` to the manifest file.
- check required permissions during app startup and request them via the ML SDK interface if not present (app shows up with storage permissions in the permission manager after initially approving).
- tried different location within the `/sdcard` directory.

Sadly, the web server always returns a 404 error as the read operation on the directory which should be served fails (see error below).

Admittedly I'm not very experienced with Android development but as far as I understand, the external storage should be an alias for everything within the `/sdcard` folder on the device or am I getting this wrong?

Thank you in advance!

**Unity Editor version** : 2022.2.0b16  
**ML2 OS version** : 1.1.0  
**MLSDK version** : 1.2.0  
**Host OS** : Windows

**Error messages from logs** (syntax-highlighting is supported via Markdown):

```auto
System.UnauthorizedAccessException: Access to the path "/sdcard/Public/debug-client/index.html" is denied.
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x00000] in <00000000000000000000000000000000>:0 
  at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.IO.FileOptions options) [0x00000] in <00000000000000000000000000000000>:0 
  at System.IO.StreamReader..ctor (System.String path, System.Text.Encoding encoding, System.Boolean detectEncodingFromByteOrderMarks, System.Int32 bufferSize) [0x00000] in <00000000000000000000000000000000>:0 
  at System.IO.File.InternalReadAllText (System.String path, System.Text.Encoding encoding) [0x00000] in <00000000000000000000000000000000>:0 
  at Websockets.Server.DebugServer+<>c __DisplayClass5_0.<.ctor>b__ 0 (System.Object sender, WebSocketSharp.Server.HttpRequestEventArgs e) [0x00000] in <00000000000000000000000000000000>:0 
  at WebSocketSharp.Server.HttpServer.processRequest (WebSocketSharp.Net.HttpListenerContext context) [0x00000] in <00000000000000000000000000000000>:0 
  at WebSocketSharp.Server.HttpServer+<>c __DisplayClass87_0.<receiveRequest>b__ 0 (System.Object state) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00000] in <00000000000000000000000000000000>:0 

```

**The manifest file** :

```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.unity3d.player" xmlns:tools="http://schemas.android.com/tools">
  <application>
    <activity android:name="com.unity3d.player.UnityPlayerActivity" android:theme="@style/UnityThemeSelector">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    </activity>
  </application>
  <uses-permission android:name="com.magicleap.permission.SPATIAL_MAPPING" />
  <uses-permission android:name="com.magicleap.permission.SPATIAL_ANCHOR" />
  <uses-permission android:name="com.magicleap.permission.HAND_TRACKING" />
  <uses-permission android:name="com.magicleap.permission.WEBVIEW" />
  <uses-permission android:name="com.magicleap.permission.MARKER_TRACKING" />
  <uses-permission android:name="android.permission.CAMERA" />
  <uses-permission android:name="com.magicleap.permission.VOICE_INPUT" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

```

**Mono Behaviour permissions snippet** :

```auto
    void Start()
    {
        if (MLPermissions.CheckPermission(MLPermission.ReadExternalStorage).IsOk)
        {
            InitServer();
        }
        else
        {
            MLPermissions.RequestPermission(MLPermission.ReadExternalStorage, permissionCallbacks);
        }
    }

```

---

<div class="post-metadata">

**Author:** ![kdowney](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.magicleap.cloud/kdowney/32/481_2.png) [@kdowney](https://forum.magicleap.cloud/u/kdowney)\
**Post date:** [January 12, 2023, 7:48pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383/2 "2023-01-12T19:48:43Z")

</div>

Hi @julian.schlenker, let me look into this and I'll report back. Thank you for your post.

---

<div class="post-metadata">

**Author:** ![kdowney](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.magicleap.cloud/kdowney/32/481_2.png) [@kdowney](https://forum.magicleap.cloud/u/kdowney)\
**Post date:** [January 18, 2023, 1:59pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383/3 "2023-01-18T13:59:24Z")

</div>

Hi @julian.schlenker Thank you for your post. I had a conversation with our engineering team. Have you tried `adb reverse`? We use that frequently and run a simple web server using:

`python -m http.server 8080`

where the above command will use it's current directory as the root of the web server.

The python web server would run on your machine, but you could talk to it with your app and send JSON data and other such things.

External storage is heavily restricted, per [Android documentation:](https://developer.android.com/training/data-storage) Generally, apps can not read another app's data, but they can get access to media, but that's mostly about it.

Example `adb reverse` command:

`adb reverse tcp:8080 tcp:8080`

So now if your app connects to [https://localhost:8080](https://localhost:8080) you will get the web server, if you started it at port 8080 on your machine. Here is an example:

```auto
(base) 
user@path/to/repo/ml2_aosp_$ adb shell 
demophon:/ $ telnet localhost:8080 
HEAD / HTTP/1.0 

HTTP/1.0 200 OK Server: SimpleHTTP/0.6 Python/3.9.7 
Date: Tue, 17 Jan 2023 19:22:10 GMT 
Content-type: text/html; charset=utf-8 Content-Length: 1903

```

Please let me know if this unblocks you.

---

<div class="post-metadata">

**Author:** ![julian.schlenker](https://avatars.discourse-cdn.com/v4/letter/j/e495f1/32.png) [@julian.schlenker](https://forum.magicleap.cloud/u/julian.schlenker)\
**Post date:** [January 18, 2023, 3:05pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383/4 "2023-01-18T15:05:43Z")

</div>

Hey @kdowney ,

thank you for the response. It seems we have a bit of a misunderstanding.  
My goal is to serve a website which connects to the app/ML2 via a websocket to allow for easy manipulation of some parameters and report some data back.  
While this could be achieved w/o actually serving the website from the ML2 and only providing a websocket in the ML2 app, it is way more convenient if everything is served from the device(s) in our scenario.

So the essential question is how I can read any files from the `/sdcard` directory (or any sub directories) from within a Unity application while `READ_EXTERNAL_STORAGE` is permitted.

---

<div class="post-metadata">

**Author:** ![kdowney](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.magicleap.cloud/kdowney/32/481_2.png) [@kdowney](https://forum.magicleap.cloud/u/kdowney)\
**Post date:** [January 19, 2023, 7:53pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383/5 "2023-01-19T19:53:18Z")

</div>

Thank you @julian.schlenker. According to the engineer with whom I spoke, I believe this should help: [Data and file storage overview | Android Developers](https://developer.android.com/training/data-storage)

The engineer said you may need something like this to make it work, but you'd need the Unity equivalent: [Android permission to read a file from SD card issues](https://stackoverflow.com/questions/52507705/android-permission-to-read-a-file-from-sd-card-issues)

Let us know if you're successful. Thanks for your post.

---

<div class="post-metadata">

**Author:** ![julian.schlenker](https://avatars.discourse-cdn.com/v4/letter/j/e495f1/32.png) [@julian.schlenker](https://forum.magicleap.cloud/u/julian.schlenker)\
**Post date:** [February 16, 2023, 2:29pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383/6 "2023-02-16T14:29:25Z")

</div>

Hey @kdowney ,

thanks for the response and sorry for the long absence.  
As stated in my initial post I am aware of these problems but I can't seem to figure them out.  
Permissions are requested and granted and I see no reason for the read access to error.

The android docs also state:

> **Caution:** The exact location of where your files can be saved might vary across devices. For this reason, don't use hard-coded file paths.

This makes me wonder if I'm misunderstanding the location of external storage on the ML2.  
If you could provide some example snippets were you actually access files from the device from within a Unity Application this would be greatly appreciated and helpful.

---

<div class="post-metadata">

**Author:** ![kdowney](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.magicleap.cloud/kdowney/32/481_2.png) [@kdowney](https://forum.magicleap.cloud/u/kdowney)\
**Post date:** [February 16, 2023, 5:10pm UTC](https://forum.magicleap.cloud/t/unauthorized-file-access-although-mlpermission-readexternalstorage-was-requested-and-granted/1383/7 "2023-02-16T17:10:58Z")

</div>

Hi there @julian.schlenker, no unfortunately we don't have ready-made example code for external storage to share.
