Android ndk windows path

  • Introduction
  • Configure NDK for Android Gradle Plugins

    • NDK with AGP 4.1

      • Under the hood
    • NDK with AGP 4.0 and 3.6

      • Under the hood
    • NDK with AGP 3.5

      • Under the hood
    • NDK with AGP 3.4
  • NDK Version Specification
  • NDK Release Channels
  • Install NDKs

    • SDK Manager UI
    • The sdkmanager command line tool
    • Manually install NDK
  • Terminologies

    • ndkVersion
    • non-ndkVersion
    • ndk.dir
    • ANDROID_NDK_HOME
    • The default NDK version
    • The default NDK location

Introduction

This document guides developers through NDK configuration in recent Android Gradle Plugin (AGP) versions. For Android Studio, this document assumes it uses the same version of Android Gradle Plugin (AGP):

  • in this doc, Android Studio is the same as Android Gradle Plugin(AGP)
  • AGP version is in project’s build.gradle:
    classpath 'com.android.tools.build:gradle:4.1.0-alpha02'

The possible directories that AGP locates NDK are:

Android Studio/Gradle Plugin Version
4.1 4.0 — 3.6 3.5 3.4
Default NDK Location $SDK/ndk/$version

$SDK/ndk-bundle

$SDK/ndk/$version

$SDK/ndk-bundle

$SDK/ndk/$version

$SDK/ndk-bundle

$SDK/ndk-bundle
ndkPath available Not available Not available Not available
ANDROID_NDK_HOME removed deprecated deprecated available
ndk.dir deprecated available available available

The related available features that could affect which version of NDK to use are:

Android Studio/Gradle Plugin Version
4.1 4.0 3.6 3.5 3.4
ndkVersion defines specific NDK version Not available
Default NDK Version assign one NDK version by AGP Not available Not available
Autodownload $default & $ndkVersion $ndkVersion not available not available not available

Out of the NDK path configuration channels, ndkVersion feature added in version 3.5 and above provides a major flexibility for applications: NDK dependency moves from project level to module level! We strongly recommend developers to take full advantage of the feature.

With the addition of android.ndkVersion, Android Studio may work in 2 ways:

  • ndkVersion way: where android.ndkVersion is used in the application
  • legacy way: NDK version does not matter to your application — any one would work

The motivation for the evolutions is:

  • NDK usage is being integrated into build.gradle DSL
  • let sdkmanager tool to manage NDK installation

Configure NDK for Android Gradle Plugins

This section outlines the NDK path resolution with regard to recent Android Studio/Android Gradle Plugin versions; assuming that Android Studio uses the same version of AGP, the instructions directly apply to Android Studio IDE.

NDK with AGP 4.1

With AGP 4.1, NDK path configuration is automatically done with:

  • if you need a specific NDK for any module, use ndkVersion in module’s build.gradle
  • otherwise, make sure do not use ndkVersion and AGP will behave as if ndkVersion was set to the default NDK version

If you have the needed NDK versions on your local system, it will be used; otherwise, AGP 4.1 will automatically download it to the $SDK/ndk/$version and proceed to build.

That is all for AGP 4.1! If you want to know more, read onto the next section.

Under the hood

AGP 4.1.x, added the android.ndkPath to support some special usage cases such as that your own NDK must be in certain locations or even have your own customized NDK; on the other hand, AGP 4.1 deprecates ndk.dir and $SDK/ndk-bundle. Taking all of the possible ways into the consideration, AGP 4.1 searches the needed NDK in the following directories:

NDK Location if using ndkVersion if not using ndkVersion
$SDK/ndk/${ndk-version} the exact version the internal default NDK Version
$SDK/ndk-bundle the exact version(deprecated) the internal default NDK version (deprecated)
android.ndkPath Not Used any version
ndk.dir the exact version (deprecated) any version(deprecated)

With the above, you could use any NDK locations to configure your local development system to fit your special needs.

NDK with AGP 4.0 and 3.6

The correct way to use NDK is the ndkVersion way:

  • set your NDK version to android.ndkVersion in module’s build.gradle;
  • if building from command line with gradle, you need to install the NDK

The location for NDK is $SDK/ndk/$ndk-version. One noticeable difference is that AGP 4.0, when used inside Android Studio IDE, will auto download the needed NDK version if it is NOT installed locally; you need to install NDK yourself with AGP 3.6.

Under the hood

For the apps that do not use ndkVersion, AGP 3.6 and later versions embed a default NDK version, which is the NDK version used to test this AGP version at the release time. The purpose is to offer a “known good” NDK for applications that does not specify any particular NDK.

Including the default NDK version, AGP 3.6+ searches NDK in the following locations for the needed version:

Location using ndkVersion without ndkVersion
$SDK/ndk/${ndk-version} required version the internal default NDK Version
$SDK/ndk-bundle required version(deprecated) the internal default NDK version(deprecated)
ndk.dir required version any version

The above behaviour provides some flexibility when developers have to customize NDK path.

NDK with AGP 3.5

Android Gradle Plugin(AGP) 3.5.x added the ndkVersion feature (also called NDK “side by side”, SxS, means multiple NDKs could be installed under the same directory) to support NDK dependency at module level: different modules could use different NDKs to build a single application or multiple applications. ndkVersion creates a new NDK default location at $SDK/ndk/$version:

Under [ndkVersion](#ndkversion) way, NDKs are expected to be installed in a new default location

    $SDK/ndk/${ndk-version-1}
    $SDK/ndk/${ndk-version-2}

Refer to ndkVersion for additional information about the feature.

From AGP 3.5 and onward, developers are recommended to use the ndkVersion:

  • configure your NDK version to android.ndkVersion in module’s build.gradle
  • with Android Studio, the required NDK will be prompted to download if not there
  • if using command line environment or CI, you need to install the NDK

and that is all to get NDK working with Android Gradle Plugin/Android Studio 3.5.

Under the hood

With this great ndkVersion considered, AGP 3.5 finds the matching NDK in the following locations:

NDK Location with ndkVersion non-ndkVersion
$SDK/ndk/${ndk-version} required version the newest NDK there
$SDK/ndk-bundle required version any version
ndk.dir required version any version

NDK with AGP 3.4

Android Gradle Plugin 3.4 is legacy now, configuring NDK path is relatively fixed and straightforward:

  • ndk.dir in local.properties
  • ANDROID_NDK_HOME environment variable
  • $SDK/ndk-bundle (default location for Studio 3.4)

Refer to “Install NDK” for NDK installation details.

NDK Version Specification

There are 4 parts to NDK version number as $major.$minor.$build-$suffix, for example, NDK 21.0.6011959-beta2:

  • major version, i.e. 21
  • minor version, i.e. 0
  • build number, i.e. 6113669
  • suffix, i.e. “beta2

The NDK version could be found in the ${ndk}/source.properties file; however when looking at the SDKManager or using sdkmanager command line tool, the suffix string, follows “rc”(release candidate) scheme, for example, the above version would become

The exact NDK version format in android.ndkVersion are AGP version dependent:

AGP Version $major.$minor.$build$suffix $major.$minor.$build $major.$minor
4.1 / 4.0 21.0.6011959 rc2"

21.0.6011959-beta2" all work!

"21.0.6011959" works NO
3.6 NO NO
3.5 NO "21.0" works

The recommendation is:

  • $major.$minor.$build: for AGP version 4.0/4.1, forget about the lengthy suffix format
  • $major.$minor.$build$suffix: AGP 3.5/3.6 need to use the full version, and all legal suffixes string would work ( “beta”, “rc”).

The regex format is not supported!

NDK Release Channels

Similar to other SDK components, NDKs are also released through different channels:

  • Stable for stable releases
  • Beta for beta release
  • Canary including developer preview NDKs

Formal releases could be installed with all installation channels, but, as it is now for Android R time, the developer preview releases are only installable through Android SDK Manager (UI or command line tool) that has a canary channel.

Install NDKs

The preferred way is to let AGP/Android Studio (4.0+) to auto download NDK into the $SDK/ndk/$version.

For AGP versions that could not auto-download NDK, there are at least 3 common ways to install NDK, probably the easiest one is to use the sdkmanager tool (UI or the command line version) shipped inside Android SDK for best compatibility purpose with your AGP version.

SDK Manager UI

Before using SDK Manager, if you need to install NDKs available only on canary channel, you would need to turn it on. Canary Channel could be enabled inside Android Studio IDE:

  • Preferences > Appearance & Behavior > System Settings > Updates

SDK Manager GUI is integrated into Android Studio IDE. You could start SDK Manager GUI within Android Studio IDE:

  1. menu «Tools» > «SDK Manager», or use the “SDK Manager Toolkit”

  2. left hand pane, “Appearance & Behaviour” > “System Settings” > “Android SDK”

  3. tab “SDK Tools”

  4. enable “Show Package Details” at the lower right corner

  5. Select NDK

    1. for Android Studio 3.5.0+, install “Side by Side NDK”

      • expand “NDK(Side by Side)”
      • select the right version you need

      NDK will be installed to ${sdk}/ndk/${selected_version}

    2. for Android Studio versions before 3.5.0, select “NDK”:
      the latest NDK at the time will be picked up automatically, and installed to ${sdk}/ndk-bundle

  6. “Apply” or “OK” button to install NDK.

The sdkmanager command line tool

The sdkmanager command line tool shipped inside SDK could also be used to install all NDKs; for some scenarios like CI environment, the command line tool might be more helpful. The generic syntax for NDK purpose is:

${sdk}/cmdline-tools/latest/bin/sdkmanager --install "ndk-selection"  --channel=${channel}

the relevant options are

  • ndk-selection:
    • ndk;${your-ndk-version}”: for “side by side” NDK; installed location is $SDK/ndk/${your-ndk-version}
    • ndk-bundle” for legacy ndk-bundle way; installed location is ${SDK}/ndk-bundle
  • channels for NDK
    • 0: Stable NDK
    • 1: beta NDK
    • 3: canary NDK, including Developer Preview NDKs

Note: depending on your SDK version, your sdkmanager tool might be under tools/bin.

Example:

${sdk}/tools/bin/sdkmanager --channel=3 --install "ndk;21.1.6273396"

To view how many NDK versions are available, use "--list" option:

    ${sdk}/tools/bin/sdkmanager --list

For additional sdkmanager usages, refer to the formal documentation.

The Manual Way

For some reason you need to install NDK manually, you could do that:

  • download NDK from official NDK site
  • unzip it to $SDK/ndk/

There might be differences comparing to the SDK Manager way to install, for example

  • currently you may not manually download canary NDKs

Terminologies

ndkVersion

In order to support multiple NDKs co-existing:

  • different NDKs to build different modules in one project
  • different NDKs to build different projects inside the same Studio IDE

Android Studio 3.5+ implemented the module level android.ndkVersion gradle DSL, for example in app/build.gradle :

    android {
        ndkVersion "21.1.6273396"
    }

ndkVersion is the modern NDK SxS** (**side by side) way for Android Studio:

  • NDK SxS = android.ndkVersion: it is (still relatively new and) modern Studio way.

Otherwise Studio works in the old fashioned legacy way. Please refer to
NDK Version Specification for your specific AGP version’s requirement about version string format!

non-ndkVersion

If application does not use the new ndkVersion feature, Studio is working in the legacy mode:

  • legacy mode = !android.ndkVersion

We strongly recommend developers to use the modern ndkVersion way!

Android Studio 4.1+ added a new way to customize NDK location with android.ndkPath, for example, in module’s app/build.gradle, you could simply do:

    android {
        ndkPath "/Users/ndkPath/ndk21"  // pointing to your own NDK
    }

please remember to remove the ndkPath before distributing your source code: _it should be left outside your version control system.

ndk.dir

Android Studio creates file local.properties at the root of the project to save project level settings including NDK and SDK paths, for example:

  • sdk.dir=/Users/ndkPath/dev/sdk
  • ndk.dir=/Users/ndkPath/dev/latest_ndk

The cached NDK path is called **ndk.dir, normally it is the first place that AGP/Android Studio looks for NDK; on the other hand, ndk.dir is deprecated from AGP 4.1.

The value of ndk.dir may come from 3 sources:

  • ANDROID_NDK_HOME environment variable when Studio starts up
  • **“Android NDK location” **within Android Studio IDE
  • brutally editing ndk.dir in local.properties file

Android NDK location” in Android Studio IDE would always be in sync with ndk.dir: one gets changed, the other will be mirrored automatically; you could find “Android NDK location” under “File” > “Project Structure” > “Android NDK location”:

Cautions for ndk.dir:

  1. ndk.dir’s setting is local to your system: file local.properties is Studio generated file; as the name implies, it is local to your development machine , and should not be distributed with source code.
  2. ndk.dir is being deprecated from AGP 4.1+.
  3. The ANDROID_NDK_HOME environment variable was deprecated from AGP 3.6+.

ANDROID_NDK_HOME

The ANDROID_NDK_HOME environment setting is the oldest of all NDK path configurations: an antique! It is the development system wise configuration: once set, it applies to all — Android Studio reads this settings and caches it to UI/ndk.dir at starting up:

  • $ANDROID_NDK_HOME got populated into ndk.dir/Studio IDE
  • ANDROID_NDK_HOME is old and deprecated

The replacement for ANDROID_NDK_HOME is the modern_
ndkVersion way_: configure NDK in your modules, and install NDK to $SDK/ndk/$version

For CI purposes, the environmental variable ANDROID_NDK_HOME(deprecated) might be useful when building on the command line

  • Gradle does check ANDROID_NDK_HOME to find NDK if no local.properties file exists.
  • You could make ANDROID_NDK_HOME into your project’s ndkPath, for example, in module gradle file:
    ndkPath = System.getenv("ANDROID_NDK_HOME")

The default NDK version

AGP 3.6+ embeds a default NDK version (ANDROID_GRADLE_PLUGIN_FIXED_DEFAULT_NDK_VERSION), the “known-good” version when a specific AGP was released for application to use if application does not specify a particular NDK version:

  • the default version will not be used when application uses ndkVersion feature, and
  • the default version will not be used if application uses ndk.dir inside local.properties

Please be reminded that each AGP version has its own embedded default NDK version number.
Once the default NDK version is triggered, the application behaves as if ndkVersion were set with the following:

    android.ndkVersion "${the-default-NDK-version}"

From here, all android.ndkVersion path searching rules apply, check the related AGP version description in this documentation for the expected behaviors.

The default NDK location

Unless Android Studio/Android Gradle Plugin(AGP) is purposely configured to go to a specific local directory for NDK, the default NDK locations will be used; in that sense, the default NDK locations are behind the customized NDK location(s).

The exact default NDK location depends on AGP version:

  • $SDK/ndk/: This is the new location for ndkVersion way. Multiple NDKs could be installed under this default NDK location, like:
    • SDK/ndk/version1
    • SDK/ndk/version2

The subdirectory names under $SDK/ndk could be anything, sdkmanager tool by default chooses to use the ${version number}‘s as sub-directory names, but you could name them freely: AGP finds the version string in source.properties packed inside NDK.

  • $SDK/ndk-bundle: existed before ndkVersion was added. It could only host one NDK version and is deprecated now but still part of the AGP’s NDK search path.

Refer to the specific AGP version section for the deprecation status.

Время на прочтение25 мин

Количество просмотров224K

На днях я обнаружил, что версия Android Studio неуклонно стремится к единице, в связи с чем задумался об изучении этого инструмента. Чтобы не было скучно, я решил поделиться своим опытом и собранными граблями в виде статьи-туториала.

Сразу хочу оговориться, что я не являюсь гуру Android-разработки, поэтому каких-либо откровений в тексте вы не найдете. Зато тут есть пошаговая инструкция по установке и настройке Android Studio под Windows и созданию простейшего проекта с использованием Android NDK.

Также заранее предупреждаю: статья получилась большой и очень подробной (честно, сам не ожидал), даже несмотря на то, что я почти все скриншоты и некоторые листинги кода спрятал под спойлеры.

На момент написания последней версией Android Studio была 0.8.1, для последующих версий необходимые действия могут отличаться от нижеописанных (очень надеюсь, что в лучшую сторону).

Для тех, кого интересует только NDK
Для тех, кого интересуют только настройки Gradle для NDK

Установка и настройка Android Studio

1. Необходимо установить JDK (Java Development Kit) и JRE (Java Runtime Environment).

Раньше Android SDK поддерживал только JDK версии 6, но теперь это в прошлом. Поддерживается 7 и даже 8 (по крайней мере, именно 8-ю версию я указал в качестве JAVA_HOME и в настройках Android Studio, и никаких проблем не испытал).
JRE же нужен для запуска самой студии. У меня она использует версию 7.
Скачать JDK и JRE версий больше 6 можно с сайта Oracle.

Переменную JAVA_HOME теперь, вроде бы, можно не устанавливать, так как в Android Studio мы будем в настройках прописывать путь к JDK. Но я ее установил. Для этого нужно:

  • Зайти в Панель управления\Система и безопасность\Система, выбрать слева Дополнительные параметры системы, в открывшемся диалоге найти кнопку Переменные среды.
  • Создать системную или пользовательскую переменную JAVA_HOME и указать для нее путь к JDK. У меня указан вот такой путь: C:\Program Files\Java\jdk1.8.0_05.

Если вы по каким-либо причинам нуждаетесь в 6 версии JDK

JDK 6 без регистрации можно получить так:

  • Скачать Java EE 6 с сайта Oracle.
  • Установить его. В комплекте есть JDK 6.
  • В качестве JAVA_HOME в этом случае нужно указать путь к JDK из Java EE, по умолчанию это C:/glassfish3/jdk.

2. Если у вас установлен Android SDK.

В комплекте с Android Studio идет свой Android SDK. И, если вы хотите использовать именно его, то в некоторых случаях может случиться странное. Например, у меня при обновлении SDK через SDK Manager часть файлов записывалась в старую папку, и возникли проблемы, когда я эту папку удалил. Скорее всего это произошло из-за того, что в реестре хранился ключ с путем к старой папке. Поэтому имеет смысл почистить реестр. Для этого нужно запустить regedit.exe и найти HKEY_LOCAL_MACHINE\Software\Android SDK Tools для 32-битных машин либо HKEY_LOCAL_MACHINE\Software\Wow6432Node\Android SDK Tools для 64-битных машин и удалить Android SDK Tools. Если в реестре вашей системы таких ключей нет, то все в порядке.

Если у вас установлена переменная среды ANDROID_SDK_HOME и вы хотите, чтобы она указывала на старую установку, то, по идее, это не должно стать проблемой, так как при настройке Android Studio мы укажем ей путь к SDK. Проблемы могут возникнуть, если эту переменную использует какое-либо из приложений, входящих в состав Android SDK.

3. Теперь переходим к установке Android Studio.

Нужно скачать Android Studio для вашей системы с официальной страницы и установить ее. По умолчанию, если выбрать «Установить только для меня» ставится в \Users\<user>\AppData\Local\Android\android-studio\, иначе ставится в \Program FIles (x86)\Android\android-studio\. Можно выбрать и другую папку.

После установки запускаем Android Studio.

Видим вот такой диалог

В нем делаем следующее:

  • Проверяем обновления и, при необходимости, обновляемся (для этого нажмите на Check в нижней части окна)
  • Заходим в Configure->SDK Manager (на всякий случай: SDK Manager — это не часть Android Studio, а утилита из Android SDK) и устанавливаем то, что вам необходимо. Если вы не знаете, что необходимо, то лучше установить все, что он предложит.

    Вот что он установил у меня

  • Затем я сменил тему на Darcula.

    Как это сделать

    нужно зайти в Configure->Settings->Appearance:

  • Далее заходим в Configure->Project Defaults->Project Structure и меняем SDK Location на путь к вашему Android SDK, а JDK Location на путь к JDK.

    Скриншот

Создание проекта

1. New Project

Жмем New Project.

Появляется вот такой диалог

В нем можно настроить:

  • Имя проекта (я оставил по умолчанию: My Application)
  • Домен компании, по умолчанию <username>.example.com, в моем случае markedone.example.com
  • Имя пакета тоже можно отредактировать, нажав на Edit справа. По умолчанию генерируется из имени проекта и домена компании и выглядит как com.example.<username>.<имя проекта в lowercase без пробелов&gt, я его изменил на com.example.markedone.myapp.
  • Путь, куда будет сохранен проект. Я указал свою папку для всяких тестовых проектов.

Когда все введено, жмем Next.

2. Form Factors

В этом диалоге выбираем целевые платформы и API.

Диалог выглядит так

Здесь я все оставил по умолчанию: Phone and Tablet и 4.0.3 IceCreamSandwich. Если API для каких-то платформ не установлен, выдается сообщение Not Insatlled. Например, как видно на скриншоте, у меня не установлены библиотеки для Google Glass (сделать это можно через SDK Manager).

Также обратите внимание на Help me choose, прикольная штука

Если нажать Help me choose, то откроется вот такой интересный диалог

Он содержит информацию по охвату устройств при выборе той или иной версии API. Прямоугольники версий API кликабельны, справа будет выведен список доступного в них функционала. Например, для предлагаемого по умолчанию Ice Cream Sandwich’а:

Жмем Next.

3. Add Activity

На следующем экране нам предлагается выбрать Activity

Естественно, я не смог пройти мимо Fullscreen Activity и выбрал ее. Вы можете выбрать другую Activity, но в этом случае у нас будут отличаться исходники на Java, и вам придется самостоятельно добавлять вызов нативного метода из Java (впрочем, в этом нет ничего сложного).
Делаем выбор, нажимаем Next.

Появляется следующий диалог

Здесь нам предлагается настроить Activity.

  • Activity Name — имя класса, я оставил по умолчанию: FullscreenActivity.
  • Layout Name — имя layout, для редактора UI, также оставляем по умолчанию.
  • Title — по умолчанию предлагается FullscreenActivity, я поставил пробел: Fullscreen Activity.

Нажимаем Finish.

В итоге должен открыться проект

Сборка и запуск

1. Сборка проекта

Запускаем сборку через меню: Build->Make Project (для пунктов меню указаны иконки и горячие клавиши, так что с ними будет несложно разобраться).
У меня при первой сборке возникла ошибка:

Произошло это в файле MyApplication/app/build.gradle
Для того, чтобы понять в чем дело, достаточно навести курсор на подчеркнутую строку:

Все просто, здесь указана версия 19, а у нас установлена только 20, да и в настройках проекта мы указали 20 как целевую. Просто поменяем цифру:

Как видно, студия на этом не успокоилась, и предлагает установить еще более новую версию. Но нам сейчас это не нужно.

Снова запускаем Build->Make Project. На этот раз у меня все собралось. Надеюсь, у вас тоже.

2. Настройка виртуального устройства

Для того чтобы запустить программу в эмуляторе, нужно настроить виртуальное устройство. Заходим в Tools->Android->AVD Manager (это, как и SDK Manager, утилита из Android SDK). Нам нужна первая вкладка, Android Virtual Device, она и открыта по умолчанию. Справа находим кнопку Create… и нажимаем ее.

Появится диалог настройки виртуального устройства

  • AVD Name — имя виртуального устройства, я ввел TestPhone. Дальше я, правда, выбрал планшет, но уже не стал менять название.
  • Device — различные предустановленные настройки устройства, значение выбирается из доступных в выпадающем списке, я выбрал 7» WSVGA (Tablet) (1024 x 600: mdpi).
  • Target — целевая версия API, доступны только те, которые есть в SDK. Установить их можно через SDK Manager.

    W в названии означает Wear, версия для носимых устройств (часы и прочее). Так как мы в настройках проекта выбирали Tablet&Phone, то нам нужен другой пункт: Android L (Preview) — API Level L.

  • CPU/ABI — платформа, я выбрал ARM (armeabi-v7a).
  • Keyboard — тут, думаю, все понятно.
  • Skin — как я понял, внешний вид устройства, я выбрал значение, соответствующее установленному значению Device: WSVGA.
  • Front Camera и Back Camera — наличие камер.
  • Memory Options — оперативная память.
  • Internal Storage — жесткий диск устройства.
  • SD Card — думаю, понятно.
  • Emulation options: Snapshot — позволяет эмулятору сохранять свое состояние между запусками, Use Host GPU — позволяет использовать видеокарту компьютера для OpenGL ES. Последнюю опцию я включил, но OpenGL — приложение у меня впоследствии упало на этом эмуляторе при старте. Наверное, из-за ARM vs x86_64.

Внизу диалога выводится, какую ошибку вы допустили при настройке. Например, в имени устройства нельзя вводить пробелы, а некоторые поля обязательны для заполнения. Когда внизу нет надписи — все введено верно. Жмем OK.

Устройство появилось в списке

Пара слов о вкладке Device Definitions

На ней заданы доступные устройства (те, которые потом отображаются в выпадающем списке Device при создании нового виртуального устройства). Чтобы создать новое устройство, нужно нажать на кнопку Create Device… и озаботиться заполнением следующего диалога:

Закрываем AVD Manager и возвращаемся в главное окно Android Studio.

3. Запуск на эмуляторе

Выполняем Run->Run ‘app’.
Придется подождать, пока произойдет сборка проекта для запуска.

В конце концов, появится окно выбора устройства

Здесь единственный доступный вариант для выбора — это наше виртуальное устройство. Он нам сразу предложен, так что просто жмем OK.

Запускается эмулятор, довольно долго

Можно открыть Tools->Android->Android Device Monitor (утилита из Android SDK), чтобы увидеть логи с эмулятора. Он должен автоматически подцепить виртуальное устройство и сразу начать выводить лог.

Android Device Monitor

А вот приложение после запуска эмулятора у меня с первого раза не открылось, пришлось еще раз нажать Run->Run ‘app’.

Появился немного изменившийся диалог

Здесь устройство перекочевало из списка для запуска в список уже запущенных. В этом списке, само собой, оказываются и реальные устройства.

После этого дело пошло, и приложение довольно быстро установилось и запустилось.

Полноэкранный режим

А если на приложение тапнуть, то выглядит оно так

Это не поведение системы, обработка клика происходит в приложении (файл FullscreenActivity.java):

        // Set up the user interaction to manually show or hide the system UI.
        contentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TOGGLE_ON_CLICK) {
                    mSystemUiHider.toggle();
                } else {
                    mSystemUiHider.show();
                }
            }
        });

