Install mono on android

Install mono on android

How to install Mono and MSBuild inside Termux

Termux is an Android terminal app and Linux environment.

Mono is an implementation of .Net Framework on various platforms, including Android.

MSBuild is the default build system in Mono (and .Net).

Skip Build Mono from source and Install MSBuild if you want to use the prebuilt binaries from Releases .

Build Mono from source

There is no pre-compiled binary for Mono on Termux now, except for prooted Arch Linux and Ubuntu. (40)

Here I describe a process to cross-compile Mono 6.12 from source on Linux.

Termux now defaults to Android 7.0 (API Level 24, /data/data/com.termux/files/usr/include/android/api-level.h ). I cross-compile on Ubuntu 20.04 x86_64 and target Android 7.0.

Don’t try to build MSBuild from source, it depends on a .Net Core version which is not shipped with Visual Studio and is very difficult to compile both on Windows or on Linux. Just download the pre-compiled binary from Mono. It contains only portable .Net binaries.

Modify the path of msbuild command.

Roslyn is buggy on Mono on arm64 as it assumes the legacy x86/x86_64 memory model which guarantees memory access order in some situations on the metal.

This problem can not really be fixed in Mono, as there is a huge performance penalty. To workaround this problem, we have to force Roslyn to run single-threaded.

Transfer to device

Transfer file to /data/data/com.termux/files/usr on device.

Extract files on device.

Add usr/local/bin to system environment variable PATH if it isn’t already there.

/.bash_profile # only do this if you use a version built for Api Level >

Build AOT cache for system libraries

For our binaries to run faster, we can build AOT cache for some system libraries on device.

SSL certificate store

To use SSL, a certificate store is required.

Android provides a system certificate store at /system/etc/security/cacerts with read-only access.

Mono can use Android system certificate store, but requires Mono for Android (Xamarin Android).

But we can also use a separate certificate store like on Linux. Just copy /usr/share/.mono from a Linux device with Mono installed to

Источник

Пишем первое приложение на Mono Android

Здравствуйте. В этой статье я бы хотел поделиться своим опытом создания приложений для мобильной платформы Android с использованием Mono и разобрать простой пример.

Для начала работы с Mono Android необходимо установить:

  • Visual Studio Professional и выше либо MonoDevelop 2.6 beta 1
  • Java SDK
  • Android SDK
  • Плагин Mono for Android для Windows или Mac

Также, для создания xml layout (назовем его разметкой) нам понадобится один из графических инструментов. Я использую DroidDraw, но в сети существует множество альтернатив. Так что каждый может подобрать себе что-нибудь по вкусу.
После установки всего вышеперечисленного необходимо создать и сконфигурировать один (или несколько) эмуляторов устройств с платформой Android. Также это можно сделать при первом запуске приложения. В своем примере я использую эмулятор с версией Android 2.1.1.
Теперь можно создавать наш первый Mono Android проект.

Читайте также:  Аудиоплеер для андроид воспроизведение по папкам

Первый проект Mono Android

Создадим новый проект

И назовем его MyFirstMonoAndroidApplication.

Новый проект содержит несколько элементов: директории Assets и Resources и класс с названием Activity1.
Assets в данном примере затрагиваться не будут. На остальных элементах я бы хотел остановиться немного подробнее.
С ресурсами все достаточно просто. В директории Drawable хранятся, используемые в приложении, изображения. Директория Layout содержит набор xml разметок. А в директории Values хранятся различные предопределенные строковые значения, которые мы используем в своем приложении.
Все ресурсы, использующиеся в приложении, должны быть отмечены в свойствах как AndroidResource.
Перейдем к нашему классу Activity1. Как видно, он наследуется от базового класса Activity. Что такое Activity? Activity это одна определенная задача, которую может выполнить пользователь. Практически все Activity взаимодействуют с пользователем посредством графического интерфейса (xml разметки).

Обратим внимание на строку SetContentView(Resource.Layout.Main);
Именно в этом месте происходит загрузка и установка разметки для текущей Activity.
Немного изменим разметку и код самой Activity.
Пусть это будет простая форма с двумя кнопками, каждая из которых обрабатывает исполнение другой Activity.

