facebook twitter hatena line email

Unity/Csharp/Request

提供: 初心者エンジニアの簡易メモ
移動: 案内検索

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"でエンコードしてあげると、うまくいく。