Какое api соответствует android 4.1 1. «Сердце робота»: Как использовать системный API Android в личных целях. Как использовать системный API

Какое api соответствует android 4.1 1. «Сердце робота»: Как использовать системный API Android в личных целях. Как использовать системный API

Android SDK включает в себя разнообразные библиотеки, документацию и инструменты, которые помогают разрабатывать мобильные приложения для платформы Android .

  • API Android SDK - APIбиблиотеки Android, предоставляемые для разработки приложений.
  • Документация SDK- включает обширную справочную информацию, детализирующую, что включено в каждый пакет и класс и как это использовать при разработке приложений.
  • AVD (Android Virtual Device)- интерактивный эмулятор мобильного устройства Android. Используя эмулятор, можно запускать и тестировать приложения без использования реального Androidycтpoйcтвa.
  • Development Tools - SDK включает несколько инструментальных средств для разработки, которые позволяют компилировать и отлаживать создаваемые приложения.
  • Sample Code - Android SDK предоставляет типовые приложения, которые демонстрируют некоторые из возможностей Android, и простые программы, которые показывают, как использовать индивидуальные особенности API в вашем коде.

Версии SDK и Android API Level

Перед началом разработки приложений для Android полезно понять общий подход платформы к управлению изменением API. Также важно понять Android API Level (Идентификатор уровня API) и его роль в обеспечении совместимости вашего приложения с устройствами, на которых оно будет устанавливаться.

Уровень API - целочисленное значение, которое однозначно определяет версию API платформы Android. Платформа обеспечивает структуры API, которые приложения могут использовать для взаимодействия с системой Android. Каждая следующая версия платформы Android может включать обновления API.

Обновления API-структуры разработаны так, чтобы новый API оставался совместимым с более ранними версиями API. Таким образом, большинство изменений в API является совокупным и вводит новые функциональные возможности или исправляет предыдущие. Поскольку часть API постоянно обновляется, устаревшие API не рекомендуются к использованию, но не удаляются из соображений совместимости с имеющимися приложениями.

Уровень API, который использует приложение для Android, определяется целочисленным идентификатором, который указывается в файле конфигурации каждого Android-приложения.

Таблица определяет соответствие уровня API и версии платформы Android.

Соответствие версии платформы и уровня АРI

Инструменты для разработки и отладки приложений

Кроме эмулятора, SDK также включает множество других инструментальных средств для отладки и установки создаваемых приложений. Если вы разрабатываете приложения для Android с помощью IDE Eclipse, многие инструменты командной строки, входящие в состав SDK, уже используются при сборке и компиляции проекта. Однако кроме них SDK содержит еще ряд полезных инструментов для разработки и отладки приложений:

  • android - важный инструмент разработки, запускаемый из командной строки, который позволяет создавать, удалять и конфигурировать виртуальные устройства, создавать и обновлять Androidпроекты (при работе вне среды Eclipse) и обновлять Android SDK новыми платформами, дополнениями и документацией;
  • Dalvik Debug Monitor Service (DDMS) - интегрированный с Dalvik Virtual Machine, стандартной виртуальной машиной платформы Android, этот инструмент позволяет управлять процессам и на эмуляторе ил и устройстве, а также помогает в отладке приложений. Вы можете использовать этот сервис для завершения процессов, выбора определенного процесса для отладки, генерирования трассировочных данных, просмотра "кучи" или информации о пото ках, делать скриншоты эмулятора ил и устройства и многое другое;
  • Hierarchy Viewer - визуальный инструмент, который позволяет отлаживать и оптимизировать пользовательский интерфейс разрабатываемого приложения. Он показывает визуальное дерево иерархии представлений, анализирует быстродействие перерисовки графических изображений на экране и может выполнять еще много других функций для анализа графического интерфейса приложений;
  • Layoutopt - инструмент командной строки, который помогает оптимизировать схемы разметки и иерархии разметок в создаваемом приложении. Необходим для решения проблем при создании сложных графических интерфейсов, которые могут затрагивать производительность приложения;
  • Draw 9-patc h - графический редактор, который позволяет легко создавать NinеРаtсhграфику для графического интерфейса разрабатываемых приложений;
  • sqlite3 - инструмент для доступа к файлам данных SQLite, созданных и используемых приложениями для Android;
  • Traceview - этот инструмент выдает графический анализ трассировочных логов, которые можно генерировать из приложений;
  • mksdcard - инструмент для создания образа диска, который вы можете использовать в эмуляторе для симуляции наличия внешней карты памяти (например, карты SD).
  • Наиболее важный из них- эмулятор мобильного устройства , однако в состав SDK входят и другие инструменты для отладки, упаковки и инсталляции ваших приложений на эмулятор.

Android Virtual Device

Android Virtual Device (Виртуальное устройство Android )- это эмулятор, который запускается на обычном компьютере. Эмулятор используется для проектирования, отладки и тестирования приложений в реальной среде выполнения.

Прежде чем вы сможете запускать Androidэмулятор устройства, необходимо создать Android Virtual Device (AVD) . AVD определяет системное изображение и параметры настройки устройства, используемые эмулятором.

Создавать эмулятор устройства можно двумя способами:

  1. В командной строке утилитой android, доступной в каталоге, куда вы установили Android SDK, в папке tools.
  2. Визуально с помощью Android SDK and AVD Manager в IDE Eclipse , выбрав пункт меню Window | Android SDK and AVD Manager. Появится окно Android SDK and AVD Manager, с помощью которого можно создавать и конфигурировать эмуляторы мобильного устройства, а также загружать обновления Android SDK.

Окно Android SDK and AVD Manager также появится, если в командной строке вызвать android.exe без параметров.

iAndroid SDK and AVD Manager

Окно Android SDK and AVD Manager

В правой части панели List of existing Android Virtual Devices нажмите кнопку New, при этом откроется окно Create new AVD.

