HoloLens File Transfer

Tranferring file to and from HoloLens seems non-trivial. It is written in HoloLens official document about saving and sending your files:

Unlike Windows on a PC or phone, HoloLens does not have a File Explorer application.

Getting access to non-media file is not an easy task. Tools like file picker and OneDrive are definitly over-kill for this task.

Goal

The goals here are two-folded:

  • Save something to a file in HoloLens application, and later access it
  • Create a file elsewhere, and make HoloLens application read it

File Explorer on Device Portal

File explorer on the device portal is used as a bridge. But the directories listed on the device portal is not complete. Therefore, we need to find out the accessible directory for both HoloLens application and user on PC.

Luckily I found such a location. The folder LocalAppData\SOMEAPP\RoamingState on the device portal is mapped to ApplicationData.Current.RoamingFolder.Path in the application at runtime.

Device Portal Screenshot

So, when the file is written to this path in UWP application, it will appear here, and you can download it by simply clicking on the download button. On the other hand, if you upload a file to this path, it can be read out by UWP application.

Scripts

The scripts are adapted from HoloToolkit.

Reading

The sample script for reading file is:

public void ReadString() {
  string s;
#if !UNITY_EDITOR && UNITY_METRO
  try {
    using (Stream stream = OpenFileForRead(ApplicationData.Current.RoamingFolder.Path, "filename.txt")) {
      byte[] data = new byte[stream.Length];
      stream.Read(data, 0, data.Length);
      s = Encoding.ASCII.GetString(data);
    }
  }
  catch (Exception e) {
    Debug.Log(e);
  }
#endif
  return s;
}

private static Stream OpenFileForRead(string folderName, string fileName) {
  Stream stream = null;
#if !UNITY_EDITOR && UNITY_METRO
  Task task = new Task(
    async () => {
      StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(folderName);
      StorageFile file = await folder.GetFileAsync(fileName);
      stream = await file.OpenStreamForReadAsync();
    });
  task.Start();
  task.Wait();
#endif
  return stream;
}

Writing

The sample script for writing file is:

public void WriteString(string s) {
#if !UNITY_EDITOR && UNITY_METRO
  using (Stream stream = OpenFileForWrite(ApplicationData.Current.RoamingFolder.Path, "filename.txt")) {
    byte[] data = Encoding.ASCII.GetBytes(s);
    stream.Write(data, 0, data.Length);
    stream.Flush();
  }
#endif
}


private static Stream OpenFileForWrite(string folderName, string fileName) {
  Stream stream = null;
#if !UNITY_EDITOR && UNITY_METRO
  Task task = new Task(
    async () => {
      StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(folderName);
      StorageFile file = await folder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
      stream = await file.OpenStreamForWriteAsync();
    });
  task.Start();
  task.Wait();
#endif
  return stream;
}

In the above sample code, the file that is queried must exist. In the case when you want to list existing files in a given folder, it is as simple as:

StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(folderName);
foreach (StorageFile f in allFiles) {
  Debug.Log(TAG + ": found file " + f.Name + ", " + f.DateCreated);
}

The above code snippets are tested with the following configurations:

  • Unity 5.5 + Visual Studio 2015
  • Unity 5.6 + Visual Studio 2017

Further Reading

Apart from the RoamingState folder on HoloLens Device Portal, some other folders are accessible as well, for example, TempState and LocalState etc. More information can be found on UWP API page of Windows.Storage.ApplicationData.

Thanks for reading!


HoloLens Video Streaming

There have been lots of discussion about streaming on HoloLens. Here is a demo of my implementation.

Demo

This is the soccer match between Barcelona and Atlético Madrid today. The screen on the right is the real monitor, and the left one is a virtual screen showing streamed video. The application runs at a reasonably frame rate and resolution (20fps with 896x594 frame resolution). Video is taken via HoloLens Device Portal.

Implementation

This application is implemented using the following toolset:

On PC

  • Epiphan DVI2USB 3.0 and its SDK
  • Python for socket, queue, and interfacing Epiphan SDK via ctypes
  • Network connection

On HoloLens

  • Made with Unity 5.5.0f3
  • Windows.Networking.Sockets.StreamSocket
  • HoloToolkit
  • Network connection

Thanks for reading!