아키텍처Architecture

Xamarin Android 응용 프로그램은 Mono 실행 환경에서 실행 됩니다.Xamarin.Android applications run within the Mono execution environment. 이 실행 환경은 Android 런타임 (ART) 가상 머신과 side-by-side 방식으로 실행 됩니다.This execution environment runs side-by-side with the Android Runtime (ART) virtual machine. 두 런타임 환경은 모두 Linux 커널 위에서 실행 되며 개발자가 기본 시스템에 액세스할 수 있도록 하는 다양 한 Api를 사용자 코드에 노출 합니다.Both runtime environments run on top of the Linux kernel and expose various APIs to the user code that allows developers to access the underlying system. Mono 런타임은 C 언어로 작성 됩니다.The Mono runtime is written in the C language.

시스템, System.IO, System.Net 및 나머지 .net 클래스 라이브러리를 사용 하 여 기본 Linux 운영 체제 기능에 액세스할 수 있습니다.You can be using the System, System.IO, System.Net and the rest of the .NET class libraries to access the underlying Linux operating system facilities.

Android에서 오디오, 그래픽, OpenGL 및 전화 통신과 같은 대부분의 시스템 기능은 네이티브 응용 프로그램에 직접 사용할 수 없으며, java. * 네임 스페이스 또는 android. * 네임 스페이스. 중 하나에 있는 Android Runtime java api를 통해서만 노출 됩니다.On Android, most of the system facilities like Audio, Graphics, OpenGL and Telephony are not available directly to native applications, they are only exposed through the Android Runtime Java APIs residing in one of the Java.* namespaces or the Android.* namespaces. 아키텍처는 대략적으로 다음과 같습니다.The architecture is roughly like this:

커널 및 기타 .NET/Java + 바인딩 위에 있는 Mono 및 아트의다이어그램Diagram of Mono and ART above the kernel and below .NET/Java + bindings

Xamarin Android 개발자는에 의해 노출 되는 Java Api에 대 한 연결을 제공 하는 .NET Api를 호출 하 여 운영 체제의 다양 한 기능에 액세스할 수 있습니다 (낮은 수준 액세스의 경우). Android 런타임입니다.Xamarin.Android developers access the various features in the operating system either by calling into .NET APIs that they know (for low-level access) or using the classes exposed in the Android namespaces which provides a bridge to the Java APIs that are exposed by the Android Runtime.

Android 클래스가 Android 런타임 클래스와 통신 하는 방법에 대 한 자세한 내용은 API 디자인 문서를 참조 하세요.For more information on how the Android classes communicate with the Android Runtime classes see the API Design document.

애플리케이션 패키지Application Packages

Android 응용 프로그램 패키지는 .apk 파일 확장명을 가진 ZIP 컨테이너입니다.Android application packages are ZIP containers with a .apk file extension. Xamarin Android 응용 프로그램 패키지는 일반적인 Android 패키지와 동일한 구조와 레이아웃을 가지 며 다음과 같이 추가 되었습니다.Xamarin.Android application packages have the same structure and layout as normal Android packages, with the following additions:

  • 응용 프로그램 어셈블리 (IL 포함)는 어셈블리 폴더 내에 압축 되지 않은 상태로 저장 됩니다.The application assemblies (containing IL) are stored uncompressed within the assemblies folder. 릴리스 빌드에서 프로세스를 시작 하는 동안 . apk 는 프로세스에 대 한 mmap () 이 고 어셈블리는 메모리에서 로드 됩니다.During process startup in Release builds the .apk is mmap() ed into the process and the assemblies are loaded from memory. 따라서 어셈블리를 실행 하기 전에 추출할 필요가 없기 때문에 앱 시작 속도를 높일 수 있습니다.This permits faster app startup, as assemblies do not need to be extracted prior to execution.

  • 참고: Assembly . locationassembly 와 같은 어셈블리 위치 정보는 릴리스 빌드에서 사용할 수 없습니다 .Note: Assembly location information such as Assembly.Location and Assembly.CodeBase cannot be relied upon in Release builds. 이러한 항목은 고유 파일 시스템 항목으로 존재 하지 않으며 사용 가능한 위치를 갖지 않습니다.They do not exist as distinct filesystem entries, and they have no usable location.

  • Mono 런타임을 포함 하는 네이티브 라이브러리는 .apk 내에 있습니다.Native libraries containing the Mono runtime are present within the .apk . Xamarin.ios 응용 프로그램에는 원하는/대상 Android 아키텍처에 대 한 네이티브 라이브러리가 포함 되어야 합니다 (예: armeabi-v7a , armeabi-v7a-armeabi-v7a , x86 ).A Xamarin.Android application must contain native libraries for the desired/targeted Android architectures, e.g. armeabi , armeabi-v7a , x86 . Xamarin Android 응용 프로그램은 적절 한 런타임 라이브러리가 포함 된 경우를 제외 하 고 플랫폼에서 실행할 수 없습니다.Xamarin.Android applications cannot run on a platform unless it contains the appropriate runtime libraries.

