API-интерфейсы Android 4.1

Уровень API: 16

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

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

Чтобы лучше оптимизировать свое приложение для устройств под управлением Android 4.1, вам следует установить для targetSdkVersion значение "16" , установить его в образ системы Android 4.1, протестировать его, а затем опубликовать обновление с этим изменением.

Вы можете использовать API в Android 4.1, одновременно поддерживая более старые версии, добавив в код условия, которые проверяют уровень системного API перед выполнением API, не поддерживаемых вашим minSdkVersion . Чтобы узнать больше о обеспечении обратной совместимости, прочтите «Создание обратно совместимых пользовательских интерфейсов» .

Дополнительную информацию о том, как работают уровни API, можно найти в разделе «Что такое уровень API?».

Компоненты приложения

Изолированные сервисы

Указав android:isolatedProcess="true" в теге <service> , ваша Service будет работать под собственным изолированным процессом идентификатора пользователя, который не имеет собственных разрешений.

Управление памятью

Новые константы ComponentCallbacks2 , такие как TRIM_MEMORY_RUNNING_LOW и TRIM_MEMORY_RUNNING_CRITICAL предоставляют процессам переднего плана дополнительную информацию о состоянии памяти до того, как система вызовет onLowMemory() .

Новый метод getMyMemoryState(ActivityManager.RunningAppProcessInfo) позволяет получить общее состояние памяти.

Поставщики контента

Новый acquireUnstableContentProviderClient() позволяет вам получить доступ к ContentProviderClient , который может быть «нестабильным», поэтому ваше приложение не выйдет из строя, если это произойдет с поставщиком контента. Это полезно, когда вы взаимодействуете с поставщиками контента в отдельном приложении.

Живые обои

Новый протокол намерений, позволяющий напрямую запускать предварительный просмотр живых обоев, чтобы вы могли помочь пользователям легко выбирать живые обои, не заставляя их покидать приложение и переходить к средству выбора обоев «Домой».

Чтобы запустить средство выбора живых обоев, вызовите startActivity() с Intent используя ACTION_CHANGE_LIVE_WALLPAPER и дополнительный параметр, который указывает ComponentName живых обоев в виде строки в EXTRA_LIVE_WALLPAPER_COMPONENT .

Навигация по стеку приложений

Android 4.1 значительно упрощает реализацию правильных шаблонов проектирования для навигации вверх. Все, что вам нужно сделать, это добавить android:parentActivityName к каждому элементу <activity> в файле манифеста. Система использует эту информацию для открытия соответствующего действия, когда пользователь нажимает кнопку «Вверх» на панели действий (при этом также завершая текущее действие). Поэтому, если вы объявите android:parentActivityName для каждого действия, вам не понадобится метод onOptionsItemSelected() для обработки событий щелчка на значке приложения на панели действий — теперь система обрабатывает это событие и возобновляет или создает соответствующее действие.

Это особенно полезно для сценариев, в которых пользователь входит в одно из действий вашего приложения через намерение «глубокого погружения», например из уведомления или намерения из другого приложения (как описано в руководстве по проектированию « Навигация между приложениями »). Когда пользователь таким образом входит в вашу активность, ваше приложение, естественно, может не иметь стопки действий, которые можно было бы возобновить при переходе пользователя вверх. Однако когда вы указываете атрибут android:parentActivityName для своих действий, система распознает, содержит ли ваше приложение уже задний стек родительских действий, и, если нет, создает синтетический задний стек, содержащий все родительские действия.

Примечание. Когда пользователь выполняет глубокое действие в вашем приложении и создает для него новую задачу, система фактически вставляет в задачу стек родительских действий. Таким образом, нажатие кнопки «Назад» также позволяет вернуться назад по стеку родительских действий.