После запуска, Android Studio предложила мне выключить Android Device Monitor, для того чтобы интегрировать вывод прямо в IDE.

Вот как выглядит интеграция

4. Запуск в Debug-режиме

Run->Debug ‘app’

Снова уже знакомый нам диалог

Жмем OK.

Ждем, пока запустится приложение и приконнектится дебаггер. Я поставил точку останова при нажатии на кнопку Dummy Button.

Android Studio в дебаге

Немного раздражает отсутствие панельки со всякими Step Into, Step Out etc.

Все это находится в меню Run

5. Запуск на 4.0.3

В процессе создания и запуска проекта вы, наверное, заметили, что мы создали приложение, совместимое с версией 4.0.3, но запускали его только на самой последней версии Android. Сейчас мы это исправим. Для этого нужно установить версию 4.0.3 через Tools->Android->SDK Manager.

Необходимое отмечено галочками на скриншоте

Это SDK Platform, ARM EABI v7a System Image и Intel x86 Atom System Image. На самом деле, мы запускали эмулятор ARM, и Intel нам сейчас ставить не обязательно. Я его поставил сугубо потому, что он установлен и для Android L.
Теперь создадим еще одно устройство для новой старой версии Android (или же вы можете отредактировать старое).

Настройки нового устройства

Запускаем (Run->Run ‘app’).

