Unity+Android+JenkinsでVersion番号を変えようと四苦八苦した話


# 前提

dev環境のアプリをJenkinsビルドするときは特にBundleVersionを変更していませんでした。

ただ、SmartBeat (http://smrtbeat.com/)
でクラッシュレポートを見る時、最新のバージョンでは直っているのか
まだ直っていないのか判別がつかないという問題が><
(SmartBeatではBundleVersionでエラーのフィルタリングが出来ます。)

これを解決する為にJenkinsでAndroidのVersionを弄りたい！
というのが前提になります。

## アプローチ1 AndroidManifest.xmlを弄る

jenkins-script/update-AndroidManifest.sh
https://github.com/eaglesakura/jenkins-script/blob/master/update-AndroidManifest.sh
こちらのshを使って軽い気持ちで変更を試みました。

が

"manifest not found!!"

そもそもUnityのProjectには自分で置かない限りAndroidManifest.xmlは
存在しないので変更のしようがなかった。。。

Assets/Plugins/Android/以下にAndroidManifest.xmlを置いて試してみました
UnityProjectがこれを上書きする為にBundleVersionを変更することはできませんでした。。。

## アプローチ2 PlayerSettingsを弄る

```rb:projectSettingChanger.rb
require 'yaml'

path = ARGV[0]
properties = YAML.load_file(path)

properties["PlayerSettings"]["iPhoneBundleVersion"] = ARGV[1]
properties["PlayerSettings"]["iPhoneShortBundleVersion"] = ARGV[1]

File::open(path , "w") do |f|
  YAML.dump(properties,f)
end
```
上のようなrubyを書いて、PlayerSettingsのyamlの改変を試してみました。

が

PlayerSettingsは改変できたものの、apkのBundleVersionは変更されていませんでした。

尚、perlのワンライナーでも変更自体は出来るようです。
(strings.xml内のアプリ名変更とかはこれでいける)

perl -pi -e "s/iPhoneBundleVersion: 1.0/iPhoneBundleVersion: 1.0.${BUILD_NUMBER}/" ProjectSettings/ProjectSettings.asset


## アプローチ3 apkを弄る

こうなったらapkを解凍して中のAndroidManifest.xmlを直接書き換えてやろうと思いましたが、
壊れたら嫌なので中止 ><


## アプローチ4 バッチコマンドでEditorから弄る

PlayerSettings.assetを直接弄るのではなく、正規の方法で変更すれば反映されるのでは？
ということで以下のようなEditorScriptを書きました。

```csharp
:ProjectSettingChanger.cs
using UnityEngine;
using UnityEditor;
using System.Collections;


public class ProjectSettingsChanger : Editor {

	public static void SetBundleVersion ()
	{
		var commands = System.Environment.GetCommandLineArgs ();
		int methodIndex = -1;
		for (int i = 0; i < commands.Length; i++) {
			if (commands [i] == "SetBundleVersion") {
				methodIndex = i;
			}
			Debug.Log (commands [i]);
		}
		var version = commands [methodIndex + 7];
		
		//SetVersion
		PlayerSettings.bundleVersion = version; 
		PlayerSettings.shortBundleVersion = version;
	}
}
```

これをJenkinsから↓のように呼べば！？
![スクリーンショット 2015-03-31 22.15.54.png](https://qiita-image-store.s3.amazonaws.com/0/8904/f1ad2245-a819-8100-37c7-fac9b2bfb52f.png)

変わらなかった。。。

絶望の中で見つけたこの記事
http://answers.unity3d.com/questions/394834/set-bundle-version-code-through-editor-script.html

もしかしたらEditorさんが忙しい時にversion変えてたからいけなかったのでは？
という予測から

```csharp:ProjectSettingChanger.cs改
public class ProjectSettingsChanger : Editor {

	public static void SetBundleVersion ()
	{
		var commands = System.Environment.GetCommandLineArgs ();
		int methodIndex = -1;
		for (int i = 0; i < commands.Length; i++) {
			if (commands [i] == "SetBundleVersion") {
				methodIndex = i;
			}
			Debug.Log (commands [i]);
		}
		var version = commands [methodIndex + 7];
		SetBundleVersion (version);
	}

	public static void SetBundleVersion(string version)
	{
		if (EditorApplication.isUpdating != true) 
		{
			SetVersion(version);
		}
		EditorApplication.update += () =>
		{
			SetVersion(version);
		;
	}

	public static void SetVersion(string version)
	{
		PlayerSettings.bundleVersion = version; 
		PlayerSettings.shortBundleVersion = version;
	}
}
```
↑のようにEditorに優しい作りにしてみたところ。。。

Versionが変更できていました(涙

#まとめ
UnityのことはUnity内でやろう。

あまりJenkinsのことを知らない状態から試行錯誤した為結構な時間がかかってしまいましたが、
Jenkinsとちょっと仲良くなれた気がします。