【Unity】iOS と Android でストレージの空き容量を取得するスクリプト

2021/05/12DEVELOP, Unity

アプリを利用している端末へ、データを追加ダウンロードしたりする際に必要となる「端末のストレージ空き容量チェック」。商用アプリでも稀にストレージの空き容量チェックが実装されておらず、データダウンロード中にフリーズしているアプリを見ますが、それはあまりにも酷いので面倒臭がらず対応しましょう。

目次

サンプルコード

まずはiOS 様にネイティブコードを作成します。Assets 以下に Plugins フォルダを作成し、その中に iOS フォルダを作成します。さらにiOS フォルダにiOS用のプログラムファイルを作成します。名前は storage.mm としました。

iOS 洋のネイティブコードはストレージの空き容量を取得する関数がひとつあるだけのシンプルなものです。

/// <summary>
/// ストレージ空き容量の取得。
/// </summary>
extern "C" long _GetAvailableStorageMB()
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
    NSDictionary *dict = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error:nil];
    if(dict)
    {
        int MB = 1024 * 1024;
        float free = (([[dict objectForKey: NSFileSystemFreeSize] floatValue])+1023) / MB;
        return (long)free;
    }
    return 0;
}

そして C# 側はアプリ側から呼び出すための関数を作成します。

using UnityEngine;
using System.Runtime.InteropServices;
 
namespace mira
{
    /// <summary>
    /// ストレージ操作
    /// </summary>
    public class Storage
    {
#if UNITY_IOS
        [DllImport("__Internal")]
        private static extern long _GetAvailableStorageMB();
#endif
 
        /// <summary>
        /// ストレージの空き容量を取得します。
        /// </summary>
        public static long GetFreeDiscSpaceMB()
        {
            long freeByteSize = 0;
#if UNITY_EDITOR
            freeByteSize = 0;
#elif UNITY_ANDROID
            freeByteSize = GetAvailableStorageByteMB();
#elif UNITY_IOS
            freeByteSize = GetAvailableStorageByteMB();
#else
            // 未実装。
            Debug.Assert(false);
#endif
            return freeByteSize;
        }
 
#if UNITY_ANDROID
        private static long GetAvailableStorageByteMB()
        {
            int MB = 1024 * 1024;
 
            var statFs = new AndroidJavaObject ("android.os.StatFs", Application.temporaryCachePath);
            var availableBlocks = statFs.Call<long> ("getAvailableBlocksLong");
            var blockSize = statFs.Call<long> ("getBlockSizeLong");
            var freeBytes = ((availableBlocks * blockSize)+1023) / MB;
            return freeBytes;
        }
 
#elif UNITY_IOS
        private static long GetAvailableStorageByteMB()
        {
            if (Application.platform == RuntimePlatform.IPhonePlayer)
            {
                return _GetAvailableStorageMB();
            }
            throw new System.NotSupportedException ();
        }
#endif
    }
}

使用方法

var freeSpaceMB = mira.Storage.GetFreeDiscSpaceMB();
var checkMB = 10;
if(freeSpaceMB < checkMB)
{
    // 「ストレージの空き容量が足りません。
    // アプリを削除するなどして空き容量を確保して下さい」メッセージを表示する等。
}

Posted by kazupon