ipaファイルの中身を調べる

作成したipaファイルについて調べたいということってあったりしますよね？

 - Xcodeはどのバージョンでビルドされたの？
 - 求めているProvisioningProfileは使われたの？

ビルド時のログを追えば分かる点もありますが、必ずしもログがあるとは限らないですしipaファイルの中身を見ることが出来るようになっていると便利かと思います。


そこで今回は、ipaファイルの中身の軽いチェックの仕方について書きたいと思います。
こういう情報を知るとアプリの再署名などの理解が深まるかと思います。


## ipaファイル内のチェック対象
ipaファイルをunzipするとPayload/xxxx.appファイルがあります。
app内には色々なファイルがありますが、今回チェックするのは以下の2ファイル。

 - embedded.mobileprovision
 - Info.plist


### チェックするのに便利なツール
ipaファイルをunzipして、appファイルに対してcodesignコマンドやdefaultsコマンドを使って調べたりするというのも良いのですが、世には便利なツールが存在するのでそれを使ってしまうのが良いかとは思います。

今回は下記2ツールを紹介していますが、それ以外にも同様の機能をもつツールは存在します。

#### shenzhen
https://github.com/nomad/shenzhen

```:install
gem install shenzhen
```

```:command
ipa info xxxx.ipa
```

shenzhenはInfo.plistまでは出力してくれません。
ipaファイルを作ったりすることがメインですし、今回の目的に特化したツールというわけでもないですが、コマンドが短いので好きです。

 
#### ipa_analyzer
https://github.com/bitrise-io/ipa_analyzer

```:install
gem install ipa_analyzer
```

```:command
ipa_analyzer -i xxxx.ipa -p --info-plist --prov
```

ipa_analyzerはInfo.plistの中身まで出力(JSON pretty print)してくれるので機能としては豊富です。


## embedded.mobileprovisionのチェック
Payloadフォルダにあるappファイル内にはembedded.mobileprovisionファイルがあります。
これはビルド時に利用されたProvisioningProfileになります。

Xcode8のPROVISIONING_PROFILE_SPECIFIERの登場により、ProvisioningProfileの名前だけを指定すれば良くなったので、このファイルをチェックする機会は今後増えるかもしれません。


このファイルの中には様々な情報が含まれています。
shenzhenを使った出力結果の例は以下のとおりです。

```:出力例
+-----------------------------+--------------------------------------------------------------+
| AppIDName                   | AppIDの名前                                                  |
| ApplicationIdentifierPrefix | XXXXX                                                        |
| CreationDate                | 2016-12-17T11:05:31+00:00                                    |
| Platform                    | iOS                                                          |
| Entitlements                | keychain-access-groups: ["XXXXX.*"]                          |
|                             | get-task-allow: false                                        |
|                             | application-identifier: XXXXX-AppID                          |
|                             | com.apple.developer.team-identifier: XXXXX                   |
| ExpirationDate              | 2017-08-22T11:26:34+00:00                                    |
| Name                        | Provisioning Profileの名前                                    |
| ProvisionedDevices          | 端末のID一覧                                                  |
| TeamIdentifier              | TeamID                                                       |
| TeamName                    | TeamName                                                     |
| TimeToLive                  | 有効期限                                                      |
| UUID                        | UUID                                                         |
| Version                     | 1                                                            |
| Codesigned                  | True                                                         |
+-----------------------------+--------------------------------------------------------------+
```

### チェック対象
#### Entitlements
上記の出力例にはないのですが、APNsを利用している場合は以下も出力されます。

   - aps-environment: production

上記の場合だと、developmentではなくproductionを使っていることがわかります。


#### ProvisionedDevices
登録されている端末のID一覧が表示されます。

ProvisioningProfileの作成時にDevelopmentやDistribution(AdHoc)では端末を1つも指定せずに登録できないので、端末が1つも表示されない場合は、Distribution(AppStore)用に作成したものと考えられます。


