Android — Android. Передача индекса массива через Intent


Содержание

Полный список

— передаем данные с помощью Intent

На прошлых уроках мы узнали, что такое Intent и как им пользоваться. Из одного Activity мы просто вызывали другое, передавая action. Теперь научимся передавать данные. Сделаем простейшее приложение. На первом экране мы будем вводить наше имя и фамилию, а второй экран будет эти данные отображать. Передавать данные будем внутри Intent.

Создадим проект:

Project name: P0281_IntentExtras
Build Target: Android 2.3.3
Application name: IntentExtras
Package name: ru.startandroid.develop.p0281intentextras
Create Activity: MainActivity

Открываем main.xml и рисуем экран с полями и кнопкой отправки:

В EditText будем вводить имя и фамилию, а кнопка Submit будет вызывать другой экран и передавать ему эти данные.

Пишем код для MainActivity.java:

Определяем поля ввода и кнопку. Кнопке присваиваем обработчик – Activity (this). Рассмотрим реализацию метода onClick. Мы создаем Intent с использованием класса, а не action. Если помните, с такого способа мы начинали знакомство с Intent. Напомню — это означает, что система просмотрит манифест файл нашего приложения, и если найдет Activity с таким классом – отобразит его. ViewActivity пока не создан, поэтому код будет подчеркнут красным. Это не мешает нам сохранить файл. Чуть позже мы создадим это Activity и ошибка исчезнет.

Итак, Intent создан, смотрим код дальше. Используется метод putExtra. Он имеет множество вариаций и аналогичен методу put для Map, т.е. добавляет к объекту пару. Первый параметр – это ключ(имя), второй — значение.

Мы поместили в Intent два объекта с именами: fname и lname. fname содержит значение поля etFName, lname – значение поля etLName. Остается только отправить укомплектованный Intent с помощью метода startActivity.

Теперь создадим второе Activity. Назовем его ViewActivity.

Создаем для него layout-файл view.xml:

Здесь просто TextView, который будет отображать пришедшие данные.

Создаем класс ViewActivity. И пишем код:

Находим TextView, затем получаем Intent и извлекаем из него String-объекты с именами fname и lname. Это те самые значения, которые мы помещали в коде MainActivity.java. Формируем строку вывода в TextView с использованием полученных данных.

Не забудьте прописать ViewActivity в манифесте. На этот раз никаких Intent Filter не нужно, т.к. мы точно знаем имя класса Activity и используем явный вызов.

Все сохраним и запустим.

Видим такой экран:

Заполняете поля как пожелаете. Я напишу John в поле First Name и Smith в поле Last Name.

ViewActivity отобразилось, считало данные из Intent и вывело их на экран.

Поместить в Intent можно данные не только типа String. В списке методов Intent можно посмотреть все многообразие типов, которые умеет принимать на вход метод putExtra.

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

— вызываем Activity с возвратом результата

Присоединяйтесь к нам в Telegram:

— в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

— в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Kotlin, RxJava, Dagger, Тестирование

— ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня

— новый чат Performance для обсуждения проблем производительности и для ваших пожеланий по содержанию курса по этой теме

Знакомство с Andro > 18/02/2020 javadevbloger Android

В нашем последнем уроке по Andro >

Что такое Intent в Android?


Android Intent (возможен еще дословный вариант перевода, как «Намерение», однако я предпочитаю использовать слово в оригинале Intent или читать как «интент»). И так, Intent представляет собой структуру данных, содержащую описание операции, которую следует выполнить.
Одна из наиболее мощных функций Intent механизма в том, что вы можете асинхронно отправить сообщения другим Activity (активностям) или сервисам.
В этом уроке мы сделаем акцент на типах и обработке Android Intent (намерений).

Типы Android Intent

  • Явное намерение (Explicit intent) явно определяет компонент по имени. Чаще всего в наших приложениях мы будем использовать явное намерение для запуска какого-то компонента. Суть Explicit intent в том, что вы знаете имя класса Activity или Service (сервиса), который нужно запустить. При использовании явного намерения система немедленно запускает компонент приложения, указанный в объекте Intent .
  • Неявное намерения (Implicit intent) не определяет конкретный компонент, а просто заявляет о некотором действии, позволяя компонентам других приложений его обработать. При создании неявного намерения Android система находит все возможные компоненты, которые могут обрабатывать заявленное действие, и предлагает выбрать одно из найденного списка.

Как использовать Android Intent для запуска Activity?

Чтобы создать объект Intent и запустить с помощью него Activity , нужно в параметрах передать объект-Activity класса, который вызывает и имя Activity, которое нужно запустить:

Android Передача разных данных через Intent in Activity

пример

1. Передача целочисленных данных:

SenderActivity

ReceiverActivity

2. Передача двойных данных:

SenderActivity

ReceiverActivity

3. Передача данных строки:

SenderActivity

ReceiverActivity

4. Передача данных ArrayList:

SenderActivity

ReceiverActivity

5. Передача данных объекта:

SenderActivity

ReceiverActivity

Примечание. Имейте в виду, что ваш пользовательский класс должен реализовывать интерфейс Serializable .

6. Передача данных HashMap :

SenderActivity

ReceiverActivity

7. Передача данных растрового изображения:

Объекты Intent и фильтры объектов Intent

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


Компонент Activity представляет собой один экран в приложении. Для запуска нового экземпляра компонента Activity необходимо передать объект Intent методу startActivity() . Объект Intent описывает операцию, которую требуется запустить, а также содержит все остальные необходимые данные.

Если после завершения операции от нее требуется получить результат, вызовите метод startActivityForResult() . Ваша операция получит результат в виде отдельного объекта Intent в обратном вызове метода onActivityResult() операции. Подробные сведения см. в руководстве Операции.

