Xamarin.Android applications use a linker in order to reduce the size of the application. The linker employes static analysis of your application to determine which assemblies are actually used, which types are actually used, and which members are actually used. The linker then behaves like a garbage collector, continually looking for the assemblies, types, and members that are referenced until the entire closure of referenced assemblies, types, and members is found. Then everything outside of this closure is discarded.

For example, the Hello, Android sample:

Configuration 1.2.0 Size 4.0.1 Size
Release without Linking: 14.0 MB 16.0 MB
Release with Linking: 4.2 MB 2.9 MB

Linking results in a package that is 30% the size of the original (unlinked) package in 1.2.0, and 18% of the unlinked package in 4.0.1.

Control

Linking is based on static analysis. Consequently, anything that depends upon the runtime environment won't be detected:

// To play along at home, Example must be in a different assembly from MyActivity.
public class Example {
// Compiler provides default constructor...
} [Activity (Label="Linker Example", MainLauncher=true)]
public class MyActivity {
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle); // Will this work?
var o = Activator.CreateInstance (typeof (ExampleLibrary.Example));
}
}

Linker Behavior

The primary mechanism for controlling the linker is the Linker Behavior drop-down within the Project Options dialog box. There are three options:

  1. Don't Link
  2. Link SDK Assemblies
  3. Link All Assemblies

The Don't Link option turns off the linker; the above "Release without Linking" application size used this behavior. This is useful for troubleshooting runtime failures, to see if the linker is responsible.

The Link SDK Assemblies option only links assemblies that come with Xamarin.Android. All other assemblies are not linked.

The Link All Assemblies option links all assemblies.

The above example will work with the Don't Link and Link SDK Assemblies options, and will fail with the Link All Assemblies behavior, generating the following error:

E/mono    (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
I/MonoDroid(17755): UNHANDLED EXCEPTION: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type,bool) <0x00180>
I/MonoDroid(17755): at System.Activator.CreateInstance (System.Type) <0x00017>
I/MonoDroid(17755): at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle) <0x00027>
I/MonoDroid(17755): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (intptr,intptr,intptr) <0x00057>
I/MonoDroid(17755): at (wrapper dynamic-method) object.95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124 (intptr,intptr,intptr) <0x00033>
E/mono (17755): [0xafd4d440:] EXCEPTION handling: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
E/mono (17755):
E/mono (17755): Unhandled Exception: System.MissingMethodException: Default constructor not found for type ExampleLibrary.Example.
E/mono (17755): at System.Activator.CreateInstance (System.Type type, Boolean nonPublic) [0x00000] in <filename unknown>:0
E/mono (17755): at System.Activator.CreateInstance (System.Type type) [0x00000] in <filename unknown>:0
E/mono (17755): at LinkerScratch2.Activity1.OnCreate (Android.OS.Bundle bundle) [0x00000] in <filename unknown>:0
E/mono (17755): at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState) [0x00000] in
<filename unknown>:0
E/mono (17755): at (wrapper dynamic-method) object:95bb4fbe-bef8-4e5b-8e99-ca83a5d7a124 (intptr,intptr,intptr)

PreserveAttribute

The Android.Runtime.PreserveAttribute can be used to explicitly add members to be preserved by the linker, and should be placed on a member when the linker would otherwise remove it. Thus, for the above example to work, we could either place [Preserve] on the constructor:

public class Example {
[Android.Runtime.Preserve]
public Example ()
{
}
}

Or we could use [Preserve(AllMembers=true)] on the type to preseve all members. This is also useful for XML serialization:

[Android.Runtime.Preserve(AllMembers=true)]
class Example {
// Compiler provides default constructor...
}

falseflag

If the [Preserve] attribute can't be used, it is often useful to provide a block of code so that the linker believes that the type is used, while preventing the block of code from being executed at runtime. To make use of this technique, we could do:

[Activity (Label="Linker Example", MainLauncher=true)]
class MyActivity { #pragma warning disable 0219, 0649
static bool falseflag = false;
static MyActivity ()
{
if (falseflag) {
var ignore = new Example ();
}
}
#pragma warning restore 0219, 0649 // ...
}

linkskip

It is possible to specify that a set of user-provided assemblies should not be linked at all, while allowing other user assemblies to be skipped with the Link SDK Assemblies behavior by using the AndroidLinkSkip MSBuild property:

<PropertyGroup>
<AndroidLinkSkip>Assembly1;Assembly2</AndroidLinkSkip>
</PropertyGroup>

Custom Attributes

When an assembly is linked, the following custom attribute types will be removed from all members:

  • System.ObsoleteAttribute
  • System.MonoDocumentationNoteAttribute
  • System.MonoExtensionAttribute
  • System.MonoInternalNoteAttribute
  • System.MonoLimitationAttribute
  • System.MonoNotSupportedAttribute
  • System.MonoTODOAttribute
  • System.Xml.MonoFIXAttribute

When an assembly is linked, the following custom attribute types will be removed from all members in Release builds:

  • System.Diagnostics.DebuggableAttribute
  • System.Diagnostics.DebuggerBrowsableAttribute
  • System.Diagnostics.DebuggerDisplayAttribute
  • System.Diagnostics.DebuggerHiddenAttribute
  • System.Diagnostics.DebuggerNonUserCodeAttribute
  • System.Diagnostics.DebuggerStepperBoundaryAttribute
  • System.Diagnostics.DebuggerStepThroughAttribute
  • System.Diagnostics.DebuggerTypeProxyAttribute
  • System.Diagnostics.DebuggerVisualizerAttribute