xml version =»1.0″ encoding =»utf-8″ ? >
LinearLayout
android:layout_width =»fill_parent»
android:layout_height =»fill_parent»
xmlns:android =»http://schemas.android.com/apk/res/android»
android:orientation =»vertical» >
Button
android:id =»@+id/FirstExample»
android:layout_width =»fill_parent»
android:layout_height =»wrap_content»
android:text =»First Example» > Button >
Button
android:id =»@+id/SecondExample»
android:layout_width =»fill_parent»
android:layout_height =»wrap_content»
android:text =»Second Example» > Button >
LinearLayout >

* This source code was highlighted with Source Code Highlighter .

Основной класс приложения. Именно его мы увидим при запуске.

[Activity(Label = «My first mono android activity» , MainLauncher = true , Icon = «@drawable/icon» )]
public class MyMainActivity : Activity
<
protected override void OnCreate(Bundle bundle)
<
base .OnCreate(bundle);
SetContentView(Resource.Layout.Main);
Button firstExample = FindViewById (Resource.Id.FirstExample);
firstExample.Click += firstExample_Click;
Button secondExample = FindViewById (Resource.Id.SecondExample);
secondExample.Click += secondExample_Click;
>

void firstExample_Click( object sender, EventArgs e)
<
Intent titlesIntent = new Intent( this , typeof (TitlesListActivity));
StartActivity(titlesIntent);
>

void secondExample_Click( object sender, EventArgs e)
<
Intent friendlyListIntent = new Intent( this , typeof (MoreFriendlyRssFeedActivity));
StartActivity(friendlyListIntent);
>
>

* This source code was highlighted with Source Code Highlighter .

Код достаточно прост и понятен, за исключением использования нового класса Intent.
Что такое Intent? Это абстрактное описание выполняемой операции. Другими словами это намерение пользователя сделать что-то определенное. В нашем случае, при нажатии на кнопку, пользователь перейдет на другую Activity.
Чтобы скомпилировать код необходимо добавить классы, на которые мы ссылаемся. Через контекстное меню проекта добавляем две новых Activity с именами TitlesListActivity и MoreFriendlyRssFeedActivity.

Я хотел бы продемонстрировать несколько простых примеров, которые могут помочь в изучении Mono Android. Одна из основных вещей, с которой сталкивается любой программист, это отображение списка.
Пусть это будет список заголовков из RSS ленты. Создадим простенький класс для чтения RSS.

public class RssReader
<
private const string _title = «title» ;
private const string _link = «link» ;
private const string _item = «item» ;
private const string _channel = «channel» ;

private static Func XElement , RssListItem> GetTitlesAndLinksFunc = (x => new RssListItem < Title = x.Element(_title).Value, Link = x.Element(_link).Value >);

public static IList GetRssListItems( params string [] rssUris)
<
List fullList = new List ();

IEnumerable XElement > itemsFromConcreteIteration;
foreach ( string rssUri in rssUris)
<
itemsFromConcreteIteration = GetRssFeedChannel(rssUri).Elements(_item);
fullList.AddRange(itemsFromConcreteIteration.Select(GetTitlesAndLinksFunc));
>

public static IEnumerable string > GetTitles( string rssUri)
<
IEnumerable XElement > items = GetRssFeedChannel(rssUri).Elements(_item);
return items.Select(x => x.Element(_title).Value);
>

Читайте также:  System settings android что это такое

public static XElement GetRssFeedChannel( string rssUri)
<
XElement feed = XElement .Load(rssUri);
return feed.Element(_channel);
>
>

public class RssListItem
<
public string Title < get ; set ; >
public string Link < get ; set ; >
>

* This source code was highlighted with Source Code Highlighter .

Теперь отобразим этот список в Activity с именем TitlesListActivity.
Для этого будем использовать ListActivity, чье основное (и единственное) назначение – отображение списка.
Заметим, что для него не нужно задавать xml разметку и вызывать SetContentView.

[Activity(Label = «List» )]
public class TitlesListActivity : ListActivity
<
protected override void OnCreate(Bundle bundle)
<
base .OnCreate(bundle);

