同社の業務上の必要により、「菜の花」とHTTPプロトコルインターフェースのドッキング作業が行われました。
Http プロトコルに完全に独立して接続するのはこれが初めてであり、外部プロトコルに接続するのも初めてであるため、そのプロセスで遭遇した主なキー ポイントと落とし穴がここに記録されます。今後のお問い合わせのために残しておきます。
1. Decimal 型のデータと精度の問題
10進数型のデータが実際に使われるのは今回が初めてで、一般的に精度が高く、金融や金銭の計算に適しています。詳しくは、 こちらの記事 を参照してください。
ここで Decimal について言及する理由は主にピットを踏むためであり、これは Json 化時のシリアル化操作にも関係します。ここでは、 Unity 独自の ではなく、 Newtonsoft
プラグインをシリアル化操作に使用しています。その理由は、このタイプのデータをサポートできないようであり、このタイプを使用すると精度が大幅に低下するためです。たとえば、次のようになります。データの処理中 シリアル化後、次のような結果が表示される場合があります。ただし、Decimal 型データを使用すると精度の問題は解決できますが、さらに難しい問題がまだあります。つまり、シリアル化する場合、Decimal はデフォルトで少なくとも 1 つの小数点を保持します。つまり、それが整数であってもです。 、連載後は とも表示されます。問題は、署名暗号化の必要性により、この Decimal 型データが演算を実行し、その後に表示されるスタイルがシリアル化で表示されるスタイルと同じであることが保証されていることです。質問は次のとおりです。JsonUtility
JsonUtility
Decimal
Float
1.0f
0.9998641
5m
5.0
ToString()
ToString()
decimal a = 5M;
Debug.Log(a.ToString()); // 显示结果为 5
Debug.Log(a.ToString("#.#")); // 显示结果为 5.0 但是遇到 a = 1.23 的情况也只能显示 1.2
解決:
// 对 Decimal 进行扩展
public static class DeciamlExtension
{
/// <summary>
/// Decimal 扩展方法
/// 由于 Decimal 在转换为 json 格式时默认至少保留 1 位小数,
/// 例如:decimal num = 1 在转换成 json 后就是 1.0
/// 为了在 ToString 时和 json 保持一致,添加此扩展方法
/// </summary>
/// <param name="data"></param>
/// <param name="scale"></param>
/// <returns></returns>
public static string ToString_JsonStyle(this decimal data)
{
string strData = data.ToString();
// 获取小数点的位置,当无法获取到小数点时即数据为整数时,index = -1
int index = strData.IndexOf(".");
// 获取数据的总长度
int dataLength = strData.Length;
if (index != -1)
{
// 对小数点前后的数字进行重新拼接
return string.Format("{0}.{1}", strData.Substring(0, index), strData.Substring(index + 1, dataLength - index - 1));
}
else
{
// 当小数点不存在时,默认显示小数点后一位
return string.Format("{0}.0", strData);
}
}
}
2. 13ビットタイムスタンプの取得方法について
値をミリ秒に換算したタイムスタンプは 13 桁で、秒のみを取得した場合は 10 桁になります。一般に、システムは 13 ビットまたは 10 ビットのいずれかを必要とします。
タイムスタンプ: タイムスタンプは、グリニッジ標準時 1970 年 1 月 1 日の 00:00:00 (北京時間 1970 年 1 月 1 日 08:00:00) から現在までの合計秒数を指します。平たく言えば、タイムスタンプは、特定の時点でデータが存在していたことを示す、完全で検証可能なデータです。その提案は主に、ユーザーの特定のデータの生成時間を証明する電子証拠をユーザーに提供することです。実用化では電子商取引や金融活動などさまざまな場面で利用でき、特に公開鍵基盤の「否認防止」サービスのサポートに利用できる。
1 秒 = 1000 ミリ秒
1 ミリ秒 = 1000 マイクロ秒
1 マイクロ秒 = 1000 ナノ秒
1 ミリ秒 = 1000000 ナノ秒
DateTime.Ticks は、0001 年 1 月 1 日の午前 12:00:00 から経過した 100 ナノ秒の数を表します。つまり、Ticks のプロパティは 100 ナノ秒 (1 Ticks = 0.0001 ミリ秒) です。
// 设置初始时间
public DateTime StartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0);
// 获取 13 位时间戳
public string GetTimeStamp()
{
// 获取当前时间
DateTime endTime = System.DateTime.UtcNow;
// 获取时间差值(时间戳)
TimeSpan timeSpan = endTime - StartTime;
// 返回 13 位时间戳
return (timeSpan.Ticks / 10000).ToString();
}
3. Http PostアクセスにJson型データを使用する
Http にはさまざまなリクエストメソッドがあり、Post メソッドを使用してアクセスする必要があります。
最新バージョンの Unity に基づいて、WWW クラスの使用は放棄され、より高度な UnityWebRequest に置き換えられました。
httpレスポンスヘッダ情報の設定には特に注意が必要ですので、「HTTPレスポンスヘッダ情報」と「HTTPコンテンツタイプ」の内容を参照して理解してください。
とりあえず、Unityにおけるこのレスポンスヘッダのデフォルト設定はこんな感じのようですが、SetRequestHeader("Content-Type", "application/json;charset=utf-8");
いくつか資料を確認したところ、基本的にはこの設定方法で、せいぜい一部がcharset=utf-8
削除する程度のようですSetRequestHeader("Content-Type", "application/json");
。それとも普段はこのように設定されているのでしょうか?
ただし、データを検討した結果、この特定の設定方法はサーバー側の構成にも関連している可能性があり、特定の調整が必要であることがわかりました。少なくとも今回はこの構成で問題ありません。
完全なコードは次のとおりです。
/// <summary>
/// Http 使用 Post 方式请求
/// </summary>
/// <param name="url"></param>
/// <param name="json"></param>
/// <param name="callback"></param>
public void SendPostRequest(string url, string json, Action<string> callback)
{
StartCoroutine(HttpPostRequest(url, json, callback));
}
// 使用协程调用 UnityWebRequest 进行 Http 通信
private IEnumerator HttpPostRequest(string url, string json, Action<string> callback)
{
// 将需要提交的数据转换为 UTF-8 编码的 byte 数组
byte[] dataBody = Encoding.UTF8.GetBytes(json);
// 创建 UnityWebRequest 实例
// 使用 using 关键字,可以让程序在结束任务后自动释放 UnityWebRequest 实例,防止内存泄漏
using (UnityWebRequest unityWebRequest = new UnityWebRequest(url, "POST"))
{
// UploadHander 用于控制数据的上传
unityWebRequest.uploadHandler = (UploadHandler)new UploadHandlerRaw(dataBody);
// 设置 http 响应头信息
unityWebRequest.SetRequestHeader("Content-Type", "application/json;charset=utf-8");
// DownloadHander 用于控制数据的下载
unityWebRequest.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer();
// 正式发送 http 请求
yield return unityWebRequest.SendWebRequest();
if (unityWebRequest.isHttpError || unityWebRequest.isNetworkError)
{
if (callback != null) callback(unityWebRequest.downloadHandler.text);
Debug.LogError("Http Error: " + unityWebRequest.error + "\n" + unityWebRequest.downloadHandler.text);
}
else
{
if (unityWebRequest.isDone)
{
if (callback != null) callback(unityWebRequest.downloadHandler.text);
}
else
{
Debug.LogError("Http 请求失败: " + unityWebRequest.error);
}
}
}
}
4. Android Q(Android 10)のHTTP接続不具合について
テスト パッケージを印刷した後、実際の Android デバイスにインストールすると次の問題が発生します。
Cleartext HTTP traffic to xxx.xxx.xxx.xx not permitted
ここで、 はxxx.xxx.xxx.xx
要求された http URL アドレスです。
問い合わせの結果、この問題は Android 9 (Android P) 以降に発生し始めたことが判明しました。ユーザー データとデバイスのセキュリティを確保するために、Android システム用の Google アプリケーション (Android P 以降のバージョン) ではデフォルトで暗号化された接続が必要になりますが、http ネットワーク リクエストでは暗号化されていないプレーンテキスト トラフィックが使用されます。
利用可能な解決策がいくつかあります。この記事を確認してください。
以下は比較的単純で大雑把な方法です。
AndroidManifest.xml 設定ファイルの<application>
タグに以下の内容を追加します。
android:usesCleartextTraffic="true
android:usesCleartextTraffic
アプリケーションがクリアテキスト HTTP などのクリアテキスト ネットワーク トラフィックを使用するかどうかを示します。API レベル 27 以下をターゲットとするアプリケーションのデフォルト値は「true」です。API レベル 28 以降をターゲットとするアプリのデフォルトは「false」です。
このプロパティが「false」に設定されている場合、プラットフォーム コンポーネント (HTTP および FTP スタック、DownloadManager および MediaPlayer など) は、クリアテキスト トラフィックを使用するアプリケーションのリクエストを拒否します。サードパーティのライブラリもこの設定を採用することを強くお勧めします。クリア テキスト通信を避ける主な理由は、機密性、信頼性、改ざん防止の欠如であり、サイバー攻撃者は送信データを盗聴したり、検出されずにデータを変更したりする可能性があります。
これまでのところ、より重要な問題について検討してきました。