facebook twitter hatena line email

「Unity/Csharp/Request」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
(iosで、"Malformed URL"エラーになるとき)
 
(同じ利用者による、間の7版が非表示)
行3: 行3:
 
*WebHttpRequest.cs
 
*WebHttpRequest.cs
 
<pre>
 
<pre>
using System;
 
 
using System.Collections;
 
using System.Collections;
 
using System.Threading;
 
using System.Threading;
行10: 行9:
  
 
public class WebHttpRequest : MonoBehaviour {
 
public class WebHttpRequest : MonoBehaviour {
string text = "";
+
    string text = "";
 
     private int retry = 10;
 
     private int retry = 10;
public bool errorFlag = false;
+
    public bool errorFlag = false;
 
     private int timeout = 2;
 
     private int timeout = 2;
 
     // 現在のretry回数
 
     // 現在のretry回数
 
     private int retryNum = 0;
 
     private int retryNum = 0;
UnityWebRequest request;
+
    UnityWebRequest request;
SynchronizationContext context;
+
    SynchronizationContext context;
WWWForm paramPostForm;
+
    WWWForm paramPostForm;
 
     public enum ResponseType
 
     public enum ResponseType
 
     {
 
     {
行31: 行30:
 
         callbacks += callback;
 
         callbacks += callback;
 
     }
 
     }
public void Init () {
+
    public void Init () {
Debug.Log ("WebHttpRequest.Init()");
+
        Debug.Log ("WebHttpRequest.Init()");
paramPostForm = new WWWForm ();
+
        paramPostForm = new WWWForm ();
}
+
    }
 