Xamarin Android 응용 프로그램에는 android에서 관리 코드를 호출할 수 있도록 하는 Android 호출 가능 래퍼 도 포함 됩니다.Xamarin.Android applications also contain Android Callable Wrappers to allow Android to call into managed code.

Android 호출 가능 래퍼Android Callable Wrappers

  • Android 호출 가능 래퍼 는 android 런타임에서 관리 코드를 호출 해야 하는 경우 언제 든 지 사용 되는 JNI 브리지입니다.Android callable wrappers are a JNI bridge which are used any time the Android runtime needs to invoke managed code. Android 호출 가능 래퍼는 가상 메서드를 재정의 하 고 Java 인터페이스를 구현할 수 있는 방법입니다.Android callable wrappers are how virtual methods can be overridden and Java interfaces can be implemented. 자세한 내용은 Java 통합 개요 문서를 참조 하세요.See the Java Integration Overview doc for more.

관리 되는 호출 가능 래퍼Managed Callable Wrappers

관리 되는 호출 가능 래퍼는 관리 코드에서 Android 코드를 호출 하 고 가상 메서드를 재정의 하 고 Java 인터페이스를 구현 하는 데 필요한 시간에 사용 되는 JNI 브리지입니다.Managed callable wrappers are a JNI bridge which are used any time managed code needs to invoke Android code and provide support for overriding virtual methods and implementing Java interfaces. 전체 Android. * 및 관련 네임 스페이스는 jar 바인딩을통해 생성 된 관리 되는 호출 가능 래퍼입니다.The entire Android.* and related namespaces are managed callable wrappers generated via .jar binding. 관리 되는 호출 가능 래퍼는 관리 되는 형식과 Android 형식 간에 변환 하 고 JNI를 통해 기본 Android 플랫폼 메서드를 호출 합니다.Managed callable wrappers are responsible for converting between managed and Android types and invoking the underlying Android platform methods via JNI.

생성 된 각 관리 되는 호출 가능 래퍼에는 Java 전역 참조 ( IJavaObject 속성을 통해 액세스 가능)가 포함 됩니다.Each created managed callable wrapper holds a Java global reference, which is accessible through the Android.Runtime.IJavaObject.Handle property. 전역 참조를 사용 하 여 Java 인스턴스와 관리 되는 인스턴스 간의 매핑을 제공 합니다.Global references are used to provide the mapping between Java instances and managed instances. 전역 참조는 제한 된 리소스입니다. 에뮬레이터에서 한 번에 2000 전역 참조만 존재할 수 있지만 대부분의 하드웨어는 한 번에 하나의 52000 전역 참조를 사용할 수 있습니다.Global references are a limited resource: emulators allow only 2000 global references to exist at a time, while most hardware allows over 52,000 global references to exist at a time.