В диалоге выбираем новое устройство для запуска

И смотрим, как выглядит новый эмулятор — явно брутальнее.

Запуск

Полноэкранный режим

После нажатия

5. Запуск на устройстве

Перед тем как перейти к работе с NDK, давайте запустим проект на реальном устройстве. Я буду запускать на телефоне

Huawei Ascend G300 с Android 4.0.3

Первое, что нужно сделать, это установить adb-драйвер. У меня с этим все довольно просто, драйвер находится прямо на телефоне, единственное, что нужно сделать, это воткнуть шнур в компьютер, зайти в примонтировавшийся диск и запустить исполняемый файл, который и установит adb-драйвер. Для других устройств все может быть сложнее. Например, для планшета Prestigio мне в свое время пришлось прописывать Vendor ID в специальный файл (чтобы использовался стандартный драйвер от Google), для Samsung нужен их собственный Kies, был отдельный драйвер для HTC и так далее. В общем, вам придется самостоятельно разобраться, как установить драйвер для вашего устройства.

После того как драйвер был установлен, нужно на устройстве разрешить отладку по USB. У меня на телефоне для этого нужно зайти в Настройки->Для разработчиков->Отладка по USB. Но для разных устройств, а также сборок и версий Android, расположение этого пункта меню может отличаться.

Теперь телефон будет находиться Android SDK, а разрабатываемые приложения будут устанавливаться. Однако, для Huawei это еще не все: с телефона не идут логи, нужно их включить.

Как включить логи на Huawei

Набрать в качестве телефонного номера: *#*#2846579#*#*
Появится сервисное меню.
Перейти в ProjectMenu->Background Setting->Log Setting
Открыть Log switch и установить там ON.
Открыть Log level setting и установить необходимый вам уровень логирования (я поставил verbose).
Перезагрузить телефон.

Теперь можно запускать приложение на устройстве: Run->Run ‘app’

В диалоге выбора устройства появилось реальное устройство

Запускаемся на телефоне.

Результат запуска.

Приложение в портрете:

Приложение в ландшафте:

Установка и настройка Android NDK

1. Установка NDK

Android SDK, как мы уже выяснили, входит в комплект Android Studio, а вот NDK — нет. Скачиваем NDK, подходящий для вашей системы, отсюда. Распаковываем архив и кладем в какую-нибудь папку, например, в D:\ndk, так, чтобы файл ndk-build.cmd лежал прямо в ней. Важно: необходимо, чтобы в пути к NDK не было пробелов.

2. Добавим переменную ANDROID_NDK_HOME

Заходим в Панель управления\Система и безопасность\Система, выбираем слева Дополнительные параметры системы, в открывшемся диалоге нажимаем кнопку Переменные среды. Создаем переменную с именем ANDROID_NDK_HOME и значением D:\ndk (путь к вашей NDK).

Альтернативно, вместо указания глобальной переменной можно прописать путь к ndk в файле local.properties вашего проекта (прямо в корневой папке: MyApplication\local.properties). Содержимое файла будет выглядеть примерно так (обратите внимание на двойные бэкслеши, так как для Windows это критично):

## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file should *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=C:\\Users\\<user>\\AppData\\Local\\Android\\android-studio\\sdk
ndk.dir=D:\\ndk

Не верьте дисклеймеру про «ваши изменения будут выкинуты», в данном случае это не так. Обратите внимание, что этот файл рекомендуется исключать из-под контроля версий, так как он содержит только локальную для пользователя информацию. Для разнообразия в этом нам не соврали. Ну и, само собой, это изменение никак не повлияет на другие Ваши проекты. При установленной ANDROID_NDK_HOME прописывать путь в local.properties необязательно.

3. Установим необходимую версию Android API

Зайдите в NDK\platforms (у меня это D:\ndk\platforms) и посмотрите максимальную версию доступных API. В моем случае максимальная версия 19. Но при этом в SDK у нас установлены только версии 20 и 15. Так что заходим в SDK Manager и скачиваем SDK Platform версии 19, иначе ничего не соберется.

Что надо скачать

4. Настроим gradle для работы с NDK

Информацию я брал из сэмплов, скачать их можно здесь, в самом низу страницы. Я скачивал сэмплы для версии 0.11. В качестве основного примера я брал ndkSanAngeles.

Как запустить ndkSanAngeles

После того, как сэмплы скачаны, их нужно распаковать. Затем нужно открыть проект ndkSanAngeles. Для Android Studio проектом является папка, так что открывать надо именно ее. Для того этого выполняем File->Open, либо, если вы в Welcome диалоге, Open Project. Ищем папку ndkSanAngeles через диалог открытия файла.

После открытия проекта стоит обратить взор на файл build.gradle. Вот его оригинал:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.11.0'
    }
}
apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion '19.1.0'

    defaultConfig {
        ndk {
            moduleName "sanangeles"
            cFlags "-DANDROID_NDK -DDISABLE_IMPORTGL"
            ldLibs "GLESv1_CM", "dl", "log"
            stl "stlport_static"
        }

        // This actual the app version code. Giving ourselves 1,000,000 values
        versionCode = 123

    }

    buildTypes.debug.jniDebugBuild true

    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }

            // this is the flavor part of the version code.
            // It must be higher than the arm one for devices supporting
            // both, as x86 is preferred.
            versionCode = 3
        }
        arm {
            ndk {
                abiFilter "armeabi-v7a"
            }
            versionCode = 2
        }
        mips {
            ndk {
                abiFilter "mips"
            }
            versionCode = 1
        }
        fat {
            // fat binary, lowest version code to be
            // the last option
            versionCode = 0
        }
    }

    // make per-variant version code
    applicationVariants.all { variant ->
        // get the single flavor
        def flavorVersion = variant.productFlavors.get(0).versionCode

        // set the composite code
        variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode
    }
}

А вот измененная версия, чтобы проект собирался у меня:

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.12.+'
    }
}
apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion '20.0.0'

    defaultConfig {
        ndk {
            moduleName "sanangeles"
            cFlags "-DANDROID_NDK -DDISABLE_IMPORTGL"
            ldLibs "GLESv1_CM", "dl", "log"
            stl "stlport_static"
        }

        // This actual the app version code. Giving ourselves 1,000,000 values
        versionCode = 123

    }

    buildTypes.debug.jniDebugBuild true

    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }

            // this is the flavor part of the version code.
            // It must be higher than the arm one for devices supporting
            // both, as x86 is preferred.
            versionCode = 3
        }
        arm {
            ndk {
                abiFilter "armeabi-v7a"
            }
            versionCode = 2
        }
        mips {
            ndk {
                abiFilter "mips"
            }
            versionCode = 1
        }
        fat {
            // fat binary, lowest version code to be
            // the last option
            versionCode = 0
        }
    }

    // make per-variant version code
    applicationVariants.all { variant ->
        // get the single flavor
        def flavorVersion = variant.productFlavors.get(0).versionCode

        // set the composite code
        variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode
    }
}

Изменения следующие:

  • О несовпадении версии плагина gradle (classpath ‘com.android.tools.build:gradle:0.11.0’) будет сказано при попытке сборки и предложен правильный номер версии. У меня это 0.12.+.
  • compileSdkVersion 19 остается, так как это максимальная версия для текущего NDK.
  • buildToolsVersion изменился на 20. Установленные версии можно посмотреть в SDK Manager, там же можно установить другие.

После этого ndkSanAngeles должен собраться. Будьте внимательны, проверяйте версии, установленные у вас.