Для запуска службы:

Service является компонентом, который выполняет действия в фоновом режиме без пользовательского интерфейса. Службу можно запустить для выполнения однократного действия (например, чтобы загрузить файл), передав объект Intent методу startService() . Объект Intent описывает службу, которую требуется запустить, а также содержит все остальные необходимые данные.

Если служба сконструирована с интерфейсом клиент-сервер, к ней можно установить привязку из другого компонента, передав объект Intent методу bindService() . Подробные сведения см. в руководстве Службы.

Для рассылки широковещательных сообщений:

Широковещательное сообщение ― это сообщение, которое может принять любое приложение. Система выдает различные широковещательные сообщения о системных событиях, например, когда система загружается или устройство начинает заряжаться. Для выдачи широковещательных сообщений другим приложениям необходимо передать объект Intent методу sendBroadcast() , sendOrderedBroadcast() или sendStickyBroadcast() .

Типы объектов Intent

Есть два типа объектов Intent:

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

Когда создан явный объект Intent для запуска операции или службы, система немедленно запускает компонент приложения, указанный в объекте Intent .

Рисунок 1. Схематическое изображение процесса передачи неявного объекта Intent по системе для запуска другой операции: [1] Операция А создает объект Intent с описанием действия и передает его методу startActivity() . [2] Система Android ищет во всех приложениях фильтры Intent, которые соответствуют данному объекту Intent. Когда приложение с подходящим фильтром найдено, [3] система запускает соответствующую операцию (Операция B), вызвав ее метод onCreate() и передав ему объект Intent .

Когда создан неявный объект Intent, система Android находит подходящий компонент путем сравнения содержимого объекта Intent с фильтрами Intent, объявленными в файлах манифеста других приложений, имеющихся на устройстве. Если объект Intent совпадает с фильтром Intent, система запускает этот компонент и передает ему объект Intent . Если подходящими оказываются несколько фильтров Intent, система выводит диалоговое окно, где пользователь может выбрать приложение для выполнения данного действия.

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

Внимание! В целях обеспечения безопасности приложения всегда используйте явный объект Intent при запуске Service и не объявляйте фильтры Intent для своих служб. Запуск служб с помощью неявных объектов Intent является рискованным с точки зрения безопасности, поскольку нельзя быть на абсолютно уверенным, какая служба отреагирует на такой объект Intent, а пользователь не может видеть, какая служба запускается. Начиная с Android 5.0 (уровень API 21) система вызывает исключение при вызове метода bindService() с помощью неявного объекта Intent.

Создание объекта Intent

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

Основные сведения, содержащиеся в объекте Intent :

Имя компонента Имя компонента, который требуется запустить.

Эта информация является необязательной, но именно она и делает объект Intent явным. Ее наличие означает, что объект Intent следует доставить только компоненту приложения, определенному по имени. При отсутствии имени компонента объект Intent является неявным, а система определяет, какой компонент получит этот объект Intent по другим сведениям, которые в нем содержатся (например, по действию, данным и категории — см. описание далее). Поэтому, если вам требуется запустить определенный компонент из своего приложения, следует указать его имя.

Примечание. При запуске Service следует всегда указывать имя компонента. В противном случае вы не сможете быть на абсолютно уверенным в том, какая служба отреагирует на объект Intent, а пользователь не может видеть, какая служба запускается.

Это поле объекта Intent представляет собой объект ComponentName , который можно указать с помощью полного имени класса целевого компонента, включая имя пакета приложения. Например, com.example.ExampleActivity . Задать имя компонента можно с помощью метода setComponent() , )»>setClass() , setClassName() или конструктора Intent .

Действие Строка, определяющая стандартное действие, которое требуется выполнить (например, view (просмотр) или pick (выбор)).

При выдаче объектов Intent с широковещательными сообщениями это действие, которое произошло и о котором сообщается. Действие в значительной степени определяет, каким образом структурирована остальная часть объекта Intent,—в частности, что именно содержится в разделе данных и дополнительных данных.

Для использования объектами Intent в пределах своего приложения (либо для использования другими приложениями, чтобы вызывать компоненты из вашего приложения) можно указать собственные действия. Обычно же следует использовать константы действий, определенные классом Intent или другими классами платформы. Вот несколько стандартных действий для запуска операции:

ACTION_VIEW Используйте это действие в объекте Intent с методом startActivity() , когда имеется определенная информация, которую операция может показать пользователю, например, фотография в приложении галереи или адрес для просмотра в картографическом приложении. ACTION_SEND Его еще называют объектом Intent «share» (намерение предоставить общий доступ). Это действие следует использовать в объекте Intent с методом startActivity() , при наличии определенных данных, доступ к которым пользователь может предоставить через другое приложение, например приложение для работы с электронной почтой или социальными сетями.

Цукерберг рекомендует:  Обучение - Задачка с хешами на питоне

Другие константы, определяющие стандартные действия, см. в справочнике по классу Intent . Другие действия определяются в других частях платформы Android. Например, в Settings определяются действия, открывающие ряд экранов приложения настройки системы.

Действие можно указать для объекта Intent с методом setAction() или конструктором Intent .


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

Данные URI (объект Uri ), ссылающийся на данные, с которыми будет выполняться действие и/или тип MIME этих данных. Тип передаваемых данных обычно определяется действием объекта Intent. Например, если действием является ACTION_EDIT , в данных должен содержаться URI документа, который требуется отредактировать.

При создании объекта Intent, помимо URI, зачастую бывает важно указать тип данных (их тип MIME). Например, операция, которая может выводить на экран изображения, скорее всего, не сможет воспроизвести аудиофайл, даже если и у тех, и у других данных будут одинаковые форматы URI. Поэтому указание типа MIME данных помогает системе Android найти наиболее подходящий компонент для получения вашего объекта Intent. Однако тип MIME иногда можно унаследовать от URI — в частности, когда данные представляют собой content: URI, который указывает, что данные находятся на устройстве и ими управляет ContentProvider , а это дает возможность системе видеть тип MIME данных.

