Сборка плагинов для Android
На этой странице описан нативный код плагинов для Android.
Сборка плагина для Android
Чтобы построить плагин для Android, вы должны сначала получить Android NDK и ознакомиться с инструкцией по созданию общей библиотеки.
Если вы используете C++ (.cpp), при создании плагина вы должны убедиться, что функции объявлены с C-связями, чтобы избежать проблем с коверканьем имен.
extern "C"
Использование вашего плагина из C
После сборки, общая библиотека должна быть скопированы в папку Assets->Plugins->Android . Unity будет искать её по имени, когда вы определяете функцию вроде следующей в C#-скрипте:-
[DllImport ("PluginName")] private static extern float FooPluginFunction ();
Обратите внимание, что 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++ код:
jint JNI_OnLoad(JavaVM* vm, void* reserved) < JNIEnv* jni_env = 0; vm->AttachCurrentThread(&jni_env, 0); return JNI_VERSION_1_6; >
Это все, что необходимо, чтобы начать использовать Java из C/C++. Полное объяснение JNI выходит за рамки этого документа. Однако его использование, как правило, включает в себя поиск определения класса, поиск метода конструктора () и создание нового экземпляра объекта, как показано в этом примере:-
jobject createJavaObject(JNIEnv* jni_env) < jclass cls_JavaClass = jni_env->FindClass("com/your/java/Class"); // find class definition jmethodID mid_JavaClass = jni_env->GetMethodID (cls_JavaClass, "", "()V"); // find constructor method jobject obj_JavaClass = jni_env->NewObject(cls_JavaClass, mid_JavaClass); // create object instance return jni_env->NewGlobalRef(obj_JavaClass); // return object with a global reference >
Использование 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
//The comments describe what you would need to do if you were using raw JNI AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", "some_string"); // jni.FindClass("java.lang.String"); // jni.GetMethodID(classID, "", "(Ljava/lang/String;)V"); // jni.NewStringUTF("some_string"); // jni.NewObject(classID, methodID, javaString); int hash = jo.Call("hashCode"); // jni.GetMethodID(classID, "hashCode", "()I"); // jni.CallIntMethod(objectID, methodID);
Здесь мы создаем экземпляр java.lang.String, инициализируемстроку на свой выбор и извлекаем хеш значение для этой строки.
Конструктор AndroidJavaObject принимает минимум один параметр, имя класса, экземпляр которого хотим создать. Любые параметры после имени класса предназначены для вызова конструктора объекта, в данном случае строка “some_string”. Последующий Call (Вызов) метода hashCode() возвращает ‘int’, который мы используем в качестве параметра универсального типа в Call (Вызове) метода.
Примечание: Вы не можете создать экземпляр вложенного класса Java с помощью разделения точкой. Внутренние классы должны использовать разделитель $, и это должно работать в точечном и слэш формате. Так \[android.view.ViewGroup$LayoutParams или android/view/ViewGroup$LayoutParams могут быть использованы, где LayoutParams класс вложенный в класс ViewGroup\] .
Пример 2
Один из примеров плагина выше показывал, как получить директорию кэша для текущего приложения. Вот, как вы могли бы сделать то же самое на C# без плагинов:-
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); // jni.FindClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic("currentActivity"); // jni.GetStaticFieldID(classID, "Ljava/lang/Object;"); // jni.GetStaticObjectField(classID, fieldID); // jni.FindClass("java.lang.Object"); Debug.Log(jo.Call("getCacheDir").Call("getCanonicalPath")); // jni.GetMethodID(classID, "getCacheDir", "()Ljava/io/File;"); // or any baseclass thereof! // jni.CallObjectMethod(objectID, methodID); // jni.FindClass("java.io.File"); // jni.GetMethodID(classID, "getCanonicalPath", "()Ljava/lang/String;"); // jni.CallObjectMethod(objectID, methodID); // jni.GetStringUTFChars(javaString);
В этом случае, мы начинаем с 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 .
using UnityEngine; public class NewBehaviourScript : MonoBehaviour < void Start () < AndroidJNIHelper.debug = true; using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) < jc.CallStatic("UnitySendMessage", "Main Camera", "JavaMessage", "whoowhoo"); >> void JavaMessage(string message) < Debug.Log("message from java: " + message); >>
Класс 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 попробуют кэшировать столько данных, сколько возможно, чтобы улучшить производительность.
//The first time you call a Java function like AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", "some_string"); // somewhat expensive int hash = jo.Call("hashCode"); // first time - expensive int hash = jo.Call("hashCode"); // second time - not as expensive as we already know the java method and can call it directly
Сборщик мусора Mono должен освободить все созданные экземпляры AndroidJavaObject и AndroidJavaClass после использования, но желательно держать их в операторе using()<> , чтобы они удалялись как можно скорее. Без этого вы не можете точно знать, когда они будут уничтожены. Если вы установите значение AndroidJNIHelper.debug в true, вы увидите запись деятельности сборщика мусора в журнале отладки.
//Getting the system language with the safe approach void Start () < using (AndroidJavaClass cls = new AndroidJavaClass("java.util.Locale")) < using(AndroidJavaObject locale = cls.CallStatic("getDefault")) < Debug.Log("current lang = " + locale.Call("getDisplayLanguage")); > > >
Вы также можете непосредственно вызвать метод .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:
package com.company.product; import com.unity3d.player.UnityPlayerActivity; import android.os.Bundle; import android.util.Log; public class OverrideExample extends UnityPlayerActivity < protected void onCreate(Bundle savedInstanceState) < // call UnityPlayerActivity.onCreate() super.onCreate(savedInstanceState); // print debug message to logcat Log.d("OverrideActivity", "onCreate called!"); >public void onBackPressed() < // instead of calling UnityPlayerActivity.onBackPressed() we just ignore the back button event // super.onBackPressed(); >>
И соответствующий 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#.
Где находится r java в android studio
В прошлой теме мы рассмотрели создание простого приложения, который предлагает Android Studio по умолчанию и которое просто выводит на экран строку Hello Android.
Но почему у нас выводится именно эта строка? Почему у нас вообще создается именно такой визуальный интерфейс?
Выполнение приложения Android по умолчанию начинается с класса MainActivity , который по умолчанию открыт в Android Studio:
package com.example.helloapp; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; public class MainActivity extends AppCompatActivity < @Override protected void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); >>
Каждый отдельный экран или страница в приложении описывается таким понятием как activity. В литературе могут использоваться различные термины: экран, страница, активность. В данном случае я буду использовать понятие «activity». Так вот, если мы запустим приложение на устройстве, то на экране мы по сути увидим определенную activity, которая предсталяет данный интерфейс.
Класс MainActivity по сути представляет обычный класс java, в начале которого идет определение пакета данного класса:
package com.example.helloapp;
Далее идет импорт классов из других пакетов, функциональность которых используется в MainActivity:
import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle;
Затем идет собственно определение класса:
public class MainActivity extends AppCompatActivity
По умолчанию MainActivity наследуется от класса AppCompatActivity, который выше подключен с помощью директивы импорта. Класс AppCompatActivity по сути представляет отдельный экран (страницу) приложения или его визуальный интерфейс. И MainActivity наследует весь этот функционал.
По умолчанию MainActivity содержит только один метод onCreate() , в котором фактически и создается весь интерфейс приложения:
protected void onCreate(Bundle savedInstanceState)
В метод setContentView() передается ресурс разметки графического интерфейса:
setContentView(R.layout.activity_main);
Именно здесь и решается, какой именно визуальный интерфейс будет иметь MainActivity. Но что в данном случае представляет ресурс R.layout.activity_main ? Это файл activity_main.xml из папки res/layout (в принципе можно заметить, что название ресурса соответствует названию файла), который также по умолчанию открыт в Android Studio:

