# 機能設計書 61-Androidワークロード

## 概要

本ドキュメントは、.NET RuntimeにおけるAndroidワークロード（Android Workload）機能の設計仕様を定義する。Androidワークロードは、Android向け.NETアプリケーション開発をサポートするための開発ツールキット群であり、.NETコードをAndroidデバイスやエミュレータで実行可能なAPKパッケージにビルドする機能を提供する。

### 本機能の処理概要

Androidワークロードは、.NET開発者がC#やF#で記述したコードをAndroidプラットフォーム上で実行するための包括的なビルドおよびランタイムサポートを提供する機能である。

**業務上の目的・背景**：モバイルアプリケーション市場においてAndroidは最大のシェアを持つプラットフォームである。.NET開発者がAndroid向けアプリケーションを開発するためには、.NETコードをAndroidネイティブコードに変換し、Android SDKと連携してAPKパッケージを生成する必要がある。Androidワークロードは、この複雑なビルドプロセスを抽象化し、.NET開発者が慣れ親しんだ開発環境でAndroidアプリケーションを開発できるようにする。

**機能の利用シーン**：
- .NET MAUIを使用したクロスプラットフォームモバイルアプリケーション開発
- Xamarin.Androidからの移行プロジェクト
- Android専用の.NETアプリケーション開発
- パフォーマンスが重要なモバイルゲームやエンタープライズアプリケーション開発

**主要な処理内容**：
1. MonoランタイムまたはCoreCLRを使用したAndroid向けアプリケーションの構築
2. AOT（Ahead-of-Time）コンパイルによるネイティブコード生成
3. Android SDK/NDKとの連携によるAPKパッケージ生成
4. アセンブリのバンドリングとネイティブライブラリのリンク
5. デバッグおよび診断機能のサポート（EventPipe、診断ポートなど）

**関連システム・外部連携**：
- Android SDK（aapt、d8/dx、zipalign、apksigner等のツール）
- Android NDK（ネイティブコードビルド用CMakeツールチェーン）
- Mono AOTコンパイラ（LLVMベースの事前コンパイル）
- NativeAOTランタイム（オプション）

**権限による制御**：本機能は開発ツールであり、実行時の権限制御はビルド対象のアプリケーション側で管理される。ビルドプロセス自体には特別な権限制御は存在しない。

## 関連画面

本機能は開発ツールであり、直接的なUI画面は提供しない。ただし、以下のサンプルアプリケーションが関連する。

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | AndroidSampleApp | 参照サンプル | Androidビルド機能のテストと検証用サンプル |

## 機能種別

ビルドタスク / 開発ツールキット

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| RuntimeIdentifier | string | Yes | ターゲットのRID（例：android-arm64） | android-arm/arm64/x64/x86のいずれか |
| AppDir | string | Yes | ビルド対象のアセンブリが含まれるディレクトリ | 存在するディレクトリパス |
| OutputDir | string | Yes | APK出力先ディレクトリ | 書き込み可能なパス |
| ProjectName | string | Yes | プロジェクト名 | スペースを含まない文字列 |
| MainLibraryFileName | string | No | エントリーポイントのDLLファイル名 | AppDir内に存在するファイル |
| AndroidSdk | string | No | Android SDKのパス | 環境変数ANDROID_SDK_ROOTでも設定可 |
| AndroidNdk | string | No | Android NDKのパス | 環境変数ANDROID_NDK_ROOTでも設定可 |
| MinApiLevel | string | No | 最小APIレベル（デフォルト：21） | 21以上の整数 |
| TargetApiLevel | string | No | ターゲットAPIレベル（デフォルト：31） | MinApiLevel以上 |
| ForceAOT | bool | No | AOTコンパイルを強制 | true/false |
| ForceFullAOT | bool | No | フルAOTモードを強制 | true/false |
| ForceInterpreter | bool | No | インタープリターモードを強制 | ForceAOTと排他 |
| RuntimeFlavor | string | No | ランタイムの種類（デフォルト：Mono） | Mono/CoreCLR/NativeAOT |
| StaticLinkedRuntime | bool | No | ランタイムを静的リンク | true/false |
| StripDebugSymbols | bool | No | デバッグシンボルを削除 | true/false |
| DiagnosticPorts | string | No | 診断ポート設定 | RuntimeComponentsにdiagnostics_tracingが必要 |