     public void setTimeout(int sec) {
 
     public void setTimeout(int sec) {
 
         timeout = sec;
 
         timeout = sec;
行45: 行44:
 
         return retryNum;
 
         return retryNum;
 
     }
 
     }
public void Exec (string url) {
+
    public void Exec (string url) {
text = "";
+
        text = "";
errorFlag = false;
+
        errorFlag = false;
context = SynchronizationContext.Current; // メインスレッドでcontextを設置
+
        context = SynchronizationContext.Current; // メインスレッドでcontextを設置
StartCoroutine(Get(url));
+
        StartCoroutine(Get(url));
}
+
    }
IEnumerator Get (string url) {
+
    IEnumerator Get (string url) {
    request = new UnityWebRequest();
+
        request = new UnityWebRequest();
request.downloadHandler = new DownloadHandlerBuffer();
+
        request.downloadHandler = new DownloadHandlerBuffer();
request.url = url;
+
        request.url = url;
request.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
+
        request.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
request.method = UnityWebRequest.kHttpVerbGET;
+
        request.method = UnityWebRequest.kHttpVerbGET;
request.timeout = timeout;
+
        request.timeout = timeout;
Debug.Log ("WebHttpRequest Get timeout=" + timeout);
+
        Debug.Log ("WebHttpRequest Get timeout=" + timeout);
 
         yield return request.Send();
 
         yield return request.Send();
 
         retryNum = 0;
 
         retryNum = 0;
if (request.isNetworkError) {
+
        if (request.isNetworkError) {
Debug.Log("request.isNetworkError request.error=" + request.error);
+
            Debug.Log("request.isNetworkError request.error=" + request.error);
if (request.error.Equals ("Request timeout")) {
+
            if (request.error.Equals ("Request timeout")) {
 
                 retryNum++;
 
                 retryNum++;
 
                 if (retryNum < retry) {
 
                 if (retryNum < retry) {
 
                     Debug.Log ("WebHttpRequest Get timeout " + request.error + " retryNum = "+retryNum);
 
                     Debug.Log ("WebHttpRequest Get timeout " + request.error + " retryNum = "+retryNum);
Exec (url); // IEnumerator Get(url) メソッドへ
+
                    Exec (url); // IEnumerator Get(url) メソッドへ
} else {
+
                } else {
 
                     errorFlag = true;
 
                     errorFlag = true;
// メインスレッドへ戻す
+
                    // メインスレッドへ戻す
context.Post(d =>
+
                    context.Post(d =>
{
+
                    {
if (callbacks != null)
+
                        if (callbacks != null)
{
+
                        {
callbacks(ResponseType.NetworkError);
+
                            callbacks(ResponseType.NetworkError);
}
+
                        }
}, null);
+
                    }, null);
}
+
                }
} else {
+
            } else {
Debug.Log ("WebHttpRequest Get request.error=" + request.error);
+
                Debug.Log ("WebHttpRequest Get request.error=" + request.error);
 
                 errorFlag = true;
 
                 errorFlag = true;
// メインスレッドへ戻す
+
                // メインスレッドへ戻す
context.Post(d =>
+
                context.Post(d =>
{
+
                {
if (callbacks != null)
+
                    if (callbacks != null)
{
+
                    {
callbacks(ResponseType.NetworkError);
+
                        callbacks(ResponseType.NetworkError);
}
+
                    }
}, null);
+
                }, null);
}
+
            }
} else {
+
        } else {
if (request.responseCode == 200) {
+
            if (request.responseCode == 200) {
Debug.Log ("WebHttpRequest Get success request.responseCode=" + request.responseCode);
+
                Debug.Log ("WebHttpRequest Get success request.responseCode=" + request.responseCode);
 
                 text = request.downloadHandler.text;
 
                 text = request.downloadHandler.text;
 
                 Debug.Log("WebHttpRequest Get text=" + text);
 
                 Debug.Log("WebHttpRequest Get text=" + text);
 
                 // メインスレッドへ戻す
 
                 // メインスレッドへ戻す
context.Post(d =>
+
                context.Post(d =>
{
+
                {
if (callbacks != null)
+
                    if (callbacks != null)
{
+
                    {
callbacks(ResponseType.Success);
+
                        callbacks(ResponseType.Success);
}
+
                    }
}, null);
+
                }, null);
} else {
+
            } else {
errorFlag = true;
+
                errorFlag = true;
 
                 Debug.Log ("WebHttpRequest Get failed" + request.responseCode);
 
                 Debug.Log ("WebHttpRequest Get failed" + request.responseCode);
 
                 // メインスレッドへ戻す
 
                 // メインスレッドへ戻す
context.Post(d =>
+
                context.Post(d =>
{
+
                {
if (callbacks != null)
+
                    if (callbacks != null)
{
+
                    {
callbacks(ResponseType.Failure);
+
                        callbacks(ResponseType.Failure);
}
+
                    }
}, null);
+
                }, null);
}
+
            }
}
+
        }
}
+
    }
public void ExecPost (string url) {
+
    public void ExecPost (string url) {
text = "";
+
        text = "";
errorFlag = false;
+
        errorFlag = false;
StartCoroutine(Post (url));
+
        context = SynchronizationContext.Current; // メインスレッドでcontextを設置
}
+
        StartCoroutine(Post (url));
public void ParamPost (string key, string value) {
+
    }
paramPostForm.AddField(key, value);
+
    public void ParamPost (string key, string value) {
}
+
        paramPostForm.AddField(key, value);
IEnumerator Post (string url) {
+
    }
request = UnityWebRequest.Post(url, paramPostForm);
+
    IEnumerator Post (string url) {
request.downloadHandler = new DownloadHandlerBuffer();
+
        request = UnityWebRequest.Post(url, paramPostForm);
request.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
+
        request.downloadHandler = new DownloadHandlerBuffer();
request.method = UnityWebRequest.kHttpVerbPOST;
+
        request.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
request.timeout = timeout;
+
        request.method = UnityWebRequest.kHttpVerbPOST;
Debug.Log ("WebHttpRequest Post timeout=" + timeout);
+
        request.timeout = timeout;
 +
        Debug.Log ("WebHttpRequest Post timeout=" + timeout);
 
         yield return request.Send();
 
         yield return request.Send();
 
         retryNum = 0;
 
         retryNum = 0;
if (request.isNetworkError) {
+
        if (request.isNetworkError) {
Debug.Log("WebHttpRequest Post " + request.error);
+
            Debug.Log("WebHttpRequest Post " + request.error);
if (request.error.Equals ("Request timeout")) {
+
            if (request.error.Equals ("Request timeout")) {
 
                 retryNum++;
 
                 retryNum++;
 
                 if (retryNum < retry) {
 
                 if (retryNum < retry) {
 
                     Debug.Log ("WebHttpRequest Post " + request.error + " retryNum= "+retryNum);
 
                     Debug.Log ("WebHttpRequest Post " + request.error + " retryNum= "+retryNum);
Exec (url); // IEnumerator Get(url) メソッドへ
+
                    Exec (url); // IEnumerator Get(url) メソッドへ
} else {
+
                } else {
errorFlag = true;
+
                    errorFlag = true;
// メインスレッドへ戻す
+
                    // メインスレッドへ戻す
context.Post(d =>
+
                    context.Post(d =>
{
+
                    {
if (callbacks != null)
+
                        if (callbacks != null)
{
+
                        {
callbacks(ResponseType.NetworkError);
+
                            callbacks(ResponseType.NetworkError);
}
+
                        }
}, null);
+
                    }, null);
}
+
                }
} else {
+
            } else {
Debug.Log ("WebHttpRequest Post " + request.error);
+
                Debug.Log ("WebHttpRequest Post " + request.error);
errorFlag = true;
+
                errorFlag = true;
// メインスレッドへ戻す
+
                // メインスレッドへ戻す
context.Post(d =>
+
                context.Post(d =>
{
+
                {
if (callbacks != null)
+
                    if (callbacks != null)
{
+
                    {
callbacks(ResponseType.NetworkError);
+
                        callbacks(ResponseType.NetworkError);
}
+
                    }
}, null);
+
                }, null);
}
+
            }
} else {
+
        } else {
if (request.responseCode == 200) {
+
            if (request.responseCode == 200) {
Debug.Log ("WebHttpRequest Post success" + request.responseCode);
+
                Debug.Log ("WebHttpRequest Post success" + request.responseCode);
text = request.downloadHandler.text;
+
                text = request.downloadHandler.text;
Debug.Log("WebHttpRequest Post " + text);
+
                Debug.Log("WebHttpRequest Post " + text);
// メインスレッドへ戻す
+
                // メインスレッドへ戻す
context.Post(d =>
+
                context.Post(d =>
{
+
                {
if (callbacks != null)
+
                    if (callbacks != null)
{
+
                    {
callbacks(ResponseType.Success);
+
                        callbacks(ResponseType.Success);
}
+
                    }
}, null);
+
                }, null);
} else {
+
            } else {
errorFlag = true;
+
                errorFlag = true;
Debug.Log ("WebHttpRequest Post failed request.responseCode=" + request.responseCode);
+
                Debug.Log ("WebHttpRequest Post failed request.responseCode=" + request.responseCode);
// メインスレッドへ戻す
+
                // メインスレッドへ戻す
context.Post(d =>
+
                context.Post(d =>
{
+
                {
if (callbacks != null)
+
                    if (callbacks != null)
{
+
                    {
callbacks(ResponseType.Failure);
+
                        callbacks(ResponseType.Failure);
}
+
                    }
}, null);
+
                }, null);
}
+
            }
}
+
        }
}
+
    }
public string GetBody() {
+
    public string GetBody() {
return text;
+
        return text;
}
+
    }
public void Reset() {
+
    public void Reset() {
text = "";
+
        text = "";
errorFlag = false;
+
        errorFlag = false;
paramPostForm = new WWWForm();
+
        paramPostForm = new WWWForm();
}
+
    }
public string GetError()
+
    public string GetError()
 