Когда система создает синтетический стек для вашего приложения, она создает базовое Intent для создания нового экземпляра каждого родительского действия. Таким образом, для родительских действий нет сохраненного состояния, как можно было бы ожидать, если бы пользователь естественным образом перемещался по каждому действию. Если какое-либо из родительских действий обычно отображает пользовательский интерфейс, зависящий от контекста пользователя, эта информация о контексте будет отсутствовать, и вам следует доставить ее, когда пользователь вернется обратно через стек. Например, если пользователь просматривает альбом в музыкальном приложении, переход вверх может привести его к действию, в котором перечислены все альбомы выбранного музыкального жанра. В этом случае, если необходимо создать стек, необходимо сообщить родительскому действию, к какому жанру принадлежит текущий альбом, чтобы родительский элемент мог отобразить правильный список, как если бы пользователь действительно пришел из этого действия. Чтобы доставить такую ​​информацию синтетическому родительскому действию, необходимо переопределить метод onPrepareNavigateUpTaskStack() . Это предоставляет вам объект TaskStackBuilder , созданный системой для синтеза родительских действий. TaskStackBuilder содержит объекты Intent , которые система использует для создания каждого родительского действия. В вашей реализации onPrepareNavigateUpTaskStack() вы можете изменить соответствующее Intent , добавив дополнительные данные, которые родительское действие может использовать для определения соответствующего контекста и отображения соответствующего пользовательского интерфейса.

Когда система создает TaskStackBuilder , она добавляет объекты Intent , которые используются для создания родительских действий, в их логическом порядке, начиная с вершины дерева действий. Итак, последнее Intent , добавленное во внутренний массив, является прямым родителем текущего действия. Если вы хотите изменить Intent родительского элемента действия, сначала определите длину массива с помощью getIntentCount() и передайте это значение в editIntentAt() .

Если структура вашего приложения более сложная, доступно несколько других API, которые позволяют вам управлять поведением навигации вверх и полностью настраивать синтетический обратный стек. Некоторые из API, которые дают вам дополнительный контроль, включают:

onNavigateUp()
Переопределите это, чтобы выполнять пользовательское действие, когда пользователь нажимает кнопку «Вверх».
navigateUpTo(Intent)
Вызовите это, чтобы завершить текущее действие и перейти к действию, указанному в указанном Intent . Если действие существует в заднем стеке, но не является ближайшим родителем, то все остальные действия между текущим действием и действием, указанным в намерении, также завершаются.
getParentActivityIntent()
Вызовите это, чтобы получить Intent , которое запустит логического родительского объекта для текущего действия.
shouldUpRecreateTask(Intent)
Вызовите это, чтобы узнать, необходимо ли создать синтетический задний стек для перехода вверх. Возвращает true, если необходимо создать синтетический стек, и false, если соответствующий стек уже существует.
finishAffinity()
Вызовите это, чтобы завершить текущее действие и все родительские действия с той же привязкой к задаче, которые привязаны к текущему действию. Если вы переопределяете поведение по умолчанию, такое как onNavigateUp() , вам следует вызывать этот метод при создании синтетического обратного стека при навигации вверх.
onCreateNavigateUpTaskStack
Переопределите это значение, если вам нужно полностью контролировать создание синтетического стека задач. Если вы хотите просто добавить дополнительные данные в намерения вашего обратного стека, вместо этого вам следует переопределить onPrepareNavigateUpTaskStack()

Однако большинству приложений не требуется использовать эти API или реализовывать onPrepareNavigateUpTaskStack() , но можно добиться правильного поведения, просто добавив android:parentActivityName к каждому элементу <activity> .

Мультимедиа

Медиакодеки

Класс MediaCodec предоставляет доступ к медиакодекам низкого уровня для кодирования и декодирования медиафайлов. Вы можете создать экземпляр MediaCodec , вызвав createEncoderByType() для кодирования мультимедиа или вызвав createDecoderByType() для декодирования мультимедиа. Каждый из этих методов принимает тип MIME для типа мультимедиа, который вы хотите кодировать или декодировать, например "video/3gpp" или "audio/vorbis" .

После создания экземпляра MediaCodec вы можете вызвать configure() чтобы указать такие свойства, как формат мультимедиа или зашифровано ли содержимое.

Независимо от того, кодируете ли вы или декодируете медиафайлы, остальная часть процесса после создания MediaCodec остается одинаковой. Сначала вызовите getInputBuffers() , чтобы получить массив входных объектов ByteBuffer , и getOutputBuffers() , чтобы получить массив выходных объектов ByteBuffer .

Когда вы будете готовы к кодированию или декодированию, вызовите dequeueInputBuffer() чтобы получить индексную позицию ByteBuffer (из массива входных буферов), которую вы должны использовать для подачи исходного мультимедиа. После того, как вы заполните ByteBuffer исходным медиафайлом, освободите право владения буфером, вызвав queueInputBuffer() .