Чтобы задать только URI данных, вызовите setData() . Чтобы задать только тип MIME, вызовите setType() . При необходимости оба этих параметра можно в явном виде задать с помощью setDataAndType() .

Внимание! Если требуется задать и URI, и тип MIME, не вызывайте setData() и setType() , поскольку каждый из этих методов аннулирует результат выполнения другого. Чтобы задать URI и тип MIME всегда используйте метод setDataAndType() .

Категория Строка, содержащая прочие сведения о том, каким компонентом должна выполняться обработка этого объекта Intent. В объект Intent можно поместить любое количество описаний категорий, однако большинству объектов Intent категория не требуется. Вот некоторые стандартные категории: CATEGORY_BROWSABLE Целевая операция позволяет запускать себя веб-браузером для отображения данных, указанных по ссылке — например, изображения или сообщения электронной почты. CATEGORY_LAUNCHER Эта операция является начальной операцией задачи, она указана в средстве запуска приложений системы.

Полный список категорий см. в описании класса Intent .

Указать категорию можно с помощью addCategory() .

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

Однако в объекте Intent может быть приведена и другая информация, которая не влияет на то, каким образом определяется требуемый компонент приложения. Объект Intent также может содержать:

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

Добавлять дополнительные данные можно с помощью различных методов putExtra() , каждый из которых принимает два параметра: имя и значение ключа. Также можно создать объект Bundle со всеми дополнительными данными, затем вставить объект Bundle в объект Intent с помощью метода putExtras() .

Например, при создании объекта Intent для отправки сообщения электронной почты с методом ACTION_SEND можно указать получателя с помощью ключа EXTRA_EMAIL , а тему сообщения ― с помощью ключа EXTRA_SUBJECT .

Класс Intent указывает много констант EXTRA_* для стандартных типов данных. Если вам требуется объявить собственные дополнительные ключи (для объектов Intent, которые принимает ваше приложение), обязательно указывайте в качестве префикса имя пакета своего приложения. Например:

Флаги Флаги, определенные в классе Intent , которые действуют как метаданные для объекта Intent. Флаги должны указывать системе Android, каким образом следует запускать операцию (например, к какой задаче должна принадлежать операция ) и как с ней обращаться после запуска (например, будет ли она указана в списке последних операций).

Подробные сведения см. в документе, посвященном методу setFlags() .

Пример явного объекта Intent

Явные объекты Intent используются для запуска конкретных компонентов приложения, например определенной операции или службы. Чтобы создать явный объект Intent, задайте имя компонента для объекта Intent — все остальные свойства объекта Intent можно не задавать.

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

Конструктор )»>Intent(Context, Class) предоставляет Context приложению, а компоненту ― объект Class . Фактически этот объект Intent явно запускает класс DownloadService в приложении.

Подробные сведения о создании и запуске службы см. в руководстве Службы.

Пример неявного объекта Intent

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

Например, если у вас есть контент и вы хотите, чтобы пользователь поделился им с другими людьми, создайте объект Intent с действием ACTION_SEND и добавьте дополнительные данные, указывающие на контент, общий доступ к которому следует предоставить. Когда с помощью этого объекта Intent вы вызываете startActivity() , пользователь сможет выбрать приложение, посредством которого к контенту будет предоставлен общий доступ.

Внимание! Возможна ситуация, когда на устройстве пользователя не будетникакого приложения, которое может откликнуться на неявный объект Intent, отправленный вами методу startActivity() . В этом случае вызов закончится неудачей, а работа приложения аварийно завершится. Чтобы проверить, будет получен ли операцией объект Intent, вызовите метод resolveActivity() для своего объекта Intent . Если результатом будет значение, отличное от null, значит, имеется хотя бы одно приложение, которое способно откликнуться на объект Intent и можно вызывать startActivity() . Если же результатом будет значение null, объект Intent не следует использовать и по возможности следует отключить функцию, которая выдает этот объект Intent.

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

При вызове метода startActivity() система анализирует все установленные приложения, чтобы определить, какие из них могут откликнуться на объект Intent этого вида (объект Intent с действием ACTION_SEND и данными «text/plain» ). Если имеется только одно подходящее приложение, оно будет сразу же открыто и получит данный объект Intent. Если объект Intent принимают несколько операций, система отображает диалоговое окно, в котором пользователь может выбрать приложение для выполнения данного действия.

Рисунок 2. Диалоговое окно выбора.

Принудительное использование блока выбора приложения

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

Однако если на объект Intent могут откликнуться несколько приложений, возможно, пользователь предпочтет каждый раз использовать другое приложение, поэтому следует явно выводить диалоговое окно выбора. В диалоговом окне выбора приложения пользователю предлагается при каждом запуске выбирать, какое приложение использовать для действия (пользователь не может выбрать приложение, используемое по умолчанию). Например, когда ваше приложение выполняет операцию «share» (поделиться) с помощью действия ACTION_SEND , пользователи могут, в зависимости от ситуации, предпочесть каждый раз делать это с помощью разных приложений , поэтому следует всегда использовать диалоговое окно выбора, как показано на рисунке 2.

Чтобы вывести на экран блок выбора приложения, создайте Intent с помощью createChooser() и передайте его startActivity() . Например:


В результате на экран будет выведено диалоговое окно со списком приложений, которые могут отреагировать на объект Intent, переданный методу createChooser() и используют указанный текст в качестве заголовка диалога.

Получение неявного объекта Intent