アプリがインストール出来ないときに、インストールしたい端末のIDが含まれているかを確認したりします。
端末IDの確認方法も色々ありますが、[mobiledevice](https://github.com/imkira/mobiledevice)を使って以下のコマンドを使って確認したりしています。

```
mobiledevice list_devices
```


## Info.plistのチェック
Payloadフォルダにあるappファイル内にはInfo.plistファイルがあります。
アプリ作成時にInfo.plistに指定した情報以外も含まれています。

ipa_analyzerを使っての出力結果の例は以下のとおりです。
設定している情報が非常に少ないので出力されているものは少なめになっています。
//mobileprovisionのほうの情報は削除しています。

```:出力例
  "info_plist": {
    "path_in_ipa": "Payload/xxxx.app/Info.plist",
    "content": {
      "BuildMachineOSBuild": "15F34",
      "CFBundleDevelopmentRegion": "en",
      "CFBundleExecutable": "xxxx",
      "CFBundleIdentifier": "xxxx",
      "CFBundleInfoDictionaryVersion": "6.0",
      "CFBundleName": "xxxx",
      "CFBundlePackageType": "APPL",
      "CFBundleShortVersionString": "1.0.0",
      "CFBundleSignature": "????",
      "CFBundleSupportedPlatforms": [
        "iPhoneOS"
      ],
      "CFBundleVersion": "2",
      "DTCompiler": "com.apple.compilers.llvm.clang.1_0",
      "DTPlatformBuild": "14B72",
      "DTPlatformName": "iphoneos",
      "DTPlatformVersion": "10.1",
      "DTSDKBuild": "14B72",
      "DTSDKName": "iphoneos10.1",
      "DTXcode": "0810",
      "DTXcodeBuild": "8B62",
      "LSRequiresIPhoneOS": "true",
      "MinimumOSVersion": "8.0",
      "UIDeviceFamily": [
        1,
        2
      ],
      "UILaunchStoryboardName": "LaunchScreen",
      "UIMainStoryboardFile": "Main",
      "UIRequiredDeviceCapabilities": [
        "armv7"
      ],
      "UISupportedInterfaceOrientations": [
        "UIInterfaceOrientationPortrait",
        "UIInterfaceOrientationLandscapeLeft",
        "UIInterfaceOrientationLandscapeRight"
      ],
      "UISupportedInterfaceOrientations~ipad": [
        "UIInterfaceOrientationPortrait",
        "UIInterfaceOrientationPortraitUpsideDown",
        "UIInterfaceOrientationLandscapeLeft",
        "UIInterfaceOrientationLandscapeRight"
      ]
    }
  }
}
```

### チェック対象
#### DTXcode / DTXcodeBuild
DTXcodeはビルド時に利用されたXcodeのバージョンになります。
上記の場合だと0810となっており、8.1を表しています。

DTXcodeBuildはビルドしたXcodeのバージョン番号です。
XcodeのAbout Xcodeで表示されているカッコ内の値です。
最新のXcode8.2だと8C38になります。

DTXcodeはβ版においても0820のように表示されるので、DTXcodeBuildまで見るのが良いです。


#### BuildMachineOSBuild
アプリをビルドしたマシンのOSのバージョン番号になります。

番号については以下のサイトにのっています。

 - https://support.apple.com/ja-jp/HT201260


##### 蛇足
本件に関する蛇足になりますが、ある時点からipaファイルのファイルサイズが増えていました。
調べたところ、_CodeSignature/CodeResources内の値が増えておりhash2というkeyが増えていました。

どうもある時点のMacのOSバージョン以降だとその値が増えていたようです。


## 最後に
これで生成されたipaファイルの中身の確認ができます。
何かあったときに役に立つので活用してもらえると嬉しい限りです。

ちなみに私は、CI環境(Jenkins)でipaファイルを作り終えた後に上記の情報を全て取得しファイル出力させるようにしたりもしています。


今回は情報の見方だったわけですが、情報を変える方法も当然あります。
それは関連記事を見て頂ければと思います。

アプリのビルドにはどうしても時間がかかるので、1つベースとなるipaファイルを作成して設定だけを変えるといった手はよく使います。


## 関連記事
 - [再ビルドせずに設定を変える方法(iOS/Android)](http://qiita.com/tarappo/items/e3d9116af93fb11687f1)

 - 上記の記事のやり方にかぎらず、fastlaneに[resign](https://github.com/fastlane/fastlane/blob/master/fastlane/lib/fastlane/actions/resign.rb)というactionもあります。