В этом окне задайте нужную конфигурацию для создаваемого эмулятора устройства:

  • Name - имя создаваемого устройства;
  • Target - версия Android SDK, поддерживаемая устройством. Устройство имеет обратную совместимость со старыми версиями SDK, т. е. если выбрана версия Android 2.0, эмулятор будет поддерживать версии SDK 1.6, 1.5, 1.1;
  • SD Card - устанавливает виртуальную карту SD;
  • Skin -тип экрана устройства. Загружаемая платформа включает ряд скинов для эмулятора, которые можно использовать для моделирования работы приложения в устройствах с разными размерами и разрешением экрана. Набор скинов для эмулятора в зависимости от установленной версии SDK, указанной в поле Target, содержит различные типы и размеры экрана, например:
  • HVGA (Halfsize VGA Video Graphics Array ), размер 320x480, средняя плотность, нормальный экран;
  • WVGA800 (Wide Video Graphics Array ), размер 480x800, высокая плотность, нормальный экран;
  • WVGA854 (Wide Video Graphics Array ), 480x854, высокая плотность, нормальный экран;
  • QVGA (Quarter Video Graphics Array ), размер 240x320, низкая плотность, малый экран;
  • WQVGA (Wide Quarter Video Graphics Array ), размер 240x400, низкая плотность, нормальный экран;

  • Hardware - имитация оборудования, установленного на устройстве. При необходимости нажатием кнопки New можно вызвать окно для добавления дополнительного виртуального оборудования.

Окно для добавления дополнительного виртуального оборудования

После задания конфигурации и нажатия кнопки Create AVD менеджер создаст новое виртуальное устройство, название и версия API которого появятся в списке List of existing Android Virtual Devices .

Для более тонкой настройки лучше использовать инструмент командной строки andnoid.exe. Он имеет более широкие возможности, чем визуальный AVD Мапа9ег, и удобен для конфигурации сети, портов и виртуального оборудования эмулятора. К сожалению, изза ограниченного объема книги нет возможности рассмотреть подробнее этот инструмент.

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

Окно эмулятора оформлено в виде телефона с дополнительной клавиатурой. После загрузки системы появляется Home screen - рабочий стол Android. Для доступа к нему используется кнопка со значком домика. Эмулятор также имитирует сенсорный экран реального мобильного устройства- в эмуляторе на экран нажимают левой кнопкой мыши.

В эмуляторе два виртуальных рабочих стола, перемещение по которым осуществляется с помощью кнопок со стрелками на навигационной панели устройства или передвижением курсора при нажатой левой кнопке мыши (в реальном устройстве- перемещая палец по экрану). Кроме ярлыков программы на рабочем столе можно размещать виджеты.

Внешний вид AVD версии 1.5

Внешний вид AVD версии 2.0

Для тестирования внешнего вида создаваемого приложения при разных положениях экрана комбинацией клавиш + можно изменять расположение экрана с вертикального на горизонтальный и наоборот.

Панель в верхней части экрана - это Status Bar. На ней расположены значки системных уведомлений: мощность сигнала станции мобильной связи, заряд аккумулятора и текущее время. Панель Status Bar также предназначена для отображения (в виде значков, появляющихся в левой части панели) пользовательских уведомлений о пропущенных звонках, непрочитанных текстовых и мультимедийных сообщениях, полученной почте и системных уведомлений от служб, работающих в фоновом режиме. Если в Status Bar выбрать значок уведомления и потянуть вниз появившийся маркер, открывается расширенная панель уведомления с более подробной информацией и кнопкой закрытия уведомления.

Маркер внизу экрана позволяет открыть окно запуска установленных в системе приложений- Application Launcher. Окно выдвигается при нажатии на маркер.

Эмулятор, тем не менее, не поддерживает некоторые функциональности, доступные на реальных устройствах:

  • входящие и исходящие сообщения. Однако можно моделировать обращения по телефону через интерфейс эмулятора;

Панель запуска установленных приложений Application Launcher

  • соединение через USB;
  • видеокамера (однако есть имитатор работы видеокамеры);
  • подключение наушников;
  • определение статуса соединения;
  • определение уровня заряда аккумуляторной батареи; D определение вставки или изъятия карты SD;
  • соединение по Bluetooth.

Конечно, реальные телефоны несколько отличаются от эмулятора, но в целом AVD разработан очень качественно и близок по функциональности к реальному устройству.

Любой, кто писал более или менее серьезный софт для разных мобильных ОС, знает, что Android - самая открытая для разработчика ОС. Доступный для сторонних приложений API здесь гораздо шире, сама система гибче, а правила размещения приложений в маркете очень либеральные. Однако и в Android есть ряд системных API, скрытых от сторонних приложений и доступных только стоковому софту. В этой статье мы попробуем разобраться, как получить доступ к этим API и какие возможности они открывают.

Немного теории

Как мы все знаем, в Android есть такое понятие - полномочия приложений (permissions, разрешения). Полномочия прописываются в файл Manifest.xml каждого приложения и определяют то, к каким функциям API сможет получить доступ приложение. Хочешь работать с камерой - добавь в Manifest.xml строку . Нужен доступ к карте памяти - android.permission.READ_EXTERNAL_STORAGE . Все просто и логично, к тому же все доступные приложениям полномочия хорошо документированы .

Есть, однако, в этой стройной схеме одна очень важная деталь, которую сами создатели Android называют уровень доступа (protection level). Чтобы понять, что это такое, попробуй добавить в Manifest.xml любого своего приложения следующую строку:

По идее, данное полномочие должно открыть доступ к API, позволяющему переводить смартфон в режим полета, включать/выключать GPS и делать другие полезные вещи. Но IDE так не считает и поэтому сразу подчеркивает строку как ошибку с формулировкой «Permission is only granted to system apps». Это и есть предупреждение о нарушении того самого уровня доступа. IDE как бы говорит нам: да, ты можешь попробовать дать своему приложению полномочие WRITE_SECURE_SETTINGS , но Android все равно не разрешит тебе использовать закрепленный за ним API до тех пор, пока ты не сделаешь свое приложение системным. А что значит «системным» в данном случае? Это значит: подпишешь его тем же цифровым ключом, каким подписана сама прошивка (иди попробуй раздобыть такой ключ у какой-нибудь Samsung или LG!).