Чтобы указать, какие неявные объекты Intent может принимать ваше приложение, объявите один или несколько фильтров Intent для каждого компонента приложения с помощью элемента в файле манифеста. Каждый фильтр Intent указывает тип объектов Intent, которые принимает компонент на основании действия, данных и категории, заданных в объекте Intent. Система передаст неявный объект Intent вашему приложению, только если он может пройти через один из ваших фильтров Intent.

Примечание. Явный объект Intent всегда доставляется его целевому компоненту, без учета любых фильтров Intent, объявленных компонентом.

Компонент приложения должен объявлять отдельные фильтры для каждой уникальной работы, которую он может выполнить. Например, у операции из приложения для работы с галереей изображений может быть два фильтра: один фильтр для просмотра изображения, и второй для его редактирования. Когда операция запускается, она анализирует объект Intent и выбирает режим своей работы на основании информации, приведенной в Intent (например, показывать элементы управления редактора или нет).

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

Примечание. Для получения неявных объектов Intent необходимо включить категорию CATEGORY_DEFAULT в фильтр Intent. Методы startActivity() и startActivityForResult() обрабатывают все объекты Intent, как если бы они объявляли категорию CATEGORY_DEFAULT . Если вы не объявляете эту категорию в своем фильтре Intent, никакие неявные объекты Intent не будут переданы в вашу операцию.

В следующем примере объявлена операция с фильтром Intent, определяющим получение объекта Intent ACTION_SEND , когда данные относятся к типу text:

Когда требуется обрабатывать объекты Intent нескольких видов, но только в определенных сочетаниях действия, типа данных и категории, необходимо создать несколько фильтров Intent.

Ограничение доступа к компонентам

Использование фильтра Intent не является безопасным способом предотвращения запуска ваших компонентов другими приложениями. Несмотря на то, что после применения фильтров Intent компонент будет реагировать только на неявные объекты Intent определенного вида, другое приложение теоретически может запустить компонент вашего приложения с помощью явного объекта Intent, если разработчик определит имена ваших компонентов. Если важно, чтобы только ваше собственное приложение могло запускать один из ваших компонентов, задайте для атрибута exported этого компонента значение «false» .

Неявный объект Intent проверяется фильтром путем сравнения объекта Intent с каждым из этих трех элементов. Чтобы объект Intent был доставлен компоненту, он должен пройти все три теста. Если он не будет соответствовать хотя бы одному из них, система Android не доставит этот объект Intent компоненту. Однако, поскольку у компонента может быть несколько фильтров Intent, объект Intent, который не проходит через один из фильтров компонента, может пройти через другой фильтр. Подробные сведения о том, каким образом система принимает решения по поводу объектов Intent, см. в приведенном далее разделе Разрешение объектов Intent.

Внимание! Чтобы случайно не запустить Service другого приложения, всегда используйте явные объекты Intent для запуска собственных служб и не объявляйте для них фильтры Intent.

Примечание. Фильтры Intent необходимо объявлять в файле манифеста для всех операций. Фильтры для приемников широковещательных сообщений можно регистрировать динамически путем вызова registerReceiver() . После этого регистрацию приемника широковещательных сообщений можно отменить с помощью unregisterReceiver() . В результате ваше приложение сможет воспринимать определенные объявления только в течение указанного периода времени в процессе работы приложения.

Примеры фильтров

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

Первая операция ( MainActivity ) является основной точкой входа приложения — это операция, которая открывается, когда пользователь запускает приложение нажатием на его значок:

  • Действие ACTION_MAIN указывает на то, что это основная точка входа, и не ожидает никаких данных объекта Intent.
  • Категория CATEGORY_LAUNCHER указывает, что значок этой операции следует поместить в средство запуска приложений системы. Если элемент не содержит указаний на конкретный значок с помощью icon , то система воспользуется значком из элемента .

Чтобы операция отображалась в средстве запуска приложений системы, два этих элемента необходимо связать вместе.

Вторая операция ( ShareActivity ) предназначена для упрощения обмена текстовым и мультимедийным контентом. Несмотря на то, что пользователи могут входить в эту операцию, выбрав ее из MainActivity , они также могут входить в ShareActivity напрямую из другого приложения, которое выдает неявный объект Intent, соответствующий одному из двух фильтров Intent.

Примечание. Тип MIME ( application/vnd.google.panorama360+jpg ) является особым типом данных, указывающим на панорамные фотографии, с которыми можно работать с помощью API-интерфейсов Google panorama.

Использование ожидающего объекта Intent

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

Основные варианты использования ожидающего объекта Intent:

  • Объявление объекта Intent, который должен будет исполняться, когда пользователь выполняет действие с вашим уведомлением ( NotificationManager системы Android исполняет Intent ).
  • Объявление объекта Intent, который должен будет исполняться, когда пользователь выполняет действие с вашим виджетом приложения (приложение главного экрана исполняет Intent ).
  • Объявление объекта Intent, который должен будет исполняться в указанное время в будущем ( AlarmManager системы Android исполняет Intent ).
Цукерберг рекомендует:  Из юриста в заклинатели змей. История разработчика Python

Поскольку каждый объект Intent предназначен для обработки компонентом приложения, который относится к определенному типу ( Activity , Service или BroadcastReceiver ), объект PendingIntent также следует создавать с учетом этого обстоятельства. При использовании ожидающего объекта Intent ваше приложение не будет исполнять объект Intent вызовом, например, startActivity() . Вместо этого вам необходимо будет объявить требуемый тип компонента при создании PendingIntent путем вызова соответствующего метода-создателя:

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

Каждый метод принимает текущий Context приложения, объект Intent , который требуется поместить в оболочку, и один или несколько флагов, указывающих, каким образом следует использовать объект Intent (например, можно ли использовать объект Intent неоднократно).