В нашем проекте нужно выбрать правильный файд build.gradle, так как здесь их два. Дело в том, что MyApplication — это проект, а app — это модуль проекта (или подпроект), и у них build.gradle для каждого свой. Сначала рассмотрим файл проекта

MyApplication->build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:0.12.+'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

Из комментариев в коде явно следует, что нам нужен файл модуля

MyApplication->app->build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 20
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.example.markedone.myapp"
        minSdkVersion 15
        targetSdkVersion 20
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    // You must install or update the Support Repository through the SDK manager to use this dependency.
    //compile 'com.android.support:support-v4:19.+'
    compile 'com.android.support:support-v4:20.+'
}

Настроим его для работы с NDK, используя в качестве «донора» build.gradle из ndkSanAngeles.

Для начала, заменим
compileSdkVersion 20
на
compileSdkVersion 19
так как NDK ограничен версией 19.

В defaultConfig мы добавим настройки ndk, а также заменим targetSdkVersion на 19:

defaultConfig {
        applicationId "com.example.markedone.myapp"
        minSdkVersion 15
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "myapp"
            cFlags "-DANDROID_NDK"
            ldLibs "log"
            stl "stlport_static"
        }
    }

Настройки NDK включают в себя

  • moduleName — имя модуля, будет использовано для именования *.so файла
  • cFlags — флаги C
  • ldLibs — библиотеки, которые вы хотите подключить к нативному коду
  • stl — версия библиотеки STL

В buildTypes включим для debug дебажную сборку JNI:

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug.jniDebugBuild true
    }

Теперь добавим productFlavors. Здесь мы указываем, какие собранные *.so библиотеки включать в сборку под конкретную архитектуру. Таким образом, *.apk собранный для arm будет содержать версию библиотеки только для arm, под x86 — для x86 и так далее. Этот кусок полностью скопирован с ndkSanAngeles. Объяснение значений versionCode из комментариев: для x86 ставим максимальное значение versionCode, так как если устройство поддерживает и x86 и arm, то сборка x86 предпочтительнее (видимо, так как у нее большая версия, то установлена будет именно она), а минимальный versionCode прописывается для fat (по идее это должен быть «толстый» *.apk, содержащий сразу все возможные версии библиотек).

    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }

            // this is the flavor part of the version code.
            // It must be higher than the arm one for devices supporting
            // both, as x86 is preferred.
            versionCode = 3
        }
        arm {
            ndk {
                abiFilter "armeabi-v7a"
            }
            versionCode = 2
        }
        mips {
            ndk {
                abiFilter "mips"
            }
            versionCode = 1
        }
        fat {
            // fat binary, lowest version code to be
            // the last option
            versionCode = 0
        }
    }

«Собираем» значение versionCode для каждого из вариантов сборки:

    // make per-variant version code
    applicationVariants.all { variant ->
        // get the single flavor
        def flavorVersion = variant.productFlavors.get(0).versionCode

        // set the composite code
        variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode
    }

Наконец, последняя секция, dependencies. Если помните, здесь мы меняли compile ‘com.android.support:support-v4:19.+’ на compile ‘com.android.support:support-v4:20.+’, чтобы собирать с единственной установленной у нас версией библиотеки. Теперь придется поменять обратно на 19.

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    // You must install or update the Support Repository through the SDK manager to use this dependency.
    compile 'com.android.support:support-v4:19.+'
}

Полный листинг измененного файла build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 19
    buildToolsVersion "20.0.0"

    defaultConfig {
        applicationId "com.example.markedone.myapp"
        minSdkVersion 15
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "myapp"
            cFlags "-DANDROID_NDK"
            ldLibs "log"
            stl "stlport_static"
        }
    }

    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug.jniDebugBuild true
    }

    productFlavors {
        x86 {
            ndk {
                abiFilter "x86"
            }

            // this is the flavor part of the version code.
            // It must be higher than the arm one for devices supporting
            // both, as x86 is preferred.
            versionCode = 3
        }
        arm {
            ndk {
                abiFilter "armeabi-v7a"
            }
            versionCode = 2
        }
        mips {
            ndk {
                abiFilter "mips"
            }
            versionCode = 1
        }
        fat {
            // fat binary, lowest version code to be
            // the last option
            versionCode = 0
        }
    }

    // make per-variant version code
    applicationVariants.all { variant ->
        // get the single flavor
        def flavorVersion = variant.productFlavors.get(0).versionCode

        // set the composite code
        variant.mergedFlavor.versionCode = flavorVersion * 1000000 + defaultConfig.versionCode
    }

    sourceSets { main { jni.srcDirs = ['src/main/jni', 'src/main/jni/'] } }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    // You must install or update the Support Repository through the SDK manager to use this dependency.
    compile 'com.android.support:support-v4:19.+'
}

5. Создаем папку jni

В папке jni мы будем сохранять C/C++ файлы. Этого от нас ожидает NDK. Папку нам нужно создать в MyApplication/app/src/main. Это можно сделать прямо из Android Studio, причем, двумя способами.
Во-первых, можно кликнуть правой кнопкой на main и просто создать папку через

New->Directory

Во вторых, можно воспользоваться специальным пунктом меню

New->Folder->JNI Folder

Он запускает визард создания папки

В первом диалоге мы выбираем, для какой части модуля будет создана папка jni, а во втором можно изменить ее расположение.

6. Добавим C++ файлы

Визарда для C++ файлов нет, поэтому для создания файла мы кликаем правой кнопкой на папке jni и выбираем

New->File

Для начала создадим заголовочный файл myapp.h:

#pragma once

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz);

#ifdef __cplusplus
}
#endif

Описание

  • #pragma once — вместо стандартной (#ifndef/#define/#endif) защиты от повторного включения. Сейчас #pragma once понимается большинством C++ компиляторов.
  • #include <jni.h> — включаем заголовок JNI, чтобы можно было использовать типы, объявленные там.
  • #ifdef __cplusplus ... #endif — код внутри будет скомпилирован только в C++ (но не в C).
  • extern "C" { ... } — избавляемся от name mangling (что это и почему, хорошо описано тут).
  • JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz); — объявление функции, которую будем реализовывать.
    Разберем это объявление подробнее.

    • JNIEXPORT необходимо для грамотной линковки.
    • JNICALL для правильного соглашения о вызове.
    • jstring — тип возвращаемого значения функции, в данном случае это строка, совместимая со строкой Java.
    • Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI — имя функции, состоит из:
      Java — язык, который вызывает.
      com_example_markedone_myapp — это id приложения (com.example.markedone.myapp).
      FullscreenActivity — имя класса Java, который содержит объявление метода, представляющего нативную функцию.
      stringFromJNI — собственно, имя функции (таким оно будет в Java).
    • JNIEnv* env, jclass clazz — обязательные параметры, передающиеся из Java.
      JNIEnv* env — указатель на объект, представляющий из себя JNI-окружение.
      jclass clazz — класс, которому принадлежит объявление нативного метода в Java. Здесь нужно оговориться, что jclass clazz — это для статического нативного (static native) метода. Для нестатического метода будет нужно писать jobject obj.

Теперь создадим файл реализации, myapp.cpp. В нем мы напишем следующий код:

#include <android/log.h>
#include <string>
#include "myapp.h"

JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz)
{
    std::string tag("GREETING");
    std::string message("Hello from C++!");
    __android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%s", message.c_str());
    std::string jniMessage("Hello from JNI!");
    return env->NewStringUTF(jniMessage.c_str());
}

Описание

  • #include <android/log.h> — подключаем лог, ради которого мы даже добавили библиотеку (ldLibs «log»)
  • #include - для std::string, который мы используем для проверки наличия STL.
    #include "myapp.h" — подключаем наш заголовочный файл.
    JNIEXPORT jstring JNICALL Java_com_example_markedone_myapp_FullscreenActivity_stringFromJNI(JNIEnv* env, jclass clazz) { ... } - реализуем функцию, объявленную в "myapp.h".
    std::string tag("GREETING"); std::string message("Hello from C++!"); — создаем строки для вывода в лог.
    __android_log_print(ANDROID_LOG_INFO, tag.c_str(), "%s", message.c_str()); — вывод в лог. Обратите внимание, что необходимо указывать 4 параметра: тип сообщения в логе, тэг, формат строки, и, наконец, само сообщение.
    std::string jniMessage("Hello from JNI!"); — строка, которую мы будем передавать в Java.
    return env->NewStringUTF(jniMessage.c_str()); — возвращаемое значение, при помощи JNIEnv создаем jstring из C-строки. Обратите внимание, что нам не нужна конструкция вида (*env)->, так как мы пишем на C++, а не на C.

А теперь мы создадим еще один файл: stub.cpp, и оставим его пустым. Дело в том, что если оставить только один *.cpp файл в папке jni, то ndk-build будет выдавать ошибку «no rule to make target».

7. Добавим вызов нативной функции из Java

