АрхитектураArchitecture

В среде выполнения Mono запуска приложений Xamarin.Android.Xamarin.Android applications run within the Mono execution environment. Этот выполнения среды запусков side-by-side с виртуальной машиной Android среды выполнения (ГРАФИКА).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 и телефонии недоступны напрямую для собственных приложений, они доступны только через Android API среды выполнения Java, находящихся в одном из Java. * пространства имен или Android. * пространства имен.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:

Схема Mono и ИСКУССТВО выше ядра и ниже .NET и Java + привязкиDiagram of Mono and ART above the kernel and below .NET/Java + bindings

Xamarin.Android разработчики получают доступ к функциям операционной системы, либо вызов интерфейсов API .NET, они знают (для низкого уровня доступа), либо с помощью классов в пространства имен Android, который предоставляет доступ к которым предоставляет API-интерфейсы Java моста среды выполнения 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 — это контейнеры ZIP с .apk расширение файла.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. Во время процесса построения запуска в выпуске .apkmmap() ed в процесс и сборки загружаются из памяти.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.Location и Assembly.CodeBase нельзя рассчитывать в сборках выпуска.Note: Assembly location information such as Assembly.Location and Assembly.CodeBase cannot be relied upon in Release builds. Они не существуют как операции distinct файловой системы и имеют расположение не может использоваться.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.Android должно содержать собственные библиотеки для требуемого целевые Android архитектур, например armeabi , 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.

Вызываемые программы-оболочки AndroidAndroid Callable Wrappers

  • Вызываемые оболочки времени Android являются JNI моста, которые используются в любое время, в среде выполнения Android необходимо вызывать управляемый код.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

Управляемые вызываемых оболочек являются моста JNI, которые используются в любое время, управляемый код должен вызывать код для Android и обеспечивают поддержку для переопределения виртуальных методов и реализация интерфейсов Java.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 и вызов методов базовой платформы Android через JNI.Managed callable wrappers are responsible for converting between managed and Android types and invoking the underlying Android platform methods via JNI.

Каждый создан управляемый вызываемая оболочка содержит глобальные ссылки Java, который доступен через Android.Runtime.IJavaObject.Handle свойство.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 глобальные ссылки существовать одновременно, то время как большинство оборудования позволяет более 52,000 глобальные ссылки на одновременно существовать.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.

Для отслеживания, когда глобальные ссылки создаются и удаляются, можно задать debug.mono.log системное свойство, чтобы содержать gref, установленное.To track when global references are created and destroyed, you can set the debug.mono.log system property to contain gref.