Аналогично для выходного буфера вызовите dequeueOutputBuffer() чтобы получить позицию индекса ByteBuffer , где вы получите результаты. После того, как вы прочтете выходные данные ByteBuffer , освободите владение, вызвав releaseOutputBuffer() .

Вы можете обрабатывать зашифрованные медиаданные в кодеках, вызывая queueSecureInputBuffer() в сочетании с API MediaCrypto вместо обычного queueInputBuffer() .

Дополнительные сведения об использовании кодеков см. в документации MediaCodec .

Запись звука по сигналу

Новый метод startRecording() позволяет начать запись звука на основе сигнала, определенного MediaSyncEvent . MediaSyncEvent указывает аудиосеанс (например, определенный MediaPlayer ), который после завершения запускает запись звука на устройстве записи. Например, вы можете использовать эту функцию для воспроизведения звукового сигнала, указывающего на начало сеанса записи, и запись начинается автоматически, поэтому вам не придется вручную синхронизировать звуковой сигнал и начало записи.

Синхронизированные текстовые дорожки

MediaPlayer теперь обрабатывает как внутриполосные, так и внеполосные текстовые дорожки. Внутриполосные текстовые дорожки представляют собой текстовую дорожку внутри медиа-источника MP4 или 3GPP. Внеполосные текстовые дорожки можно добавить в качестве внешнего источника текста с помощью метода addTimedTextSource() . После добавления всех внешних источников текстовых дорожек следует вызвать getTrackInfo() , чтобы получить обновленный список всех доступных дорожек в источнике данных.

Чтобы установить дорожку для использования с MediaPlayer , вы должны вызвать selectTrack() , используя индексную позицию дорожки, которую вы хотите использовать.

Чтобы получать уведомления о том, что текстовая дорожка готова к воспроизведению, реализуйте интерфейс MediaPlayer.OnTimedTextListener и передайте его в setOnTimedTextListener() .

Аудио эффекты

Класс AudioEffect теперь поддерживает дополнительные типы предварительной обработки звука при захвате звука:

  • Acoustic Echo Canceler (AEC) с AcousticEchoCanceler удаляет вклад сигнала, полученного от удаленной стороны, из захваченного аудиосигнала.
  • Автоматическая регулировка усиления (АРУ) с помощью AutomaticGainControl автоматически нормализует выходной сигнал захваченного сигнала.
  • Подавитель шума (NS) с NoiseSuppressor удаляет фоновый шум из захваченного сигнала.

Вы можете применить эти эффекты препроцессора к звуку, записанному с помощью AudioRecord , используя один из подклассов AudioEffect .

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

Воспроизведение без пауз

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

Медиа-роутер. Новые API MediaRouter, MediaRouteActionProvider и MediaRouteButton предоставляют стандартные механизмы и пользовательский интерфейс для выбора места воспроизведения мультимедиа.

Камера

Движение автофокуса

Новый интерфейс Camera.AutoFocusMoveCallback позволяет прослушивать изменения в движении автофокуса. Вы можете зарегистрировать свой интерфейс с помощью setAutoFocusMoveCallback() . Затем, когда камера находится в режиме непрерывной автофокусировки ( FOCUS_MODE_CONTINUOUS_VIDEO или FOCUS_MODE_CONTINUOUS_PICTURE ), вы получите вызов onAutoFocusMoving() , который сообщит вам, начал ли автофокус двигаться или остановился.

Звуки камеры

Класс MediaActionSound предоставляет простой набор API-интерфейсов для создания стандартных звуков, издаваемых камерой, или других действий с мультимедиа. Эти API следует использовать для воспроизведения соответствующего звука при создании собственной фото- или видеокамеры.

Чтобы воспроизвести звук, просто создайте экземпляр объекта MediaActionSound , вызовите load() для предварительной загрузки желаемого звука, а затем в нужный момент вызовите play() .

Возможности подключения

Android-луч

