유니티에서 스크린 캡쳐를 하고, 이걸 스크린샷 폴더에 저장하고 싶다.
뭐, 유니티에서 잘 지원해주겠지 하고 막상 시도해보니까 생각보다 막히는 부분이 많았다.
문제점 1. 유니티에서 지원해주는 ScreenCapture.CaptureScreenshot()이 제대로 동작하지 않음.
- https://docs.unity3d.com/ScriptReference/ScreenCapture.CaptureScreenshot.html
- 유니티 자체적으로 지원하는 스크린캡쳐는 ScreenCapture.CaptureScreenshot() 라고 하는데,
이게 문제가 많은지 커뮤니티 개발자들은 텍스쳐를 저장하는 식의 방법으로 대체 활용하고 있다.
문제점 2. 저장소 권한 문제.
- 파일을 만들어서 경로에 넣는 것이기 때문에 저장소 권한이 없으면 오류가 난다.
- 매니페스트를 추가하고 저장소 권한을 획득하자.
문제점 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); | |
} | |
} | |
} |
'🌍 Unity > 유니티 프로그래밍' 카테고리의 다른 글
유니티 csv 파일 읽기 ( Unity csv file read ) 수정 19.11.15 (2) | 2019.11.15 |
---|---|
유니티 싱글톤(싱글턴) 기본 패턴 Unity singleton parttern (0) | 2019.11.15 |
유니티 앱 설정 열기 (Unity open App setting) (0) | 2019.11.14 |
사운드/오디오 매니저 Unity Sound Manager (0) | 2019.07.29 |
Unity Fade in Fade out 유니티 페이드 인 페이드 아웃 스크립트 (0) | 2019.06.30 |