2019
11.14

 

 

유니티에서 스크린 캡쳐를 하고, 이걸 스크린샷 폴더에 저장하고 싶다.

뭐, 유니티에서 잘 지원해주겠지 하고 막상 시도해보니까 생각보다 막히는 부분이 많았다.

 

 

문제점 1. 유니티에서 지원해주는 ScreenCapture.CaptureScreenshot()이 제대로 동작하지 않음.

 - https://docs.unity3d.com/ScriptReference/ScreenCapture.CaptureScreenshot.html

 - 유니티 자체적으로 지원하는 스크린캡쳐는 ScreenCapture.CaptureScreenshot() 라고 하는데,

   이게 문제가 많은지 커뮤니티 개발자들은 텍스쳐를 저장하는 식의 방법으로 대체 활용하고 있다.

 

문제점 2. 저장소 권한 문제.

 - 파일을 만들어서 경로에 넣는 것이기 때문에 저장소 권한이 없으면 오류가 난다.

 - 매니페스트를 추가하고 저장소 권한을 획득하자.

 - https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Android.Permission.RequestUserPermission.html

 

문제점 3. 저장은 되나 갤러리에 나타나지 않음.

 - 저장까지는 잘 되고 파일이 생성되기 까지 하는데, 갤러리에 뜨지는 않는다. 이 또한 별도의 처리를 해줘야 한다.

 - https://answers.unity.com/questions/200173/android-how-to-refresh-the-gallery-.html

 

 

이러한 문제들을 반영해서 최종적으로 만든 코드는 아래와 같다.

 

 

//using DeadMosquito.AndroidGoodies;
using System;
using System.Collections;
using System.IO;
using UnityEngine;
using UnityEngine.Android;
// 매니페스트 선언필요. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
//https://answers.unity.com/questions/200173/android-how-to-refresh-the-gallery-.html
public class ScreenCaptureManager : MonoBehaviour
{
bool onCapture = false;
public void PressBtnCapture()
{
if (onCapture == false)
{
StartCoroutine("CRSaveScreenshot");
}
}
IEnumerator CRSaveScreenshot()
{
onCapture = true;
yield return new WaitForEndOfFrame();
if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite) == false)
{
Permission.RequestUserPermission(Permission.ExternalStorageWrite);
yield return new WaitForSeconds(0.2f);
yield return new WaitUntil(() => Application.isFocused == true);
if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite) == false)
{
//다이얼로그를 위해 별도의 플러그인을 사용했었다. 이 코드는 주석 처리함.
//AGAlertDialog.ShowMessageDialog("권한 필요", "스크린샷을 저장하기 위해 저장소 권한이 필요합니다.",
//"Ok", () => OpenAppSetting(),
//"No!", () => AGUIMisc.ShowToast("저장소 요청 거절됨"));
// 별도로 확인 팝업을 띄우지 않을꺼면 OpenAppSetting()을 바로 호출함.
OpenAppSetting();
onCapture = false;
yield break;
}
}
string fileLocation = "mnt/sdcard/DCIM/Screenshots/";
string filename = Application.productName + "_" + System.DateTime.Now.ToString("yyyyMMddHHmmss") + ".png";
string finalLOC = fileLocation + filename;
if (!Directory.Exists(fileLocation))
{
Directory.CreateDirectory(fileLocation);
}
byte[] imageByte; //스크린샷을 Byte로 저장.Texture2D use
Texture2D tex = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, true);
tex.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0, true);
tex.Apply();
imageByte = tex.EncodeToPNG();
DestroyImmediate(tex);
File.WriteAllBytes(finalLOC, imageByte);
AndroidJavaClass classPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject objActivity = classPlayer.GetStatic<AndroidJavaObject>("currentActivity");
AndroidJavaClass classUri = new AndroidJavaClass("android.net.Uri");
AndroidJavaObject objIntent = new AndroidJavaObject("android.content.Intent", new object[2] { "android.intent.action.MEDIA_SCANNER_SCAN_FILE", classUri.CallStatic<AndroidJavaObject>("parse", "file://" + finalLOC) });
objActivity.Call("sendBroadcast", objIntent);
//아래 한 줄 또한 별도의 안드로이드 플러그인. 별도로 만들어서 호출하는 함수를 넣어주면 된다.
//AGUIMisc.ShowToast(finalLOC + "로 저장했습니다.");
onCapture = false;
}
// https://forum.unity.com/threads/redirect-to-app-settings.461140/
private void OpenAppSetting()
{
try
{
#if UNITY_ANDROID
using (var unityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
using (AndroidJavaObject currentActivityObject = unityClass.GetStatic<AndroidJavaObject>("currentActivity"))
{
string packageName = currentActivityObject.Call<string>("getPackageName");
using (var uriClass = new AndroidJavaClass("android.net.Uri"))
using (AndroidJavaObject uriObject = uriClass.CallStatic<AndroidJavaObject>("fromParts", "package", packageName, null))
using (var intentObject = new AndroidJavaObject("android.content.Intent", "android.settings.APPLICATION_DETAILS_SETTINGS", uriObject))
{
intentObject.Call<AndroidJavaObject>("addCategory", "android.intent.category.DEFAULT");
intentObject.Call<AndroidJavaObject>("setFlags", 0x10000000);
currentActivityObject.Call("startActivity", intentObject);
}
}
#endif
}
catch (Exception ex)
{
Debug.LogException(ex);
}
}
}