전역 참조가 생성 되 고 삭제 되는 시기를 추적 하려면 gref시스템 속성 을 포함 하도록 설정 하면 됩니다.To track when global references are created and destroyed, you can set the debug.mono.log system property to contain gref.

관리 되는 호출 가능 래퍼에서 node.js () 를 호출 하 여 전역 참조를 명시적으로 해제할 수 있습니다.Global references can be explicitly freed by calling Java.Lang.Object.Dispose() on the managed callable wrapper. 그러면 Java 인스턴스와 관리 되는 인스턴스 간의 매핑이 제거 되 고 Java 인스턴스를 수집할 수 있습니다.This will remove the mapping between the Java instance and the managed instance and allow the Java instance to be collected. 관리 코드에서 Java 인스턴스를 다시 액세스 하는 경우 관리 되는 호출 가능 래퍼가 새로 생성 됩니다.If the Java instance is re-accessed from managed code, a new managed callable wrapper will be created for it.

인스턴스가 스레드 간에 실수로 공유 될 수 있는 경우 관리 되는 호출 가능 래퍼를 삭제할 때 주의가 필요 합니다. 인스턴스를 삭제 하면 다른 스레드의 참조에 영향을 줍니다.Care must be exercised when disposing of Managed Callable Wrappers if the instance can be inadvertently shared between threads, as disposing the instance will impact references from any other threads. 최대 보안을 위해 항상 새 인스턴스를 할당 하 고 캐시 된 인스턴스가 아닌 새 인스턴스를 할당 하는 메서드 또는 new를 통해 할당 된 인스턴스의 Dispose()만 스레드 간에 실수로 인스턴스가 공유 되도록 할 수 있습니다.For maximum safety, only Dispose() of instances which have been allocated via new or from methods which you know always allocate new instances and not cached instances which may cause accidental instance sharing between threads.

관리 되는 호출 가능 래퍼 서브 클래스Managed Callable Wrapper Subclasses

관리 되는 호출 가능 래퍼 서브 클래스는 모든 "흥미로운" 응용 프로그램별 논리가 존재할 수 있는 위치입니다.Managed callable wrapper subclasses are where all the "interesting" application-specific logic may live. 여기에는 사용자 지정 Android.App.Activity 서브 클래스 (예: 기본 프로젝트 템플릿의 Activity1 형식)가 포함 됩니다.These include custom Android.App.Activity subclasses (such as the Activity1 type in the default project template). 특히 registerattribute 사용자 지정 특성 또는 registerattribute 를 포함 하지 않는 DoNotGenerateAcw 하위 클래스입니다 . 기본값은 false입니다.(Specifically, these are any Java.Lang.Object subclasses which do not contain a RegisterAttribute custom attribute or RegisterAttribute.DoNotGenerateAcw is false, which is the default.)

관리 되는 호출 가능 래퍼와 같이 관리 되는 호출 가능 래퍼 서브 클래스에는 Java. 개체. Handle 속성을 통해 액세스할 수 있는 전역 참조도 포함 됩니다.Like managed callable wrappers, managed callable wrapper subclasses also contain a global reference, accessible through the Java.Lang.Object.Handle property. 관리 되는 호출 가능 래퍼의 경우와 마찬가지로, Java. system.object. Dispose ()를 호출 하 여 전역 참조를 명시적으로 해제할 수 있습니다.Just as with managed callable wrappers, global references can be explicitly freed by calling Java.Lang.Object.Dispose(). 관리 되는 호출 가능 래퍼와 달리 인스턴스를 삭제하기 전에 해당 인스턴스를 삭제 하기 전에 수행 해야 하는 일은 Java 인스턴스 (Android 호출 가능 래퍼의 인스턴스)와 관리 되는 인스턴스.Unlike managed callable wrappers, great care should be taken before disposing of such instances, as Dispose()-ing of the instance will break the mapping between the Java instance (an instance of an Android Callable Wrapper) and the managed instance.