     {
 
     {
if (request != null && request.error != null)
+
        if (request != null && request.error != null)
 
         {
 
         {
return request.error;
+
            return request.error;
}
+
        }
return "";
+
        return "";
}
+
    }
 
}
 
}
 
</pre>
 
</pre>
行274: 行274:
 
#unity/build setting/ios/other setting/Configuration
 
#unity/build setting/ios/other setting/Configuration
 
#Allow downloads over HTTPをチェック
 
#Allow downloads over HTTPをチェック
 +
#Supported URL schemesのSizeに1を入れ、許可するドメイン"project1.example.net"などを入れる
  
 
チェックをつけると以下警告が出る
 
チェックをつけると以下警告が出る
行320: 行321:
 
     </array>
 
     </array>
 
</pre>
 
</pre>
 +
 +
====iosで、"Malformed URL"エラーになるとき====
 +
エラー詳細
 +
WebHttpRequest Get request.error=Malformed URL
 +
たとえば、urlが
 +
ttps://example.com/unityapi/statusread?uids[]=1515&uids[]=1130
 +
のように、パラメータに"[]"を含むとurl形式エラーとなるみたい。"[]"を"%5B%5D"でエンコードしてあげると、うまくいく。

2024年9月17日 (火) 04:01時点における最新版

Httpリクエストサンプル

以下delegateを使ったhttpリクエストサンプルコード

  • WebHttpRequest.cs
using System.Collections;
using System.Threading;
using UnityEngine;
using UnityEngine.Networking;