Официально в Android существует четыре уровня доступа:

  • normal - «обычные» полномочия, дающие приложению доступ к безобидным функциям, которые не получится зловредно использовать (примеры: SET_ALARM, ACCESS_NETWORK_STATE, VIBRATE). Система даже не скажет тебе, что приложение вообще их использует;
  • dangerous - «опасные» полномочия, юзер будет информирован о них при установке приложения либо увидит окошко с предупреждением в Android 6.0 (примеры: READ_SMS, SEND_SMS, CALL_PHONE, READ_CALL_LOG);
  • signature - доступны только приложениям, подписанным ключом прошивки (примеры: GET_TASKS, MANAGE_USERS, WRITE_SETTINGS, MOUNT_UNMOUNT_FILESYSTEMS);
  • privileged - доступны приложениям, располагающимся в каталоге /system/priv-app .

В большинстве случаев уровни доступа signature и privileged равноценны. Например, чтобы получить полномочие MANAGE_USERS, приложение должно быть либо подписано ключом прошивки, либо размещено в каталоге /system/priv-app . Но есть и исключения: например, полномочие MANAGE_DEVICE_ADMIN имеет уровень доступа signature, то есть единственный способ его получить - подписать приложение ключом прошивки.

Есть также набор внутренних уровней доступа, введенных в Android для решения определенных проблем: installer , development , preinstalled , appop , pre23 . По сути, это костыли, и на данном этапе ты можешь о них не думать, однако к уровню доступа development мы еще вернемся, и он нам очень сильно пригодится. А пока поговорим о том, как получить нужные нам уровни доступа и что они дают.

Уровень доступа privileged

Privileged не самый высокий уровень доступа и позволяет использовать далеко не весь API Android. Однако в большинстве случаев он оказывается вполне достаточным, так как позволяет устанавливать и удалять приложения и пользователей (INSTALL_PACKAGES, DELETE_PACKAGES, MANAGE_USERS), управлять статусной строкой (STATUS_BAR), управлять некоторыми настройками питания (WRITE_SECURE_SETTINGS), читать и изменять настройки Wi-Fi (READ_WIFI_CREDENTIAL, OVERRIDE_WIFI_CONFIG), отключать приложения и их компоненты (CHANGE_COMPONENT_ENABLED_STATE) и многое другое.

Чтобы приложение получило уровень доступа privileged, оно должно быть установлено в каталог /system/priv-app , а это значит - поставляться предустановленным в составе прошивки. Однако, имея root, мы можем поместить свое приложение в данный каталог с помощью двух функций:

// Подсобная функция, которая просто выполняет shell-команду static public boolean runCommandWait(String cmd, boolean needsu) { try { String su = "sh"; if (needsu) { su = "su"; } Process process = Runtime.getRuntime().exec(new String{su, "-c", cmd}); int result = process.waitFor(); return (result == 0); } catch (IOException e) { throw new RuntimeException(e); } catch (InterruptedException e) { throw new RuntimeException(e); } } // Функция делает указанное приложение системным и отправляет смартфон в мягкую перезагрузку static public void makeAppSystem(String appName) { String systemPrivAppDir = "/system/priv-app/"; String systemAppDir = "/system/app/"; String appPath = "/data/app/" + appName; // Подключаем /system в режиме чтения-записи if (!runCommandWait("mount -o remount,rw /system", true)) { Log.e(TAG, "makeAppSystem: Can"t mount /system"); return; } int api = Build.VERSION.SDK_INT; String appDir = systemPrivAppDir; // Копируем приложение в /system/priv-app или /system/app в зависимости от версии Android if (api >= 21) { runCommandWait("cp -R " + appPath + "* " + appDir, true); runCommandWait("chown -R 0:0 " + appDir + appName + "*", true); runCommandWait("rm -Rf " + appPath + "*", true); } else { if (api < 20) { appDir = systemAppDir; } runCommandWait("cp " + appPath + "* " + appDir, true); runCommandWait("chown 0:0 " + appDir + appName + "*", true); runCommandWait("rm -f " + appPath + "*", true); } // Отправляем смартфон в мягкую перезагрузку Shell.runCommand("am restart", true); }

Функцию runCommandWait я описывать не буду, она просто выполняет shell-команду и ждет ее завершения (подробнее читай в моей статье про написание приложений с правами root). Функция makeAppSystem, в свою очередь, принимает полное имя приложения (это то самое com.example.app, которое ты указываешь при создании нового проекта в Android Studio) и переносит его в /system/priv-app или /system/app , в зависимости от используемой версии Android. Код может показаться тебе несколько странным, на самом деле он абсолютно корректен и учитывает два фактора:

  • до Android 4.4 (API Level: 20) каталога /system/priv-app не существовало и все системные приложения размещались в /system/app ;
  • начиная с Android 5.0 (API Level: 21) пакеты с приложениями не просто складируются в /data/app и /system/priv-app , а размещаются внутри своих обособленных подкаталогов.

Как использовать этот код? Очень просто: ты определяешь в Manifest.xml своего приложения все privileged-полномочия, которые ему нужны, не обращая внимания на ошибки IDE. Затем в самое начало кода приложения вставляешь вызов makeAppSystem с именем самого приложения в качестве аргумента, компилируешь и запускаешь. После запуска приложение перемещает само себя в /system/priv-app , перезагружает смартфон, и ему открываются все privileged API.

Список privileged-полномочий можно посмотреть в исходниках Android . Просто ищи по слову privileged. О том, как их использовать, - чуть позже.

Уровень доступа signature

Подпись ключом прошивки позволяет получить самый высокий уровень доступа к API - signature. Имеющее такой доступ приложение может делать практически все что угодно: манипулировать любыми настройками Android (WRITE_SETTINGS, WRITE_SECURE_SETTINGS), наделять приложения правами администратора (MANAGE_DEVICE_ADMINS), программно нажимать кнопки и вводить данные в любое окно (INJECT_EVENTS) и многое другое.

Получить такой уровень доступа на стоковой прошивке почти невозможно. Ни один производитель смартфонов не предоставит тебе ключ для подписи своих прошивок. Но если речь идет о кастомной прошивке, то все становится немного проще. Например, ночные сборки того же CyanogenMod (а я напомню, что пользователей у нее больше, чем юзеров всех версий Windows Phone, вместе взятых) подписываются тестовым ключом, а его особенность в том, что он есть в открытом доступе .

Но это еще не все, в CyanogenMod есть механизм безопасности, который, в отличие от чистого Android, позволяет получать уровень доступа signature не абсолютно всем приложениям, подписанным ключом прошивки, а только тем, что размещены в /system/priv-app . Поэтому, чтобы получить уровень доступа signature в CyanogenMod (не в Cyanogen OS, я подчеркиваю), необходимо:

  1. Добавить в Manifest.xml приложения необходимые полномочия.
  2. Добавить в приложение вызов функции makeAppSystem(), описанной в предыдущем разделе.
  3. Подписать релизную версию приложения ключом platform из репозитория CyanogenMod.

Уровень доступа development

В Android есть специальный уровень доступа development, отличие которого заключается в том, что приложения получают его не по факту размещения в /system/priv-app или использования цифровой подписи прошивки, а динамически. То есть система может дать такой уровень доступа любому приложению, а может и отозвать обратно. Но самое важное, что, имея права root, приложение может наделить себя таким уровнем доступа самостоятельно.

Чтобы это сделать, достаточно использовать примерно такой код:

RunCommandWait("pm grant " + appName + " android.permission.WRITE_SECURE_SETTINGS", true);

В данном случае приложение appName получит полномочие WRITE_SECURE_SETTINGS вне зависимости от того, где оно размещено и каким ключом подписано. Круто? Вне сомнения, однако WRITE_SECURE_SETTINGS - фактически единственное полезное полномочие с уровнем доступа development. Остальные четырнадцать - это полномочия для отладки и тестирования (чтение логов, дампы памяти и так далее).

Как использовать системный API?

Основная проблема, с которой ты столкнешься при работе с системным API, - это полное (за небольшими исключениями) отсутствие документации. Ни в официальных руководствах, ни в неофициальных ты не найдешь почти никаких упоминаний об этом. Информацию придется собирать по крупицам, прошаривая сотни страниц форумов и читая тысячи страниц исходников Android. Однако хоть и небольшую, но отправную точку в виде парочки полезных примеров мы тебе дадим.

WRITE_SECURE_SETTINGS

Полномочие WRITE_SECURE_SETTINGS появилось в Android 4.2 для защиты некоторых критически важных настроек Android. Среди таких настроек: включение/выключение режима полета, управление настройками местоположения и передачи данных. Оно защищено сразу тремя уровнями доступа: signature, privileged и development. То есть ты можешь использовать любой из перечисленных выше способов получения уровня доступа, чтобы наделить свое приложение полномочием WRITE_SECURE_SETTINGS.

Как использовать открывшиеся возможности? Например, так:

// Читаем текущее значение настройки boolean isEnabled = Settings.System.getInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0) == 1; // Переключаем настройку Settings.System.putInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, isEnabled ? 0: 1); // Отправляем интент для переключения Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); intent.putExtra("state", !isEnabled); sendBroadcast(intent);

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

INSTALL_PACKAGES

Как ясно из названия, полномочие INSTALL_PACKAGES позволяет «втихую» устанавливать в систему APK-пакеты. Использовать эту возможность могут либо подписанные ключом прошивки приложения (signature), либо установленные в /system/priv-app . При этом даже не обязательно использовать Java API, достаточно вызвать консолью команду pm (Package Manager) с нужными параметрами:

RunCommandWait("pm install " + apkPath, false);

После отработки команды пакет apkPath будет установлен в систему. Ты можешь возразить, что то же самое можно сделать и с правами root, и будешь прав: в данном случае достаточно изменить последний аргумент функции runCommandWait() на true. Однако стоит иметь в виду, что приложения с правами root, во-первых, приводят к появлению окна запроса соответствующих полномочий у юзера, а во-вторых, логируются тем же SuperSU. А так достаточно один раз прописать свою софтину в /system/priv-app , и она сможет устанавливать сколько угодно софта без всяких вопросов.

Вместо выводов

Вот и все. Доступ к закрытому API в Android не так уж и сложно получить. С другой стороны, с легитимным софтом использовать его в большинстве случаев не имеет смысла, проще получить права root и вызывать соответствующие консольные команды: settings для изменения настроек, pm для установки/удаления приложений, setprop для изменения низкоуровневых настроек и так далее. Однако если речь идет о не совсем обычном программном обеспечении...


Поделитесь пожалуйста пустым проектом, готовым к публикации для TV устройств.
что-то никак не получается опубликовать, сейчас отклонили с такими ошибками:
APK:8
No Now Playing notification "
Your App does not contain a “Now Playing” notification for when the user has selected the HOME button within the app. Please refer to our Displaying a Now Playing Card documentation for more details.
APK:8
Play/Pause key event is not respected during playback
Your media apps that play video or music content must respect the play/pause key during playback. Please refer to our Media Play/Pause documentation and Update the Playback State documentation for details.
Missing DPad functionality
Your app requires user interaction for menus or app navigation. Please make sure that all menus and app navigation are fully functional using a DPad. Please refer to our DPAD Control and Hardware Declaration documentation.
ну и баннер не прилепил
No full-size app banner
Your app does not contain a full-size app banner or is it not visible in the launcher. We are targeting 1080P, which we consider xhdpi. Apps should include the banner in the xhdpi (320 dpi) drawables folder with a size of (320px × 180px). Please refer to our Home Screen Banner and UI Patterns documentation.
The title should help users identify apps in the launcher. Please refer to our Visual Design and User Interaction documentation for more information.
был бы очень благодарен за рабочий пустой костяк с манифестом.

От

В процессе разработки столкнулся с очень странной ситуацией, корни которой до сих пор неясны, но решение нашлось.
Итак. Делфи 10.3.3. Чистое приложение - пустая форма и кнопка. Отлично работает на разных устройствах кроме Samsung Galaxy Tab A (2016). Android 5.1.1
Программа падает, не успев даже загрузиться. Любая. При этом она же, скомпилированная на другом компе, запускается нормально. И даже после изменения SDK/NDK на нем, ничего не падает.
LogCat дает крайне странную картину
java.lang.IllegalArgumentException: Unable to load native library: /data/app-lib/com.embarcadero.Project1-1/libProject1.so
Начинаем экспериментировать с SDK, NDK и т.д. Поставил также хотфиксы для 10.3.3.
Сразу скажу, SDK/NDK ставились отдельно через Android studio, не скачивались вместе с Delphi. Не торопитесь бросать чтение на этом месте!)) На другом компе, где все работает, все ставилось точно так же.
Короче, очень много комбинаций версий SDK/NDK проверено.
Результат такой. При постепенном понижении версии NDK все взлетело при NDK v22.

При этом версия SDK видимо такого большого влияния не имеет, потому что этот вариант нормально работает

Повторюсь. На других устройствах все работало и на более новых Ndk. Xiaomi Mi Pad4 , Samsung Galaxy Tab A (2019), Xiaomi Redmi 5 и 5Plus

Спасибо за участие и помощь в разборе завалов @Andrey Efimov

От

У меня в работе два приложения, и оба они не предназначены для Play market, так как имеют ограниченный круг использования, по сути, чисто внутрикорпоративные. Так что нежелательно и выкладывание их и на альтернативные магазины приложений.
Автоматически возникает вопрос обновления. Если в первый раз мы можем установить приложение сами при помощи админов, то обновлять их не так просто. А контингент пользователей не справится с "скачайте APK по ссылке, найдите, куда его скачал браузер, и запустите вручную именно последний скачанный, а не какой попало"...
Простейший способ - дать приложению скачать свежую копию с сайта и натравить на полученный файл системный инсталлер.
Вот только свежие Andoird делать это напрямик запрещают. Нужен filepropvider. Целый день шуровал по мануалам и YT,
Вот то что получилось в результате.
Если у вас 10.3.3 как у меня, уже можно не вносить ... в манифест и свой файл file_paths.xml (или как вам его советуют назвать в интернетах) в деплой.
Теперь все это делается хоть несколько странно и однобоко, но автоматически, путем установки галочки Secure File Sharing

После этого в манифесте автоматически пропишется один из вариантов размещения файлов, которые вы можете найти в интернете. Используется алиас external-path
файл, показанный на рисунке, создается автоматически самой делфи.

Теперь остается отгадать, какой путь реально подставится вместо "."
Как показала практика, все пути выглядят не так, как кажется, если исходить из простого здравого смысла. Целый день использования GetHomeDir и других полезных методов TPath завел меня совсем в тупик.
Оказалось все проще (?)
st:TMemoryStream; OutputDir: JFile; ApkFile: JFile; ApkUri: Jnet_Uri; path, filename: string; ... OutputDir:= TAndroidHelper.Context.getExternalCacheDir(); path:= JStringToString(OutputDir.getAbsolutePath); filename:= path+"/ASDroid2.apk"; ApkFile:= TJfile.JavaClass.init(StringToJstring(filename)); FApkUri:= TAndroidHelper.JFileToJURI(ApkFile); st.Position:= 0; st.SaveToFile(filename); обратите внимание, в provider_paths мы задаем external-paths, а в коде ищем ExternalCacheDir.!!! (For.Unbelievably.Creative.Knowers!)
Потом все просто. FApkUri передаем в интент и запускаем
итоговый код примерно таков. (скачивание в потоке с использованием небольшого собственного API, но там ничего важного, можно не обращать внимания)
procedure TasdSettingsFrame.bDownloadClick(Sender: TObject); begin {$IFDEF ANDROID} bDownload.Enabled:= False; DownloadAndRun(); {$ENDIF} end; {$IFDEF ANDROID} procedure TasdSettingsFrame.DownloadAndRun(); begin ttask.Run(procedure var aapi:TasdAPI; st:TMemoryStream; OutputDir: JFile; ApkFile: JFile; ApkUri: Jnet_Uri; path, filename: string; begin st:= TMemoryStream.Create; aapi:= TasdAPI.Clone(_API); try aapi.OnReceiveData:= OnReceiveData; aapi.getApk(st); if aapi.Err.Code=0 then begin OutputDir:= TAndroidHelper.Context.getExternalCacheDir(); path:= JStringToString(OutputDir.getAbsolutePath); filename:= path+"/ASDroid2.apk"; ApkFile:= TJfile.JavaClass.init(StringToJstring(filename)); FApkUri:= TAndroidHelper.JFileToJURI(ApkFile); st.Position:= 0; st.SaveToFile(filename); TThread.Synchronize(nil,procedure begin bDownload.Enabled:= true; StartActivity(FApkUri); end); end; finally st.Free; aapi.Free; end; end); end; procedure StartActivity(ApkUri: Jnet_Uri); var Intent: JIntent; begin Intent:= TJIntent.Create(); Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.addFlags(TJIntent.JavaClass.FLAG_ACTIVITY_NEW_TASK or TJIntent.JavaClass.FLAG_ACTIVITY_CLEAR_TOP or TJIntent.JavaClass.FLAG_GRANT_WRITE_URI_PERMISSION or TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION); Intent.setDataAndType(apkuri, StringToJString("application/vnd.android.package-archive")); TAndroidHelper.Activity.startActivity(Intent); end; procedure TasdSettingsFrame.OnReceiveData(const Sender: TObject; AContentLength: Int64; AReadCount: Int64; var Abort: Boolean); begin tthread.Synchronize(nil, procedure begin pb1.Max:= AContentLength; pb1.Value:= AReadCount; end); end; {$ENDIF} Вопросы остались конечно, почему так странно с каталогами, но выяснять пока нет желания. Работает - не трожь.
Всем удачи.
UPD.
Для того, чтобы системный инсталлер запускался, нужно не забыть отметить еще одну галочку