Файл activity_main.xml
Android Studio позволяет работать с визуальным интерфейсом как в режиме кода, так и в графическом режиме. Так, по умолчанию файл открыт в графическом режиме, и мы наглядно можем увидеть, как у нас примерно будет выглядеть экран приложения. И даже набрасать с панели инструментов какие-нибудь элементы управления, например, кнопки или текстовые поля.
Но также мы можем работать с файлом в режиме кода, поскольку activity_main.xml — это обычный текстовый файл с разметкой xml. Для переключения к коду нажмем на кнопку Code над графическим представлением. (Дополнительно с помощью кнопки Split можно переключиться на комбинированное представление код + графический дизайнер)

Здесь мы увидим, что на уровне кода файл activity_main.xml содержит следующую разметку:
Весь интерфейс представлен элементом-контейнером androidx.constraintlayout.widget.ConstraintLayout :
ConstraintLayout позволяет расположить вложенные элементы в определенных местах экрана. Вначале элемента ConstraintLayout идет определение пространств имен XML:
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
Каждое пространство имен задается следующим образом: xmlns:префикс=»название_ресурса» . Например, в
xmlns:android="http://schemas.android.com/apk/res/android"
Название ресурса (или URI — Uniform Resource Indicator) — «http://schemas.android.com/apk/res/android» . И этот ресурс сопоставляется с префиксом android ( xmlns:android ).
Зачем эти пространства имен нужны? Каждый ресурс или URI определяет некоторую функциональность, которая используется в приложении, например, предоставляют теги и атрибуты, которые необходимые для построения приложения.
- xmlns:android=»http://schemas.android.com/apk/res/android» : содержит основные атрибуты, которые предоставляются платформой Android, применяются в элементах управления и определяют их визуальные свойства (например, размер, позиционирование)
- xmlns:app=»http://schemas.android.com/apk/res-auto» : содержит атрибуты, которые определены в рамках приложения
- xmlns:tools=»http://schemas.android.com/tools» : применяется для работы с режиме дизайнера в Android Studio
И чтобы упростить работу с этими ресурсами, применяются префиксы. Например, дальше мы видим:
android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity">
android:layout_width определяет ширину контейнера. Этот атрибут ( layout_width ) расположен в ресурсе «http://schemas.android.com/apk/res/android». И поскольку этот ресурс сопоставляется с префиксом android , то для обращения к атрибуту перед ним через двоеточие указывается префикс данного ресурса.
Значением атрибута android:layout_width является «match_parent» . Это значит, что элемент (ConstraintLayout) будет растягиваться по всей ширине контейнера (экрана устройства).
Атрибут android:layout_height=»match_parent» определяет высоту контейнера и также определен в «http://schemas.android.com/apk/res/android». Значение «match_parent» указывает, что ConstraintLayout будет растягивается по всей длине контейнера (экрана устройства).
Атрибут tools:context определяет, какой класс activity (экрана приложения) связан с текущим определением интерфейса. В данном случае это класс MainActivity. Это позволяет использовать в Android Studio различные возможности в режиме дизайнера, которые зависят от класса activity.
TextView
Текстовое поле устанавливает текст с помощью атрибута android:text .
- android:layout_width устанавливает ширину виджета. Значение wrap_content задает для виджета величину, достаточную для отображения в контейнере.
- android:layout_height устанавливает высоту виджета. Значение wrap_content аналогично установке ширины задает для виджета высоту, достаточную для отображения в контейнере
- android:text устанавливает текст, который будет выводиться в TextView (в данном случае это строка «Hello World!»)
- app:layout_constraintLeft_toLeftOf=»parent» : указывает, что левая граница элемента будет выравниваться по левой стороне контейнера ConstraintLayout Обратите внимание, что этот атрибут определен в пространстве имен с префиксом app, то есть в «http://schemas.android.com/apk/res-auto».
- app:layout_constraintTop_toTopOf=»parent» : указывает, что верхняя граница элемента будет выравниваться по верхней стороне контейнера ConstraintLayout
- app:layout_constraintRight_toRightOf=»parent» : указывает, что правая граница элемента будет выравниваться по правой стороне контейнера ConstraintLayout
- app:layout_constraintBottom_toBottomOf=»parent» : указывает, что нижняя граница элемента будет выравниваться по нижней стороне контейнера ConstraintLayout
Стоит отметить, что последние четыре атрибута вместе будут приводить к расположению TextView по центру экрана.
Таким образом, при запуске приложения сначала запускается класс MainActivity, который в качестве графического интерфейса устанавливает разметку из файла activity_main.xml. И поскольку в этой разметке прописан элемент TextView, который представляет некоторый текст, то мы и увидим его текст на экране смартфона.
Урок 8. Работаем с элементами экрана из кода
Чтобы обратиться к элементу экрана из кода, нам нужен его ID. Он прописывается либо в Properties, либо в layout-файлах, как вам удобнее. Для ID существует четкий формат — @+id/name, где + означает, что это новый ресурс и он должен добавиться в R.java класс, если он там еще не существует.
Давайте откроем main.xml, для TextView укажем и сохраним
Теперь откроем R.java и видим, что для класса id появилась константа myText. Т.е. чтобы к ней обратиться, надо написать R.id.myText.
Она связана с элементом TextView и мы можем ее использовать, чтобы обратиться к элементу программно. Для этого нам понадобится метод findViewById. Он по ID возвращает View. Давайте напишем вызов этого метода. Напомню, что пока мы пишем наш код в методе onCreate. Это метод, который вызывается при создании Activity. Если вдруг непонятно, куда писать, можно подсмотреть в конец урока, там я выложил код.
Откроем MainActivity.java и после строки с вызовом метода setContentView напишем:
View myTextView = findViewById(R.id.myText);
Если View подчеркнуто красным, то скорей всего этот класс не добавлен в секцию import. Нажмите CTRL+SHIFT+O для автоматического обновления импорта.
Теперь myTextView (типа View) – это наш TextView на экране. Но тип View – это предок для TextView (и остальных View-элементов). И он нам не подходит, если мы хотим проделывать операции соответствующие TextView. Поэтому нам необходимо преобразование View в TextView. Изменим наш код на следующий:
TextView myTextView = (TextView) findViewById(R.id.myText);
Теперь myTextView имеет тип TextView, а результат метода findViewById мы преобразуем из View в TextView. Теперь мы можем применять к myTextView методы класса TextView. Для примера возьмем метод setText. Сейчас отображаемый текст = Hello World, MainActivity!. Мы его программно поменяем на New text in TextView
myTextView.setText("New text in TextView");
Сохраняем, запускаем (CTRL+F11) и видим, что текст изменился
Добавим на экран кнопку (Button), текст оставим по умолчанию. Сохраняем — CTRL+SHIFT+S (если не сохранить, то в R.java не появится ID).
Button myBtn = (Button) findViewById(R.id.myBtn);
Обратите внимание, что у меня совпадает имя объекта и ID
Они друг другу не мешают и так делать даже логичнее. Это остается на ваше усмотрение. Так, кнопку мы нашли, теперь давайте изменим ее текст:
myBtn.setText("My button");
Запустим приложение. Текст на кнопке поменялся, на кнопку можно понажимать, но ничего происходить не будет. Т.к. мы нигде не указывали, что надо делать при нажатии. Этим займемся на следующем уроке. А пока давайте сделаем кнопку неактивной.
myBtn.setEnabled(false);
Мы поменяли параметр Enabled. Теперь на кнопку нельзя нажать. Сохраним, запустим и убедимся.