public class WebHttpRequest : MonoBehaviour {
    string text = "";
    private int retry = 10;
    public bool errorFlag = false;
    private int timeout = 2;
    // 現在のretry回数
    private int retryNum = 0;
    UnityWebRequest request;
    SynchronizationContext context;
    WWWForm paramPostForm;
    public enum ResponseType
    {
        Success,
        Failure,
        NetworkError
    }
    public delegate void CustomCallback(ResponseType responseType);
    private CustomCallback callbacks;
    public void AddCallback(CustomCallback callback)
    {
        callbacks += callback;
    }
    public void Init () {
        Debug.Log ("WebHttpRequest.Init()");
        paramPostForm = new WWWForm ();
    }
    public void setTimeout(int sec) {
        timeout = sec;
    }
    public void setRetry(int tmpRetry)
    {
        retry = tmpRetry;
    }
    public int getRetryNum() {
        return retryNum;
    }
    public void Exec (string url) {
        text = "";
        errorFlag = false;
        context = SynchronizationContext.Current; // メインスレッドでcontextを設置
        StartCoroutine(Get(url));
    }
    IEnumerator Get (string url) {
        request = new UnityWebRequest();
        request.downloadHandler = new DownloadHandlerBuffer();
        request.url = url;
        request.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
        request.method = UnityWebRequest.kHttpVerbGET;
        request.timeout = timeout;
        Debug.Log ("WebHttpRequest Get timeout=" + timeout);
        yield return request.Send();
        retryNum = 0;
        if (request.isNetworkError) {
            Debug.Log("request.isNetworkError request.error=" + request.error);
            if (request.error.Equals ("Request timeout")) {
                retryNum++;
                if (retryNum < retry) {
                    Debug.Log ("WebHttpRequest Get timeout " + request.error + " retryNum = "+retryNum);
                    Exec (url); // IEnumerator Get(url) メソッドへ
                } else {
                    errorFlag = true;
                    // メインスレッドへ戻す
                    context.Post(d =>
                    {
                        if (callbacks != null)
                        {
                            callbacks(ResponseType.NetworkError);
                        }
                    }, null);
                }
            } else {
                Debug.Log ("WebHttpRequest Get request.error=" + request.error);
                errorFlag = true;
                // メインスレッドへ戻す
                context.Post(d =>
                {
                    if (callbacks != null)
                    {
                        callbacks(ResponseType.NetworkError);
                    }
                }, null);
            }
        } else {
            if (request.responseCode == 200) {
                Debug.Log ("WebHttpRequest Get success request.responseCode=" + request.responseCode);
                text = request.downloadHandler.text;
                Debug.Log("WebHttpRequest Get text=" + text);
                // メインスレッドへ戻す
                context.Post(d =>
                {
                    if (callbacks != null)
                    {
                        callbacks(ResponseType.Success);
                    }
                }, null);
            } else {
                errorFlag = true;
                Debug.Log ("WebHttpRequest Get failed" + request.responseCode);
                // メインスレッドへ戻す
                context.Post(d =>
                {
                    if (callbacks != null)
                    {
                        callbacks(ResponseType.Failure);
                    }
                }, null);
            }
        }
    }
    public void ExecPost (string url) {
        text = "";
        errorFlag = false;
        context = SynchronizationContext.Current; // メインスレッドでcontextを設置
        StartCoroutine(Post (url));
    }
    public void ParamPost (string key, string value) {
        paramPostForm.AddField(key, value);
    }
    IEnumerator Post (string url) {
        request = UnityWebRequest.Post(url, paramPostForm);
        request.downloadHandler = new DownloadHandlerBuffer();
        request.SetRequestHeader("Content-Type", "application/json; charset=UTF-8");
        request.method = UnityWebRequest.kHttpVerbPOST;
        request.timeout = timeout;
        Debug.Log ("WebHttpRequest Post timeout=" + timeout);
        yield return request.Send();
        retryNum = 0;
        if (request.isNetworkError) {
            Debug.Log("WebHttpRequest Post " + request.error);
            if (request.error.Equals ("Request timeout")) {
                retryNum++;
                if (retryNum < retry) {
                    Debug.Log ("WebHttpRequest Post " + request.error + " retryNum= "+retryNum);
                    Exec (url); // IEnumerator Get(url) メソッドへ
                } else {
                    errorFlag = true;
                    // メインスレッドへ戻す
                    context.Post(d =>
                    {
                        if (callbacks != null)
                        {
                            callbacks(ResponseType.NetworkError);
                        }
                    }, null);
                }
            } else {
                Debug.Log ("WebHttpRequest Post " + request.error);
                errorFlag = true;
                // メインスレッドへ戻す
                context.Post(d =>
                {
                    if (callbacks != null)
                    {
                        callbacks(ResponseType.NetworkError);
                    }
                }, null);
            }
        } else {
            if (request.responseCode == 200) {
                Debug.Log ("WebHttpRequest Post success" + request.responseCode);
                text = request.downloadHandler.text;
                Debug.Log("WebHttpRequest Post " + text);
                // メインスレッドへ戻す
                context.Post(d =>
                {
                    if (callbacks != null)
                    {
                        callbacks(ResponseType.Success);
                    }
                }, null);
            } else {
                errorFlag = true;
                Debug.Log ("WebHttpRequest Post failed request.responseCode=" + request.responseCode);
                // メインスレッドへ戻す
                context.Post(d =>
                {
                    if (callbacks != null)
                    {
                        callbacks(ResponseType.Failure);
                    }
                }, null);
            }
        }
    }
    public string GetBody() {
        return text;
    }
    public void Reset() {
        text = "";
        errorFlag = false;
        paramPostForm = new WWWForm();
    }
    public string GetError()
    {
        if (request != null && request.error != null)
        {
            return request.error;
        }
        return "";
    }
}

