- В недрах процесса построения Android сборки
- Сжатие текстур.
- Google Android Project
- Сборка плагинов для Android
- Сборка плагина для Android
- Использование вашего плагина из C
- Проекты библиотек для Android
- Развертывание
- Использование плагинов Java
- Сборка Java-плагина для Android
- Использование ваших Java-плагинов из нативного кода
- Использование Java-плагинов со вспомогательными классами
- Пример 1
- Пример 2
- Пример 3
- Лучшая практика при использовании плагинов Java с Unity
- Расширение Java-кода UnityPlayerActivity
- UnityPlayerNativeActivity
- Примеры
- Пример нативного плагина
- Пример плагина Java
В недрах процесса построения Android сборки
Сборка Android-приложения происходит в два этапа:
- Генерируется дистрибутив приложения (.apk-файл) со всеми необходимыми библиотеками и сериализованными ассетами.
- Пакет приложения разворачивается на текущем устройстве.
Кнопка “Build” в окне “Build settings” запускает лишь первый этап. Кнопка “Build and Run” выполняет оба этапа.
При первой сборке Android-проекта Unity попросит вас указать путь до Android SDK, требуемого для сборки и установки вашего Android приложения на устройство. Вы можете поменять его позже в Preferences .
При сборке приложения под Android убедитесь, что в настройках устройства включены “USB Debugging” и “Allow mock locations”.
Run the adb devices command found in your Android SDK/platform-tools folder, so that the operating system can see your device. This should work both for Mac and Windows.
Unity соберёт дистрибутив приложения (.apk-файл) и установит его на ваше подключенное устройство. Иногда ваше приложение не сможет запуститься само как на iPhone, и вам нужно будет разблокировать экран; в редких случаях вам придётся запустить только что установленное приложение из меню.
Сжатие текстур.
В Build Settings вы также найдёте опцию Texture Compression . По умолчанию, Unity использует ETC1/RGBA16 формат для текстур, которые не имеют индивидуальных переопределений (см. 2D текстуры / переопределения для платформ).
Если вы желаете собрать архив приложения (.apk файл), нацеленного на определённую архитектуру оборудования, вы можете использовать опцию Texture Compression для переопределения поведения по умолчанию. Все несжатые текстуры (с отключенным сжатием в настройках импортера) останутся без изменений; только текстуры со сжатым форматом будут использовать выбранный в Texture Compression формат.
Чтобы убедиться, что приложение разворачивается только на устройствах, поддерживающих выбранное сжатие текстур, Unity включит в AndroidManifest тэги, соответствующие выбранному формату. Это позволит механизму фильтрации Android Market’а предоставлять приложение только тем устройствам, у которых имеется соответствующее графическое оборудование.
Google Android Project
Generates a project which can be opened by Android Studio. Simply follow the steps:
- Download Android Studio.
- Export the project from Unity with Google Android project checkbox selected.
- Open Android Studio:
- File->Import Project. For ex., if you project was exported to C:\MyProjects, pick C:\MyProjects
Источник
Сборка плагинов для Android
На этой странице описан нативный код плагинов для Android.
Сборка плагина для Android
Чтобы построить плагин для Android, вы должны сначала получить Android NDK и ознакомиться с инструкцией по созданию общей библиотеки.
Если вы используете C++ (.cpp), при создании плагина вы должны убедиться, что функции объявлены с C-связями, чтобы избежать проблем с коверканьем имен.
Использование вашего плагина из C
После сборки, общая библиотека должна быть скопированы в папку Assets->Plugins->Android . Unity будет искать её по имени, когда вы определяете функцию вроде следующей в C#-скрипте:-
Обратите внимание, что PluginName не должно включать ни префикс (‘Lib’), ни расширение (‘.so’). Вы должны обернуть все нативные методы кода дополнительным слоем C#-кода. Этот код должен проверить Application.platform и вызывать собственные методы только тогда, когда приложение работает на реальном устройстве; фиктивные значения могут быть возвращены из С#-кода при работе в редакторе. Вы также можете использовать определения платформы для контроля зависимости компиляции кода от платформы.
Проекты библиотек для Android
Вы можете закинуть проекты прекомпилированной Android библиотеки в папку Assets->Plugins->Android . Прекомпилированная — значит все .java файлы должны быть скомпилированы в jar файлы, расположенные либо в папке bin/, либо в папке libs/ проекта. AndroidManifest.xml из этих папок будет автоматически объединяться с основным файлом манифеста при сборке проекта.
Смотрите Проекты библиотек для Android для большей информации.
Развертывание
Для кросс-платформенного развертывания, ваш проект должен включать плагины для каждой поддерживаемой платформы (т.е. libPlugin.so для Android, Plugin.bundle для Mac и Plugin.dll для Windows). Unity автоматически выбирает правильный плагин для целевой платформы и включает его с плеером.
For specific Android platform (armv7, x86), the libraries (lib*.so) should be placed in the following:
Использование плагинов Java
Механизм Android-плагина также обеспечивает Java, который будет использоваться для взаимодействия с ОС Android.
Сборка Java-плагина для Android
Есть несколько способов создать плагин Java, но результатом во всех случаях является файл .jar, содержащий файлы .class для вашего плагина. Один из подходов — скачать JDK, затем скомпилировать файлы .java из командной строки с javac. Это создаст файлы .class, которые затем можно упаковать в .jar из командной строки с утилитой jar. Другой вариант заключается в использовании Eclipse IDE вместе с ADT.
Примечание: Unity ожидает Java-плагины, которые будут построены с использованием JDK v1.6. Если вы используете v1.7, вы должны включить “-source 1,6 -target 1,6” в параметрах командной строки для компилятора.
Использование ваших Java-плагинов из нативного кода
После того как вы создали свой Java-плагин (.jar), вы должны скопировать его в папку Assets->Plugins->Android в проекте Unity. Unity упакует ваши файлы .class вместе с остальной частью Java-кода, а затем получить доступ к коду, используя Java Native Interface (JNI). JNI используется как при вызове нативного кода из Java, так и при взаимодействии с Java (или JavaVM) из нативного кода.
Чтобы найти Java код из нативной части, вы должны иметь доступ к Java VM. К счастью, доступ можно легко получить, добавив такую функцию в свой C/C++ код:
Это все, что необходимо, чтобы начать использовать Java из C/C++. Полное объяснение JNI выходит за рамки этого документа. Однако его использование, как правило, включает в себя поиск определения класса, поиск метода конструктора ( ) и создание нового экземпляра объекта, как показано в этом примере:-
Использование Java-плагинов со вспомогательными классами
AndroidJNIHelper и AndroidJNI могут быть использованы для избавления от некоторых проблем с первичным JNI.
AndroidJavaObject и AndroidJavaClass автоматизируют множество задач и используют кэширование для ускорения вызовов к Java. Комбинация AndroidJavaObject и AndroidJavaClass надстраивается над AndroidJNI и AndroidJNIHelper , но также содержит много логики сама по себе (для управления автоматизацией). Эти классы также идут в ‘static’ версии для доступа к статическим членам Java классов.
Вы можете выбрать в зависимости от того, что вам подходит, будь то первичный JNI с помощью методов класса AndroidJNI , или AndroidJNIHelper вместе с AndroidJNI , и в конце концов AndroidJavaObject/AndroidJavaClass для максимальной автоматизации и удобства.
UnityEngine.AndroidJNI является оберткой для вызовов JNI доступных в C (как описано выше). Все методы этого класса являются статическими и соответствуют 1:1 Java Native Interface. UnityEngine.AndroidJNIHelper предоставляет вспомогательный модуль, используемый на следующем уровне, но предоставляется как открытые методы, потому что они могут быть полезны для некоторых частных случаев.
Экземпляры UnityEngine.AndroidJavaObject и UnityEngine.AndroidJavaClass соответствуют один-в-один экземпляру java.lang.Object и java.lang.Class (или их подклассов) на стороне Java, соответственно. Они по существу обеспечивают 3 типа взаимодействия с Java:-
- Вызов метода
- Получить значения поля
- Установить значение поля
Call (Вызов) разделяется на две категории: Call (Вызов) ‘void’ метода, и Call (Вызов) метода, возвращающего не-void тип. Универсальный тип используется для представления типа возвращаемого методами, которые возвращают не-void тип. Get и Set всегда берут универсальный тип, представляющий тип поля.
Пример 1
Здесь мы создаем экземпляр java.lang.String, инициализируемстроку на свой выбор и извлекаем хеш значение для этой строки.
Конструктор AndroidJavaObject принимает минимум один параметр, имя класса, экземпляр которого хотим создать. Любые параметры после имени класса предназначены для вызова конструктора объекта, в данном случае строка “some_string”. Последующий Call (Вызов) метода hashCode() возвращает ‘int’, который мы используем в качестве параметра универсального типа в Call (Вызове) метода.
Примечание: Вы не можете создать экземпляр вложенного класса Java с помощью разделения точкой. Внутренние классы должны использовать разделитель $, и это должно работать в точечном и слэш формате. Так \[android.view.ViewGroup$LayoutParams или android/view/ViewGroup$LayoutParams могут быть использованы, где LayoutParams класс вложенный в класс ViewGroup\] .
Пример 2
Один из примеров плагина выше показывал, как получить директорию кэша для текущего приложения. Вот, как вы могли бы сделать то же самое на C# без плагинов:-
В этом случае, мы начинаем с AndroidJavaClass вместо AndroidJavaObject , потому что мы хотим получить доступ к статическому члену com.unity3d.player.UnityPlayer , а не создавать новый объект (экземпляр создается автоматически в Android UnityPlayer ). Затем мы получаем доступ к статическому полю “currentActivity”, но на этот раз мы используем AndroidJavaObject как универсальный параметр. Потому что фактический тип поля (android.app.Activity) — это подкласс java.lang.Object), и любой не-примитивный тип обязательно должен быть доступен как AndroidJavaObject . Исключением из этого правила являются строки, которые могут быть доступны непосредственно, даже если они не представляют собой примитивный тип в Java.
После чего это уже просто вопрос обхода Activity через getCacheDir() для получения объекта File, представляющего папку кэша с последующим вызовом getCanonicalPath() для получения строкового представления.
Конечно, в настоящее время вам не нужно делать этого, чтобы получить каталог кэша, поскольку Unity предоставляет доступ к директории кэша и файлов приложения с Application.temporaryCachePath и Application.persistentDataPath.
Пример 3
Наконец, здесь есть уловка для передачи данных из Java в код скрипта с помощью UnitySendMessage .
Класс Java com.unity3d.player.UnityPlayer теперь имеет статический метод UnitySendMessage , что эквивалентно функции UnitySendMessage в нативной части iOS. Он может быть использован в Java для передачи данных в код скрипта.
Здесь, однако, мы вызываем непосредственно из кода скрипта, который по сути передает сообщение Java. Это посылает обратный вызов нативному/Unity коду, чтобы доставить сообщение объекту с именем “Main Camera”. Этот объект имеет скрипт, который содержит метод, называемый “JavaMessage”.
Лучшая практика при использовании плагинов Java с Unity
Так как этот раздел в основном ориентирован на людей, которые не имеют большого опыта работы с JNI, Java и Android, мы предполагаем, что подход с AndroidJavaObject/AndroidJavaClass был использован для взаимодействия с кодом Java из Unity.
Первое, что нужно отметить, это то, что любая операция выполненная с AndroidJavaObject или AndroidJavaClass дорогая в отношении производительности (как первичный JNI подход). Крайне желательно, чтобы количество переходов между управляемым и нативным/Java кодом было минимальным, ради производительности, а также ясности кода.
У вас может быть метод Java, чтобы сделать всю фактическую работу, а затем использовать AndroidJavaObject/AndroidJavaClass для взаимодействия с этим методом и получения результата. Однако стоит иметь в виду, что вспомогательные классы JNI попробуют кэшировать столько данных, сколько возможно, чтобы улучшить производительность.
Сборщик мусора Mono должен освободить все созданные экземпляры AndroidJavaObject и AndroidJavaClass после использования, но желательно держать их в операторе using()<> , чтобы они удалялись как можно скорее. Без этого вы не можете точно знать, когда они будут уничтожены. Если вы установите значение AndroidJNIHelper.debug в true, вы увидите запись деятельности сборщика мусора в журнале отладки.
Вы также можете непосредственно вызвать метод .Dispose() для гарантии, что нет сохранившихся Java-объектов. Фактически C# объект может жить немного дольше, но в конце концов будет удалён сборщиком мусора mono.
Расширение Java-кода UnityPlayerActivity
С Unity Android можно расширить стандартный класс UnityPlayerActivity (основной класс Java для Unity плеера на Android, аналогично AppController.mm на Unity iOS).
Приложение может переопределить любые и все основные взаимодействия между ОС Android и Unity Android. Вы можете cделать это, создав новую Activity, которая является производной от UnityPlayerActivity(UnityPlayerActivity.java можно найти в /Applications/Unity/Unity.app/Contents/PlaybackEngines/AndroidPlayer/src/com/unity3d/player на Mac и обычно в C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\src\com\unity3d\player на Windows).
Чтобы сделать это, сначала найдите classes.jar , поставляемый с Unity Android. Он находится в папке установки (обычно C:\Program Files\Unity\Editor\Data (на Windows) или /Applications/Unity (на Mac)) в подпапке PlaybackEngines/AndroidPlayer/bin . Затем добавить PlaybackEngines/AndroidPlayer/bin в папку с классами, используемыми для компиляции новой Activity. Полученный(-ые) .class файл(ы) должны быть сжаты в .jar файл, а этот файл надо добавить в папку Assets->Plugins->Android . Поскольку манифест определяет запуск Activity, его также необходимо создать новый AndroidManifest.xml. Файл AndroidManifest.xml также должен быть помещен в папку Assets->Plugins->Android (размещение пользовательского манифеста полностью заменяет манифест Unity Android по умолчанию).
Новая Activity может выглядеть, как в следующем примере OverrideExample.java:
И соответствующий AndroidManifest.xml будет выглядеть так:
UnityPlayerNativeActivity
Кроме того, можно создать свой собственный подкласс UnityPlayerNativeActivity . Это будет иметь такой же эффект, как создать подкласс UnityPlayerActivity но с улучшенной задержкой ввода. Помните, однако, что NativeActivity был введен в Gingerbread и не работает со старыми устройствами. Поскольку события касания/движения обрабатываются в нативном коде, окна Java обычно не увидят эти события. Существует, однако, механизм переадресации в Unity, который позволяет, чтобы события распространялись на DalvikVM. Для доступа к этому механизму, необходимо изменить файл манифеста, выглядит следующим образом:-
Обратите внимание на атрибут “.OverrideExampleNative” в элементе Activity и два дополнительных элемента мета-данных. Первый элемент мета-данных является инструкцией по использованию библиотеки libunity.so для Unity. Второй обеспечивает события, которые будут переданы пользовательскому подклассу UnityPlayerNativeActivity.
Примеры
Пример нативного плагина
Простой пример использования кода нативного плагина можно найти здесь
В этом примере демонстрируется как код С может быть вызван из приложения Unity Android. Пакет содержит сцену, которая отображает сумму двух значений, рассчитанную нативным плагином. Пожалуйста, обратите внимание, что вам нужен будет Android NDKдля компиляции плагина.
Пример плагина Java
Используемый в примере код Java можно найти здесь
В этом примере демонстрируется как код Java может быть использован для взаимодействия с ОС Android, и как C++ создает мост между C# и Java. Сцена в пакете отображает кнопку, при нажатии на которую выдается каталог кэша приложения, как это определено в ОС Android. Пожалуйста, обратите внимание, что вам понадобится JDK и Android NDK для компиляции плагинов.
Здесь находиться подобный пример, но на основе предварительно собранной библиотеки JNI, чтобы обернуть нативный код в C#.
Источник