Android Beam™ теперь поддерживает передачу больших объемов полезной нагрузки через Bluetooth. Когда вы определяете данные для передачи с помощью нового метода setBeamPushUris() или нового интерфейса обратного вызова NfcAdapter.CreateBeamUrisCallback , Android передает данные на Bluetooth или другой альтернативный транспорт для достижения более высоких скоростей передачи. Это особенно полезно для больших полезных данных, таких как изображения и аудиофайлы, и не требует видимого сопряжения между устройствами. Чтобы воспользоваться преимуществами передачи через Bluetooth, вашему приложению не требуется никаких дополнительных действий.

Метод setBeamPushUris() принимает массив объектов Uri , определяющих данные, которые вы хотите передать из вашего приложения. Альтернативно вы можете реализовать интерфейс NfcAdapter.CreateBeamUrisCallback , который вы можете указать для своей деятельности, вызвав setBeamPushUrisCallback() .

При использовании интерфейса обратного вызова система вызывает метод интерфейса createBeamUris() , когда пользователь выполняет совместное использование с помощью Android Beam, чтобы вы могли определить URI для совместного использования во время совместного использования. Это полезно, если URI для совместного использования могут различаться в зависимости от пользовательского контекста внутри действия, тогда как вызов setBeamPushUris() полезен, когда URI для совместного использования не меняются, и вы можете безопасно определить их заранее.

Обнаружение сетевых служб

В Android 4.1 добавлена ​​поддержка обнаружения служб многоадресной рассылки на основе DNS, которая позволяет находить и подключаться к службам, предлагаемым одноранговыми устройствами через Wi-Fi, такими как мобильные устройства, принтеры, камеры, медиаплееры и другие, зарегистрированные на локальной сети. сеть.

Новый пакет android.net.nsd содержит новые API, которые позволяют транслировать ваши сервисы в локальной сети, обнаруживать локальные устройства в сети и подключаться к устройствам.

Чтобы зарегистрировать свою службу, вы должны сначала создать объект NsdServiceInfo и определить различные свойства вашей службы с помощью таких методов, как setServiceName() , setServiceType() и setPort() .

Затем вам нужно реализовать NsdManager.RegistrationListener и передать его в registerService() с вашим NsdServiceInfo .

Чтобы обнаружить сервисы в сети, реализуйте NsdManager.DiscoveryListener и передайте его в discoverServices() .

Когда ваш NsdManager.DiscoveryListener получает обратные вызовы о найденных службах, вам необходимо разрешить службу, resolveService() , передав ей реализацию NsdManager.ResolveListener , которая получает объект NsdServiceInfo , содержащий информацию об обнаруженной службе, что позволяет вам инициировать соединение. .

Обнаружение службы Wi-Fi P2P

API-интерфейсы Wi-Fi P2P улучшены в Android 4.1 для поддержки обнаружения служб предварительного связывания в WifiP2pManager . Это позволяет вам обнаруживать и фильтровать близлежащие устройства по службам с использованием Wi-Fi P2P перед подключением к ним, а обнаружение сетевых служб позволяет обнаруживать службы в существующей подключенной сети (например, в локальной сети Wi-Fi).

Чтобы транслировать ваше приложение как службу через Wi-Fi, чтобы другие устройства могли обнаружить ваше приложение и подключиться к нему, вызовите addLocalService() с объектом WifiP2pServiceInfo , который описывает службы вашего приложения.

Чтобы начать обнаружение ближайших устройств через Wi-Fi, вам необходимо сначала решить, будете ли вы общаться через Bonjour или Upnp. Чтобы использовать Bonjour, сначала настройте несколько прослушивателей обратного вызова с помощью setDnsSdResponseListeners() , который принимает как WifiP2pManager.DnsSdServiceResponseListener , так и WifiP2pManager.DnsSdTxtRecordListener . Чтобы использовать Upnp, вызовите setUpnpServiceResponseListener() , который принимает WifiP2pManager.UpnpServiceResponseListener .

Прежде чем вы сможете начать обнаруживать службы на локальных устройствах, вам также необходимо вызвать addServiceRequest() . Когда WifiP2pManager.ActionListener , который вы передаете этому методу, получает успешный обратный вызов, вы можете начать обнаружение служб на локальных устройствах, вызвав discoverServices() .

При обнаружении локальных служб вы получите обратный вызов либо к WifiP2pManager.DnsSdServiceResponseListener , либо WifiP2pManager.UpnpServiceResponseListener , в зависимости от того, зарегистрировались ли вы для использования Bonjour или Upnp. Обратный вызов, полученный в любом случае, содержит объект WifiP2pDevice представляющий одноранговое устройство.