Java 활성화Java Activation

Java에서 acw ( Android 호출 가능 래퍼 )를 만들면 acw 생성자가 해당 C# 생성자를 호출 합니다.When an Android Callable Wrapper (ACW) is created from Java, the ACW constructor will cause the corresponding C# constructor to be invoked. 예를 들어, Mainactivity 의 acw에는 mainactivity의 기본 생성자를 호출 하는 기본 생성자가 포함 됩니다.For example, the ACW for MainActivity will contain a default constructor which will invoke MainActivity's default constructor. 이 작업은 ACW 생성자 내에서 Typemanager. Activate () 호출을 통해 수행 됩니다.(This is done through the TypeManager.Activate() call within the ACW constructors.)

결과의 다른 생성자 시그니처는 (IntPtr, JniHandleOwnership) 생성자입니다.There is one other constructor signature of consequence: the (IntPtr, JniHandleOwnership) constructor. (IntPtr, JniHandleOwnership) 생성자는 Java 개체가 관리 코드에 노출 되 고 관리 되는 호출 가능 래퍼가 JNI 핸들을 관리 하기 위해 생성 되어야 할 때마다 호출 됩니다.The (IntPtr, JniHandleOwnership) constructor is invoked whenever a Java object is exposed to managed code and a Managed Callable Wrapper needs to be constructed to manage the JNI handle. 일반적으로이 작업은 자동으로 수행 됩니다.This is usually done automatically.

관리 되는 호출 가능 래퍼 서브 클래스에서 (IntPtr, JniHandleOwnership) 생성자를 수동으로 제공 해야 하는 두 가지 시나리오가 있습니다.There are two scenarios in which the (IntPtr, JniHandleOwnership) constructor must be manually provided on a Managed Callable Wrapper subclass:

  1. Android. 응용 프로그램이 서브클래싱된 경우.Android.App.Application is subclassed. 응용 프로그램 은 특수 합니다. 기본 응용 프로그램 생성자는 호출 되지 않으며 , 대신 (IntPtr, JniHandleOwnership) 생성자를 제공 해야합니다.Application is special; the default Applicaton constructor will never be invoked, and the (IntPtr, JniHandleOwnership) constructor must instead be provided.

  2. 기본 클래스 생성자에서 가상 메서드를 호출 합니다.Virtual method invocation from a base class constructor.

(2)은 누설 추상화입니다.Note that (2) is a leaky abstraction. 에서 C#와 같이 Java에서 생성자의 가상 메서드 호출은 항상 가장 많이 파생 된 메서드 구현을 호출 합니다.In Java, as in C#, calls to virtual methods from a constructor always invoke the most derived method implementation. 예를 들어 TextView (Context, AttributeSet, int) 생성자 는 TextView TextView getDefaultMovementMethod ()를 호출 합니다 .이 메서드는 . defaultmovementmethod 속성으로 바인딩됩니다.For example, the TextView(Context, AttributeSet, int) constructor invokes the virtual method TextView.getDefaultMovementMethod(), which is bound as the TextView.DefaultMovementMethod property. 따라서 Logtextbox 형식이 (1) 서브 클래스 TextView, (2) TextView를 재정의하 고 (3) XML을 통해 해당 클래스의 인스턴스를 활성화 하는 경우 재정의 된 defaultmovementmethod 속성은 ACW 생성자를 실행 하기 전에 호출 하 고 생성자를 C# 실행 하기 전에 발생 합니다.Thus, if a type LogTextBox were to (1) subclass TextView, (2) override TextView.DefaultMovementMethod, and (3) activate an instance of that class via XML, the overridden DefaultMovementMethod property would be invoked before the ACW constructor had a chance to execute, and it would occur before the C# constructor had a chance to execute.