Подробные сведения об использовании ожидающих объектов Intent приведены в документации по каждому из соответствующих вариантов использования, например, в руководствах, посвященным API-интерфейсам: Уведомления и Виджеты приложений.

Разрешение объектов Intent


Когда система получает неявный объект Intent для запуска операции, она выполняет поиск наиболее подходящей операции путем сравнения объекта Intent с фильтрами Intent по трем критериям:

  • действие объекта Intent;
  • данные объекта Intent (тип URI и данных);
  • категория объекта Intent.

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

Тестирование действия

Для указания принимаемых действий объекта Intent фильтр Intent может объявлять любое (в том числе нулевое) число элементов action> . Например:

Чтобы пройти через этот фильтр, действие, указанное в объекте Intent , должно соответствовать одному или нескольким действиям, перечисленным в фильтре.

Если в фильтре не перечислены какие-либо действия, объекту Intent будет нечему соответствовать, поэтому все объекты Intent не пройдут этот тест. Однако, если в объекте Intent не указано действие, он пройдет тест (если в фильтре содержится хотя бы одно действие).

Тестирование категории

Для указания принимаемых категорий объекта Intent фильтр Intent может объявлять любое (в том числе нулевое) число элементов . Например:

Чтобы объект Intent прошел тестирование категории, все категории, приведенные в объекте Intent , должны соответствовать категории из фильтра. Обратное не требуется — фильтр Intent может объявлять и другие категории, которых нет в объекте Intent , объект Intent при этом все равно пройдет тест. Поэтому объект Intent без категорий всегда пройдет этот тест, независимо от того, какие категории объявлены в фильтре.

Примечание. Система Android автоматически применяет категорию CATEGORY_DEFAULT ко всем неявным объектам Intent, которые передаются в startActivity() и startActivityForResult() . Поэтому, если вы хотите, чтобы ваша операция принимала неявные объекты Intent, в ее фильтрах Intent должна быть указана категория для «android.intent.category.DEFAULT» (как показано в предыдущем примере ).

Тестирование данных

Для указания принимаемых данных объекта Intent фильтр Intent может объявлять любое (в том числе нулевое) число элементов . Например:

Каждый элемент может конкретизировать структуру URI и тип данных (тип мультимедиа MIME). Имеются отдельные атрибуты — scheme , host , port и path — для каждой составной части URI:

В этом URI схема имеет вид content , узел ― com.example.project , порт ― 200 , а путь ― folder/subfolder/etc .

Каждый из этих атрибутов является необязательным в элементе , однако имеются линейные зависимости:

  • Если схема не указана, узел игнорируется.
  • Если узел не указан, порт игнорируется.
  • Если не указана ни схема, ни узел, путь игнорируется.

Когда URI, указанный в объекте Intent, сравнивается с URI из фильтра, сравнение выполняется только с теми составными частями URI, которые приведены в фильтре. Например:

  • Если в фильтре указана только схема, то все URI с этой схемой будет соответствовать фильтру.
  • Если в фильтре указаны схема и полномочия, но отсутствует путь, все URI с такими же схемой и полномочиями пройдут фильтр, а их пути учитываться не будут.
  • Если в фильтре указаны схема, полномочия и путь, то только URI с такими же схемой, полномочиями и путем пройдут фильтр.

Примечание. Путь может быть указан с подстановочным символом (*), чтобы потребовалось только частичное соответствие имени пути.

При выполнении тестирования данных сравнивается и URI, и тип MIME, указанные в объекте Intent, с URI и типом MIME из фильтра. Действуют следующие правила:

  1. Объект Intent, который не содержит ни URI, ни тип MIME, пройдет этот тест, только если в фильтре не указано никаких URI или типов MIME.
  2. Объект Intent, в котором имеется URI, но отсутствует тип MIME (ни явный, ни тот, который можно вывести из URI), пройдет этот тест, только если URI соответствует формату URI из фильтра , а в фильтре также не указан тип MIME.
  3. Объект Intent, в котором имеется тип MIME, но отсутствует URI, пройдет этот тест, только если в фильтре указан тот же тип MIME и не указан формат URI.
  4. Объект Intent, в котором имеется и URI, и тип MIME (явный или тот, который можно вывести из URI), пройдет только часть этого теста, проверяющую тип MIME, в том случае, если этот тип совпадает с типом, приведенным в фильтре. Он пройдет часть этого теста, которая проверяет URI, либо если его URI совпадает с URI из фильтра, либо если этот объект содержит URI content: или file: , а в фильтре URI не указан. Другими словами, предполагается, что компонент поддерживает данные content: и file: , если в его фильтре указан только тип MIME.

Это последнее правило (правило (d)) отражает ожидание того, что компоненты будут в состоянии получать локальные данные из файла или от поставщика контента. Поэтому их фильтры могут содержать только тип данных, а явно указывать схемы content: и file: не требуется. Это типичный случай. Например, такой элемент , как приведенный далее, сообщает системе Android, что компонент может получать данные изображений от поставщика контента и выводить их на экран:

Поскольку имеющиеся данные преимущественно распространяются поставщиками контента, фильтры, в которых указан тип данных и нет URI, вероятно, являются самыми распространенными.

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

Сопоставление объектов Intent

Объекты Intent сопоставляются с фильтрами Intent не только для определения целевого компонента, который требуется активировать, но также для выявления определенных сведений о наборе компонентов, имеющихся на устройстве. Например, приложение главного экрана заполняет средство запуска приложений путем поиска всех операций с фильтрами Intent, в которых указано действие ACTION_MAIN и категория CATEGORY_LAUNCHER .

