「Unity/Csharp/Request」の版間の差分
提供: 初心者エンジニアの簡易メモ
(→Httpリクエストサンプル) |
(→iosで、"Malformed URL"エラーになるとき) |
||
(同じ利用者による、間の37版が非表示) | |||
行1: | 行1: | ||
==Httpリクエストサンプル== | ==Httpリクエストサンプル== | ||
− | + | 以下delegateを使ったhttpリクエストサンプルコード | |
− | + | *WebHttpRequest.cs | |
− | + | <pre> | |
− | + | using System.Collections; | |
− | + | using System.Threading; | |
− | + | using UnityEngine; | |
− | + | using UnityEngine.Networking; | |
+ | |||
+ | public class WebHttpRequest : MonoBehaviour { | ||
string text = ""; | string text = ""; | ||
+ | private int retry = 10; | ||
public bool errorFlag = false; | 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) { | 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.responseCode == 200) { | + | 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 ""; | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | 呼び出し元 | ||
+ | *NewBehaviourScript.cs | ||
+ | <pre> | ||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | ==http通信許可== | ||
+ | |||
+ | ===android=== | ||
+ | android9でhttp通信ができなくなってる。 | ||
+ | |||
+ | 取り急ぎhttp通信を対応したい場合 | ||
+ | AndroidManifest.xmlのapplicationに以下属性追加 | ||
+ | android:usesCleartextTraffic="true" | ||
+ | |||
+ | https://ameblo.jp/znky/entry-12459683348.html | ||
+ | |||
+ | ===ios=== | ||
+ | |||
+ | #unity/build setting/ios/other setting/Configuration | ||
+ | #Allow downloads over HTTPをチェック | ||
+ | #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へ以下を追加 | ||
+ | <pre> | ||
+ | <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> | ||
+ | </pre> | ||
+ | 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ではないので、機能しない。 | ||
+ | |||
+ | <pre> | ||
+ | <key>CFBundleURLTypes</key> | ||
+ | <array> | ||
+ | <dict> | ||
+ | <key>CFBundleURLName</key> | ||
+ | <string></string> | ||
+ | <key>CFBundleURLSchemes</key> | ||
+ | <array> | ||
+ | <string>project1.example.net</string> | ||
+ | </array> | ||
+ | </dict> | ||
+ | </array> | ||
+ | </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
- unity/build setting/ios/other setting/Configuration
- Allow downloads over HTTPをチェック
- 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"でエンコードしてあげると、うまくいく。