Глобальные ссылки можно явно освободить путем вызова Java.Lang.Object.Dispose() на управляемых вызываемой оболочки.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 должны быть реализованы при освобождение управляемых вызываемых оболочек, если экземпляр случайно могут передаваться между потоками, как удаление экземпляра повлияет на ссылки из другим потокам.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. Для максимальной безопасности только Dispose() экземпляров, которые были выделены с помощью new или из методов какие вы знать всегда выделить новые экземпляры и не кэшированные экземпляры, которые могут вызвать случайного экземпляра, совместное использование между потоками.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). (В частности, это любой Java.Lang.Object подклассов, которые выполняют не содержат RegisterAttribute настраиваемый атрибут или RegisterAttribute.DoNotGenerateAcwfalse, который используется по умолчанию.)(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.Lang.Object.Handle свойство.Like managed callable wrappers, managed callable wrapper subclasses also contain a global reference, accessible through the Java.Lang.Object.Handle property. Так же, как с помощью управляемых вызываемых оболочек, глобальные ссылки можно явно освободить путем вызова Java.Lang.Object.Dispose().Just as with managed callable wrappers, global references can be explicitly freed by calling Java.Lang.Object.Dispose(). В отличие от управляемого вызываемых оболочек внимательно следить за возникновением должна применяться перед удалением из таких экземпляров, как Dispose()- ing экземпляра приведет к разрыву сопоставление между экземплярами 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.

Активация JavaJava Activation

Когда Android вызываемая оболочка (ACW) создается на основе Java, конструктор ACW вызовет соответствующий конструктор C# для вызова.When an Android Callable Wrapper (ACW) is created from Java, the ACW constructor will cause the corresponding C# constructor to be invoked. Например, ACW для MainActivity будет содержать конструктор по умолчанию, который будет вызывать MainActivityв конструктор по умолчанию.For example, the ACW for MainActivity will contain a default constructor which will invoke MainActivity's default constructor. (Это осуществляется посредством TypeManager.Activate() вызова конструкторов ACW.)(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.App.Application является подклассом.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. В Java, как в C# вызовы виртуальных методов из конструктора всегда вызывать наиболее производный метод реализации.In Java, as in C#, calls to virtual methods from a constructor always invoke the most derived method implementation. Например TextView (контекст, AttributeSet, int) конструктор вызывает виртуальный метод TextView.getDefaultMovementMethod(), который привязан как Свойство TextView.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.DefaultMovementMethodи (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.

Это поддерживается путем создания его экземпляра LogTextBox через LogTextView (IntPtr, JniHandleOwnership) конструктор, когда экземпляр ACW LogTextBox сначала переходит в управляемый код и последующим вызовом LogTextBox (контекст, IAttributeSet, int) конструктор в одном экземпляре при выполнении 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 и создает экземпляр monodroid.apidemo.LogTextBox , ACW для LogTextBox .Android instantiates the Layout object graph, and instantiates an instance of monodroid.apidemo.LogTextBox , the ACW for LogTextBox .

  3. Monodroid.apidemo.LogTextBox конструктор выполняет android.widget.TextView конструктор.The monodroid.apidemo.LogTextBox constructor executes the android.widget.TextView constructor.

  4. TextView конструктор вызывает monodroid.apidemo.LogTextBox.getDefaultMovementMethod() .The TextView constructor invokes monodroid.apidemo.LogTextBox.getDefaultMovementMethod() .

  5. monodroid.apidemo.LogTextBox.getDefaultMovementMethod() вызывает LogTextBox.n_getDefaultMovementMethod() , который вызывает TextView.n_GetDefaultMovementMethod() , что вызывает Java.Lang.Object.GetObject<TextView> (обрабатывать, 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. Java.Lang.Object.GetObject<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. В этом случае отсутствует, поэтому Object.GetObject<T>() необходимо создать его.In this scenario, there isn't, so Object.GetObject<T>() must create one.

  7. Object.GetObject<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 метода считывания свойства.TextView.n_GetDefaultMovementMethod() invokes the LogTextBox.DefaultMovementMethod property getter.

  9. Элемент управления возвращается к android.widget.TextView конструктор, который завершает выполнение.Control returns to the android.widget.TextView constructor, which finishes execution.

  10. Monodroid.apidemo.LogTextBox конструктор выполняет вызов TypeManager.Activate() .The monodroid.apidemo.LogTextBox constructor executes, invoking TypeManager.Activate() .

  11. LogTextBox (контекст, IAttributeSet, int) конструктор выполняет на том же экземпляре, созданные в (7) .The LogTextBox(Context, IAttributeSet, int) constructor executes on the same instance created in (7) .

  12. Если (IntPtr, JniHandleOwnership) не удалось найти конструктор, то будет создано System.MissingMethodException](xref:System.MissingMethodException).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. Java.Lang.Object.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. Если конструктор не существует, будет создано исключение.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);
    }
}

Если мы создаем экземпляр Dispose() и вызвать управляемый вызываемая оболочка повторного создания: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 ());

Программа будет die: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=]

Только Dispose() из управляемых подклассов вызываемой оболочки, если известно, что больше не будет использоваться объект Java или подкласса не содержит экземпляр данных и (IntPtr, JniHandleOwnership) предоставляется конструктор.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 сначала проверяет, чтобы увидеть, существует ли уже процессом, выполняемым для размещения действие/service/etc. Если процесс не существует, то будет создан новый процесс, AndroidManifest.xml считывается и типа, указанного в /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.attachInfo%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 в AndroidManifest.xml в процессе сборки.Xamarin.Android hooks into this by adding a mono.MonoRuntimeProvider ContentProvider to AndroidManifest.xml during the build process. Mono. MonoRuntimeProvider.attachInfo() метод отвечает за загрузку среды выполнения Mono в процесс.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. ( Примечание: Вот почему типов, являющихся подклассами Android.App.Application необходимо предоставить (IntPtr, JniHandleOwnership) конструктор, как создается экземпляр приложения, перед инициализацией Mono.)( 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.app.Activity.For Activities, this type must inherit android.app.Activity. Указанный тип загружается через Class.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, затем вызовет Activity.onCreate(Bundle) , что вызовет соответствующий Activity.OnCreate(Bundle) должен быть вызван, и Готово состояния гонки.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.