Ваше приложение может использовать сопоставление объектов Intent таким же образом. В PackageManager имеется набор методов query. () , которые возвращают все компоненты, способные принять определенный объект, а также схожий набор методов resolve. () , которые определяют наиболее подходящий компонент, способный реагировать на объект Intent. Например, метод queryIntentActivities() возвращает передаваемый как аргумент список всех операций, которые могут выполнить объект Intent, а метод queryIntentServices() возвращает такой же список служб. Ни тот, ни другой метод не активирует компоненты; они просто перечисляют те из них, которые могут откликнуться. Имеется схожий метод для приемников широковещательных сообщений ( <@link android.content.pm.PackageManager#queryBroadcastReceivers ).


Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.

Урок 69. Передаем Parcelable объекты с помощью Intent

— добавляем объекту поддержку Parcelable
— передаем с помощью Intent

С Parcel мы немного поработали на прошлом уроке. Этих знаний хватит, чтобы понять, как реализовать в своем объекте интерфейс Parcelable. Создадим свой объект, реализуем в нем интерфейс Parcelable и попробуем передать в другое Activity через Intent.

Project name: P0691_Parcelable
Build Target: Android 2.3.3
Application name: Parcelable
Package name: ru.startandroid.develop.p0691parcelable
Create Activity: MainActivity

В strings.xml пропишем тексты:

В main.xml нарисуем кнопку:

Перед тем как кодить MainActivity.java, создадим свой объект для передачи MyObject.java:

Объект сам по себе несложный: пара переменных s и i, и конструктор. Все остальное используется для реализации Parcelable. Давайте смотреть.

Про метод describeContents ничего сказать не могу. Я не понял, зачем он нужен.

В методе writeToParcel мы получаем на вход Parcel и упаковываем в него наш объект. Т.е., в нашем случае, помещаем туда переменные s и i. flags не используем.

CREATOR типа Parcelable.Creator используется для создания экземпляра нашего MyObject и заполнения его данными из Parcer.

Для этого используется его метод createFromParcel, который мы должны реализовать. На вход нам дается Parcel, а вернуть мы должны готовый MyObject. В нашем примере мы используем здесь конструктор MyObject(Parcel parcel), который реализован чуть дальше.

Смысл метода newArray остался для меня непонятен.

Конструктор MyObject(Parcel parcel) принимает на вход Parcel и заполняет объект данными из него. Этот метод использовался нами чуть ранее в CREATOR.createFromParcel.

Создадим второе Activity, в которое будем передавать объект.

Сначала создаем экран second.xml:

Мы вытаскиваем наш MyObject-объект из Intent и в лог выводим значения s и i.

Создаем Intent, помещаем туда объект MyObject. В качестве ключа используем его имя класса (разумеется, это необязательно, вы можете свое имя использовать). И отправляем Intent с вызовом SecondActivity.

Все сохраним и запустим приложение.

Жмем Send, Intent уходит в SecondActivity

MyObject(String _s, int _i)
startActivity
writeToParcel
getParcelableExtra
createFromParcel
MyObject(Parcel parcel)
myObj: text, 1

Сначала вызвался конструктор MyObject(String _s, int _i) – это мы создали myObj.

startActivity – начинаем вызов Activity

writeToParcel — мы поместили объект в Intent, и похоже, что при отправке он упаковался в Parcer. Т.к. сам Parcer не знает, как именно упаковать объект, он вызвал метод writeToParcel, где мы реализовали упаковку.

getParcelableExtra – извлекаем объект из Intent

createFromParcel – это был вызван метод CREATOR.createFromParcel, которому на вход дали Parcer, а он должен вернуть MyObject. Этот метод в свою очередь для создания MyObject использует конструктор MyObject(Parcel parcel), в котором мы расписали, как надо читать Parcer и заполнить объект.

myObj: text, 1 – вывели в лог значения объекта.

Итак. Чтобы нам передать объект через Intent, нам надо реализовать в нем интерфейс Parcelable. В этом случае Intent без проблем запакует, передаст и распакует наш объект. И я так подозреваю, что делает он это с помощью Parcel. Т.е. в реализации интерфейса Parcelable мы полностью описываем алгоритм упаковки и распаковки объекта, а Parcel эти алгоритмы потом использует. Т.к. сам он не может знать, как правильно распаковать и создать передаваемый объект.

Если кто разберется, зачем нужны непонятые мною методы – пишите на форуме в ветке этого урока. Я добавлю вашу инфу в урок.

Передача массивов через intent android

Я пытаюсь передать двойной и длинный массив от одного действия к другому. Я также передаю строку. Строка успешно передана, но массивы нет — это, вероятно, что-то простое, но я просто не могу его увидеть.


Я перемещаюсь от одного действия к другому по нажатию кнопки со следующим кодом:

Я использую следующее, Чтобы получить массивы и строку:

1 ответ

Вы можете использовать.

в классе Bundle.

Здесь в вашем случае я думаю double[] (примитивный тип double) и Double[] (массив объектов) создает проблему.(То же самое для Long[] и long[])

Как метод need параметр передается как double[] не Double[]

Передача данных с одного Activity на другое Activity

В этом уроке я бы хотел вам показать как передавать данные с одного Activity на другое Activity.

Шаг 1

Создаем в нашей Intellij IDEA -> Android Application.

После создаем layout main.xml:

И так она будет выглядеть:

На этой Layout будут вводится данные и после нажатия на кнопку передаваться на другое окно.

И собственно создадим второй layout куда мы и будем передавать данные с формы.

Назовем её two.xml

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

Layout-ы мы закончили создавать переходим к Activity.

Шаг 2

Создадим теперь Activity для main.xml и назовем его MainActivity.java:

и для второго layout tow.xml создаем следующий Activity, назовем его NewActivity.java:

Шаг 3

Intent – этот класс позволяет открывать новое Activity, запускать сервис, передавать данные между Activity.

Теперь в MainActivity добавим следующий метод, который передаст значения с формы на другое Activity после клика по кнопке:

Объект намерения Intent

При рассмотрении жизненных циклов двух активностей был использован объект Intent. С помощью данного объекта выполнялся переход из одной активности в другую и обратно. В данной статье рассматривается объект намерений Intent.

Intent представляет собой объект описания операции, которую необходимо выполнить через систему Android. Т.е. необходимо сначала описать некоторую операцию в виде объекта Intent, после чего отправить её на выполнение в систему вызовом одного из методов активности Activity.

Объекты Intent в основном используются в трёх операциях :

1. Старт операции
В android-приложении один экран представлен компонентом Activity, описанном в файле манифеста. Если необходимо в приложении иметь несколько экранов (страниц/форм), то все они должны быть зарегистрированы в манифесте приложения. Переход от одной активности к другой выполняется с помощью объекта Intent, который передается методу startActivity(). Объект Intent наряду с описанием операции может дополнительно включать все необходимые данные для выполнения операции.

Если необходимо получить результат выполнения операции, то следует использовать метод startActivityForResult(), который вернет отдельный объект Intent в обратном вызове метода onActivityResult().

2. Запуск сервиса
Android-приложение может выполнять действия в фоновом режиме без пользовательского интерфейса с помощью определенного сервиса, в качестве которого используется компонент Service. Сервис можно стартовать для выполнения какого-либо действия, например, чтение файла. Для старта сервиса необходимо вызвать метод активности startService() и передать ему объект Intent.


Если сервис имеет интерфейс типа клиент-сервер, то можно с ним установить связь через вызов метода bindService(), с передачей ему в качестве параметра объекта Intent.

3. Рассылка широковещательных сообщений
Широковещательное сообщение может принимать любое приложение android. Система генерирует различные широковещательные сообщения о системных событиях, например, зарядка устройства. Широковещательные сообщения отправляются другим приложениям передачей объекта Intent методам sendBroadcast(), sendOrderedBroadcast() или sendStickyBroadcast().

Типы объектов Intent

Существует два типа объектов Intent : явные и неявные.

Явные объекты Intent

Явные объекты Intent , как правило, используются для запуска компонента из собственного приложения, где известно наименование запускаемых классов и сервисов. В примере рассмотрения жизненных циклов двух активностей был использован следующий вызов 2-ой активности :

В качестве первого параметра конструктора Intent указывается Context. Поскольку активность является наследником Context, то можно использовать укороченную запись this или полную как Class_name.this. Во втором параметре конструктора указывается наименование класса активности. Этот класс зарегистрирован в манифесте приложения. Таким образом, приложение может иметь несколько активностей, каждую из которых можно вызвать по наименованию класса. После вызова метода startActivity будет создана новая активность, которая запустится или возобновит свою работу, переместившись на вершину стека активностей.

Пример старта сервиса

Если в приложении был создан какой-либо сервис, например ServiceDownload для загрузки файлов из Интернета, то для запуска этого сервиса можно использовать следующий код :

Неявные объекты Intent

Неявные объекты Intent не содержат имени конкретного класса. Вместо этого они включают действие (action), которое требуется выполнить. Неявный Intent может включать дополнительно наименование категории (category) и тип данных (data). Такой набор параметров позволяют компоненту из другого приложения обработать этот запрос. Например, если необходимо пользователю показать место на карте, то с помощью неявного объекта Intent можно попросить это сделать другое приложение, в котором данная функция предусмотрена.

Когда android получает неявный объект Intent для выполнения, то система ищет подходящие компоненты путем сравнения содержимого Intent с фильтрами Intent других приложений, зарегистрированных в файлах манифестов. Если параметры объекта Intent совпадают с параметрами одного из фильтров Intent, то система запускает этот компонент и передает ему объект Intent. При наличии нескольких подходящих фильтров система открывает диалоговое окно, где пользователь может выбрать подходящее приложение.

Фильтр Intent представляет собой секцию в файле манифеста приложения, описывающее типы объектов Intent, которые компонент мог бы выполнить. Таким образом, наличие фильтра Intent в описании активности в манифесте позволяет другим приложениям напрямую запускать данную операцию с помощью некоторого объекта Intent. Если фильтр Intent не описан, то операцию можно будет запустить только с помощью явного объекта Intent.

Механизм использования неявных объектов Intent для вызова компонентов других приложений напоминает вызовы API. Основное отличие между вызовами компонентов и вызовами API заключается в том, что вызовы компонентов с помощью неявных Intent являются асинхронными, а API-вызовы являются синхронными. Привязка API-вызовов выполняется на этапе компиляции, тогда как вызовы неявных намерений являются привязкой ко время выполнения. Намерение, которое работает синхронно и имеет привязку к конкретной активности, становится явным.

В случае, если система не сможет выполнить неявное намерение при вызове метода startActivity или startActivityForResult, то приложение завершится с ошибкой. Чтобы не допустить этого следует использовать метод намерения resolveActivity для проверки возможности выполнения заданного действия. Пример использования метода resolveActivity рассмотрен на странице описания взаимодействия с AlarmClock.

Фильтры намерений Intent

В секциях фильтров намерений в файле манифеста можно объявить только три составляющих объекта Intent : действие, данные, категория. Рассмотрим пример описания фильтров намерений для приложения работы с социальными сетями.

Первая активность (MainActivity), открывающаяся при старте приложения, является главной точкой входа. Действие «android.intent.action.MAIN» говорит о том, что это основная точка входа в приложение и не требуется ожидания никаких объектов Intent. Категория «android.intent.category.LAUNCHER» указывает на то, что значок данной активности следует поместить в средство запуска приложений системы. Если элемент не содержит указаний на конкретный значок с помощью тега icon, то система воспользуется значком из элемента манифеста .

Вторая активность (ShareActivity) предназначена для упрощения обмена текстовым и мультимедийным контентом. Несмотря на то, что пользователи могут входить в эту активность из MainActivity, они также могут открыть ShareActivity напрямую из другого приложения, которое создаст неявный объект Intent, соответствующий одному из двух фильтров Intent.

Действие намерения, action

Действие action объекта Intent определяет, что нужно выполнить, например просмотр фото (view) или выбор фото (pick). В значительной степени действие определяет, каким образом описана остальная часть намерения Intent, в частности, что именно содержится в разделе данных. Действие для объекта Intent можно указать методом setAction() или определить в конструкторе Intent. Если Вы определяете собственные действия, то необходимо использовать наименование пакета приложения. Например :

Рассмотрим простой пример формирования неявного намерения для открытия определенной страницы сайта :

В данном примере создается намерение с действием ACTION_VIEW, означающим просмотр чего-либо. При вызове данного намерения текущая активность приостанавливает своё действие и переходит в фоновый режим. При нажатии пользователем кнопки Back исходная активность восстанавливется. Некоторые константные значения действий, используемые в java-коде, представлены в следующей таблице :

BROWSABLE Операция стартует веб-браузер для отображения данных, указанных по ссылке (url), например, изображение или сообщение электронной почты.
LAUNCHER Операция (активность) является начальной операцией задачи. Активность с данной категорией помещается в окно для запуска приложений.
DEFAULT Данная категория позволяет объявить компонент обработчиком по умолчанию для действия, выполняемого с указанным типом данных внутри фильтра намерений.
HOME Активность с данной категорией отображает главный экран (Home Screen), который открывается после включения устройства и загрузки системы, или когда нажимается клавиша HOME.


Константные наименования категории, используемые в java-коде, имеют префикс «CATEGORY_». С другими константными категориями можно познакомиться в справочнике Intent.

Данные намерения

При создании объекта Intent в некоторых случая необходимо определить данные (data). Например, для действия ACTION_EDIT, данные должны включать URI документа, который требуется отредактировать. Объект Uri ссылается на данные и/или тип этих данных MIME. Так, например, операция, которая выводит на экран изображения, скорее всего, не сможет воспроизвести аудио/видео файл, даже если и у тех, и у других данных будут одинаковые форматы URI. Поэтому указание типа данных MIME помогает системе Android найти наиболее подходящий компонент для выполнения объекта Intent.

Чтобы задать только URI данных, используйте метод setData(). Чтобы определить только тип MIME, вызовите setType(). При необходимости определения обоих параметров можно вызвать метод setDataAndType().

Примечание : чтобы определить URI и тип MIME следует использовать метод setDataAndType(). Не вызывайте методы setData() и setType() поочередно, поскольку каждый из этих методов аннулирует результат выполнения другого.

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

  • android:host – определение имени удалённого сервера, например, google.com;
  • android:port – определение порта удалённого сервера;
  • android:path – определение пути URI;
  • android:mimetype – определение типа данных, которые компонент может обрабатывать;
  • android:scheme – необходимо использовать конкретную схему (например, content или http).

В файле манифеста наряду с фильтрами намерений Intent настраиваются и другие параметры приложения. О том, как настроить атрибут configChanges, чтобы приложение реагировало на изменение ориентации устройста (portrait|landscape) или на изменение размера экрана можно прочитать здесь.

Дополнительные данные

Данные, содержащие дополнительную информацию, необходимую для выполнения запрошенного действия, определяются в виде пары «ключ-значение». Добавлять дополнительные данные можно с помощью различных методов putExtra(), каждый из которых принимает два параметра : имя и значение ключа. Также можно создать объект Bundle с дополнительными данными и вставить его в Intent с помощью метода putExtras(). Например, для отправки сообщения электронной почты адрес получателя можно указать с помощью ключа EXTRA_EMAIL, а тему сообщения ― с помощью ключа EXTRA_SUBJECT.

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

Определение намерения, запустившего активность

При старте активности с помощью неявного намерения необходимо определить действие, которое следует выполнить, и данные для этого действия. Метод getIntent активности позволяет получить объект намерения :

Методы getAction() и getData() позволяют определить действие и данные, связанные с намерением. Для получения дополнительной информации, хранящейся в параметре extras, используйте типизированные методы get Extra.

Передача массива int через намерение-Android

Я пытаюсь передать массив int через Intent для другой активности в Android

С первой стороны у меня есть:

С другой стороны у меня есть:

Этот код продолжает рушиться.
Какие-либо предложения? благодаря

Вам нужно поставить свои дополнительные функции, как показано ниже.

В своей исходной деятельности убедитесь, что ваш ключ STATISTICS определен как public static final константа. В своей деятельности вы можете ссылаться на него как

Это гарантирует, что вы не пропустите ключ и не NullPointerException в NullPointerException когда лишний не найден из-за несоответствия имени ключа.

Передача массивов с помощью Intent.putExtra

У меня есть массив целых чисел в активности A:

И я хочу отправить эту переменную в действие B, поэтому я создаю новое намерение и использую метод putExtra:

В деятельности BI получите информацию:

Но на самом деле это не отправка массива, я просто получаю значение «0» на массиве. Я искал несколько примеров, но я ничего не нашел.

Вы устанавливаете дополнительный массив с массивом. Затем вы пытаетесь получить один int.

Ваш код должен быть:

Этот код отправляет массив целых значений

Инициализировать список массивов

Добавить значения в массив Список

Отправлять значения списка массивов в целевую активность

Здесь вы получаете значения на targetActivty

Цукерберг рекомендует:  Mvc - Движок сайта на фреймворке или на чистом PHP
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих