1 of 22

How Xamarin.Android works

@atsushieno / atsushi xamarin.com

2 of 22

Agenda

How Xamarin.Android works

XAのアプリケーションモデル

.NETコードが動く仕組み

XAアプリケーションのbootstrap

YAPF寄りだけど今回はナシ

Java/Mono interopの詳細

dalvikとmonoのGC協調

IDEでAndroid開発をサポートするやり方

3 of 22

Xamarin

C#/.NET on iOS and Android

C#でnative APIを使ったアプリケーションを作れる

Visual Studio / Xamarin Studio IDE

Mono Projectの開発元

4 of 22

Mono

.NET on Linux, Mac, Windows etc.

CランタイムとC#コンパイラ/ライブラリの自前実装

GTK# (gtk+ & P/Invoke)

MonoDevelop IDE (GTK#で開発)

Cの組み込みAPI

(.NET組み込み環境: Silverlightプラグインなど)

5 of 22

Android

Android SDK: Java APIとビルドツール

Android NDK: gcc toolchainとCライブラリ

NativeActivity

LLVM/Clangもアリ

(IDE側: ADT, Android Studio)

6 of 22

NativeActivity...?

"NativeActivity allows you to write a completely native activity" "It is possible to write a completely native application"

"You should still create your project with Eclipse or <snip>"

WTF

Javaと変わらんやん…

7 of 22

Mono runtime on Android

monoランタイムはNDKでビルド可能

完全にCコード(たしか) / libcのみ依存->bionic

monoのARM JITが普通に動作可能

⇔iOS (JIT不可→AOT=事前コンパイルで対処)

(androidmono: コミュニティによる最初のandroid port)

8 of 22

Xamarin.Android

Mono.Android.dll: Android SDK API in C#

public class MyActivity : Android.App.Activity { ... }

XAはJava APIとJavaのフレームワークが前提

NativeActivity not supported.

C#コードはCILとしてmonoランタイム上で動作

Javaコードはdexとしてdalvik上で動作

(C#からdexに変換したりはしない)

9 of 22

Java Interop: from Mono to Java

Mono.Android APIがJNIをP/Invokeで呼び出す

libmonodroid: Cライブラリ(公開APIはナシ)

Android.Runtime.JNIEnvクラス

CのJNIEnv API相当

10 of 22

Java Interop: from Java to Mono

AndroidはよくJavaオブジェクトを生成・操作する

Android Callable Wrappers (ACW)

.NETベースのAndroidオブジェクトの型に

それぞれ対応するJavaコードが生成される

そのJava型がlibmonodroidをJNIで呼び出す

11 of 22

ACW

@Override

protected void onCreate(....)

{

n_onCreate(....);

}

native void n_onCreate(....); // invoked CIL

12 of 22

more ACW

static {

__md_methods =

"n_onCreate:(Landroid/os/Bundle;)V:�GetOnCreate_Landroid_os_Bundle_Handler\n" + "";

mono.android.Runtime.register(

"Some.MangedClass, Some.Assembly, ...", SomeJava.class, __md_methods);

}

(actually "ManagedClass" should be identical to "SomeJava")

13 of 22

Xamarin.Androidのapk

アプリケーションのapk(全アプリ)

"Shared Runtime" apk

共通dllとそれをアプリに提供するService

mscorlib.dll, System*.dllなど

"Platform API" apk

API Level別のdllが含まれる

Mono.Android.dllなど

14 of 22

アプリケーションの実行モデル

1) Shared Runtimeを利用 - デバッグビルド

1a) Embed: 普通のデプロイメント

毎回apkをインストール

apkに「共通のdll」は含まれない

1b) FastDev: 高速デプロイメント

apk中にdllはない(!) 1回だけインストール

アプリケーション空間にdllをコピーしてロード

更新が必要なファイルのみコピー

2) Bundle: 全部パッケージ - リリースビルド

15 of 22

アプリケーション実行モデル一覧

モデル

FastDev

Embed

Bundle

想定用途l

高速デバッグ

遅いデバッグ?

リリース

依存関係

shared runtime

shared runtime

なし(単独配布可能)

apk �deployment

一度だけ

毎回

毎回

apkサイズ

非常に小さい

大きい

小さめ

全コード量

多い

多い

削られる

16 of 22

XAアプリケーションのbootstrap

[再掲] XA appは普通のJava app

全てのAndroid appは同じ流れで起動する

アプリケーションプロセスはZygoteからfork

どのアプリにもActivityThreadが割り当てられる

monoが初期化されないとCILコードは機能しない

でも初期化プロセスはJavaの世界

XAのbootstrapはAndroidManifest.xmlから見える

17 of 22

AndroidManifest.xml

<application

~:name="mono.android.app.Application" ...>

<provider

~:name="mono.MonoRuntimeProvider" .../>

<receiver

~:name="mono.android.Seppuku">

18 of 22

XA bootstrap components

mono.android.app.Application: これはダミー(!)

mono.MonoRuntimeProvider

monoランタイムを初期化して、(処理モデルに

よってはshared runtimeからdllを取り込んで)

アプリケーションに含まれるdllをロードする

mono.android.Seppuku: デバッガの切断を受理

19 of 22

アプリケーションのbootstrap詳細

Zygoteがプロセススレッドをfork

ActivityManagerがActivityThreadをアプリにbind

ActivityThread#bindApplication()

Providerのリストが生成されて http://goo.gl/OBhLY

それがこのメソッドに渡る http://goo.gl/LZLlk

ActivityThread#handleBindApplication()

Instrumentationが生成される(既定/独自)

installContentProviders(app, providers);

mInstrumentation#callApplicationOnCreate(app);

-> この順序ならカスタムApplicationクラスも安全に初期化

20 of 22

ただし…

ApplicationとProviderの初期化順は最近の動作

Application.onCreate()が先の場合も…

カスタムInstrumentationの初期化で問題

→これらに対応するACWでも初期化処理を追加

21 of 22

まとめ

Mono.AndroidはAndroidフレームワーク準拠

.NETコードはmonoランタイムで動作

Android API とのinterop

ACWがJNI経由で.NETオブジェクトを操作

JNI関数をP/InvokeしてJavaオブジェクトを操作

アプリケーションのbootstrap

ランタイムを適切なタイミングで初期化する

mono.MonoRuntimeProvider

22 of 22

参考文献

Anatomy-Physiology of an Android

https://sites.google.com/site/io/anatomy--physiology-of-an-android

Xamarin.Android: Architecture

http://docs.xamarin.com/guides/android/advanced_topics/architecture

DSAS開発者の部屋:Android アプリケーションが起動するまでの流れ

http://dsas.blog.klab.org/archives/52003951.html