Открываем файл MyApplication/app/src/main/java/com.example.markedone.myapp.FullscreenActivity. На самом деле, у него расширение java, а com, example, markedone и myapp — это папки, но Android Studio это скрывает.

Содержимое файла

package com.example.markedone.myapp;

import com.example.markedone.myapp.util.SystemUiHider;

import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;


/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 *
 * @see SystemUiHider
 */
public class FullscreenActivity extends Activity {
    /**
     * Whether or not the system UI should be auto-hidden after
     * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
     */
    private static final boolean AUTO_HIDE = true;

    /**
     * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
     * user interaction before hiding the system UI.
     */
    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;

    /**
     * If set, will toggle the system UI visibility upon interaction. Otherwise,
     * will show the system UI visibility upon interaction.
     */
    private static final boolean TOGGLE_ON_CLICK = true;

    /**
     * The flags to pass to {@link SystemUiHider#getInstance}.
     */
    private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;

    /**
     * The instance of the {@link SystemUiHider} for this activity.
     */
    private SystemUiHider mSystemUiHider;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_fullscreen);

        final View controlsView = findViewById(R.id.fullscreen_content_controls);
        final View contentView = findViewById(R.id.fullscreen_content);

        // Set up an instance of SystemUiHider to control the system UI for
        // this activity.
        mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS);
        mSystemUiHider.setup();
        mSystemUiHider
                .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
                    // Cached values.
                    int mControlsHeight;
                    int mShortAnimTime;

                    @Override
                    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
                    public void onVisibilityChange(boolean visible) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
                            // If the ViewPropertyAnimator API is available
                            // (Honeycomb MR2 and later), use it to animate the
                            // in-layout UI controls at the bottom of the
                            // screen.
                            if (mControlsHeight == 0) {
                                mControlsHeight = controlsView.getHeight();
                            }
                            if (mShortAnimTime == 0) {
                                mShortAnimTime = getResources().getInteger(
                                        android.R.integer.config_shortAnimTime);
                            }
                            controlsView.animate()
                                    .translationY(visible ? 0 : mControlsHeight)
                                    .setDuration(mShortAnimTime);
                        } else {
                            // If the ViewPropertyAnimator APIs aren't
                            // available, simply show or hide the in-layout UI
                            // controls.
                            controlsView.setVisibility(visible ? View.VISIBLE : View.GONE);
                        }

                        if (visible && AUTO_HIDE) {
                            // Schedule a hide().
                            delayedHide(AUTO_HIDE_DELAY_MILLIS);
                        }
                    }
                });

        // Set up the user interaction to manually show or hide the system UI.
        contentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TOGGLE_ON_CLICK) {
                    mSystemUiHider.toggle();
                } else {
                    mSystemUiHider.show();
                }
            }
        });

        // Upon interacting with UI controls, delay any scheduled hide()
        // operations to prevent the jarring behavior of controls going away
        // while interacting with the UI.
        findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        // Trigger the initial hide() shortly after the activity has been
        // created, to briefly hint to the user that UI controls
        // are available.
        delayedHide(100);
    }


    /**
     * Touch listener to use for in-layout UI controls to delay hiding the
     * system UI. This is to prevent the jarring behavior of controls going away
     * while interacting with activity UI.
     */
    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (AUTO_HIDE) {
                delayedHide(AUTO_HIDE_DELAY_MILLIS);
            }
            return false;
        }
    };

    Handler mHideHandler = new Handler();
    Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            mSystemUiHider.hide();
        }
    };

    /**
     * Schedules a call to hide() in [delay] milliseconds, canceling any
     * previously scheduled calls.
     */
    private void delayedHide(int delayMillis) {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }
}

Добавим следующий код в класс FullscreenActivity:

    static {
        System.loadLibrary("myapp");
    }

    private static native String stringFromJNI();

Здесь сначала идет загрузка библиотеки, а затем объявление метода stringFromJNI, который соответствует нашей функции в C++. Обратите внимание, что он объявлен как static (это влияет на то, что (jclass или jobject) будет в качестве второго параметра C++-функции) и native. Реализовывать native-метод не нужно, мы это уже сделали в C++, а остальное за нас сделает JNI.

Теперь мы, в общем-то, уже можем вызвать нашу функцию. Если вы, как и я, выбрали FullscreenActivity, то у нас есть Dummy Button, который, по сути, ничего не делает. И даже уже есть touch listener, пусть и не самый лучший (он будет вызываться много раз, пока палец на экране), но, чтобы не плодить лишний код, используем его.

Для начала добавим в список импорта:
import android.widget.Button;
чтобы можно было нормально работать с кнопкой.

Найдем следующий код:

    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (AUTO_HIDE) {
                delayedHide(AUTO_HIDE_DELAY_MILLIS);
            }
            return false;
        }
    };

и добавим несколько строк перед return false.

    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (AUTO_HIDE) {
                delayedHide(AUTO_HIDE_DELAY_MILLIS);
            }
            final String message = stringFromJNI();
            final Button button = (Button)findViewById(R.id.dummy_button);
            final String actualText = button.getText().toString();
            if(message.equals(actualText)) {
                button.setText("Dummy Button");
            }
            else {
                button.setText(message);
            }
            return false;
        }
    };

Описание добавленного кода

  • final String message = stringFromJNI(); — получаем строку из C++. Вызов нативного метода — то, ради чего все и затевалось.
  • final Button button = (Button)findViewById(R.id.dummy_button); — находим объект кнопки.
  • final String actualText = button.getText().toString(); — вытаскиваем текущий текст кнопки.
  • if(message.equals(actualText)) — сравниваем строку, полученную из C++, с текстом кнопки.
    • button.setText("Dummy Button"); — если одинаковы, меняем текст кнопки на Dummy Button.
    • button.setText(message); — если различаются, то меняем на текст, полученный из C++.

Полный листинг класса измененного класса

package com.example.markedone.myapp;

import com.example.markedone.myapp.util.SystemUiHider;

import android.annotation.TargetApi;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;


/**
 * An example full-screen activity that shows and hides the system UI (i.e.
 * status bar and navigation/system bar) with user interaction.
 *
 * @see SystemUiHider
 */
public class FullscreenActivity extends Activity {

    static {
        System.loadLibrary("myapp");
    }

    private static native String stringFromJNI();


    /**
     * Whether or not the system UI should be auto-hidden after
     * {@link #AUTO_HIDE_DELAY_MILLIS} milliseconds.
     */
    private static final boolean AUTO_HIDE = true;

    /**
     * If {@link #AUTO_HIDE} is set, the number of milliseconds to wait after
     * user interaction before hiding the system UI.
     */
    private static final int AUTO_HIDE_DELAY_MILLIS = 3000;

    /**
     * If set, will toggle the system UI visibility upon interaction. Otherwise,
     * will show the system UI visibility upon interaction.
     */
    private static final boolean TOGGLE_ON_CLICK = true;

    /**
     * The flags to pass to {@link SystemUiHider#getInstance}.
     */
    private static final int HIDER_FLAGS = SystemUiHider.FLAG_HIDE_NAVIGATION;

    /**
     * The instance of the {@link SystemUiHider} for this activity.
     */
    private SystemUiHider mSystemUiHider;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_fullscreen);

        final View controlsView = findViewById(R.id.fullscreen_content_controls);
        final View contentView = findViewById(R.id.fullscreen_content);

        // Set up an instance of SystemUiHider to control the system UI for
        // this activity.
        mSystemUiHider = SystemUiHider.getInstance(this, contentView, HIDER_FLAGS);
        mSystemUiHider.setup();
        mSystemUiHider
                .setOnVisibilityChangeListener(new SystemUiHider.OnVisibilityChangeListener() {
                    // Cached values.
                    int mControlsHeight;
                    int mShortAnimTime;

                    @Override
                    @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
                    public void onVisibilityChange(boolean visible) {
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
                            // If the ViewPropertyAnimator API is available
                            // (Honeycomb MR2 and later), use it to animate the
                            // in-layout UI controls at the bottom of the
                            // screen.
                            if (mControlsHeight == 0) {
                                mControlsHeight = controlsView.getHeight();
                            }
                            if (mShortAnimTime == 0) {
                                mShortAnimTime = getResources().getInteger(
                                        android.R.integer.config_shortAnimTime);
                            }
                            controlsView.animate()
                                    .translationY(visible ? 0 : mControlsHeight)
                                    .setDuration(mShortAnimTime);
                        } else {
                            // If the ViewPropertyAnimator APIs aren't
                            // available, simply show or hide the in-layout UI
                            // controls.
                            controlsView.setVisibility(visible ? View.VISIBLE : View.GONE);
                        }

                        if (visible && AUTO_HIDE) {
                            // Schedule a hide().
                            delayedHide(AUTO_HIDE_DELAY_MILLIS);
                        }
                    }
                });

        // Set up the user interaction to manually show or hide the system UI.
        contentView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (TOGGLE_ON_CLICK) {
                    mSystemUiHider.toggle();
                } else {
                    mSystemUiHider.show();
                }
            }
        });

        // Upon interacting with UI controls, delay any scheduled hide()
        // operations to prevent the jarring behavior of controls going away
        // while interacting with the UI.
        findViewById(R.id.dummy_button).setOnTouchListener(mDelayHideTouchListener);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        // Trigger the initial hide() shortly after the activity has been
        // created, to briefly hint to the user that UI controls
        // are available.
        delayedHide(100);
    }


    /**
     * Touch listener to use for in-layout UI controls to delay hiding the
     * system UI. This is to prevent the jarring behavior of controls going away
     * while interacting with activity UI.
     */
    View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            if (AUTO_HIDE) {
                delayedHide(AUTO_HIDE_DELAY_MILLIS);
            }
            final String message = stringFromJNI();
            final Button button = (Button)findViewById(R.id.dummy_button);
            final String actualText = button.getText().toString();
            if(message.equals(actualText)) {
                button.setText("Dummy Button");
            }
            else {
                button.setText(message);
            }
            return false;
        }
    };

    Handler mHideHandler = new Handler();
    Runnable mHideRunnable = new Runnable() {
        @Override
        public void run() {
            mSystemUiHider.hide();
        }
    };

    /**
     * Schedules a call to hide() in [delay] milliseconds, canceling any
     * previously scheduled calls.
     */
    private void delayedHide(int delayMillis) {
        mHideHandler.removeCallbacks(mHideRunnable);
        mHideHandler.postDelayed(mHideRunnable, delayMillis);
    }

}

17. Собираем и запускаем проект

Сначала Build->Make Project. На этом этапе собирается Java-часть.
Затем Run->Run ‘app’. А вот здесь, перед стартом приложения, будет происходить сборка C++ части. Если в ней будут какие-то ошибки, то об этом будет выведено сообщение. Если ошибок нет, то появится стандартный диалог выбора устройства, и, после нажатия OK приложение запустится.

Работа на реальном устройстве

Вывод сообщения в лог

Заключение

В целом, мне Android Studio понравилась. Интеграция Android SDK выполнена довольно плотно, иногда даже забываешь, что это запускаются отдельные программы. Есть всякие интересные плюшки, такие, как Help me choose. Понравилась новая система сборки — Gradle, — но тут же и недостаток: по ней очень мало информации.

Также, видно, что поддержка NDK еще сыровата, но прослеживается движение в этом направлении. Очень надеюсь, что они все-таки сделают полноценную поддержку C++-разработки.

P.S. Дебага C++ кода пока не обнаружено.

Contents

  • 1 Android NDK Develop environment set up summary
      • 1.0.1 Step1. Download installer from official site
      • 1.0.2 Step2. Execute installer 
      • 1.0.3 Step3. Move extracted folder to favorite place
      • 1.0.4 Step4. Set environment PATH to point NDK folder path
  • 2 Sample source code testing
  • 3 More to do

Android NDK Develop environment set up summary

Usually Android application is developed by Java, but you can use C/C++ source code together with Android NDK (Android Native Development Kit). It provides us a opportunity to re-use/integrate existing C source code as well.

Below is summary for the steps how to start working with Android NDK.

Step1. Download installer from official site

Visit download site here, and choose installer depending on your development OS platform. In my case, I was working on Windows 7 64-bit OS, I chose android-ndk-r10e-windows-x86_64.exe.

Step2. Execute installer 

Double click to execute downloaded installer(.exe file in Windows case). It will just automatically extract the files to construct NDK working directory set. It takes a time, maybe ~ 10 min.

After Step2, you get extracted directory, something like “android-ndk-r10e“. Move whole this directory to any favorite place.

(For example, I moved it to C:\Users\[myUserName]\AppData\Local\Android\android-ndk-r10e, since there was sdk folders in C:\Users\[myUserName]\AppData\Local\Android\sdk .)

Step4. Set environment PATH to point NDK folder path

Windows case: Go to [Control Panel] → [System and Security] → [System] → [Advanced system settings] → [Environment Variables]

In System variables category, find “Path” variable and press [Edit…] to add NDK folder path. In my case it is adding Variable value as,

The paths already written;C:\Users\[myUserName]\AppData\Local\Android\android-ndk-r10e

That’s all. Environment Path setting is necessary for executing “ndk-build” command, which is used to compile C/C++ source code for Android development. You can find ndk-build in C:\Users\[myUserName]\AppData\Local\Android\android-ndk-r10e\ndk-build.

I will write C:\Users\[myUserName]\AppData\Local\Android\android-ndk-r10e as $NDK_PATH.

Sample source code testing

NDK folder comes with many sample source codes so that you can easily find how to write C code and JNI. The sample source codes can be found in $NDK_PATH/samples.

Details are explained in Android developer ndk setup guides page.

More to do

Usually, we build .so file from C/C++ source code and use it as library. Instead, it is also possible to build executable file and execute directory inside Android device.

Android NDK not found: a comprehensive guide

The Android NDK (Native Development Kit) is a toolset that allows you to develop native code for Android. It’s a powerful tool that can give you access to features that aren’t available in the Java programming language, such as hardware acceleration and low-level system access.

However, the NDK can also be a bit tricky to set up and use. If you’re not careful, you may run into errors like “NDK not found”. This error can be caused by a variety of factors, such as:

  • A missing or corrupt NDK installation
  • An incorrect NDK path
  • A problem with your build environment

In this guide, we’ll walk you through how to troubleshoot the “NDK not found” error. We’ll cover the different causes of the error and how to fix them. We’ll also provide some tips on how to use the NDK effectively.

By the end of this guide, you’ll be able to use the NDK to develop native code for Android without any problems.

Column 1 Column 2 Column 3
Title Description Link
Android NDK not found The Android NDK is not found on your system. This can prevent you from building Android applications from source. Android NDK Troubleshooting Guide
How to set the Android NDK path To set the Android NDK path, open the **Settings** app on your device and go to **Developer options**. Under **Build**, tap **Select NDK location** and choose the path to the Android NDK installation directory. How to Set the Android NDK Path
Android NDK missing libraries If you are missing libraries from the Android NDK, you can download them from the Android NDK downloads page. Android NDK downloads page

The Android NDK (Native Development Kit) is a toolset that allows you to develop native code for Android. This can be useful for tasks such as improving performance, accessing hardware that is not available through the Java API, or writing code that is not compatible with the Java language.

However, the NDK can sometimes be difficult to install and configure. One common problem is that the NDK is not found by the Android build system. This can prevent you from building and running your native code.

In this guide, we will discuss the reasons why the Android NDK might not be found and how to fix the problem.

What is the Android NDK?

The Android NDK is a toolset that allows you to develop native code for Android. This means that you can write code in C, C++, or assembly language and compile it into a native library that can be used by your Android app.

The NDK is useful for tasks that require high performance or access to hardware that is not available through the Java API. For example, you could use the NDK to write a graphics driver or a media codec.

The NDK is also useful if you want to write code that is not compatible with the Java language. For example, you could use the NDK to write a library that uses assembly language or a library that is not compatible with the Java Virtual Machine.

Why is the Android NDK not found?

There are a number of reasons why the Android NDK might not be found on your system. Some common reasons include:

  • The NDK is not installed.
  • The NDK is not installed in the correct location.
  • The NDK is not included in your PATH environment variable.
  • The NDK is not the correct version for your Android SDK.

Let’s take a closer look at each of these reasons.

The NDK is not installed

The first step in troubleshooting the Android NDK is to make sure that it is installed on your system. To do this, open the Android SDK Manager and check to see if the NDK package is installed. If the package is not installed, you can install it by clicking the Install button.

The NDK is not installed in the correct location

The NDK must be installed in a specific location in order for the Android build system to find it. By default, the NDK is installed in the following location:

~/Android/Sdk/ndk/

If you have installed the NDK in a different location, you must make sure to update the NDKROOT environment variable to point to the correct location.

To update the NDKROOT environment variable, open the Environment Variables dialog box and add the following line to the System variables section:

NDKROOT=/path/to/ndk

The NDK is not included in your PATH environment variable

The PATH environment variable is a list of directories that the operating system searches for executable files. In order for the Android build system to find the NDK tools, you must make sure that the NDK directory is included in the PATH environment variable.

To update the PATH environment variable, open the Environment Variables dialog box and add the following line to the System variables section:

%NDKROOT%/bin

The NDK is not the correct version for your Android SDK

The Android NDK is released in a variety of versions, each of which is compatible with a specific version of the Android SDK. If you are using an older version of the Android SDK, you may need to install an older version of the NDK.

To check the version of the Android SDK that you are using, open the Android SDK Manager and click the SDK Platforms tab. The Android SDK Platform that you are using is listed in the Installed Packages section.

To check the version of the NDK that you are using, open the Android SDK Manager and click the NDK tab. The NDK Version that you are using is listed in the Installed Packages section.

If the version of the NDK that you are using is not compatible with the version of the Android SDK that you are using, you will need to install a newer version of the NDK.

How to fix the Android NDK not found error

Once you have identified the reason why the Android NDK is not found, you can fix the problem by following the steps below:

1. Install the NDK. If the NDK is not installed, you can install it by following the instructions in the [Android N

The Android NDK (Native Development Kit) is a tool that allows you to develop native code for Android devices. If you’re trying to build an Android app that uses native code, and you get the error “NDK not found”, there are a few things you can check to try to fix the problem.

1. Install the NDK

The first step is to make sure that you have the Android NDK installed. You can download the NDK from the [Android Developers website](https://developer.android.com/ndk/). Once you’ve downloaded the NDK, extract the archive to a location on your computer.

2. Set the NDK location in your PATH environment variable

The next step is to set the NDK location in your PATH environment variable. This will tell your computer where to find the NDK when you’re trying to build an Android app. To set the NDK location in your PATH environment variable, follow these steps:

1. Open the **System Properties** window.
2. Click on the **Advanced** tab.
3. Click on the **Environment Variables** button.
4. In the **System variables** section, click on the **Path** variable and select **Edit**.
5. In the **Edit environment variable** dialog box, add the path to the NDK directory to the end of the **Value** field.
6. Click **OK** to close the **Edit environment variable** dialog box.
7. Click **OK** to close the **Environment Variables** dialog box.
8. Close the **System Properties** window.

3. Use the Android NDK Manager to install the correct version of the NDK

If you’re still getting the “NDK not found” error after you’ve installed the NDK and set the NDK location in your PATH environment variable, you may need to use the Android NDK Manager to install the correct version of the NDK. To use the Android NDK Manager, follow these steps:

1. Open the **Android Studio** IDE.
2. Click on the **Tools** menu and select **Android** > SDK Manager.
3. In the SDK Platforms tab, make sure that the Android NDK checkbox is checked.
4. Click on the OK button.

The Android NDK Manager will download and install the correct version of the NDK. Once the NDK is installed, you should be able to build your Android app without any errors.

If you’re still having trouble fixing the “NDK not found” error, you can try the following:

  • Make sure that you’re using the latest version of the Android NDK.
  • Try uninstalling and reinstalling the NDK.
  • Try building your app in a different location.
  • Try using a different compiler.
  • If you’re still having trouble, you can contact Google’s Android support team for help.

Additional resources

  • [Android NDK documentation](https://developer.android.com/ndk/)
  • [Android NDK tutorials](https://developer.android.com/ndk/guides/)
  • [Android NDK forums](https://groups.google.com/forum/!forum/android-ndk)

    Q: What is the Android NDK?

The Android NDK (Native Development Kit) is a toolset that allows you to develop native code for Android. This includes code written in C and C++, as well as assembly language. The NDK is useful for developing performance-critical code, such as graphics drivers or game engines.

Q: Why am I getting an error message that says “Android NDK not found”?

There are a few possible reasons why you might be getting this error message.

  • You may not have the Android NDK installed. To check if you have the NDK installed, open the Android Studio SDK Manager and look for the “Android NDK” package. If it is not installed, you can install it by clicking the “Install” button.
  • The Android NDK may not be installed in the correct location. By default, the Android NDK is installed in the `/Android/sdk/ndk` directory. If you have installed the NDK in a different location, you will need to set the `ANDROID_NDK_HOME` environment variable to the location of the NDK.
  • The Android NDK may be outdated. The Android NDK is updated regularly with new features and bug fixes. If you are getting an error message that says “Android NDK not found”, it is possible that you are using an outdated version of the NDK. You can check the Android NDK website to see if there is a newer version available.

Q: How do I fix the “Android NDK not found” error?

To fix the “Android NDK not found” error, you will need to do one of the following:

  • Install the Android NDK. If you do not have the Android NDK installed, you can install it by following the instructions in the [Android Studio documentation](https://developer.android.com/studio/projects/install-ndk).
  • Set the `ANDROID_NDK_HOME` environment variable. If you have installed the NDK in a different location than the default, you will need to set the `ANDROID_NDK_HOME` environment variable to the location of the NDK. To do this, open the System Properties window (Windows) or the Terminal (macOS) and type the following command:

set ANDROID_NDK_HOME=

  • Update the Android NDK. If you are using an outdated version of the Android NDK, you can update it by following the instructions in the [Android NDK documentation](https://developer.android.com/ndk/downloads).

Q: What are some common problems with the Android NDK?

There are a few common problems that people experience with the Android NDK.

  • The NDK can be difficult to use. The NDK is a complex toolset, and it can be difficult to learn how to use it. This can lead to errors and frustration.
  • The NDK can be slow. The NDK is a native compiler, and it can be slower than using a Java compiler. This can be a problem for applications that need to perform quickly.
  • The NDK can be difficult to debug. The NDK is not as well-supported as Java, and it can be difficult to debug problems with NDK code. This can lead to wasted time and frustration.

Q: What are some tips for using the Android NDK?

Here are a few tips for using the Android NDK:

  • Start with simple projects. When you are first learning how to use the NDK, it is a good idea to start with simple projects. This will help you to learn the basics of the NDK without getting overwhelmed.
  • Use the NDK documentation. The NDK documentation is a valuable resource for learning how to use the NDK. It provides detailed information on the NDK’s features and how to use them.
  • Join the Android NDK community. There are a number of online communities where you can connect with other Android developers who are using the NDK. These communities can be a valuable resource for help and support.

Q: What are the alternatives to the Android NDK?

There are a number of alternatives to the Android NDK. These include:

  • Java. Java is the official programming language for Android, and it can be used to develop native code for Android. Java is easier to use than the NDK, but it is not as fast.
  • Xamarin. Xamarin is

In this article, we discussed the Android NDK not found error. We first explained what the NDK is and why it’s important for Android development. Then, we listed the possible causes of the error and provided solutions for each one. Finally, we gave some tips on how to avoid the error in the future.

We hope that this article has been helpful in resolving your Android NDK not found error. If you have any other questions or concerns, please feel free to leave a comment below.

Key Takeaways

  • The Android NDK is a tool that allows developers to write native code for Android.
  • The NDK is important for Android development because it allows developers to access features that are not available in Java, such as hardware acceleration and low-level system calls.
  • The Android NDK not found error can occur for a variety of reasons, including missing dependencies, incorrect compiler settings, and outdated SDK versions.
  • To resolve the Android NDK not found error, you can try reinstalling the NDK, updating your SDK, or setting the correct compiler settings.
  • You can avoid the Android NDK not found error by making sure that you have the latest version of the NDK installed, that your SDK is up to date, and that you set the correct compiler settings.

Author Profile

Hatch, established in 2011 by Marcus Greenwood, has evolved significantly over the years. Marcus, a seasoned developer, brought a rich background in developing both B2B and consumer software for a diverse range of organizations, including hedge funds and web agencies.

Originally, Hatch was designed to seamlessly merge content management with social networking. We observed that social functionalities were often an afterthought in CMS-driven websites and set out to change that. Hatch was built to be inherently social, ensuring a fully integrated experience for users.

Now, Hatch embarks on a new chapter. While our past was rooted in bridging technical gaps and fostering open-source collaboration, our present and future are focused on unraveling mysteries and answering a myriad of questions. We have expanded our horizons to cover an extensive array of topics and inquiries, delving into the unknown and the unexplored.

Latest entries

The latest version extracts itself inside the current working directory. So if you launched it from the explorer, that’s the same directory as your .exe.

You should find an android-ndk-rXXX folder there. Otherwise that means it wasn’t extracted.

It’s always better to use the latest NDK, there are many bug fixes and improvements with each releases… You can open the .exe as an archive with 7zip, and extract it somewhere else if you need, or launch the .exe from a terminal set where you want to have it extracted.

I am using Visual Studio, but I also want to play with Android Studio. So, in order to get the Android SDK and NDK, I installed Android Studio.

The Answer

Android Studio installed the SDK naturally at

C:\Users\<UserName>\AppData\Local\Android\Sdk

The NDK folder is not yet ready, but is/will exist at

C:\Users\<UserName>\AppData\Local\Android\Sdk\ndk-bundle

In order to flush out the folder with the actual NDK, I had to tell Android Studio to install the NDK.

File -> Settings

Select Appearance and Behavior -> System Settings -> Android SDK

Click on the SDK Tools Tab

Checkbox the NDK (And, I think, the LLDB and CMake options).

Select Apply/Install.

Now that NDK folder should be good to go.

Android Studio 2.2 installs it in C:\Users\[username]\AppData\Local\Android\Sdk\ndk-bundle (on Windows 10).

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Управление службами windows в командной строке
  • Windows 10 зависает после спящего режима
  • Windows 10 20h1 отзывы
  • Windows can not change background
  • Файл подкачки windows 11 как настроить для 16 гб оперативной