이는 ACW LogTextBox 인스턴스가 먼저 관리 코드를 입력 한 다음 Logtextbox (Context, IAttributeSet, int)를 호출 하는 경우 LogTextView (IntPtr, JniHandleOwnership) 생성자를 통해 인스턴스 logtextbox를 인스턴스화하여 지원 됩니다. ACW 생성자가 실행 될 때 동일한 인스턴스의 생성자.This is supported by instantiating an instance LogTextBox through the LogTextView(IntPtr, JniHandleOwnership) constructor when the ACW LogTextBox instance first enters managed code, and then invoking the LogTextBox(Context, IAttributeSet, int) constructor on the same instance when the ACW constructor executes.

이벤트 순서:Order of events:

  1. 레이아웃 XML은 Contentview에 로드 됩니다.Layout XML is loaded into a ContentView.

  2. Android는 Layout 개체 그래프를 인스턴스화하고 monodroid의 인스턴스를 인스턴스화합니다 . logtextbox의 acw는 apidemo 입니다.Android instantiates the Layout object graph, and instantiates an instance of monodroid.apidemo.LogTextBox , the ACW for LogTextBox .

  3. Monodroid. apidemo 생성자는 TextView 생성자를 실행 합니다.The monodroid.apidemo.LogTextBox constructor executes the android.widget.TextView constructor.

  4. TextView 생성자는 Apidemo () getDefaultMovementMethod () 를 호출 합니다.The TextView constructor invokes monodroid.apidemo.LogTextBox.getDefaultMovementMethod() .

  5. monodroid () apidemo 를 호출 하는 *TextView (@no_)* 를 호출 하는 logtextbox. n_getDefaultMovementMethod ( )를 호출 합니다. t_4 TextView> (handle, JniHandleOwnership DoNotTransfer) .monodroid.apidemo.LogTextBox.getDefaultMovementMethod() invokes LogTextBox.n_getDefaultMovementMethod() , which invokes TextView.n_GetDefaultMovementMethod() , which invokes Java.Lang.Object.GetObject<TextView> (handle, JniHandleOwnership.DoNotTransfer) .

  6. TextView>()< 은 C# 핸들 에 대해 해당 인스턴스가 이미 있는지 확인 합니다.Java.Lang.Object.GetObject<TextView>() checks to see if there is already a corresponding C# instance for handle . 있는 경우 반환 됩니다.If there is, it is returned. 이 시나리오에서는 개체가 없으므로 GetObject<t>() 에서 만들어야 합니다.In this scenario, there isn't, so Object.GetObject<T>() must create one.

  7. <t>()Logtextbox (IntPtr, JniHandleOwneship) 생성자를 찾고 호출 하 고, 핸들과 만든 인스턴스 간의 매핑을 만들고, 만든 인스턴스를 반환 합니다.Object.GetObject<T>() looks for the LogTextBox(IntPtr, JniHandleOwneship) constructor, invokes it, creates a mapping between handle and the created instance, and returns the created instance.

  8. TextView () n_GetDefaultMovementMethod ()Logtextbox. DefaultMovementMethod 속성 getter를 호출 합니다.TextView.n_GetDefaultMovementMethod() invokes the LogTextBox.DefaultMovementMethod property getter.

  9. 컨트롤은 실행을 완료 하는 TextView 생성자로 반환 됩니다.Control returns to the android.widget.TextView constructor, which finishes execution.

  10. Apidemo monodroid 생성자가 실행 되어 Typemanager. Activate () 를 호출 합니다.The monodroid.apidemo.LogTextBox constructor executes, invoking TypeManager.Activate() .

  11. Logtextbox (Context, IAttributeSet, int) 생성자는 (7)에서 만든 동일한 인스턴스에서 실행 됩니다.The LogTextBox(Context, IAttributeSet, int) constructor executes on the same instance created in (7) .

  12. (IntPtr, JniHandleOwnership) 생성자를 찾을 수 없는 경우 MissingMethodException] (f: MissingMethodException)가 throw 됩니다.If the (IntPtr, JniHandleOwnership) constructor cannot be found, then a System.MissingMethodException](xref:System.MissingMethodException) will be thrown.