Xamarin.Android,Xamarin.iOS, Linking的更多相关文章

  1. Xamarin.Android之简单的抽屉布局

    0x01 前言 相信对于用过Android版QQ的,应该都不会陌生它那个向右滑动的菜单(虽说我用的是Lumia) 今天就用Xamarin.Android实现个比较简单的抽屉布局.下面直接进正题. 0x ...

  2. Xamarin.Android 反复报 Please Download android_m2repository_rxx.zip 的解决办法

    我原来一直用的是老版本的 Xamarin , android_m2repository_rxx.zip 早已在 C:\Users\XXX\AppData\Local\Xamarin\Android.S ...

  3. Xamarin For Visual Studio 3.0.54.0 完整离线破解版(C# 开发Android、IOS工具 吾乐吧软件站分享)

    Xamarin For Visual Studio就是原本的Xamarin For Android 以及 Xamarin For iOS,最新版的已经把两个独立的插件合并为一个exe安装包了.为了区分 ...

  4. Xamarin Mono For Android 4.6.07004 完整离线安装破解版(C#开发Android、IOS工具)

      Xamarin是由Miguel de Icaza成立的一家新的独立公司,目的是给Mono一个继续奋斗的机会.Mono for Android (原名:MonoDroid)可以让开发人员使用 Mic ...

  5. Xamarin Mono 环境搭建(使用Visual Studio 2013 开发android 和 ios )

    本文主要介绍Xamarin结合VS2013来开发Android应用程序,主要会介绍Mono和Xamarin的关系,以及整个搭建环境的过程. 一.Mono和Xamarin介绍 1.Mono简介 Mono ...

  6. ComponentOne Xuni助力Xamarin开发者突破百万,快速开发Android、IOS Apps

    在微软Build 2015上,随着VS 2015的预览版发布,Xamrine免费版已经作为VS 2015跨平台移动解决方案的核心.与此同时,Xamarin官方也宣布其用户量达到百万之多.2011年7月 ...

  7. Xamarin.Android 4.10.01068 & Xamarin.iOS 1.8.361

    Xamarin.Android 4.10.01068 & Xamarin.iOS 1.8.361 NEW support for Visual Studio 2013 & Portab ...

  8. 张高兴的 Xamarin.Forms 开发笔记:为 Android 与 iOS 引入 UWP 风格的汉堡菜单 ( MasterDetailPage )

    所谓 UWP 样式的汉堡菜单,我曾在"张高兴的 UWP 开发笔记:汉堡菜单进阶"里说过,也就是使用 Segoe MDL2 Assets 字体作为左侧 Icon,并且左侧使用填充颜色 ...

  9. Xamarin.Form与Xamarin.Android或Xamarin.IOS的区别简述

    Xamarin.Form与Xamarin.Android或Xamarin.IOS的区别简述: 可能刚刚接触Xamarin的人来说,对于这个概念比较的模糊,认为这说的不都是同一个东西吗?事实并不是这样的 ...

随机推荐

  1. 使用pt-table-checksum校验MySQL主从复制【转】

    pt-table-checksum是一个基于MySQL数据库主从架构在线数据一致性校验工具.其工作原理在主库上运行, 通过对同步的表在主从段执行checksum, 从而判断数据是否一致.在校验完毕时, ...

  2. scp拷贝文件报错-bash: scp: command not found

    今天用scp远程传输资料,报错如下: -bash: scp: command not found 在网上搜资料解决办法如下: 安装scp的软件包: # yum install openssh-clie ...

  3. Fiddler实现移动端手机抓包

    Fiddler是一个http调试代理,它能 够记录所有的你电脑和互联网之间的http通讯,Fiddler 可以也可以让你检查所有的http通讯,设置断点,以及Fiddle 所有的“进出”的数据(指co ...

  4. Coursera台大机器学习技法课程笔记08-Adaptive Boosting

    将分类器组合的过程中,将重点逐渐聚焦于那些被错分的样本点,这种做法背后的数学原因,就是这讲的内容. 在用bootstraping生成g的过程中,由于抽样对不同的g就生成了不同的u,接下来就是不断的调整 ...

  5. yum安装tomcat

    http://www.cnblogs.com/liaolongjun/p/5638740.html http://www.awspack.com/os/linux/yum-install-tomcat ...

  6. Java编程的逻辑 (35) - 泛型 (上) - 基本概念和原理

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  7. tomcat启动不成功(点击startup.bat闪退)的解决办法

    今天遇到tomcat手动启动不成功,但是再eclipse里面是可以启动成功的.我一直开始以为是端口被占用了,最后才发现是这么一回事.首先说下我的tomcat是安装版的.免安装的tomcat双击star ...

  8. 牛客练习赛16 E - 求值

    题目大意: 链接:https://www.nowcoder.com/acm/contest/84/E 给定n个数字a1, a2, ..., an. 定义f(l, r) = al | al+1| ... ...

  9. 009.MySQL-Keepalived搭配脚本03

    vim /etc/keepalived/check_MySQL.sh #vim #!/bin/bash MYSQL=/usr/local/mysql/bin/mysql MYSQL_HOST=loca ...

  10. InnoDB的锁机制浅析(五)—死锁场景(Insert死锁)

    可能的死锁场景 文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意 ...