От

Приветствую. На просторах интернета нашел BASS-библиотеку для Android и соответственно обертку для нее под Delphi.

Вроде бы все работает нормально, но вот при настройке библиотеки при помощи методов
BASS_GetConfigPtr, BASS_SetConfigPtr для работы со строковыми параметрами возникает проблема.
На Windows с этим я легко работал, там достаточно использовать такую конструкцию

PAnsiChar(BASS_GetConfigPtr(configId)) и получаем значение. BASS_SetConfigPtr(configId, PAnsiChar(value)) и задаем значение. Но вот под Android такой способ не проходит, как минимум по одной причине - он не понимает, что такое PAnsiChar. На docwiki.emarcadero.com, есть вот такая статейка. В которой написано, что PAnsiChar нужно заменить одним из трех: System.String, System.MarshalledString или System.SysUtils.TStringBuiler
Только вот, если использовать MarshalledString, то при попытке получить значение приложение просто намертво зависает и все.
Потом я подумал, так как библиотека написана на Java (вероятно), то может стоит попробовать использовать JNI в работе с ней, так как в Java файле, который прилагался вместе с библиотекой. Там я нашел объявления этих функций и заметил, что тип возвращаемого значения Object (ну, не зная Java я просто предположил, что это тоже просто ссылка на значение, например как PAnsiChar в Delphi на Windows).

Но, при попытке как-либо использовать это натыкаюсь на проблемы в виде ошибки компиляции, либо очередном зависании приложения.
Так как возвращается Object, то решил попробовать вариант с JObject и JString, но ни один вариант не хочет работать, опять ошибки на стадии компиляции, либо зависание приложение. Может быть, я что-то не так делаю.

В общем, буду признателен за помощь!

От

Доброго времени!
Есть идея сделать возможность резервирования данных приложения на Google drive под текущим аккаунтом пользователя. Ничего подобного я на форуме не нашел, может быть кто-то уже пытался решать подобную задачу? Интересует работа с Gdrive в первую очередь.

От