### 入力データソース

- MSBuildプロジェクトファイル（.csproj）からのビルドプロパティ
- 環境変数（ANDROID_SDK_ROOT、ANDROID_NDK_ROOT）
- NuGetパッケージとしてインストールされたランタイムパック

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ApkBundlePath | string | 生成されたAPKファイルのフルパス |
| ApkPackageId | string | APKのパッケージID（例：net.dot.ProjectName） |

### 出力先

- APKファイル：`{OutputDir}/bin/{ProjectName}.apk`
- ネイティブライブラリ：`{OutputDir}/lib/{abi}/libmonodroid.so`
- アセット：APK内の`assets/assets.zip`として圧縮バンドル

## 処理フロー

### 処理シーケンス

```
1. 入力パラメータの検証
   └─ RuntimeIdentifier、AppDir、Android SDK/NDKの存在確認
2. ビルドディレクトリの準備
   └─ OutputDir配下にbin、obj、assets、assets-tozipディレクトリを作成
3. アセットのバンドル
   └─ DLL等のマネージドアセンブリをassets.zipとして圧縮
4. ネイティブライブラリのビルド（CMake）
   └─ libmonodroid.soの生成（AOT済みコードを含む）
5. Javaソースのコンパイル
   └─ MainActivity.java、MonoRunner.javaをコンパイル
6. DEXファイルの生成
   └─ d8/dxツールでclassファイルをDEXに変換
7. APKの生成
   └─ aaptでAPKパッケージを作成
8. ネイティブライブラリの追加
   └─ .soファイルをAPKのlib/{abi}/に追加
9. APKのアライメント
   └─ zipalignでAPKを最適化
10. APKの署名
    └─ apksignerでデバッグキーを使用して署名
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[入力検証]
    B --> C{パラメータ有効?}
    C -->|No| D[エラー終了]
    C -->|Yes| E[ディレクトリ準備]
    E --> F[アセットバンドル]
    F --> G{LibraryMode?}
    G -->|Yes| H[外部ネイティブ依存のみ]
    G -->|No| I{NativeAOT?}
    I -->|Yes| J[NativeAOTバイナリ使用]
    I -->|No| K[CMakeでlibmonodroid.soビルド]
    H --> L[Javaコンパイル]
    J --> L
    K --> L
    L --> M[DEX生成]
    M --> N[APK作成]
    N --> O[ネイティブライブラリ追加]
    O --> P[APKアライメント]
    P --> Q[APK署名]
    Q --> R[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | AOT/インタープリター排他 | AOTモードとインタープリターモードは同時に有効化できない | ForceAOTとForceInterpreterの両方がtrueの場合 |
| BR-002 | 診断ポート要件 | DiagnosticPortsを使用する場合はdiagnostics_tracingコンポーネントが必要 | DiagnosticPortsが設定されている場合 |
| BR-003 | APIレベル整合性 | BuildApiLevelはMinApiLevelおよびTargetApiLevel以上である必要がある | 数値のAPIレベルが指定されている場合 |
| BR-004 | プロジェクト名制約 | ProjectNameにスペースを含めることはできない | ProjectNameが指定されている場合 |

### 計算ロジック

パッケージIDの生成：
```
packageId = "net.dot." + ProjectName（ハイフンはアンダースコアに置換、先頭数字はアンダースコア付加）
```

## データベース操作仕様

本機能はデータベースを使用しない。ファイルシステムへの読み書きのみを行う。

### 操作別データベース影響一覧

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| ANDROID001 | ArgumentException | AppDirが空または存在しない | 有効なAppDirを指定 |
| ANDROID002 | ArgumentException | MainLibraryFileNameがAppDir内に存在しない | ファイルパスを確認 |
| ANDROID003 | ArgumentException | RuntimeIdentifierが空または無効 | 有効なandroid RIDを指定 |
| ANDROID004 | ArgumentException | Android SDKが見つからない | ANDROID_SDK_ROOT環境変数を設定 |
| ANDROID005 | ArgumentException | Android NDKが見つからない | ANDROID_NDK_ROOT環境変数を設定 |
| ANDROID006 | InvalidOperationException | AOTとインタープリターが同時に有効 | いずれか一方のみを有効化 |
| ANDROID007 | ArgumentException | DiagnosticPorts使用時にdiagnostics_tracingが未設定 | RuntimeComponentsに追加 |

### リトライ仕様

本機能にリトライ機能は実装されていない。ビルドエラーは即座に例外としてスローされる。

## トランザクション仕様

該当なし（ファイルシステム操作のみ）

## パフォーマンス要件

- AOTコンパイルは大規模プロジェクトで数分〜数十分を要する場合がある
- APKサイズはログ出力される（`APK size: X.X Mb`）
- IncrementalビルドはMSBuildレベルでサポート

## セキュリティ考慮事項

- APK署名にはデバッグキーストア（debug.keystore）を使用
- リリースビルドでは別途署名キーの指定が推奨される
- KeyStorePathパラメータで署名キーを指定可能

## 備考

- 対応アーキテクチャ：arm、arm64、x64、x86
- サポートプラットフォーム：Windows（win-x64/arm64）、Linux（linux-x64/arm64）、macOS（osx-x64/arm64）
- .NET 6以降で利用可能

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ビルドパラメータとランタイムフレーバーの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ApkBuilder.cs | `src/tasks/AndroidAppBuilder/ApkBuilder.cs` | RuntimeFlavorEnum（17-22行目）でMono/CoreCLR/NativeAOTの3種類を定義。プロパティ（29-53行目）でビルドオプションを把握 |

**読解のコツ**: C#のpartial classとして定義されており、プロパティはMSBuildタスクからの入力を受け取る。RuntimeFlavorEnumはビルドフローの分岐に使用される重要な列挙型。

#### Step 2: エントリーポイントを理解する

MSBuildタスクの入口となるクラスを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AndroidAppBuilderTask.cs | `src/tasks/AndroidAppBuilder/AndroidAppBuilderTask.cs` | MSBuildタスクのプロパティ（12-111行目）とExecuteメソッド（117-147行目） |

**主要処理フロー**:
1. **12-116行目**: MSBuildから受け取る全プロパティの定義（[Required]属性で必須パラメータを識別）
2. **117-147行目**: Execute()メソッドでApkBuilderインスタンスを生成し、BuildApkを呼び出し

#### Step 3: コアビルドロジックを理解する

APK生成の中核ロジックを詳細に把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ApkBuilder.cs | `src/tasks/AndroidAppBuilder/ApkBuilder.cs` | BuildApkメソッド（67-587行目）がAPK生成の全体フロー |

**主要処理フロー**:
- **67-156行目**: 入力パラメータの検証（RuntimeFlavor解析、ディレクトリ存在確認、API Level整合性チェック）
- **157-193行目**: AOTアセンブリファイルの収集とリンク設定
- **195-239行目**: ディレクトリ準備とアセットのZIP圧縮
- **244-409行目**: CMakeによるネイティブライブラリ（libmonodroid.so）のビルド
- **411-485行目**: Javaソースのコンパイル、DEX生成
- **487-586行目**: APK作成、ネイティブライブラリ追加、アライメント、署名

#### Step 4: MSBuildターゲットの流れを理解する

実際のビルドパイプラインでの呼び出し順序を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AndroidBuild.props | `src/mono/msbuild/android/build/AndroidBuild.props` | AndroidBuildDependsOnプロパティ（21-43行目）でターゲットの依存関係を定義 |
| 4-2 | AndroidBuild.targets | `src/mono/msbuild/android/build/AndroidBuild.targets` | 各ターゲットの実装詳細 |

**主要処理フロー**:
- **AndroidBuild.props 21-31行目**: Monoランタイム使用時のビルドターゲット順序定義
- **AndroidBuild.targets 250-272行目**: AndroidAppBuilderTaskの呼び出しとパラメータ設定

### プログラム呼び出し階層図

```
MSBuild (dotnet build/publish)
    │
    ├─ AndroidBuild.targets::AndroidBuild
    │      │
    │      ├─ _InitializeCommonProperties
    │      ├─ _BeforeAndroidBuild
    │      ├─ _AndroidResolveReferences
    │      ├─ _AndroidPrepareProfiledAot（条件付き）
    │      ├─ _AndroidAotCompile（RunAOTCompilation=true時）
    │      │      └─ MonoAOTCompiler（外部タスク）
    │      ├─ _AndroidGenerateAppBundle
    │      │      └─ AndroidAppBuilderTask
    │      │             └─ ApkBuilder.BuildApk()
    │      │                    ├─ Utils.DirectoryCopy()
    │      │                    ├─ AndroidProject.GenerateCMake()
    │      │                    ├─ AndroidProject.BuildCMake()
    │      │                    ├─ Utils.RunProcess(javac)
    │      │                    ├─ Utils.RunProcess(d8/dx)
    │      │                    ├─ Utils.RunProcess(aapt)
    │      │                    ├─ AlignApk()
    │      │                    └─ SignApk()
    │      └─ _AfterAndroidBuild
    │
    └─ 出力: {ProjectName}.apk
```

### データフロー図

```
[入力]                              [処理]                                [出力]

.NETアセンブリ (.dll)  ─────────────┐
                                    │
runtimeconfig.json ─────────────────┼─▶ ApkBuilder.BuildApk() ─────────▶ {ProjectName}.apk
                                    │          │
ネイティブライブラリ (.so/.a) ──────┤          ├─▶ libmonodroid.so
                                    │          │
Android SDK/NDK ────────────────────┤          ├─▶ classes.dex
                                    │          │
MainActivity.java (テンプレート) ───┘          └─▶ AndroidManifest.xml
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AndroidAppBuilderTask.cs | `src/tasks/AndroidAppBuilder/AndroidAppBuilderTask.cs` | ソース | MSBuildタスクエントリーポイント |
| ApkBuilder.cs | `src/tasks/AndroidAppBuilder/ApkBuilder.cs` | ソース | APKビルドのコアロジック |
| AndroidLibBuilderTask.cs | `src/tasks/AndroidAppBuilder/AndroidLibBuilderTask.cs` | ソース | Javaライブラリビルドタスク |
| AndroidApkFileReplacerTask.cs | `src/tasks/AndroidAppBuilder/AndroidApkFileReplacerTask.cs` | ソース | APK内ファイル置換タスク |
| AndroidBuild.props | `src/mono/msbuild/android/build/AndroidBuild.props` | MSBuild | ビルドプロパティ定義 |
| AndroidBuild.targets | `src/mono/msbuild/android/build/AndroidBuild.targets` | MSBuild | ビルドターゲット定義 |
| WorkloadManifest.json.in | `src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Current.Manifest/WorkloadManifest.json.in` | テンプレート | ワークロードマニフェスト定義 |
| AndroidSampleApp.csproj | `src/mono/sample/Android/AndroidSampleApp.csproj` | プロジェクト | サンプルアプリケーション |
| CMakeLists-android.txt | `src/tasks/AndroidAppBuilder/Templates/CMakeLists-android.txt` | テンプレート | CMakeビルド設定 |
| MainActivity.java | `src/tasks/AndroidAppBuilder/Templates/MainActivity.java` | テンプレート | Androidメインアクティビティ |
| MonoRunner.java | `src/tasks/AndroidAppBuilder/Templates/MonoRunner.java` | テンプレート | Monoランタイム起動用Javaクラス |
| AndroidManifest.xml | `src/tasks/AndroidAppBuilder/Templates/AndroidManifest.xml` | テンプレート | Androidマニフェスト |