Добавим CheckBox, По умолчанию галочка не стоит. Давайте поставим ее программно, для этого используется метод setChecked, который меняет параметр Checked.
CheckBox myChb = (CheckBox) findViewById(R.id.myChb); myChb.setChecked(true);
Запустив приложение видим, что код сработал.
Как видите – все несложно. Используем метод findViewById, чтобы по ID получить объект соответствующий какому-либо View-элементу (Button, TextView, CheckBox) и далее вызываем необходимые методы объектов (setText, setEnabled, setChecked).
В итоге должен получиться такой код:
package ru.startandroid.develop.viewbyid; import android.app.Activity; import android.os.Bundle; import android.widget.Button; import android.widget.CheckBox; import android.widget.TextView; public class MainActivity extends Activity < /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) < super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView myTextView = (TextView) findViewById(R.id.myText); myTextView.setText("New text in TextView"); Button myBtn = (Button) findViewById(R.id.myBtn); myBtn.setText("My button"); myBtn.setEnabled(false); CheckBox myChb = (CheckBox) findViewById(R.id.myChb); myChb.setChecked(true); >>
На следующем уроке:
— научимся обрабатывать нажатие кнопки
Присоединяйтесь к нам в Telegram:
— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.
— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance
— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня
Как создать файл R.java?
Как в java создать исполн jar файл для выполнения с целью, что бы потом код этого jar нельзя было использовать
(Новичок) Добрый день. Подскажи пожалуйста, как быть. Как создать jar файл что бы потом его код.
Как декомпилировать .class файл обратно в .java файл?
Как декомпилировать .class файл обратно в .java файл?
Как создать свою БД на Java?
Как создать БД на Java?
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, тебе зачем?
Регистрация: 07.06.2018
Сообщений: 53
jaman_smk, недавно начал изучать и в уроках рассказывается про файл R.java, хотелось бы посмотреть где он находиться
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, он динамически генерируется, его назначение — «связка» XML и Java. Если кратко.
Регистрация: 07.06.2018
Сообщений: 53
jaman_smk, но все же где он?Если в файлах его нету
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, + поискать можно в /app/build/generated/source/r + по папкам вариантов сборки.
Регистрация: 07.06.2018
Сообщений: 53
jaman_smk, вот нету такой папки r,есть BuildConfig
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, что в каталоге ./generate есть?
Регистрация: 07.06.2018
Сообщений: 53
jaman_smk, rendrescript_source_output_dir, res, source
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, сорян, ./source/r ?
Регистрация: 07.06.2018
Сообщений: 53
jaman_smk, а в source нету такой папки.Тут ./source/apt и BuildConfig
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, ты проект собирал?
Регистрация: 07.06.2018
Сообщений: 53
jaman_smk, Да
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, вообще, должен быть в app\build\generated\source\r и по папкам.
Добавлено через 1 минуту
okeywki, но, повторюсь, ты там не найдешь ничего такого, что может представление о разработке под Android изменить. В документации все есть.
Регистрация: 07.06.2018
Сообщений: 53
jaman_smk, там нету той папки.Но все равно спасибо
145 / 135 / 22
Регистрация: 28.06.2015
Сообщений: 653
Если читали то должны знать что создать нельзя. А если создадите студия его все одно перепишет.
Храниться там где и указали.
Сообщение от jaman_smk 
app\build\generated\source\r
Только в студии нужно выбрать не Android а Project
Регистрация: 07.06.2018
Сообщений: 53
Vladimir93, я там и смотрел.Такой папки нету
111 / 89 / 29
Регистрация: 07.01.2017
Сообщений: 456
okeywki, внутри папок пробежись, not_namespaced_r_class_sources или еще что посмотри.
Регистрация: 24.11.2017
Сообщений: 74
Пожалуйста, скиньте фотографию полностью раскрытой (раскрыты все папки) левой колонки Android Studio
Пример (тут не полностью раскрыта):
Кликните здесь для просмотра всего текста
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь
Как создать файл с расширением txt и добавить в файл определенного количества строк заданным пользователем?
C# Как создать файл с расширением txt и добавить в файл определенного количества строк заданным.
Как создать папку средствами Java?
Помогите пожалуйста !:help: У меня вопрос: Как создать папку средствами язика JAVA. wall:

Как создать веб-приложение на JAVA?
Вычитал, что нужен сервер с Tomcat или аналогичной штукой. но ничерта не понял Какую IDE можно.
Легкое приложение на Java EE. Как создать ?
Ребят, помогите, пожалуйста, кто шарит в Java EE. Мне нужно сделать очень просто веб приложение. Он.
Как можно создать messenger в Java?
Я узнал, Java-классы. но я планирую идеальный Messenger в Java. но я не может создать все знаем.
Как открыть файл JAVA
Добрый день! У меня есть папка с файлами java это проект мобильного приложения , в папке имеется .