중간에 Dispose () 호출Premature Dispose() Calls

JNI 핸들과 해당 C# 인스턴스 간에 매핑이 있습니다.There is a mapping between a JNI handle and the corresponding C# instance. Node.js. Dispose ()는이 매핑을 중단 합니다.Java.Lang.Object.Dispose() breaks this mapping. 매핑이 중단 된 후 JNI 핸들이 관리 코드에 들어가면 Java 활성화와 같이 표시 되 고 (IntPtr, JniHandleOwnership) 생성자가 확인 되 고 호출 됩니다.If a JNI handle enters managed code after the mapping has been broken, it looks like Java Activation, and the (IntPtr, JniHandleOwnership) constructor will be checked for and invoked. 생성자가 없으면 예외가 throw 됩니다.If the constructor doesn't exist, then an exception will be thrown.

예를 들어 다음과 같은 관리 되는 호출 가능 Wraper 하위 클래스가 있다고 가정 합니다.For example, given the following Managed Callable Wraper subclass:

class ManagedValue : Java.Lang.Object {

    public string Value {get; private set;}

    public ManagedValue (string value)
    {
        Value = value;
    }

    public override string ToString ()
    {
        return string.Format ("[Managed: Value={0}]", Value);
    }
}

인스턴스를 만들고 ()의 인스턴스를 삭제 하 고 관리 되는 호출 가능 래퍼가 다시 만들어지도록 합니다.If we create an instance, Dispose() of it, and cause the Managed Callable Wrapper to be re-created:

var list = new JavaList<IJavaObject>();
list.Add (new ManagedValue ("value"));
list [0].Dispose ();
Console.WriteLine (list [0].ToString ());

프로그램이 다음과 같이 소멸 됩니다.The program will die:

E/mono    ( 2906): Unhandled Exception: System.NotSupportedException: Unable to activate instance of type Scratch.PrematureDispose.ManagedValue from native handle 4051c8c8 --->
System.MissingMethodException: No constructor found for Scratch.PrematureDispose.ManagedValue::.ctor(System.IntPtr, Android.Runtime.JniHandleOwnership)
E/mono    ( 2906):   at Java.Interop.TypeManager.CreateProxy (System.Type type, IntPtr handle, JniHandleOwnership transfer) [0x00000] in <filename unknown>:0
E/mono    ( 2906):   at Java.Interop.TypeManager.CreateInstance (IntPtr handle, JniHandleOwnership transfer, System.Type targetType) [0x00000] in <filename unknown>:0
E/mono    ( 2906):   --- End of inner exception stack trace ---
E/mono    ( 2906):   at Java.Interop.TypeManager.CreateInstance (IntPtr handle, JniHandleOwnership transfer, System.Type targetType) [0x00000] in <filename unknown>:0
E/mono    ( 2906):   at Java.Lang.Object.GetObject (IntPtr handle, JniHandleOwnership transfer, System.Type type) [0x00000] in <filename unknown>:0
E/mono    ( 2906):   at Java.Lang.Object._GetObject[IJavaObject] (IntPtr handle, JniHandleOwnership transfer) [0x00000

하위 클래스에 (IntPtr, JniHandleOwnership) 생성자가 포함 된 경우 형식의 인스턴스가 생성 됩니다.If the subclass does contain an (IntPtr, JniHandleOwnership) constructor, then a new instance of the type will be created. 따라서 인스턴스는 새 인스턴스 이므로 모든 인스턴스 데이터를 "손실" 하는 것으로 나타납니다.As a result, the instance will appear to "lose" all instance data, as it's a new instance. 값은 null입니다.(Note that the Value is null.)

I/mono-stdout( 2993): [Managed: Value=]

Java 개체가 더 이상 사용 되지 않거나 하위 클래스에 인스턴스 데이터가 없고 (IntPtr, JniHandleOwnership) 생성자가 제공 된 경우에만 관리 되는 호출 가능 래퍼 서브 클래스의 Dispose ()만 삭제 합니다.Only Dispose() of managed callable wrapper subclasses when you know that the Java object will not be used anymore, or the subclass contains no instance data and a (IntPtr, JniHandleOwnership) constructor has been provided.

응용 프로그램 시작Application Startup

활동, 서비스 등을 시작 하면 Android는 먼저 활동/서비스를 호스트 하는 프로세스가 이미 실행 중인지 확인 합니다. 이러한 프로세스가 없으면 새 프로세스가 생성 되 고 Androidmanifest 을 읽고 /manifest/application/@android:name 특성에 지정 된 형식이 로드 되 고 인스턴스화됩니다.When an activity, service, etc. is launched, Android will first check to see if there is already a process running to host the activity/service/etc. If no such process exists, then a new process will be created, the AndroidManifest.xml is read, and the type specified in the /manifest/application/@android:name attribute is loaded and instantiated. 그런 다음 /manifest/application/provider/@android:name 특성 값으로 지정 된 모든 형식이 인스턴스화되고 해당 contentprovider %28) 메서드가 호출 됩니다.Next, all types specified by the /manifest/application/provider/@android:name attribute values are instantiated and have their ContentProvider.attachInfo%28) method invoked. Xamarin Android는 mono를 추가 하 여이에 후크 합니다 . 빌드 프로세스 중에 MonoRuntimeProvider contentprovider To AndroidManifest.Xamarin.Android hooks into this by adding a mono.MonoRuntimeProvider ContentProvider to AndroidManifest.xml during the build process. Mono입니다. AttachInfo () 메서드는 Mono 런타임을 프로세스로 로드 하는 작업을 담당 합니다. MonoRuntimeProvider.The mono.MonoRuntimeProvider.attachInfo() method is responsible for loading the Mono runtime into the process. 이 시점 전에 Mono를 사용 하려는 시도는 실패 합니다.Any attempts to use Mono prior to this point will fail. ( 참고: 이러한 이유로 Mono를 초기화 하기 전에 응용 프로그램 인스턴스가 만들어지기 때문에 JniHandleOwnership 하위 클래스에서 (IntPtr,) 생성자를 제공 해야 하는 형식입니다.)( Note: This is why types which subclass Android.App.Application need to provide an (IntPtr, JniHandleOwnership) constructor, as the Application instance is created before Mono can be initialized.)

프로세스 초기화가 완료 되 면 AndroidManifest.xml를 확인 하 여 시작할 작업/서비스/등의 클래스 이름을 찾습니다.Once process initialization has completed, AndroidManifest.xml is consulted to find the class name of the activity/service/etc. to launch. 예를 들어 /manifest/application/activity/@android:name 특성 은 로드할 활동의 이름을 결정 하는 데 사용 됩니다.For example, the /manifest/application/activity/@android:name attribute is used to determine the name of an Activity to load. 활동의 경우이 유형은 android. Activity를 상속 해야 합니다.For Activities, this type must inherit android.app.Activity. 지정 된 형식이 클래스를 통해 로드 됩니다 . forName () (형식이 Java 형식 이어야 하며, 따라서 Android 호출 가능 래퍼).The specified type is loaded via Class.forName() (which requires that the type be a Java type, hence the Android Callable Wrappers), then instantiated. Android 호출 가능 래퍼 인스턴스를 만들면 해당 C# 형식의 인스턴스 생성이 트리거됩니다.Creation of an Android Callable Wrapper instance will trigger creation of an instance of the corresponding C# type. 그러면 Android에서 onCreate (번들) 를 호출 하 여 해당 onCreate (번들) 이 호출 되 고 경합이 발생 합니다.Android will then invoke Activity.onCreate(Bundle) , which will cause the corresponding Activity.OnCreate(Bundle) to be invoked, and you're off to the races.