Ну всё в принципе как всегда, либо я барашка, либо лыжи не едут)
А всё просто - я хочу, чтобы пока данные с сервера загружались по клику кнопки, пользователю элементарно был отклик в виде крутящейся какой нибудь фигни и он видел, что процесс идёт и что прога не зависла и никуда лишний раз не тыкал.
Пока что для тестов сделала элементарно кнопку Update (speedbutton с image), данные элементарно грузятся и отображаются в GridPanel, а поверх него, чтоб пользователь и не смог куда либо тыкнуть, замостила панелькой с Image, вращаемой по таймеру (всё это дело наверху Visible:=false). И когда клацаем по кнопке Update, то панельку сверху грида делаю отображаемой и запускаю таймер, потом этот же обработчик/процедура грузит данные, а по окончанию останавливаем таймер и скрываем полупрозрачну, еще кстати, панельку. Аля вот так:
procedure TForm1.SB_DataUpdateClick(Sender: TObject); begin //отображаем лого загрузки P_showLoad.Visible:= true; Timer_load_rotate.Enabled:= true; //с запуском таймера GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется //и скрывае лого загрузки Timer_load_rotate.Enabled:= false; //уже в обратном порядке P_showLoad.Visible:= false; end; иии... ни черта не происходит как я хочу(
Это лого вообще в итоге не отображается, а если убрать его скрытие, то оно у нас отобразится уже только тогда, когда всё загрузится. Логика мне стала подсказывать, что следовало его как то отобразить выполнив в параллельном асинхронном потоке аля так:
procedure TForm1.SB_DataUpdateClick(Sender: TObject); begin TThread.Queue(TThread.Current, //TThread.Queue TThread.Synchronize ForceQueue procedure() begin P_showLoad.Visible:= true; Timer_load_rotate.Enabled:= true; end); GetDeD_List(DE_set.Date); //процедура загрузки и отображения чего нам надо, которая весьма долго выполняется end; И опять оно отображается только после того, как всё загрузится и проработает вся процедура. И уже чего только не пробовала и Synchronize и ForceQueue; и через TTask.Run и |task:= TTask.Create(procedure () ... и т.д.| ничего не подходит, вот хоть убейся это всё дело будет отображаться только после полной отработки процедуры клика. Может я не в том направлении вообще рою и это как то по другому делается? Может я еще пока отлаживаю на Win32, а не всё на android, а там вот пара вариантов и норм на нём работают? Но чтот я никак не могу понять, что к чему... должно же быть как то просто, а я чтот никак не могу понять как(

От

Goоgle Play перестает поддерживать 32-bit Android-приложения c 01.08.2019.
А выкладывать в Goоgle Play новые УЖЕ нельзя.
Последние же Delphi XE не позволяют создать 64-bit Android-приложения.
Кто знает, когда появится новая версия с поддержкой 64 - bit? Говорили, что в конце лета, но лето кончилось

  • Последние посетители 0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

  • Первая версия Android появилась в октябре 2008 года - всего 4 года назад, что не так много для операционной системы. За это время вышло уже более двух десятков обновлений. Основная часть обновлений включала в себя новые элементы программного интерфейса (API ), которыми приложения могли пользоваться для своих нужд. Чтобы та или иная версия Android знала, сможет ли она удовлетворить программные запросы того или иного приложения, была введена нумерация программных интерфейсов. Номер, характеризующий версию интерфейса, внедрялся в само приложение, и по нему система определяла совместимость этого приложения с собой. Этот номер назвали "уровень API" (API Level). Всего набралось уже 17 уровней, каждый последующий из которых включал в себя все функции предыдущего и добавлял новые.

    Для написания приложения вместе с системой программирования на компьютер устанавливают SDK (software development kit ) — комплект средств разработки, основной частью которого является библиотека классов соответствующего API-уровня. Для каждого API-уровня существует своя библиотека, функциями которой пользуется приложение. Если мы возьмём для разработки своего приложения библиотеку первого API-уровня, то мы не получим в своё распоряжение функции, появившиеся позже. Если же мы возьмём библиотеку последнего уровня - мы рискуем сделать своё приложение несовместимым со старыми версиями Android, если вдруг используем функцию, неподдерживаемую ранее. Так как же осуществить выбор API-уровня?

    В нашем приложении мы должны установить два API-уровня (есть ещё и третий, но он фактически отмер за ненадобностью). Первый - это минимальный API-уровень, на котором приложение сможет работать, а второй - это целевой API-уровень, то есть API-уровень, на котором откомпилировано приложение. При публикации приложения этот уровень должен быть максимально доступным на тот момент, чтобы в новых версиях Android оно работало не в режиме совместимости, а использовало все рюшечки новой версии операционной системы (не зависящие от автора самой программы). В момент же написания программы её следует компилировать на минимально возможный API-уровень, чтобы не задействовать новых функций.

    В итоге получаем такую методику разработки приложения:

    1. Изучаем целевую аудиторию - какая версия Android установлена на их смартфонах. Если пишем для всех, то полезно будет ознакомиться с постоянно обновляемыми графиками использования той или иной версии системы на мобильных устройствах: http://developer.android.com/intl/ru/about/dashboards/index.html . На сегодняшний день видим, что основная масса уже сидит на уровне API 10, но также существуют немаленькие куски, сидящие на уровне 7 и 8. Различия в уровнях можно посмотреть тут (http://developer.android.com/intl/ru/guide/topics/manifest/uses-sdk-element.html), щёлкнув на номере соответствующего API в таблице.
    2. Если мы не хотим терять около 10% аудитории, выбираем минимальный уровень API 7. Иначе можем выбрать уровень API 10, на котором сидит сегодня почти половина пользователей. Устанавливаем соответствующий выбранному минимальному уровню SDK.
    3. Устанавливаем целевой уровень, равный минимальному, пишем и компилируем под него программу. Запускаем и тестируем её на эмуляторе смартфона с установленным API минимального уровня.
    4. После написания и отладки программы повышаем целевой уровень на единицу, компилируем программу под SDK нового целевого уровня и тестируем её в новом эмуляторе смартфона с соответствующим уровнем. Далее продолжаем повышать целевой API-уровень, компилировать и тестировать программу, пока не достигнем самого высокого API-уровня.
    5. Всё, теперь можно публиковать программу. При выходе новой версии Android с новым API-уровнем наша программа включится в нём в режиме совместимости и будет работать, как раньше. Чтобы программа заработала напрямую, а не в режиме совместимости, берём наш проект, скачиваем новое SDK последнего API-уровня, и компилируем приложение под ним. Теперь приложение запустится на новой системе в обычном режиме, и, возможно, станет выглядеть немного иначе, в традициях новой версии операционной системы. В то же время на старых версиях системы приложение остается таким, как было.
    В итоге, поразмыслив, для себя я остановился на уровне API 7. Кроме того, при использовании некоторых новых функций, появившихся в гораздо более поздних API (например, фрагментов), среда разработки сама мне предложила задействовать специальный пакет совместимости, и добавила его в проект. В результате я получил возможность использовать некоторые новые функции из новых API в старом. Впрочем, это уже другая тема.

    More information about how API levels work is available in What is API Level?

    App Components

    Isolated services

    App stack navigation

    Android 4.1 makes it much easier to implement the proper design patterns for Up navigation. All you need to do is add the android:parentActivityName to each element in your manifest file. The system uses this information to open the appropriate activity when the user presses the Up button in the action bar (while also finishing the current activity). So if you declare the android:parentActivityName for each activity, you don"t need the onOptionsItemSelected() method to handle click events on the action bar"s app icon—the system now handles that event and resumes or creates the appropriate activity.

    This is particularly powerful for scenarios in which the user enters one of your app"s activities through a "deep dive" intent such as from a notification or an intent from different app (as described in the design guide for Navigating Between Apps). When the user enters your activity this way, your app may not naturally have a back stack of activities that can be resumed as the user navigates up. However, when you supply the android:parentActivityName attribute for your activities, the system recognizes whether or not your app already contains a back stack of parent activities and, if not, constructs a synthetic back stack that contains all parent activities.

    Note: When the user enters a deep activity in your app and it creates a new task for your app, the system actually inserts the stack of parent activities into the task. As such, pressing the Back button also navigates back through the stack of parent activities.

    When the system creates a synthetic back stack for your app, it builds a basic Intent to create a new instance of each parent activity. So there"s no saved state for the parent activities the way you"d expect had the user naturally navigated through each activity. If any of the parent activities normally show a UI that"s dependent on the user"s context, that context information will be missing and you should deliver it when the user navigates back through the stack. For example, if the user is viewing an album in a music app, navigating up might bring them to an activity that lists all albums in a chosen music genre. In this case, if the stack must be created, it"s necessary that you inform the parent activity what genre the current album belongs to so that the parent can display the proper list as if the user actually came from that activity. To deliver such information to a synthetic parent activity, you must override the method. This provides you with a TaskStackBuilder object that the system created in order to synthesize the parent activities. The TaskStackBuilder contains Intent objects that the system uses to create each parent activity. In your implementation of onPrepareNavigateUpTaskStack() , you can modify the appropriate Intent to add extra data that the parent activity can use to determine the appropriate context and display the appropriate UI.

    If your app structure is more complex, there are several other APIs available that allow you to handle the behavior of Up navigation and fully customize the synthetic back stack. Some of the APIs that give you additional control include:

    onNavigateUp() Override this to perform a custom action when the user presses the Up button. navigateUpTo(Intent) Call this to finish the current activity and go to the activity indicated by the supplied Intent . If the activity exists in the back stack, but is not the closest parent, then all other activities between the current activity and the activity specified with the intent are finished as well. getParentActivityIntent() Call this to get the Intent that will start the logical parent for the current activity. shouldUpRecreateTask(Intent) Call this to query whether a synthetic back stack must be created in order to navigate up. Returns true if a synthetic stack must be created, false if the appropropriate stack already exists. finishAffinity() Call this to finish the current activity and all parent activities with the same task affinity that are chained to the current activity. If you override the default behaviors such as onNavigateUp() , you should call this method when you create a synthetic back stack upon Up navigation. onCreateNavigateUpTaskStack Override this if you need to fully control how the synthetic task stack is created. If you want to simply add some extra data to the intents for your back stack, you should instead override onPrepareNavigateUpTaskStack()

    However, most apps don"t need to use these APIs or implement onPrepareNavigateUpTaskStack() , but can can achieve the correct behavior simply by adding android:parentActivityName to each element.

    Multimedia

    Media codecs

    You can handle encrypted media data in the codecs by calling queueSecureInputBuffer() in conjunction with the MediaCrypto APIs, instead of the normal queueInputBuffer() .

    For more information about how to use codecs, see the MediaCodec documentation.

    Record audio on cue

    Audio effects

    Note: It"s not guaranteed that all devices support these effects, so you should always first check availability by calling isAvailable() on the corresponding audio effect class.

    Gapless playback

    You can now perform gapless playback between two separate MediaPlayer objects. At any time before your first MediaPlayer finishes, call setNextMediaPlayer() and Android attempts to start the second player the moment that the first one stops.

    Media router. The new APIs MediaRouter, MediaRouteActionProvider, and MediaRouteButton provide standard mechanisms and UI for choosing where to play media.

    Camera

    Auto focus movement

    Connectivity

    Android Beam

    Android Beam™ now supports large payload transfers over Bluetooth. When you define the data to transfer with either the new setBeamPushUris() method or the new callback interface NfcAdapter.CreateBeamUrisCallback , Android hands off the data transfer to Bluetooth or another alternate transport to achieve faster transfer speeds. This is especially useful for large payloads such as image and audio files and requires no visible pairing between the devices. No additional work is required by your app to take advantage of transfers over Bluetooth.

    When using the callback interface, the system calls the interface"s createBeamUris() method when the user executes a share with Android Beam so that you can define the URIs to share at share-time. This is useful if the URIs to share might vary depending on the user context within the activity, whereas calling setBeamPushUris() is useful when the URIs to share are unchanging and you can safely define them ahead of time.

    Network service discovery

    Android 4.1 adds support for multicast DNS-based service discovery, which allows you to find and connect to services offered by peer devices over Wi-Fi, such as mobile devices, printers, cameras, media players, and others that are registered on the local network.

    Before you can start discovering services on local devices, you also need to call addServiceRequest() . When the WifiP2pManager.ActionListener you pass to this method receives a successful callback, you can then begin discovering services on local devices by calling discoverServices() .

    When local services are discovered, you"ll receive a callback to either the WifiP2pManager.DnsSdServiceResponseListener or WifiP2pManager.UpnpServiceResponseListener , depending on whether you registered to use Bonjour or Upnp. The callback received in either case contains a WifiP2pDevice object representing the peer device.

    Network usage

    Accessibility services can also perform actions on behalf of the user, including clicking, scrolling and stepping through text using performAction and setMovementGranularities . The performGlobalAction() method also allows services to perform actions such as Back, Home, and open Recent Apps and Notifications.

    Customizable app navigation

    When building an Android app, you can now customize navigation schemes by finding focusable elements and input widgets using findFocus() and focusSearch() , and set focus using setAccessibilityFocused() .

    More accessible widgets

    The new android.view.accessibility.AccessibilityNodeProvider class allows you to surface complex custom views to accessibility services so they can present the information in a more accessible way. The android.view.accessibility.AccessibilityNodeProvider allows a user widget with advanced content, such as a calendar grid, to present a logical semantic structure for accessibility services that is completely separate from the widget’s layout structure. This semantic structure allows accessibility services to present a more useful interaction model for users who are visually impaired.

    Copy and Paste

    Copy and paste with intents

    Renderscript

    Renderscript computation functionality has been enhanced with the following features:

    • Support for multiple kernels within one script.
    • Support for reading from allocation with filtered samplers from compute in a new script API rsSample .
    • Support for different levels of FP precision in #pragma .
    • Support for querying additional information from RS objects from a compute script.
    • Numerous performance improvements.

    New pragmas are also available to define the floating point precision required by your compute Renderscripts. This lets you enable NEON like operations such as fast vector math operations on the CPU path that wouldn’t otherwise be possible with full IEEE 754-2008 standard.

    Note: The experimental Renderscript graphics engine is now deprecated.

    Animation

    Activity launch animations

    Remote views

    • "sans-serif" for regular Roboto
    • "sans-serif-light" for Roboto Light
    • "sans-serif-condensed" for Roboto Condensed

    Vibrate for input controllers

    If connected input devices have their own vibrate capabilities, you can now control the vibration of those devices using the existing Vibrator APIs simply by calling getVibrator() on the InputDevice .

    Permissions

    ...

    This feature defines "television" to be a typical living room television experience: displayed on a big screen, where the user is sitting far away and the dominant form of input is be something like a d-pad, and generally not through touch or a mouse/pointer-device.



    top