スクリーンショットをandroid端末に保存する

※この記事は2017年06月13日にqiitaに投稿した内容です。

環境

Unity5.6.1f1 Android7.0

概要

Application.CaptureScreenshot()を実行するだけでは保存されません スクリーンショットをストレージに保存し、メディアフォルダにも保存しています

ストレージ書き込みパーミッションの付与(WRITE_EXTERNAL_STORAGE)

・「BuildSettings」>「switchPlatform」でandroidにスイッチする ・「PlayerSetting」>「OtherSettings」>「WritePermission」を「External(SDcard)」に変更する

プログラム

ファイル保存した後はScanFileを実行する(重要)

ファイルを保存した後はscanFileを実行し、インデックス情報にファイルを登録してあげないとなりません そうしないとPCと接続した時にファイルが見えず、パニックになります

using System;
using System.Collections;
using System.IO;
using UnityEngine;

public class TestCapture : MonoBehaviour
{
    private string _fileName = "";
    void Start ()
    {
        StartCoroutine( WriteFileProcess() );
    }

    void Update ()
    {
    }

    private IEnumerator WriteFileProcess()
    {
        _fileName = "Screenshot" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".png";
        yield return CaptureScreenshotProcess();
        yield return MediaDirWriteFileProcess();
    }

    private IEnumerator CaptureScreenshotProcess()
    {
        Debug.Log( "CaptureScreenshotProcess" );
        yield return new WaitForEndOfFrame();
        string path = null;
#if UNITY_EDITOR
        path = _fileName;
#elif UNITY_ANDROID
        path = Application.persistentDataPath + "/" + _fileName;
#endif

        Debug.Log( "BeginCaptureScreenshot:" + path );
        Application.CaptureScreenshot( _fileName );
        Debug.Log( "AfterCaptureScreenshot:" + path );

        while ( File.Exists( path ) == false )
        {
            Debug.Log( "NoFile:" + path );
            yield return new WaitForEndOfFrame();
        }

        Debug.Log( "CaptureOK:" + path );
        scanFile( path, null );//"image/png";
    }

    private IEnumerator MediaDirWriteFileProcess()
    {
        Debug.Log( "MediaDirWriteFileProcess" );
        if( Application.platform != RuntimePlatform.Android )
            yield return null;
#if UNITY_ANDROID
        var path = Application.persistentDataPath + "/" + _fileName;
        while ( File.Exists( path ) == false )
        {
            Debug.Log( "NoFile:" + path );
            yield return new WaitForEndOfFrame();
        }
        // 保存パスを取得
        using( AndroidJavaClass jcEnvironment = new AndroidJavaClass("android.os.Environment") )
        using(AndroidJavaObject joPublicDir = jcEnvironment.CallStatic<AndroidJavaObject>("getExternalStoragePublicDirectory", jcEnvironment.GetStatic<string>( "DIRECTORY_PICTURES"/*"DIRECTORY_DCIM"*/ ) ) )
        {
            var outputPath = joPublicDir.Call<string>( "toString" );
            Debug.Log( "MediaDir:" + outputPath );
//              outputPath += "/100ANDRO/" + _fileName;
            outputPath += "/Screenshots/" + _fileName;
            var pngBytes = File.ReadAllBytes( path );
            File.WriteAllBytes( outputPath, pngBytes );
            yield return new WaitForEndOfFrame();
            while ( File.Exists( outputPath ) == false )
            {
                Debug.Log( "NoFile:" + outputPath );
                yield return new WaitForEndOfFrame();
            }
            Debug.Log( "MediaDirWriteFileOK:" + outputPath );
            scanFile( outputPath, null );
        }
#endif
    }

    //インデックス情報にファイル名を登録する
    //これをしないとPC から内部ストレージを参照した時にファイルが見えない
    static void scanFile( string path, string mimeType )
    {
        if( Application.platform != RuntimePlatform.Android )
             return;
#if UNITY_ANDROID
        using( AndroidJavaClass jcUnityPlayer = new AndroidJavaClass( "com.unity3d.player.UnityPlayer" ) )
        using( AndroidJavaObject joActivity = jcUnityPlayer.GetStatic<AndroidJavaObject>( "currentActivity" ) )
        using( AndroidJavaObject joContext = joActivity.Call<AndroidJavaObject>( "getApplicationContext" ) )
        using( AndroidJavaClass jcMediaScannerConnection = new AndroidJavaClass( "android.media.MediaScannerConnection" ) )
        using( AndroidJavaClass jcEnvironment = new AndroidJavaClass( "android.os.Environment" ) )
        using( AndroidJavaObject joExDir = jcEnvironment.CallStatic<AndroidJavaObject>( "getExternalStorageDirectory" ) )
        {
            Debug.Log( "scanFile:" + path );
            var mimeTypes = ( mimeType != null ) ? new string[] { mimeType } : null;
            jcMediaScannerConnection.CallStatic( "scanFile", joContext, new string[] { path }, mimeTypes, null );
        }
        Handheld.StopActivityIndicator();
#endif
    }
}

参考

http://marunouchi-tech.i-studio.co.jp/1190/