Использование сети

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

Доступность

API службы специальных возможностей

В Android 4.1 возможности API службы специальных возможностей были значительно расширены. Теперь он позволяет создавать службы, которые отслеживают и реагируют на большее количество событий ввода, таких как сложные жесты с использованием onGesture() и другие события ввода, посредством дополнений к классам AccessibilityEvent , AccessibilityNodeInfo и AccessibilityRecord .

Службы специальных возможностей также могут выполнять действия от имени пользователя, включая нажатие, прокрутку и пошаговое перемещение по тексту, используя performAction и setMovementGranularities . Метод performGlobalAction() также позволяет службам выполнять такие действия, как «Назад», «Домой», а также открывать последние приложения и уведомления.

Настраиваемая навигация по приложению

При создании приложения для Android теперь вы можете настраивать схемы навигации, находя фокусируемые элементы и виджеты ввода с помощью findFocus() и focusSearch() , а также устанавливая фокус с помощью setAccessibilityFocused() .

Более доступные виджеты

Новый класс android.view.accessibility.AccessibilityNodeProvider позволяет вам предоставлять сложные пользовательские представления службам специальных возможностей, чтобы они могли представлять информацию в более доступном виде. android.view.accessibility.AccessibilityNodeProvider позволяет пользовательскому виджету с расширенным содержимым, таким как сетка календаря, представлять логическую семантическую структуру для служб специальных возможностей, которая полностью отделена от структуры макета виджета. Эта семантическая структура позволяет службам доступности представлять более полезную модель взаимодействия для пользователей с нарушениями зрения.

Скопируйте и вставьте

Скопируйте и вставьте с намерением

Теперь вы можете связать объект ClipData с Intent используя метод setClipData() . Это особенно полезно при использовании намерения передать несколько URI- content: в другое приложение, например при совместном использовании нескольких документов. content: URI, предоставленные таким образом, также будут учитывать флаги намерения, предлагая доступ для чтения или записи, что позволяет вам предоставить доступ к нескольким URI в намерении. При запуске намерения ACTION_SEND или ACTION_SEND_MULTIPLE URI, указанные в намерении, теперь автоматически передаются в ClipData , чтобы получатель мог получить к ним доступ.

Поддержка HTML и стилей строк.

Класс ClipData теперь поддерживает стилизованный текст (в виде строк в стиле HTML или Android). Вы можете добавить текст в стиле HTML в ClipData с помощью newHtmlText() .

Рендерскрипт

Функциональность вычислений Renderscript была расширена за счет следующих функций:

  • Поддержка нескольких ядер в одном скрипте.
  • Поддержка чтения из выделения с помощью отфильтрованных выборок из вычислений в новом скриптовом API rsSample .
  • Поддержка различных уровней точности FP в #pragma .
  • Поддержка запроса дополнительной информации из объектов RS из сценария вычислений.
  • Многочисленные улучшения производительности.

Также доступны новые прагмы для определения точности с плавающей запятой, необходимой для ваших вычислений Renderscripts. Это позволяет вам включать операции, подобные NEON, такие как быстрые векторные математические операции на пути ЦП, которые в противном случае были бы невозможны при полном стандарте IEEE 754-2008.

Примечание. Экспериментальный графический движок Renderscript устарел.

Анимация

Анимация запуска активности

Теперь вы можете запустить Activity используя анимацию масштабирования или свою собственную анимацию. Чтобы указать нужную анимацию, используйте API-интерфейсы ActivityOptions для создания Bundle , который затем можно передать любому из методов, запускающих действие, например startActivity() .

Класс ActivityOptions включает в себя разные методы для каждого типа анимации, которую вы, возможно, захотите отобразить при открытии активности:

makeScaleUpAnimation()
Создает анимацию, которая масштабирует окно действия из указанной начальной позиции на экране и указанного начального размера. Например, на главном экране Android 4.1 это используется при открытии приложения.
makeThumbnailScaleUpAnimation()
Создает анимацию, которая масштабирует окно действия, начиная с указанной позиции и предоставленного миниатюрного изображения. Например, окно «Недавние приложения» в Android 4.1 использует это при возврате в приложение.
makeCustomAnimation()
Создает анимацию, определенную вашими собственными ресурсами: одну, которая определяет анимацию для открытия действия, а другую для остановки действия.

