1

Are there namespaces in Android which "listen to the file system change notifications and raise events when a directory, or file in a directory, changes" that compatible with Unity?

Ex:

System.IO.FileSystemWatcher

Does this quite nicely with events, see below.

Quick research leads me to believe Android.OS.FileObserver is the appropriate solution but can't quite seem to find any samples of its use with regards to Unity.

Reading in the Unity manual that one "can use Android plugins to call code created outside of Unity from their C# scripts, allowing them to access features like OS calls that would otherwise not be available to Unity".

Can we use a file watcher on Android Unity applications?

Note: Looking for FileObserver.jar files hasn't proved useful though we managed to find a FileObserver.java for Android 5.0.

Code

private void PrototypeFileWatcher_Created(object sender, FileSystemEventArgs e)
{
    Debug.Log("FileWatcher created");

    ReadFiles();

    //  prevent file access while it is still being written
    while (IsFileLocked(e.FullPath))
    {
    }

    UnityMainThreadDispatcher.Instance().Enqueue(() => GenerateMdls());
}
private void PrototypeFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
    Debug.Log("FileWatcher changed");
}
private void PrototypeFileWatcher_Deleted(object sender, FileSystemEventArgs e)
{
    Debug.Log("FileWatcher deleted");

    //  prevent file access errors
    while (IsFileLocked(e.FullPath))
    {
    }

    if (e.ChangeType == WatcherChangeTypes.Deleted)
    {
        UnityMainThreadDispatcher.Instance().Enqueue(() => RemoveMdl(e.FullPath));
    }
}

/*  Credit for below: 
 *  https://stackoverflow.com/questions/10982104/wait-until-file-is-completely-written
 */
const int ERROR_SHARING_VIOLATION = 32;
const int ERROR_LOCK_VIOLATION = 33;
private bool IsFileLocked(string file)
{
    //check that problem is not in destination file
    if (File.Exists(file) == true)
    {
        FileStream stream = null;
        try
        {
            stream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
        }
        catch (Exception ex2)
        {
            //_log.WriteLog(ex2, "Error in checking whether file is locked " + file);
            int errorCode = System.Runtime.InteropServices.Marshal.GetHRForException(ex2) & ((1 << 16) - 1);
            if ((ex2 is IOException) && (errorCode == ERROR_SHARING_VIOLATION || errorCode == ERROR_LOCK_VIOLATION))
            {
                return true;
            }
        }
        finally
        {
            if (stream != null)
                stream.Close();
        }
    }
    return false;
}
jtth
  • 876
  • 1
  • 12
  • 40

1 Answers1

1

One of the right way of doing this in Unity is creating a Android Plugin (library/AAR, for example).

There you can implement you needs using the FileObserver which you've mentioned. Then you can call you defined methods from Unity using AndroidJavaClass and AndroidJavaObject (search for unity call java method on Google).

Just send a message from your Android plugin to any of you GameObject on your scene with the information you need. Check the section The UnitySendMessage function in this link. I think the whole post can be helpful for you.

Tanaka
  • 97
  • 5
  • Understood. As not well versed in Android studio or android plugins went with a different solution native to Unity. Used `InvokeRepeating` to scan our directory every x seconds for file differences (creation, deletion, etc) and handling them from there. – jtth Aug 15 '19 at 20:02