- Publishing to Google Play Store
- Generating an upload key
- Setting up Gradle variables
- Adding signing config to your app’s Gradle config
- Generating the release AAB
- Testing the release build of your app
- Publishing to other stores
- Enabling Proguard to reduce the size of the APK (optional)
- Migrating old Android React Native apps to use App Signing by Google Play
- Default Permissions
- React Native Generate APK — Debug and Release APK
- Debug APK
- What can I use it for?
- Prerequisite:
- How to generate one in 3 steps?
- Release APK
- Создание Android-приложения с помощью React Native
- Создание сервера
- Сохранение данных
- Извлечение данных
- Создание приложения
- Установка зависимостей
- Выполнение сетевых запросов
- Главный файл приложения
- Запуск приложения
- Распространённые проблемы
- Запуск сервера React
- Проблемы с приложением
- Отладка и живая перезагрузка
- Что дальше?
Publishing to Google Play Store
Android requires that all apps be digitally signed with a certificate before they can be installed. In order to distribute your Android application via Google Play store it needs to be signed with a release key that then needs to be used for all future updates. Since 2017 it is possible for Google Play to manage signing releases automatically thanks to App Signing by Google Play functionality. However, before your application binary is uploaded to Google Play it needs to be signed with an upload key. The Signing Your Applications page on Android Developers documentation describes the topic in detail. This guide covers the process in brief, as well as lists the steps required to package the JavaScript bundle.
Generating an upload key
You can generate a private signing key using keytool . On Windows keytool must be run from C:\Program Files\Java\jdkx.x.x_x\bin .
This command prompts you for passwords for the keystore and key and for the Distinguished Name fields for your key. It then generates the keystore as a file called my-upload-key.keystore .
The keystore contains a single key, valid for 10000 days. The alias is a name that you will use later when signing your app, so remember to take note of the alias.
On Mac, if you’re not sure where your JDK bin folder is, then perform the following command to find it:
It will output the directory of the JDK, which will look something like this:
Navigate to that directory by using the command cd /your/jdk/path and use the keytool command with sudo permission as shown below.
Note: Remember to keep the keystore file private. In case you’ve lost upload key or it’s been compromised you should follow these instructions.
Setting up Gradle variables
- Place the my-upload-key.keystore file under the android/app directory in your project folder.
- Edit the file
/.gradle/gradle.properties or android/gradle.properties , and add the following (replace ***** with the correct keystore password, alias and key password),
These are going to be global Gradle variables, which we can later use in our Gradle config to sign our app.
Note about using git: Saving the above Gradle variables in
/.gradle/gradle.properties instead of android/gradle.properties prevents them from being checked in to git. You may have to create the
/.gradle/gradle.properties file in your user’s home directory before you can add the variables.
Note about security: If you are not keen on storing your passwords in plaintext, and you are running macOS, you can also store your credentials in the Keychain Access app. Then you can skip the two last rows in
Adding signing config to your app’s Gradle config
The last configuration step that needs to be done is to setup release builds to be signed using upload key. Edit the file android/app/build.gradle in your project folder, and add the signing config,
Generating the release AAB
Run the following in a terminal:
Gradle’s bundleRelease will bundle all the JavaScript needed to run your app into the AAB (Android App Bundle). If you need to change the way the JavaScript bundle and/or drawable resources are bundled (e.g. if you changed the default file/folder names or the general structure of the project), have a look at android/app/build.gradle to see how you can update it to reflect these changes.
Note: Make sure gradle.properties does not include org.gradle.configureondemand=true as that will make the release build skip bundling JS and assets into the app binary.
The generated AAB can be found under android/app/build/outputs/bundle/release/app.aab , and is ready to be uploaded to Google Play.
In order for Google Play to accept AAB format the App Signing by Google Play needs to be configured for your application on the Google Play Console. If you are updating an existing app that doesn’t use App Signing by Google Play, please check our migration section to learn how to perform that configuration change.
Testing the release build of your app
Before uploading the release build to the Play Store, make sure you test it thoroughly. First uninstall any previous version of the app you already have installed. Install it on the device using the following command in the project root:
Note that —variant release is only available if you’ve set up signing as described above.
You can terminate any running bundler instances, since all your framework and JavaScript code is bundled in the APK’s assets.
Publishing to other stores
By default, the generated APK has the native code for both x86 and ARMv7a CPU architectures. This makes it easier to share APKs that run on almost all Android devices. However, this has the downside that there will be some unused native code on any device, leading to unnecessarily bigger APKs.
You can create an APK for each CPU by changing the following line in android/app/build.gradle:
Upload both these files to markets which support device targeting, such as Google Play and Amazon AppStore, and the users will automatically get the appropriate APK. If you want to upload to other markets, such as APKFiles, which do not support multiple APKs for a single app, change the following line as well to create the default universal APK with binaries for both CPUs.
Enabling Proguard to reduce the size of the APK (optional)
Proguard is a tool that can slightly reduce the size of the APK. It does this by stripping parts of the React Native Java bytecode (and its dependencies) that your app is not using.
IMPORTANT: Make sure to thoroughly test your app if you’ve enabled Proguard. Proguard often requires configuration specific to each native library you’re using. See app/proguard-rules.pro .
To enable Proguard, edit android/app/build.gradle :
Migrating old Android React Native apps to use App Signing by Google Play
If you are migrating from previous version of React Native chances are your app does not use App Signing by Google Play feature. We recommend you enable that in order to take advantage from things like automatic app splitting. In order to migrate from the old way of signing you need to start by generating new upload key and then replacing release signing config in android/app/build.gradle to use the upload key instead of the release one (see section about adding signing config to gradle). Once that’s done you should follow the instructions from Google Play Help website in order to send your original release key to Google Play.
Default Permissions
By default, INTERNET permission is added to your Android app as pretty much all apps use it. SYSTEM_ALERT_WINDOW permission is added to your Android APK in debug mode but it will be removed in production.
Источник
React Native Generate APK — Debug and Release APK
An Android Package Kit (APK) is the package file format used by the Android OS for distribution and installation of mobile apps. It is similar to the .exe file you have on Windows OS, a .apk file is for android.
Debug APK
What can I use it for?
A debug .apk file will allow you to install and test your app before publishing to app stores. Mind you, this is not yet ready for publishing, and there are quite a few things you’ll need to do to before you can publish. Nevertheless, it’ll be useful for initial distribution and testing.
You’ll need to enable debugging options on your phone to run this apk.
Prerequisite:
How to generate one in 3 steps?
Step 1: Go to the root of the project in the terminal and run the below command:
react-native bundle —platform android —dev false —entry-file index.js —bundle-output android/app/src/main/assets/index.android.bundle —assets-dest android/app/src/main/res
Step 2: Go to android directory:
Step 3: Now in this android folder, run this command
There! you’ll find the apk file in the following path:
yourProject/android/app/build/outputs/apk/debug/app-debug.apk
Release APK
You will need a Java generated signing key which is a keystore file used to generate a React Native executable binary for Android. You can create one using the keytool in the terminal with the following command
keytool -genkey -v -keystore your_key_name.keystore -alias your_key_alias -keyalg RSA -keysize 2048 -validity 10000
Once you run the keytool utility, you’ll be prompted to type in a password. * Make sure you remember the password
You can change your_key_name with any name you want, as well as your_key_alias. This key uses key-size 2048, instead of default 1024 for security reason.
Step 2. Adding Keystore to your project
Firstly, you need to copy the file your_key_name.keystore and paste it under the android/app directory in your React Native project folder.
mv my-release-key.keystore /android/app
You need to open your android\app\build.gradle file and add the keystore configuration. There are two ways of configuring the project with keystore. First, the common and unsecured way:
This is not a good security practice since you store the password in plain text. Instead of storing your keystore password in .gradle file, you can stipulate the build process to prompt you for these passwords if you are building from the command line.
To prompt for password with the Gradle build file, change the above config as:
Place your terminal directory to android using:
cd android
For Windows,
gradlew assembleRelease
For Linux and Mac OSX:
./gradlew assembleRelease
Источник
Создание Android-приложения с помощью React Native
Как следует из названия, в этой статье мы рассмотрим процесс создания средствами React Native приложения под Android. Оно будет простеньким, всего лишь с текстовым полем. Туда нужно будет ввести имя одного из покемонов, а приложение покажет подробную информацию о полученных данных и зачитает её с помощью функции преобразования текста в речь.
Мы не будем касаться установки Android SDK, React Native и создания проекта, или каких-то иных инструментов разработчиков. Будем исходить из того, что это ваш первый опыт создания приложения с помощью React Native, поэтому подробно рассмотрим каждый кусок кода.
Создание сервера
Для начала нам нужно создать серверный компонент нашего приложения. Писать мы его будем на РНР, а в роли базы данных выступит CouchDB. Инструкции по установке: РНР и CouchDB. После инсталляции и настройки нужно проверить, чтобы была запущена база данных. Для этого выполним curl localhost:5984 и получим в ответ что-то вроде:
Для получения доступа к Futon, системе управления CouchDB, откройте в браузере http://localhost:5984/_utils. Кликните Create Database, чтобы создать базу данных для хранения подробных данных, получаемых от Pokemon API. Назовите базу pokedex и кликните Create. Можно было бы обратиться к API напрямую из React Native, но тогда увеличивается сетевой трафик. А если хранить всё в БД, то можно получать данные по единственному запросу и в любое время.
Сохранение данных
Теперь перейдём непосредственно к созданию серверного компонента. Внутри вашей папки веб-сервера сделайте рабочую папку, внутри неё создайте файл composer.json и внесите в него код:
Это означает, что библиотека doctrine/couchdb-odm теперь относится к нашему проекту. Она поможет нам работать с CouchDB в РНР. Для её установки запустите composer install .
Теперь создайте внутри рабочей папки файл pokemon.php, а затем внесите в него код:
Рассмотрим приведённый выше код. В первую очередь добавляется файл автозагрузки. Он автоматически подгружает все библиотеки, установленные нами с помощью Composer. Далее параметру set_time_limit присваивается нулевое значение. Дело в том, что у РНР-скриптов по умолчанию продолжительность выполнения ограничена, и по окончании этого времени скрипт прерывается. Обнулив вышеуказанный параметр, мы отключаем временной лимит.
На момент написания этой статьи существовал 721 покемон, и для каждого из них нам нужно выполнить по три HTTP-запроса, чтобы получить подробные данные, описание и спрайты.
Инициализируем CouchDB-клиент и внесём название нашей базы данных:
С помощью функции file_get_contents получаем от API полный список покемонов. Данные будут возвращены в формате JSON, поэтому для дальнейшей работы нам придётся конвертировать их в массив:
Прогоняем цикл по всем результатам:
Внутри цикла для каждого покемона мы обращаемся к resource_uri и используем его для создания URL, возвращающего подробные данные:
Данные, полученные в ответ на предыдущий запрос, мы используем для создания запроса на описание покемона и его спрайты:
Сохраним полученную информацию в CouchDB:
Для начала сохранения откроем в браузере файл pokemon.php. Это займёт какое-то время, а пока можно переходить к следующему шагу.
Извлечение данных
Для извлечения данных из CouchDB нам нужно создать вид (view). Зайдите в созданную нами базу данных, кликните View в выпадающем меню и выберите Temporary view. Под текстовым полем map function вставьте код:
Теперь кликните на кнопке Run, чтобы проверить, как отобразятся наши данные:
Кликните на Save as, введите в поле Design document название базы pokemon, а в поле View name — by_name. Теперь вернитесь в рабочую папку, создайте файл get.php и внесите в него код:
Давайте разберём его. Сначала мы получаем имя покемона, отправленное нам приложением:
С помощью вызова метода createViewQuery создаём вид, задаём имена для Design document и View name , а затем определяем значения опций. Метод setKey используется для описания запроса; фильтрация получаемых от вида данных осуществляется с помощью setReduce , а setIncludeDocs добавляет конкретный документ для каждого возвращённого результата. Вы могли заметить, что на приведённом выше скриншоте документ отсутствует. Дело в том, что, когда вызывается setIncludeDocs и аргумент имеет значение true , по умолчанию используется тот документ, который был сохранён при предыдущем обращении к файлу pokemon.php.
Далее нужно проверить наличие результатов. Если они есть, то возвращаем JSON-версию, в противном случае возвращаем сообщение об отсутствии данных.
Если вы работаете на локальной машине, то можете открыть для сервера доступ в интернет с помощью Ngrok. Либо воспользуйтесь внутренним IP, позднее он ещё будет использоваться в нашем приложении.
Создание приложения
Установка зависимостей
Начнём с инициализации нового проекта в React Native:
react-native init Pokedex
Когда операция будет завершена, посредством npm установите зависимости:
cd Pokedex
npm install lodash react-native-android-speech react-native-gifted-spinner —save
Что делает этот код:
- lodash — используется для перевода текста в прописное начертание и, а также для извлечения из массива конкретных данных.
- react-native-android-speech — преобразует текстовое описание в речь.
- react-native-gifted-spinner — отображает анимацию загрузки при выполнении сетевого запроса.
Просмотреть все установленные модули можно в папке node_modules/react-native/node_modules.
По завершении установки зайдите в репозиторий React Native Android Speech и настройте в соответствии с инструкциями.
Выполнение сетевых запросов
В корневой директории проекта React Native создайте папку src, внутри неё создайте файл api.js и внесите в него код:
С помощью метода fetch экспортируется функция извлечения данных с сервера. Таким способом в React Native осуществляются сетевые запросы. Этот метод получает URL для создания запроса, возвращает обещание (promise) использовать метод then и получает ответ с помощью callback-функции.
Полученные в ответе данные не получится использовать «как есть», сначала придётся передать их методу json , который доступен из объекта response . Оттуда уже можно получить данные в формате JSON, вызвав ещё один метод then . Они передаются в callback-функцию в качестве аргумента, который мы затем и возвращаем.
Обратите внимание, что возвращаемый результат метода fetch также является обещанием. Поэтому, когда мы позже вызовем этот модуль из нашего главного скрипта, до доступа к JSON-данным снова придётся использовать метод then .
Внимание: удостоверьтесь, что вы поменяли http://192.168.xxx.xxx/ на ранее упомянутый IP адрес или доменное имя. Помните, что pokedex — это папка внутри веб-индекса.
Главный файл приложения
Откройте файл index.android.js. В нём должен присутствовать некий код по умолчанию, удалите его весь.
В начале каждого файла мы будем включать строгий режим. Это поможет избежать распространённых ошибок, наподобие отсутствия определения переменной до инициализации значения.
Импортируйте React Native и дополнительные зависимости проекта:
Инициализируйте все необходимые компоненты и API:
В React Native доступны различые компоненты и API. Они по умолчанию не загружаются, поэтому вам придётся конкретно указать всё, что нужно. Можете рассматривать их как элементы пользовательского интерфейса. Допустим, в веб-странице есть текстовые поля, списки, таблицы, изображения, вкладки и т.д. В React Native все эти элементы интерфейса являются компонентами. Например, есть компоненты для отображения картинок, для отображения панелей прокрутки, для создания списков и т.д.
API в React служат для получения доступа к разным возможностям устройства, вроде камеры и пуш-уведомлений. Какими-то API вы будете пользоваться достаточно редко, а какие-то нужны в каждом проекте. В качестве примеров можно привести StyleSheet и AppRegistry.
Вот короткое описание компонентов и API, которые мы используем в нашем приложении:
- AppRegistry — регистрирует кастомные компоненты. В React Native всё подряд является компонентами, причём компоненты могут состоять из ещё более мелких компонентов.
- StyleSheet — используется для описания используемых в приложении стилей.
- Text — отвечает за отображение текста.
- TextInput — используется для создания текстовых полей.
- View — основной компонент при создании пользовательского интерфейса. Обычно используется в качестве обёртки.
- Image — отображает изображения.
- ListView — выводит списки.
Теперь импортируйте ранее созданный файл src/api.js. Это позволит осуществлять сетевые запросы с помощью вызова метода api .
Создайте новый кастомный компонент в React, содержащий всю логику интерфейса и приложения:
Инициализируйте состояние внутри класса. Под «состоянием» в React Native подразумевается способ хранения данных, которые будут доступны в рамках всего компонента.
- query — вводимый пользователем текст.
- hasResult — говорит о том, что есть результат поиска.
- noResult — говорит о том, что результата поиска нет. Он выполняет задачу, противоположную hasResult , однако используется для того, чтобы решить, отображать ли сообщение об отсутствии результата. Мы же не хотим, чтобы пользователь сразу увидел такое откровение при первой загрузке приложения, когда никакой поиск ещё не осуществлялся.
- result — хранит текущий результат, полученный от сервера.
- isLoading — отображает индикатор загрузки.
- dataSource — содержит источник данных для вида со списком. Сначала создаётся новый экземпляр ListView.DataSource , который получает объект, содержащий функцию rowHasChanged . При изменении источника данных эта функция даёт ListView команду перерендерить строку в списке. В нашем случае источником является массив, состоящий из объектов типов покемонов. Если вы посмотрите на метод search , то поймёте, как предоставляются эти данные.
Теперь взгляните на метод render . Он отвечает за рендеринг пользовательского интерфейса.
Интерфейс возвращается внутри метода.
Разберём этот код. Создаём основной контейнер:
Обратите внимание: это является обязательным условием, поскольку должен существовать единственный корневой компонент, а все остальные компоненты получаются вложенными. Значением атрибута style является объект, описывающий стилизацию компонента. Ниже вы узнаете, как объявляется объект styles , а пока просто запомните, что при использовании объектов в качестве значений не надо использовать кавычки.
Внутри основного контейнера присутствует компонент, предназначенный для ввода имени покемона. У него три атрибута:
- onChangeText — задаёт функцию, выполняемую при каждом изменении текста в текстовом поле.
- onSubmitEditing — задаёт функцию, выполняемую при каждой отправке текста в текстовом поле.
- placeholder — задаёт текст, отображаемый при отсутствии данных для ввода.
Далее идёт компонент для отображения результатов поиска. Его синтаксис немного отличается от предыдущего, он заключён в фигурные скобки, а в начале идёт условие. Благодаря этому React рендерит компонент только в том случае, если в состоянии хранится результат. Внутри этого компонента есть ещё два: Image , который выводит изображение покемона, и Text с именем зверушки. Далее идёт компонент ListView , он содержит информацию о виде покемона. Дело в том, что некоторые покемоны могут относиться к нескольким видам, поэтому нам нужен этот компонент. И наконец, компонент View отвечает за вывод описания покемона.
Давайте подробнее рассмотрим каждый из компонентов. Image получает атрибут source , который позволяет нам указать источник изображения. Это может быть картинка из сети, из локальной файловой системы или из ресурсов приложения. В нашем случае используется картинка из сети, а данные хранятся в состоянии. resizeMode задаёт изменение размера изображения, если оно не вписывается в рамку. В качестве значения использовано contain . Это означает, что изображение вписывается в рамку без искажения пропорций.
Компонент Text отображает текст. В React Native любой выводимый текст должен помещаться в компонент Text .
Компонент ListView отображает список. Здесь есть один нюанс: для определения стиля вместо атрибута style используется contentContainerStyle .
dataSource позволяет определить источник данных для рендеринга списка, а renderRow задаёт функцию, выполняемую при рендеринге каждого элемента списка.
После выведения на экран результатов поиска идёт компонент, который отображается при отсутствии результатов.
Ниже идёт индикатор загрузки, использующий для отображения анимации модуль Gifted Spinner. Индикатор показывается только в том случае, если у состояния свойство isLoading имеет значение true . Это делается сразу перед выполнением сетевого запроса, а когда ответ получен, значение меняется на false .
Затем добавляется метод для рендеринга каждый элемент списка. В объявлении компонента ListView в качестве значения атрибута renderRow использовано this.renderType . Это как раз тот самый метод.
Если вы посмотрите код ListView , то увидите, что в атрибуте renderRow мы нигде не биндили type , к которому обращаемся ниже. Дело в том, что renderRow автоматически передаёт данные скрытым образом.
Как следует из ответа, возвращаемого сервером, объект types содержит массив объектов, соответствующих разным типам покемонов:
Мы обращаемся к этому объекту в методе renderType через аргумент type . Он используется для отображения типа покемона и управления стилем. Далее, в объявлении стиля понадобится добавить разные стили для каждого типа. Как вы могли заметить, для компонента View у нас используется два объявления стиля. Таким образом в React Native добавляется в массив каждое объявление стиля.
Теперь добавляется метод changeText , исполняемый при каждом изменении текста в текстовом поле. Поскольку этому методу передаются актуальные текстовые данные, он является хорошим местом для обновления свойства состояния, хранящего текущую введённую пользователем информацию.
Метод search исполняется при каждой отправке данных в текстовом поле. При вводе текста в Android появляется кнопка Done, нажатие которой запускает событие onSubmitEditing . Выше мы уже определяли this.search в качестве значения для атрибута onSubmitEditing . В результате выполняется следующий метод:
Разберёмся с этим кодом. Предоставляемый Lodash метод capitalize вызывается для преобразования всех букв в прописные, за исключением первых букв. Затем состояние обновляется, а свойство isLoading получает значение true , благодаря чему под последним компонентом отображается индикатор загрузки.
С помощью модуля api выполняем сетевой запрос:
Обратите внимание: синтаксис callback-функции немного отличается от привычного нам.
Отличается также значение объекта this . Согласно новому синтаксису, этот объект ссылается на внешнюю область видимости, а не на callback-функцию. Это позволяет использовать this для обновления состояния изнутри callback-функции, без необходимости создания переменной для хранения текущей области видимости.
Внутри callback-функции задаётся текст по умолчанию, который будет преобразовываться в речь.
var speech = ‘Pokemon was not found. Please type the exact name.’;
Если в результатах присутствует объект doc , то массив типов извлекается и передаётся в качестве аргумента в метод cloneWithRows , который находится в состоянии, в ранее инициализированном компоненте dataSource . Таким образом возвращается объект, который можно использовать в качестве значения атрибута dataSource в ListView .
Для отображения результатов в интерфейсе обновляем состояние. После этого создаётся новый массив type_names , содержащий только типы, к которым принадлежит покемон. Делается это с помощью предоставляемого Lodash метода map . После этого можно преобразовывать в речь имя покемона, его тип и описание:
Иными словами, вы должны настроить все необходимые значения в состоянии:
- hasResult нужно присвоить значение false , чтобы не отображался компонент, ответственный за вывод результата.
- noResult нужно присвоить true , чтобы отображалось сообщение об отсутствии результата.
- isLoading нужно присвоить false , чтобы индикаторы загрузки был скрыт.
- result нужно присвоить null для очистки предыдущего результата.
Сразу под условиями задействуйте модуль преобразования в речь:
После закрывающих скобок класса Pokodex добавьте стили с помощью StyleSheet API:
Разберём этот кусок кода. У нас есть основной контейнер, в котором flex присвоено значение 1 , поскольку для создания макета используется Flexbox. Единица означает, что задействуется весь экран. Так сделано потому, что мы применили стиль к корневому компоненту. А поскольку у нас нет других компонентов того же уровня, то используется весь экран.
У нас есть стили для поиска, вывода результата, отсутствия результата и загрузки:
Все они являются дочерними, и потому совместно используют доступную площадь. Раз корневой компонент растянулся на весь экран, то и его дочерние компоненты будут делить между собой всю площадь экрана. Удобнее всего это воспринимать в виде дробей. У компонентов поиска и загрузки flex: 1 , поэтому им достанется меньше всего места. Поскольку одновременно могут отображаться 10 секций, то каждый из них получит по 1 секции, а компоненты наличия и отсутствия результатов занимают 8 секций.
В качестве контейнера для изображения, имени, типа и описания покемона выступает main_details . Выровняйте все по центру, но не забудьте про поля, чтобы текст не лип к краям.
Далее идёт объявление стилей – стандартный CSS.
Теперь очередь стилей для списка типов. В компоненте ListView аргумент flexDirection имеет значение row . Это означает, что отведённое для списка пространство поделено на секции в соответствии со строками, что обеспечивает эффект поточного встраивания (inline effect). То есть элементы списка рендерятся один за другим. Ширина у них одинаковая вне зависимости от длины текста, поскольку для каждого элемента задаётся параметр width . Благодаря отступу шириной в 5 пикселей текст не прилипает к краям контейнера. Для выравнивания текста по центру используется alignItems .
Далее настраиваем стили для типа покемона. К примеру, если это электрический покемон, то фон контейнера будет жёлтого цвета.
Зарегистрируйте компонент в AppRegistry . Тогда React Native будет рендерить компонент Pokedex при открытии приложения.
Запуск приложения
Сначала удостоверьтесь, что работает ваш РНР-бэкенд, а затем с помощью команды react-native run-android запустите компиляцию и выполнение приложения на вашем устройстве или в эмуляторе. В этот момент вы получите ошибку:
Дело в том, что сначала нужно запустить сервер React, который на лету конвертирует компоненты. Приложение будет автоматически перекомпилировано при каждом изменении исходных файлов (например, index.android.js). Для запуска сервера React в терминале выполните команду react-native start . Вы увидите нечто подобное:
По завершении Building Dependency Graph откройте новое окно с терминалом и выполните команду adb shell input keyevent 82 . Это откроет на устройстве меню разработчика. Выберите пункт Dev settings, в секции Debugging введите внутренний IP-адрес вашего компьютера и порт, на котором выполняется сервер React.
Затем вернитесь на главный экран приложения, снова откройте меню разработчика и выберите пункт Reload JS. Приложение будет перезапущено, теперь всё должно работать.
Распространённые проблемы
Запуск сервера React
Если вы получили ошибку при запуске, то причиной наверняка является Watchman.
Error building DependencyGraph:
Error: Watcher took too long to load
Try running `watchman version` from your terminal
https://facebook.github.io/watchman/docs/troubleshooting.html
at [object Object]._onTimeout (index.js:103:16)
at Timer.listOnTimeout (timers.js:89:15)
Для её исправления выполните следующие команды:
sudo sysctl fs.inotify.max_user_instances=99999
sudo sysctl fs.inotify.max_user_watches=99999
sudo sysctl fs.inotify.max_queued_events=99999
Если не сработало, попробуйте так:
echo 999999 | sudo tee -a /proc/sys/fs/inotify/max_user_instances
echo 999999 | sudo tee -a /proc/sys/fs/inotify/max_user_watches
echo 999999 | sudo tee -a /proc/sys/fs/inotify/max_queued_events
Эти команды задают количество просмотров разных корневых папок, вложенных в них папок, а также количество событий в очереди. Последняя строка прерывает выполнение сервера Watchman, чтобы применились внесённые изменения.
Проблемы с приложением
После запуска сервера React вы можете столкнуться с тем, что приложение всё равно не запускается. Это происходит по двум причинам:
- Android-устройство и компьютер находятся в разных сетях.
- Введённый на устройстве IP-адрес не совпадает с IP-адресом компьютера.
Так что просто проверьте эти два пункта, и всё будет в порядке.
Отладка и живая перезагрузка
Когда приложение запустится, вы можете воспользоваться такими приятными вещами, как отладка в Chrome и живая перезагрузка. Для этого нужно открыть меню разработчика и поставить галочки в пунктах Debug in Chrome и Enable Live Reload. Теперь вы можете просматривать console.log и отслеживать ошибки из консоли Chrome. А живая перезагрузка бывает полезна, когда нужно перезапустить приложение для внесения изменений в исходные файлы.
Что дальше?
Куда двигаться дальше после того, как вы создали своё первое приложение с помощью React Native app?
Источник