Время аниматора

Новый TimeAnimator предоставляет простой механизм обратного вызова с помощью TimeAnimator.TimeListener , который уведомляет вас о каждом кадре анимации. В этом Animator нет длительности, интерполяции или настройки значений объекта. Обратный вызов прослушивателя получает информацию для каждого кадра, включая общее прошедшее время и время, прошедшее с момента предыдущего кадра анимации.

Пользовательский интерфейс

Уведомления

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

Стили уведомлений

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

Notification.BigPictureStyle
Для уведомлений, содержащих вложение большого изображения.
Notification.BigTextStyle
Для уведомлений, содержащих много текста, например одного электронного письма.
Notification.InboxStyle
Для уведомлений, содержащих список строк, например фрагментов из нескольких электронных писем.
Действия по оповещению

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

Чтобы добавить кнопку действия, вызовите addAction() . Этот метод принимает три аргумента: рисуемый ресурс для значка, текст для кнопки и PendingIntent , определяющий выполняемое действие.

Приоритеты

Теперь вы можете намекнуть системе, насколько важно ваше уведомление для влияния на порядок вашего уведомления в списке, установив приоритет с помощью setPriority() . Вы можете передать один из пяти различных уровней приоритета, определенных константами PRIORITY_* в классе Notification . По умолчанию используется PRIORITY_DEFAULT , есть два уровня выше и два уровня ниже.

Уведомления с высоким приоритетом — это вещи, на которые пользователи обычно хотят быстро отреагировать, например новое мгновенное сообщение, текстовое сообщение или напоминание о предстоящем событии. Уведомления с низким приоритетом — это такие вещи, как истекшие события календаря или рекламные акции приложений.

Элементы управления системным пользовательским интерфейсом

В Android 4.0 (Ice Cream Sandwich) добавлены новые флаги для управления видимостью элементов системного пользовательского интерфейса, например, для затемнения внешнего вида системной панели или ее полного исчезновения на телефонах. В Android 4.1 добавлено еще несколько флагов, которые позволяют вам дополнительно контролировать внешний вид элементов системного пользовательского интерфейса и макет вашей активности по отношению к ним, вызывая setSystemUiVisibility() и передавая следующие флаги:

SYSTEM_UI_FLAG_FULLSCREEN
Скрывает некритичный системный интерфейс (например, строку состояния). Если ваша активность использует панель действий в режиме наложения (путем включения android:windowActionBarOverlay ), то этот флаг также скрывает панель действий и делает это с помощью скоординированной анимации, когда они скрываются и отображаются.
SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
Устанавливает макет вашей активности для использования той же области экрана, которая доступна, когда вы включили SYSTEM_UI_FLAG_FULLSCREEN даже если элементы системного пользовательского интерфейса все еще видны. Хотя части вашего макета будут перекрываться системным пользовательским интерфейсом, это полезно, если ваше приложение часто скрывает и показывает системный пользовательский интерфейс с помощью SYSTEM_UI_FLAG_FULLSCREEN , поскольку это позволяет избежать адаптации вашего макета к новым границам макета каждый раз, когда системный пользовательский интерфейс скрывается или появляется.
SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
Устанавливает макет вашей активности для использования той же области экрана, которая доступна, когда вы включили SYSTEM_UI_FLAG_HIDE_NAVIGATION (добавлено в Android 4.0), даже если элементы системного пользовательского интерфейса все еще видны. Хотя части вашего макета будут перекрыты панелью навигации, это полезно, если ваше приложение часто скрывает и показывает панель навигации с помощью SYSTEM_UI_FLAG_HIDE_NAVIGATION , поскольку это позволяет избежать адаптации вашего макета к новым границам макета каждый раз, когда панель навигации скрывается или появляется.
SYSTEM_UI_FLAG_LAYOUT_STABLE
Возможно, вы захотите добавить этот флаг, если вы используете SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN и/или SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION чтобы гарантировать, что при вызове fitSystemWindows() в представлении определенные границы остаются согласованными с доступным пространством экрана. То есть, если установлен этот флаг, fitSystemWindows() будет вести себя так, как будто видимость элементов системного пользовательского интерфейса не изменится, даже после того, как вы скроете весь системный интерфейс.

