어제 프로젝트를 진행하던 도중 , 모바일에서 부하가 심한지 테스트 해보려고 안드로이드 빌드를 시도했다.

근데 계속 오류가 뜨면서 빌드가 실패했다. 로그를 다 모아놓진 않아서 검색기록 키워드들이라도 적어놓아야겠다. 누군가 나같은 짓을 반복하지 않길 바라면서..

WARNING: The option setting 'android.enableR8=false' is deprecated. It will be removed in version 5.0 of the Android Gradle plugin.
Execution failed for task ':launcher:packageRelease'. > A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade > com.android.ide.common.signing.KeytoolException: Failed to read key AndroidDebugKey from store "C:\Users\Pier6.android\debug.keystore": Invalid keystore format

키스토어에 뭔가 문제가 있다고 한다.

하지만 정말 슬픈 점은 기본으로 생성되는 Debug키를 쓰고있다는것이다.

자동으로 생성되는 키스토어인데 거기 문제가 있다니..
Debug키스토어의 위치는 보통 C:\Users\사용자명.android 안에 있다.
cmd를 사용해서 다른 키스토어 열듯이 Debug키스토어를 확인해보려고 해도 Invalid keystore format라며 확인이 불가능하다.

그래서 .android폴더를 통째로 지워버렸다.

혹시모르니까 컴퓨터 재부팅 한번 하고, 폴더 통째로 지우고, 안드로이드 빌드 하니까 잘 됐다.
기존에 있던 키스토어에 뭔가 문제가 있었나보다.. 편하게 다시 만들자.

이걸 몰라서 Gradle버전, ProjectSetting , Preference 여기저기 다 뒤져봤었는데 delete키 한번 눌러서 해결 되었다.

 

 


작성일: 2022년 12월 15일

_

발단

A Native Collection has not been disposed, resulting in a memory leak.
라는 빨간줄 에러가 마구마구 뜬다.

UnityWebRequest를 쓸 때, Get에서는 안뜨는데 Post에서는 뜨는 오류였다.
(유니티 버전은 2021.3.1f1)

게다가 Post 할때마다 항상 뜨는것도 아니었다.
여러번 Post하거나, 특히 짧은시간에 여러번 보내면 저 오류가 많이떴다.

console에 뜨는 로그를 눌러도 따로 뜨는 말도없고, stackTrace를 Full로 놓아도 뜨는게 없다.

구글링을 정말 열심히 했지만...저 에러를 검색하면 가장 많이 하는 말이 request.Dispose()를 안해서 그렇다고 한다. 하지만 using문을 쓰면 dispose가 자동으로 되는걸...

_

전개

아래는 문제를 일으켰던 코드다.

    private IEnumerator SendPost(string url, string parameter, Action<string> callback)
    {

        using (UnityWebRequest request = UnityWebRequest.Post(url, parameter))
        {
            byte[] jsonToSend = new UTF8Encoding().GetBytes(parameter);

            request.uploadHandler = new UploadHandlerRaw(jsonToSend);
            request.SetRequestHeader("Content-Type", "application/json");

            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {

                callback(request.downloadHandler.text.Replace('{', ' ').Replace('}', ' ').Replace('"', ' '));
            }
            else
            {
                callback("Error");
            }
        }
    }

여기에서 request.uploadHandler = new UploadHandlerRaw(jsonToSend);
이녀석이 문제였다.

1.애초에 using문에서 post를 선언할때를 보면 url과 uploadHandler를 넣어주게 되는데, 이미 UploadHandler는 이미 이때 생성이 된것이다.

2.그리고 using문 안에서 UploadHandlerRaw를 사용해서 parameter를 인코딩후에 uploadHandler에 넣어주게 되는데,,,

쉽게 말하면 1번과 2번에서 중복해서 uploadHandler를 건드려서 A Native Collection has not been disposed 이라는 에러가 난 것 으로 보인다.
그래서 get에서는 안뜨고 uploadHandler를 건드리는 Post에서만 떴던것이다!

_

절정

UnityWebRequest 의 디폴트 설정으로, uploadHandler는 request가 dispose 된 이후에 자동으로 같이 dispose 되도록 되어있다.

하지만 그게 문제가 아니라 중복으로 값이 들어가는게 문제였기 때문에,,,
단순하게 인코딩하기 "전에" 구문 윗줄에 uploadHandler를 한번 dispose 해줬다.

   private IEnumerator SendPost(string url, string parameter, Action<string> callback)
    {
        using (UnityWebRequest request = UnityWebRequest.Post(url, parameter))
        {
            byte[] jsonToSend = new UTF8Encoding().GetBytes(parameter);

            request.uploadHandler.Dispose();
            request.uploadHandler = new UploadHandlerRaw(jsonToSend);
            request.SetRequestHeader("Content-Type", "application/json");

            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {

                callback(request.downloadHandler.text.Replace('{', ' ').Replace('}', ' ').Replace('"', ' '));
            }
            else
            {
                callback("Error");
            }
        }
    }

_

결말

오랜 시간 앉아서 고민했고, 코드 단 한줄 작성으로 문제가 해결되었다.
의미있는 삽질이었으면 좋겠다.

 

 


작성일: 2022년 10월 7일

개인적으로 가장 뿌듯했던 글이다.

 

UnityWebRequest

사용할수있는 method는 GET, POST, PUT, DELETE 가 있다.

_
UnityWebRequest의 흐름은 쉽게 말하면 이렇다.

request -> response
1.request: 클라이언트에서 URL에 정보를 요청한다.
2.response: 해당 url에서 클라이언트로 요청한 정보를 응답해준다.

우리는 그 받은 정보를 쓸 수 있게 파싱해서 사용한다.

_
응답이 툭치면 나오는게 아니라, 요청을 보내면 응답이 올때까지 기다려야 되기 때문에,
일반적인 함수가 아니라 코루틴이나 비동기를 사용한다.

아래의 예시는 내가 post를 사용할 때 썼던 코드들이다.

  StartCoroutine(SendPost(serverUrl, param, (callback) =>
        {
            Debug.Log(callback);
        }
    private IEnumerator SendPost(string url, string parameter, Action<string> callback)
    {
        using (UnityWebRequest request = UnityWebRequest.Post(url, parameter))
        {
            byte[] jsonToSend = new UTF8Encoding().GetBytes(parameter);

            request.uploadHandler.Dispose();
            request.uploadHandler = new UploadHandlerRaw(jsonToSend);
            request.SetRequestHeader("Content-Type", "application/json");

            yield return request.SendWebRequest();

            if (request.result == UnityWebRequest.Result.Success)
            {
                callback(request.downloadHandler.text.Replace('{', ' ').Replace('}', ' ').Replace('"', ' '));
            }
            else
            {
                Debug.LogError("Failed");
                callback("Error");
            }
        }
    }

 


작성일 : 2022년 10월 7일

 

 

 

+ Recent posts