呼び出し元

  • NewBehaviourScript.cs
public class NewBehaviourScript : MonoBehaviour {
    WebHttpRequest request;
    // http送信
    void Start () {
        const string uri = "http://raw.githubusercontent.com/nlohmann/json/develop/test/data/json.org/1.json";
        string param1 = "value1";
        param1 = WWW.EscapeURL(param1);
        string query = "?hoge=" + param1;
        string url = uri + query;
        GameObject gameObj = new GameObject();
        request = gameObj.AddComponent<WebHttpRequest>();
        request.AddCallback(OnResponse);
        request.Exec(url);
        Debug.Log("request=" + url);
    }
    // httpのresponse受信
    public void OnResponse(WebHttpRequest.ResponseType responseType)
    {
        Debug.Log("OnResponse=" + responseType);
        if (request)
        {
            if (responseType.Equals(WebHttpRequest.ResponseType.Success))
            {
            Debug.Log("body=" + request.GetBody());
            } else if (responseType.Equals(WebHttpRequest.ResponseType.Failure)) {
                Debug.Log("errorFlag=" + request.errorFlag);
		if (!request.GetError().Equals(""))
		{
			Debug.Log(request.GetError()); // 例:huawei android端末(SSL CA certificate error
		}
            }
            else if (responseType.Equals(WebHttpRequest.ResponseType.NetworkError))
            {
                Debug.Log("NetworkError" + request.errorFlag);
		if (!request.GetError().Equals(""))
		{
			Debug.Log(request.GetError()); // 例:huawei android端末(SSL CA certificate error
		}
            }
            request.Reset();
        }
    }
}

http通信許可

android

android9でhttp通信ができなくなってる。

取り急ぎhttp通信を対応したい場合 AndroidManifest.xmlのapplicationに以下属性追加

android:usesCleartextTraffic="true"

https://ameblo.jp/znky/entry-12459683348.html

ios

  1. unity/build setting/ios/other setting/Configuration
  2. Allow downloads over HTTPをチェック
  3. Supported URL schemesのSizeに1を入れ、許可するドメイン"project1.example.net"などを入れる

チェックをつけると以下警告が出る

You are using download over http. Currently Unity adds NSAllowsArbitraryLoads to Info.plist to simplify transition, but it will be removed soon. Please consider updating to https.

それでも、http通信時、以下が出る時

The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.

Info.plistへ以下を追加

    <key>NSAppTransportSecurity</key>
    <dict>
      <key>NSAllowsArbitraryLoads</key>
      <true />
      <key>NSAllowsArbitraryLoadsInWebContent</key>
      <true />
      <key>NSExceptionDomains</key>
      <dict>
          <key>project1.example.net</key>
          <dict>
              <key>NSIncludesSubdomains</key>
              <true />
              <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
              <true />
          </dict>
      </dict>

project1.example.netは適宜変更

参考:https://clevertap.com/blog/developing-for-ios9-app-transport-security/

補足

unityのiosの設定のAllow downloads over HTTPの下にあるSizeに1を入力しSchemaに、接続するドメイン(project1.example.netなど)を追加しても、以下が追加されるだけで、NSExceptionDomainsではないので、機能しない。

    <key>CFBundleURLTypes</key>
    <array>
      <dict>
        <key>CFBundleURLName</key>
        <string></string>
        <key>CFBundleURLSchemes</key>
        <array>
          <string>project1.example.net</string>
        </array>
      </dict>
    </array>

iosで、"Malformed URL"エラーになるとき

エラー詳細

WebHttpRequest Get request.error=Malformed URL

たとえば、urlが ttps://example.com/unityapi/statusread?uids[]=1515&uids[]=1130 のように、パラメータに"[]"を含むとurl形式エラーとなるみたい。"[]"を"%5B%5D"でエンコードしてあげると、うまくいく。