Для получения дополнительной информации о других связанных флагах системного пользовательского интерфейса прочтите о тех, которые были добавлены в Android 4.0 .

Удаленные просмотры

GridLayout и ViewStub теперь являются удаленными представлениями, поэтому вы можете использовать их в макетах виджетов вашего приложения и пользовательских макетах уведомлений.

Семейства шрифтов

В Android 4.1 добавлено еще несколько вариантов стиля шрифта Roboto, всего их 10, и все они могут использоваться приложениями. Ваши приложения теперь имеют доступ к полному набору как облегченных, так и сокращенных вариантов.

Полный набор доступных вариантов шрифта Roboto:

  • Обычный
  • Курсив
  • Смелый
  • Жирный курсив
  • Свет
  • Светлый курсив
  • Сжатый регулярный
  • Сокращенный курсив
  • Сокращенный жирный шрифт
  • Сокращенный полужирный курсив

Вы можете применить любой из них с помощью нового атрибута fontFamily в сочетании с атрибутом textStyle .

Поддерживаемые значения для fontFamily :

  • "sans-serif" для обычного Roboto
  • "sans-serif-light" для Roboto Light
  • "sans-serif-condensed" для Roboto Condensed

Затем вы можете применить полужирный и/или курсив со значениями textStyle "bold" и "italic" . Вы можете применить оба варианта следующим образом: android:textStyle="bold|italic" .

Вы также можете использовать Typeface.create() . Например, Typeface.create("sans-serif-light", Typeface.NORMAL) .

Входная структура

Несколько устройств ввода

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

Вы можете запросить все подключенные устройства ввода, вызвав getInputDeviceIds() . Возвращает массив целых чисел, каждое из которых является идентификатором отдельного устройства ввода. Затем вы можете вызвать getInputDevice() , чтобы получить InputDevice для указанного идентификатора устройства ввода.

Если вы хотите получать информацию о подключении, изменении или отключении новых устройств ввода, реализуйте интерфейс InputManager.InputDeviceListener и зарегистрируйте его с помощью registerInputDeviceListener() .

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

Если подключенные устройства ввода имеют собственные возможности вибрации, теперь вы можете управлять вибрацией этих устройств с помощью существующих API-интерфейсов Vibrator просто вызвав getVibrator() на InputDevice .

Разрешения

Ниже приведены новые разрешения:

READ_EXTERNAL_STORAGE
Обеспечивает защищенный доступ для чтения к внешнему хранилищу. В Android 4.1 по умолчанию все приложения по-прежнему имеют доступ для чтения. В будущем выпуске это будет изменено и потребует, чтобы приложения явно запрашивали доступ на чтение, используя это разрешение. Если ваше приложение уже запрашивает доступ для записи, оно также автоматически получит доступ для чтения. Появилась новая возможность для разработчиков включить ограничение доступа на чтение, чтобы разработчики могли протестировать свои приложения на предмет того, как Android будет вести себя в будущем.
android.Manifest.permission.READ_USER_DICTIONARY
Позволяет приложению читать пользовательский словарь. Это должно требоваться только для IME или редактора словарей, такого как приложение «Настройки».
READ_CALL_LOG
Позволяет приложению читать журнал вызовов системы, содержащий информацию о входящих и исходящих вызовах.
WRITE_CALL_LOG
Позволяет приложению изменять системный журнал вызовов, хранящийся на вашем телефоне.
android.Manifest.permission.WRITE_USER_DICTIONARY
Позволяет приложению выполнять запись в словарь слов пользователя.

Особенности устройства

Android 4.1 включает новую декларацию функций для устройств, предназначенных для отображения пользовательского интерфейса на экране телевизора: FEATURE_TELEVISION . Чтобы объявить, что вашему приложению требуется телевизионный интерфейс, объявите эту функцию в файле манифеста с помощью элемента <uses-feature> :

<manifest ... >
    <uses-feature android:name="android.hardware.type.television"
                  android:required="true" />
    ...
</manifest>

Эта функция определяет «телевидение» как типичный опыт просмотра телевизора в гостиной: он отображается на большом экране, где пользователь сидит далеко, а доминирующей формой ввода является что-то вроде d-pad, и обычно не посредством прикосновения или мышь/указатель-устройство.