実現する事
Unity Cloud Buildの最終ビルドをWebページ公開
- ビルドされたすべてのプラットフォームの最終ビルドを表示
- WebなのでPC、スマホ問わず確認可能です
必要なもの
- PHPが使えるサーバー
- Cloud BuildのApi Key
- Organization ID
- Project ID
使用上の注意
URLを知っていれば誰でも見れます。
URLの流出に注意が必要です。
対策として、BASIC認証を設定したり、Webでは表示せずアプリ上からダウンロードリンクを取得してアプリからのみリンクを開く事も可能です。
各IDの取得
Unityのコンソールから各値を取得します。
Cloud BuildのApi Key取得
DevOps > Settings > API Settings
Organization IDの取得
Projects > Organaization Settings > Organization details
Project IDの取得
Projects > Project Settings > Project details
ソース
下記、2つのソースをサーバーに設置してindex.html
にアクセスするだけです。
例えば、サーバーのapp
ディレクトリに設置した場合は、https://xxx.com/app/
がURLになります。2つのファイルは同じディレクトリに配置してください。
getLatest.php
の書き換える箇所
取得したIDを設定してください。
field | 説明 |
---|---|
API_KEY | Cloud BuildのApi Keyを設定 |
ORGANIZATION_ID | Organization IDを設定 |
PROJECT_ID | Project IDを設定 |
FAILURE_MESSAGE | 取得失敗時のエラーメッセージを設定 |
<?
const API_KEY = '';
const ORGANIZATION_ID = '';
const PROJECT_ID = '';
const FAILURE_MESSAGE = '取得に失敗しました。時間を空けてお試しください。';
// エラーを画面に表示しない
ini_set('display_errors', 0);
ini_set('display_startup_errors', 0);
try
{
$headers =
[
'Content-Type: application/x-www-form-urlencoded',
'Authorization: Basic ' . API_KEY
];
$context = stream_context_create([
'http' => [
'method' => 'GET',
'header' => implode("\r\n", $headers),
'ignore_errors' => true
]
]);
$response = new Responses();
$response->infos = [];
// 各プラットフォームの最終ビルド情報の取得
$buids = file_get_contents('https://build-api.cloud.unity3d.com/api/v1/orgs/' . ORGANIZATION_ID . '/projects/' . PROJECT_ID . '/buildtargets?include_last_success=true', false, $context);
if (strpos($http_response_header[0], '200') !== false)
{
// ビルド情報からシェア情報の取得
$buidObjs = json_decode($buids, true, 512, JSON_THROW_ON_ERROR);
for ($i=0; $i < count($buidObjs); $i++)
{
$buidObj = $buidObjs[$i];
$resShare = file_get_contents('https://build-api.cloud.unity3d.com/api/v1/orgs/' . ORGANIZATION_ID . '/projects/' . PROJECT_ID . '/buildtargets/' . $buidObj['buildtargetid'] . '/builds/' . $buidObj["builds"][0]['build'] . '/share', false, $context);
if (strpos($http_response_header[0], '200') !== false)
{
$resShareJson = json_decode($resShare, true, 512, JSON_THROW_ON_ERROR);
$obj = new Response();
$obj->platform = $buidObj['platform'];
$obj->platformName = ConvertToPlatformName($buidObj['platform']);
$obj->shareUrl = 'https://developer.cloud.unity3d.com/share/share.html?shareId=' . $resShareJson['shareid'];
$obj->finished = $buidObj['builds'][0]['finished'];
$obj->build = $buidObj['builds'][0]['build'];
$response->infos[] = $obj;
}
else
{
throw new WebAPIException(FAILURE_MESSAGE);
}
}
}
else
{
throw new WebAPIException(FAILURE_MESSAGE);
}
// Jsonとして書き出し
header('Content-Type: application/json; charset=utf-8');
echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
}
catch (Exception $e)
{
echo $e->getMessage();
exit();
}
function ConvertToPlatformName($current)
{
switch ($current)
{
case 'ios':
return 'iPhone';
case 'android':
return 'Android';
default:
return $current;
}
}
class Responses
{
public $infos;
}
class Response
{
public $platform;
public $platformName;
public $shareUrl;
public $build;
public $finished;
}
class WebAPIException extends Exception
{
public function __construct($msg){
parent::__construct($msg, 800);
}
}
<!doctype html>
<html lang="jp">
<head>
<meta charset="utf-8">
<title>Download App</title>
<meta name="description" content="ダウンロード">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex"><!-- クローラ-の巡回拒否 -->
<style type="text/css">
body, input, textarea
{
font-family: "游ゴシック Medium", "Yu Gothic Medium", "游ゴシック体", "YuGothic", "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", "メイリオ", "Meiryo", "verdana", sans-serif;
}
h1
{
text-align: center;
font-size: 25px;
margin-bottom: 35px;
}
a
{
color: #1669a6;
text-decoration: none;
}
ul, ol
{
background: #fcfcfc;
padding: 0.5em 0.5em 0.5em 2em;
border: solid 3px gray;
}
ul li, ol li
{
line-height: 1.5;
padding: 0.5em 0;
}
#wrap
{
max-width: 350px;
margin-left: auto;
margin-right: auto;
padding: 2em;
}
#wrap p
{
font-size: 13px;
}
#loading
{
position: absolute;
left: 0; top: 0;
width: 100%; height: 100%;
background: white;
z-index: 2147483647;
}
#loading p
{
text-align: center;
margin: 0;
position: absolute;
top: 50%;
left: 50%;
margin-right: -50%;
transform: translate(-50%, -50%)
}
#loading span
{
font-size: 3em;
display: inline-block;
background-color: #dcdcdc;
margin: 0;
animation: loading .7s infinite alternate;
}
#loading span:nth-child(2) { animation-delay: .1s; }
#loading span:nth-child(3) { animation-delay: .2s; }
#loading span:nth-child(4) { animation-delay: .3s; }
#loading span:nth-child(5) { animation-delay: .4s; }
#loading span:nth-child(6) { animation-delay: .5s; }
#loading span:nth-child(7) { animation-delay: .6s; }
#loading span:nth-child(8) { animation-delay: .7s; }
#loading span:nth-child(9) { animation-delay: .8s; }
#loading span:nth-child(10) { animation-delay: .9s; }
@keyframes loading
{
0% { transform: scale(1.2); }
100% { transform: scale(0.8); }
}
</style>
</head>
<body>
<div id="loading"><p><span>N</span><span>O</span><span>W</span><br><span>L</span><span>O</span><span>A</span><span>D</span><span>I</span><span>N</span><span>G</span></p></div>
<div id="wrap">
<h1>ダウンロード</h1>
<ul id="results"></ul>
<p id="mobileMsg">※iPhoneはSafari、AndroidはChromeで開いてください。</p>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script>
$(function()
{
$.ajax('getLatest.php',
{
type: 'get',
dataType: 'json'
}
)
// [検索成功]
.done(function(data)
{
let $results = $("#results");
if(data == null
|| data.infos == null
|| data.infos.length <= 0)
{
$results.append($("<li>").text("ビルドがありません。"));
$("#mobileMsg").css("display", "none");
return;
}
let isMobile = false;
for (let i = 0; i < data.infos.length; i++)
{
let info = data.infos[i];
let date = new Date(info.finished);
let li = $("<li>");
let a = $("<a>").attr("href", info.shareUrl).text(info.platformName + " #" + info.build + " (" + date.toLocaleDateString() + "更新)");
$results.append(li.append(a));
if(info.platform == "ios" || "android")
{
isMobile = true;
}
}
if(!isMobile)
{
$("#mobileMsg").css("display", "none");
}
$("#loading").fadeOut(200);
})
// [検索失敗]
.fail(function(XMLHttpRequest, textStatus, errorThrown)
{
$("#loading > p").html("取得の失敗<br>[" + XMLHttpRequest.responseText + "]<br>" + textStatus + "<br>" + errorThrown.message);
});
});
</script>
</html>
表示する内容をカスタマイズしたい!
Unity Cloud Build API
サイトで簡単に取得テストできます。ここでテストしてカスタマイズ内容が決まったらgetLatest.php
を修正してください。
Unity Cloud Build APIの概要
SwaggerベースのREST APIです。
端的に説明すると、特定の決まったURLにアクセスする事で情報を取得したり、ビルドを走らせたりする事ができます。
現在の取得の流れ
適応方法
テストで取得したい内容が確定するとURLが確定します。そのURLにアクセスする事で情報が取得できます。
getLatest.php
のURLを置き換えてください。
'https://build-api.cloud.unity3d.com/api/v1/orgs/' . ORGANIZATION_ID . '/projects/' . PROJECT_ID . '/buildtargets?include_last_success=true
テスト手順
1. サイトトップにAPI Keyを入力
2. 左のリストから実行したい内容を選択
3. 項目を入力してリクエスト
下記は、読み替えてください。
サイト上 | 実際の名称 |
---|---|
orgid | Organization ID |
projectid | Project ID |
Webでは表示したくない
index.html
を削除
アプリ内(Unity上)から取得
下記コードをAssets配下に保存
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public static class CloudBuildHelper
{
[Serializable]
public class BuildInfos
{
public BuildInfo[] infos;
public override string ToString()
{
var msg = $"{GetType().Name} -\n";
if (infos.Length > 0)
{
foreach (var info in infos)
{
msg += $"{info}\n";
}
}
else
{
msg += "ビルドがありません。";
}
return msg;
}
}
[Serializable]
public class BuildInfo
{
public string platform;
public string platformName;
public string shareUrl;
public int build;
public string finished;
public override string ToString() => JsonUtility.ToJson(this, true);
}
public static IEnumerator GetLatestBuildInfos(string uri, Action<BuildInfos> successAction, Action<string> failedAction)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
yield return webRequest.SendWebRequest();
if (webRequest.result == UnityWebRequest.Result.Success
&& !string.IsNullOrEmpty(webRequest.downloadHandler.text))
{
var obj = JsonUtility.FromJson<BuildInfos>(webRequest.downloadHandler.text);
if (obj != default
&& obj.infos.Length > 0)
{
foreach (var info in obj.infos)
{
if (DateTime.TryParse(info.finished, out DateTime dateTime))
{
info.finished = dateTime.ToString("yyyy/MM/dd");
}
}
successAction?.Invoke(obj);
}
else
{
failedAction?.Invoke($"Error: ダウンロードした内容を展開できませんでした。管理者にお問合せください。\n{webRequest.downloadHandler.text}");
}
}
else
{
failedAction?.Invoke($"Error: {webRequest.error}");
}
}
}
}
下記の形で利用できます。
第一引数にgetLatest.php
のURLを設定してください。
StartCoroutine(CloudBuildHelper.GetLatestBuildInfos(
"https://xxxxx.com/getLatest.php",
response =>
{
// 成功した場合
// 下記の形で取得できます。
// response.infos[0].platform;
// response.infos[0].platformName;
// response.infos[0].shareUrl;
// response.infos[0].build;
// response.infos[0].finished;
// [確認用] Json形式で一覧書き出し
Debug.Log(response);
},
error =>
{
// 失敗した場合
}));
Console: [確認用] Json形式で一覧書き出し
{
"platform": "ios",
"platformName": "iPhone",
"shareUrl": "https://developer.cloud.unity3d.com/share/share.html?shareId=xxxxx",
"build": 44,
"finished": "2022/02/10"
}
{
"platform": "android",
"platformName": "Android",
"shareUrl": "https://developer.cloud.unity3d.com/share/share.html?shareId=xxxxx",
"build": 39,
"finished": "2022/02/10"
}