var titles = RssReader.GetTitles( «http://habrahabr.ru/rss/blogs/mono/» );
ListAdapter = new ArrayAdapter string >( this , Android.Resource.Layout.SimpleListItem1, titles.ToArray());
>
>

* This source code was highlighted with Source Code Highlighter .

Особый интерес представляет следующий ресурс: Android.Resource.Layout.SimpleListItem1. Это один из предопределенных ресурсов, полный список которых (вместе с разметкой), можно найти по ссылке.

TextView xmlns:android =»http://schemas.android.com/apk/res/android»
android:id =»@android:id/text1″
android:layout_width =»fill_parent»
android:layout_height =»wrap_content»
android:textAppearance =»?android:attr/textAppearanceLarge»
android:gravity =»center_vertical»
android:paddingLeft =»6dip»
android:minHeight =»?android:attr/listPreferredItemHeight»
/>

* This source code was highlighted with Source Code Highlighter .

Пришло время запуска нашего приложения.

Нажатие на первую кнопку открывает новую Activity с отображением списка заголовков в RSS ленте.

Отлично! Все работает, но, конечно же, хочется чего-то более сложного.

Усложним задачу

xml version =»1.0″ encoding =»utf-8″ ? >
resources >
string name =»ApplicationName» > MyFirstMonoAndroidApplication string >
string-array name =»frameworks» >
item > Mono item >
item > .Net item >
item > Mono and .Net item >
string-array >
resources >

* This source code was highlighted with Source Code Highlighter .

Теперь необходимо создать новую разметку MoreFriendlyRssFeed.xml

xml version =»1.0″ encoding =»utf-8″ ? >
LinearLayout
android:layout_width =»fill_parent»
android:layout_height =»fill_parent»
xmlns:android =»http://schemas.android.com/apk/res/android»
android:orientation =»vertical» >
Spinner
android:id =»@+id/FrameworkSelector»
android:layout_width =»fill_parent»
android:layout_height =»wrap_content» >
Spinner >
ListView
android:id =»@+id/RssEntries»
android:layout_width =»fill_parent»
android:layout_height =»wrap_content» >
ListView >
LinearLayout >

* This source code was highlighted with Source Code Highlighter .

Все очень просто: Spinner для выбора ленты и ListView для отображения списка. Важно понимать, что про разметку элементов внутри списка ListView (а точнее, его адаптер), на данном этапе, ничего не знает. Исходя из данной разметки можно сказать, что ListView просто отображает «какой-то» список.

Также необходимо создать разметку для элемента списка. Назовем ее RssRow.xml. Пусть каждый элемент списка включает кнопку с изображением и текст – заголовок статьи.

xml version =»1.0″ encoding =»utf-8″ ? >
LinearLayout xmlns:android =»http://schemas.android.com/apk/res/android»
android:layout_width =»fill_parent»
android:layout_height =»wrap_content»
android:padding =»6dip» >
ImageButton
android:id =»@+id/LogoButton»
android:layout_width =»wrap_content»
android:layout_height =»wrap_content»
android:src =»@drawable/mono» >
ImageButton >
TextView
android:id =»@+id/Title»
android:layout_width =»wrap_content»
android:layout_height =»wrap_content» >
TextView >
LinearLayout >

* This source code was highlighted with Source Code Highlighter .

Настало время переходить к самому главному: реализации Activity, которая свяжет все наши части воедино.

[Activity(Label = «Friendly List» )]
public class MoreFriendlyRssFeedActivity : Activity
<
protected override void OnCreate(Bundle bundle)
<
base .OnCreate(bundle);
SetContentView(Resource.Layout.MoreFriendlyRssFeed);

Spinner spinner = FindViewById (Resource.Id.FrameworkSelector);
spinner.ItemSelected += spinner_ItemSelected;
ArrayAdapter adapter = ArrayAdapter.CreateFromResource( this , Resource.Array.frameworks, Android.Resource.Layout.SimpleSpinnerItem);
adapter.SetDropDownViewResource(
Android.Resource.Layout.SimpleSpinnerDropDownItem);
spinner.Adapter = adapter;
>

void spinner_ItemSelected( object sender, ItemEventArgs e)
<>
>

* This source code was highlighted with Source Code Highlighter .

Обратим внимание на еще один предопределенный ресурс Android.Resource.Layout.SimpleSpinnerItem. Для удобства, также приведу его разметку:

TextView xmlns:android =»http://schemas.android.com/apk/res/android»
android:id =»@android:id/text1″
style =»?android:attr/spinnerItemStyle»
android:singleLine =»true»
android:layout_width =»fill_parent»
android:layout_height =»wrap_content»/>

* This source code was highlighted with Source Code Highlighter .

Читайте также:  Alfaobd android полная версия

Для отображения текста в списке используется класс ArrayAdapter. Если же нам необходимо отобразить нечто более сложное, то мы сталкиваемся с необходимостью реализации собственного класса, наследника от ArrayAdapter, переопределяющего метод GetView. Создадим класс RssListItemAdapter для привязки и отображения данных:

public class RssListItemAdapter: ArrayAdapter
<
private IList Items;

public RssListItemAdapter(Context context, int textViewResourceId, IList items)
: base (context, textViewResourceId, items)
<
Items = items;
>

public override View GetView( int position, View convertView, ViewGroup parent)
<
View view = convertView;
if (view == null )
<
LayoutInflater inflater = (LayoutInflater)Context.GetSystemService(Context.LayoutInflaterService);
//выбираем разметку, которую будем наполнять данными.
view = inflater.Inflate(Resource.Layout.RssRow, null );
>

//получаем текущий элемент
RssListItem item = Items[position];

//находим и привязываем к данным содержимое одного элемента в списке
//пусть при нажатии на кнопку открывается браузер с соответствующей статьей
ImageButton btnLogo = (ImageButton)view.FindViewById(Resource.Id.LogoButton);
btnLogo.Click += delegate
<
Intent browserIntent = new Intent( «android.intent.action.VIEW» , Android.Net. Uri .Parse(item.Link));
Context.StartActivity(browserIntent);
>;

//добавляем картинку на кнопку (из ресурсов)
btnLogo.SetImageResource(item.Title.StartsWith( «Mono» ) ? Resource.Drawable.mono : Resource.Drawable.net);

//устанавливаем текст
TextView txtTitle = (TextView)view.FindViewById(Resource.Id.Title);
txtTitle.Text = item.Title;

//возвращаем элемент списка с привязанными данными
return view;
>
>

* This source code was highlighted with Source Code Highlighter .

Теперь возможно привязать данные к списку и отобразить их в нужном нам виде. Добавим возможность привязки к данным в обработчик события выбора элемента из списка.

void spinner_ItemSelected( object sender, ItemEventArgs e)
<
ListView view = FindViewById
(Resource.Id.RssEntries);

switch (e.Position)
<
case 0:
view.Adapter = new RssListItemAdapter( this , Resource.Layout.RssRow, RssReader.GetRssListItems( «http://habrahabr.ru/rss/blogs/mono/» ));
break ;
case 1:
view.Adapter = new RssListItemAdapter( this , Resource.Layout.RssRow, RssReader.GetRssListItems( «http://habrahabr.ru/rss/blogs/net/» ));
break ;
case 2:
view.Adapter = new RssListItemAdapter( this , Resource.Layout.RssRow, RssReader.GetRssListItems( «http://habrahabr.ru/rss/blogs/mono/» , «http://habrahabr.ru/rss/blogs/net/» ));
break ;
>
>

* This source code was highlighted with Source Code Highlighter .

Запустим приложение и откроем второй пример. Теперь у нас есть возможность выбора RSS ленты (или набора лент).

Наш список будет выглядеть следующим образом:

При нажатии на кнопку рядом с заголовком, соответствующая статья откроется в браузере.

Запуск приложения на Android устройстве

Дело за малым: запустить приложение на конкретном Android устройстве. Если мы попытаемся сделать это прямо сейчас, то получим ошибку при попытке сборки apk (Android Package) файла. Также хотел бы указать, что trial версия Mono Android позволяет запускать приложения только на эмуляторе. К счастью, моя версия уже не trial, поэтому я смогу довести пример до логического завершения.
Для корректной сборки инсталляционного пакета необходимо создать AndroidManifest.xml. Этот файл содержит ключевую информацию о приложении, информацию без которой запуск приложения на устройстве невозможен.

Существует возможность создания AndroidManifest.xml через свойства проекта:

Но гораздо интереснее будет написать его руками:

xml version =»1.0″ encoding =»utf-8″ ? >
manifest xmlns:android =»http://schemas.android.com/apk/res/android» package =»First.MonoApp» android:versionCode =»1″ android:versionName =»1.0″ >
application android:label =»MyMonoApp» >
application >
uses-sdk android:minSdkVersion =»4″/>
uses-permission android:name =»android.permission.INTERNET»/>
manifest >

* This source code was highlighted with Source Code Highlighter .

Теперь можно собирать apk файл. Build -> Package MyFirstMonoAndroidApplication for Android (.apk)
Копируем его на устройство с системой Android и запускаем. В процессе инсталляции будет показано предупреждение:
Allow this application to: Full access to Internet.
То есть все необходимые требования из манифеста будут показаны пользователю до инсталляции. Подтверждаем, ждем окончания инсталляции. И…

Источник

Оцените статью