Creation of Android applications. Android application structure. Introduction to Android Application Development

Android applications are written in the Java programming language. Android SDK (Software Development Kit) tools compile the code you write—and all required data and resource files—into an APK file – software package Android, which is an archive file with the extension .apk. IN APK file contains everything that is required for an Android application to work, and it allows you to install the application on any device running the Android system.

Each Android application installed on the device runs in its own sandbox (isolated software environment):

  • The Android operating system is a multi-user Linux system in which each application is a separate user;
  • By default, the system assigns a unique identifier to each application Linux user(this identifier is used only by the system and is unknown to the application); the system sets permissions for all files in the application so that access to them is allowed only to the user with the identifier assigned to that application;
  • Each process has its own virtual machine (VM), so that application code runs in isolation from other applications;
  • by default, each application runs in its own Linux process. Android starts a process when a component of an application needs to run, and then terminates the process when it is no longer needed or when the system needs to free up memory for other applications.

Thus the Android system implements principle of granting minimum rights. That is, each application, by default, has access only to those components that it needs to operate, and no others. This creates an extremely secure environment in which the application does not have access to unauthorized areas of the system.

However, an application has options for sharing its data with other applications and accessing system services:

  • two applications can be assigned the same Linux user ID. In this case, each of them will be able to access the files of the other application. To save system resources, you can also make sure that applications with the same user ID run in the same Linux process and use the same VM (applications must also be signed with the same certificate);
  • The application may request permission to access device data, such as user contacts, SMS messages, plug-in memory card (SD card), camera, Bluetooth, etc. All permissions must be granted to the application when installing it.

This is the basic information about how an Android application exists on the system. The remainder of this document covers the following topics:

  • the core components that define the application;
  • a manifest file that declares the device components and functions required by the application;
  • resources that exist separately from the application code and allow the application to adapt its operation to devices with different configurations.

Application Components

Application components are the building blocks that make up an Android application. Each component represents a separate point through which the system can enter the application. Not all components are entry points for the user, and some of them depend on each other. Moreover, each component is an independent structural unit and plays a specific role - each of them represents a unique structural element that determines the operation of the application as a whole.

Application components can be classified into one of four types. Each type of component is designed for a specific purpose, they have their own life cycle, which defines how the component is created and terminated.

Four types of components:

Operations Operation is is one screen with a user interface. For example, in an email application, one operation might be used to display a list of new messages, another to compose a message, and a third operation to read messages. Although the activities together form a cohesive user experience with the email application, each activity is independent of the other activities. Any of these operations can be started by another application (if the email application allows it). For example, a camera app might trigger an activity in an email app that composes a new message so the user can send a photo.

The operation is a subclass of the class. For more information on this, please refer to the developer guide in this article.

Services Service is is a component that runs in the background and performs time-consuming operations associated with the operation of remote processes. The service does not have a user interface. For example, it can play music in the background while the user is working in another application, or it can receive data over the network without blocking the user's interaction with the operation. A service can be started by another component that then interacts with it, such as an operation.

Service is a subclass of the class. For more information on this, please refer to the developer guide in this article.

Content providers Provider Content provider manages the application's overall data set. Data can be stored in a file system, database SQLite data, the Internet, or any other persistent storage location that your application has access to. Through the content provider, other applications can query or even modify data (if the content provider allows them to do so). For example, the Android system has a content provider that manages the user's contact information. Any application that has the appropriate permissions can request a portion of this content provider (such as ) to read and write information about a specific person.

Content providers are also used to read and write data that the application does not expose to external components. For example, the sample application uses a content provider to save notes.

Content Provider is a subclass of the . It must implement a standard set of APIs that other applications will use to perform transactions. For more details, see the developer guide in this article.

Receivers broadcast messages Broadcast receiver is is a component that responds to advertisements distributed throughout the system. Many of these announcements are sent by the system, such as announcements that the screen has turned off, the battery is low, or a photo has been taken. Announcements can also be sent by apps, for example to let other apps know that some data has been downloaded to the device and is now ready for use. Although broadcast receivers do not have a user interface, they can alert the user to an "announcement broadcast" event. However, most often they are simply a "gateway" for other components and are designed to do a minimal amount of work. For example, they can trigger a service to take specific actions when an event occurs.

The broadcast receiver is a subclass of the class, and each broadcast message is exposed as an object. See the class manual for details.

Unique feature The Android system is that any application can launch a component of another application. For example, if you want to give the user the ability to take a photo using the device's camera, then since there is likely to be another application that can perform this action, instead of designing the photo operation in your application, you can call that application. You don't need to embed code from the camera app or even link to it. Instead, you can simply launch the photo operation from the camera app. Once this operation is complete, the photo will be returned to your application and ready to be used. To the user it will look like one application.

When the system starts a component, it starts a process for that application (if it is not already running) and creates instances of the classes that the component requires. For example, if your app starts a photo operation in a camera app, that operation will run in the process that belongs to that third-party app, not in your app's process. Therefore, unlike applications for most other systems, Android applications do not have a single entry point (for example, they do not have a main() function).

Because the system runs each application in a separate process with file permissions that restrict access to other applications, your application cannot directly call a component from another application. This can be done by the Android system itself. Therefore, to call a component in another application, you need to inform the system of your intent ( Intent) launch a specific component. After this, the system will activate this component for you.

Activating components

Components of three of four possible types- operations, services and broadcast message receivers - are activated by an asynchronous message called Intent(intention). Intent objects communicate with each other individual components at runtime, whether they are components of your application or a third-party application (these Intent objects can be thought of as messengers that send requests to other components to perform actions).

An Intent object is created using a , which describes a request to activate either a specific component or a component of a specific type— accordingly, the Intent can be explicit or implicit.

For operations and services, the Intent object specifies the action to be performed (for example, view or send something), and can also indicate the URI (Uniform Resource Identifier) ​​of the data on which this action is to be performed. execute (among other information that the component being launched needs to know). For example, an Intent object can convey a request to perform the operation "show an image" or "open a web page." In some situations, an operation can be run to produce a result. In this case, the operation also returns the result as an object (for example, you could send an Intent message to let the user select a contact and return it to you - the Intent response message would contain a URI pointing to the selected contact).

For broadcast message receivers, the Intent simply specifies the advertisement to be transmitted (for example, a low battery broadcast message contains only the string "battery low").

Components of the fourth type—content providers—are not activated by Intent messages. They are activated upon request from . The content resolver handles all direct transactions with the content provider so that the component that performs transactions with the provider does not have to do so. Instead, it calls methods on the . This forms a layer that abstracts (for security purposes) the content provider from the component requesting the information.

There are separate methods for activating components of each type:

  • You can start an operation (or define some new action for it) by passing an object to the or method (if you want the operation to return a result).
  • You can start a service (or issue new instructions to a running service) by passing an object to the . Alternatively, you can establish a binding to the service by passing the object to the .
  • You can initiate the sending of messages by passing an object to methods such as , and .
  • You can query the content provider by calling a method on the .

For details on using Intents, see the document. For more information about activating certain components, see the following documents: , and .

Manifest file

To run an application component, Android needs to know that the component exists. To do this, it reads the application's AndroidManifest.xml file (manifest file). This file, which must be located in the application's root folder, must declare all application components.

In addition to declaring application components, the manifest serves other purposes, including:

  • Specifying any user permissions that the application requires, such as permission to access the Internet or read the user's contacts;
  • declaring the minimum required by the application, given which APIs it uses;
  • announcement of hardware and software functions that the application needs or uses, such as cameras, Bluetooth services, or touch screen;
  • specifying the API libraries with which the application should be linked (other than the Android platform APIs), such as the Google Maps libraries;
  • and much more.

Component Declaration

The main task of the manifest is to inform the system about the components of the application. For example, a manifest file might declare an operation like this:

...

For details on structuring the manifest file for an application, see the document.

Declaring Component Capabilities

As discussed in the section, you can use the object to start operations, services, and broadcast receivers. To do this, you must explicitly specify the name of the target component in the Intent object (using the component class name). However, the full capabilities of Intent objects are revealed when using the concept implicit Intent. An implicit Intent message simply describes the type of action you want to perform (and, although not required, the data on which you would like to perform the action). The system is given the opportunity to find a component on the device that can perform this action and launch it. If there are multiple components that can perform the action described in the Intent message, the user chooses which one will be used.

The system determines components that can respond to an Intent message by comparing the received Intent message with Intent object filters, specified in the manifest file of other applications available on the device.

When you declare an activity in your application's manifest, you can optionally specify Intent object filters that specify the capabilities of the activity so that it can respond to Intent messages from other applications. To declare an Intent filter for your component, you must add an element as a child of the component declaration element.

For example, if you created an email application with a compose new message operation, you could declare a filter to respond to Intents of type "send" (to send a new email) as follows:

...

Then, if another application creates an Intent object with an action and passes it to , the system can trigger your activity, giving the user the ability to write and send an email.

For details on creating Intent object filters, see the document.

Declaring Application Requirements

There are a huge number of devices running Android, and not all of them have the same functionality. To prevent your app from being installed on devices that lack the features your app requires, it is important to clearly define a profile for the device types supported by your app by specifying the hardware and software requirements in the manifest file. These advertisements are mostly informational in nature; the system does not read them. However, they are read by external services such as Google Play to provide filtering for users searching for apps for their devices.

For example, if your application requires a camera and uses APIs from Android 2.1 (7), these settings should be declared as requirements in the manifest file as follows:

...

Now your application will not be able to be installed from Google Play on devices with No cameras, as well as on devices running Android version below 2.1.

However, you can also declare that the application uses the camera, but it is not necessary for it to work. absolutely necessary. In this case, the application must set the attribute to "false" and at runtime it must check to see if the device has a camera and, if necessary, disable its functions that use the camera.

For more information about managing your app's cross-device compatibility, see the document.

Application Resources

An Android application is made up of more than just code; it requires resources that exist separately from the source code, such as images, audio files, and anything else that goes into visually presenting the application. For example, you need to define animations, menus, styles, colors, and layout of activity user interfaces in XML files. By using application resources, you can easily change various characteristics of your application without changing your code, and by providing sets of alternative resources, you can optimize your application to work with different device configurations (for example, different languages ​​or screen sizes).

For each resource included in an Android project, the SDK tools specify a unique integer identifier that can be used to reference the resource from application code or from other resources defined in XML. For example, if your application has an image file named logo.png (saved in the res/drawable/ folder), the SDK tools will generate a resource identifier called R.drawable.logo that can be used to reference the image and insert it into the user's interface.

One of the most important aspects of providing resources separately from source code is the ability to use alternative resources for different device configurations. For example, by defining UI strings in XML, you can translate them into other languages ​​and store those translations in separate files. Then by qualifier language appended to the resource directory name (say res/values-fr/ for French strings), and the user-selected language, Android will apply strings in the appropriate language to your UI.

Android supports different qualifiers for related resources. The qualifier is a short string that is included in resource directory names to determine the device configuration for which those resources should be used. As another example, you should create different layouts for your operations to suit the device screen size and orientation. For example, when the device screen is in portrait orientation (positioned vertically), the buttons in the layout can also be placed vertically, and when the screen is in horizontal orientation (landscape orientation), the buttons should be placed horizontally. To ensure that the layout changes when the screen orientation changes, you can define two different layouts and apply the appropriate qualifier to the directory name of each layout. The system will then automatically apply the appropriate layout based on the orientation of the device.

Providing Resources Describes the structure of Android applications, in which application resources exist separately from its code, and how to provide alternative resources for certain device configurations.

You might also be interested in:

Learn how Android works on different types of devices and general information about how to optimize your app for each device or limit the devices that can install your app.

Learn how Android limits app access to certain APIs through a permissions system that requires user consent before your app can use those APIs.

Have you ever wondered how fastboot or ADB work? Or why is it almost impossible to turn a smartphone running Android into a brick? Or maybe you have long wanted to know where the magic of the Xposed framework lies and why the /system/etc/init.d boot scripts are needed? What about the recovery console? Is this part of Android or a thing in itself and why is regular recovery not suitable for installing third-party firmware? You will find answers to all these and many other questions in this article.

You can learn about the hidden capabilities of software systems by understanding the principle of their operation. In some cases, this is difficult to do, since the system code may be closed, but in the case of Android, we can study the entire system inside and out. In this article, I will not talk about all the nuances of Android and will only focus on how the OS starts and what events take place in the interval between pressing the power button and the appearance of the desktop.

Along the way, I will explain what we can change in this chain of events and how custom firmware developers use these capabilities to implement such things as tuning OS parameters, expanding application storage space, connecting swap, various customizations and much more. All this information can be used to create your own firmware and implement various hacks and modifications.

Step one. ABOOT and partition table

It all starts with the primary bootloader. After turning on the power, the system executes the bootloader code stored in the device’s permanent memory. It then passes control to the aboot bootloader with built-in support for the fastboot protocol, but the manufacturer of the mobile chip or smartphone/tablet has the right to choose any other bootloader of his choice. For example, Rockchip uses its own bootloader that is not fastboot compatible and requires proprietary tools to flash and manage.

The fastboot protocol, in turn, is a system for managing the bootloader from a PC, which allows you to perform actions such as unlocking the bootloader, flashing a new kernel and recovery, installing firmware and many others. The raison d'être of fastboot is to be able to restore a smartphone to its original state in a situation where all other means fail. Fastboot will remain in place even if, as a result of experiments, you erase all NAND memory partitions containing Android and recovery from your smartphone.

Having received control, aboot checks the partition table and transfers control to the kernel flashed into the partition named boot, after which the kernel extracts the RAM image from the same partition into memory and begins loading either Android or the recovery console. NAND memory in Android devices is divided into six conditionally required sections:

  • boot - contains the kernel and RAM disk, usually around 16 MB in size;
  • recovery - recovery console, consists of a kernel, a set of console applications and a settings file, size 16 MB;
  • system - contains Android, in modern devices the size is at least 1 GB;
  • cache - designed for storing cached data, also used to save firmware during an OTA update and therefore has a size similar to the size of the system partition;
  • userdata - contains settings, applications and user data, all remaining NAND memory space is allocated to it;
  • misc - contains a flag that determines what mode the system should boot in: Android or recovery.

In addition to them, there may also be other sections, but the general markup is determined at the design stage of the smartphone and, in the case of aboot, is sewn into the bootloader code. This means that: 1) the partition table cannot be killed, since it can always be restored using the fastboot oem format command; 2) to change the partition table, you will have to unlock and reflash the bootloader with new parameters. There are, however, exceptions to this rule. For example, the bootloader of the same Rockchip stores information about partitions in the first block of NAND memory, so flashing the bootloader is not necessary to change it.

The misc section is especially interesting. There is an assumption that it was originally created to store various settings independently of the main system, but at the moment it is used for only one purpose: to indicate to the bootloader from which partition the system should be loaded - boot or recovery. This feature, in particular, is used by the ROM Manager application to automatically reboot the system into recovery with automatic installation of the firmware. On its basis, the Ubuntu Touch dual boot mechanism is built, which flashes the Ubuntu bootloader into recovery and allows you to control which system to boot next time. Erased the misc partition - Android loads, filled it with data - recovery loads... that is, Ubuntu Touch.

Step two. Boot section

If the misc section does not have a recovery boot flag, aboot transfers control to the code located in the boot section. This is nothing more than the Linux kernel; it is located at the beginning of the section, and immediately followed by a RAM disk image packed using cpio and gzip archivers, containing the directories necessary for Android to work, the init initialization system and other tools. There is no file system on the boot partition; the kernel and RAM disk simply follow each other. The contents of the RAM disk are:

  • data - directory for mounting the partition of the same name;
  • dev - device files;
  • proc - procfs is mounted here;
  • res - a set of images for the charger (see below);
  • sbin - a set of utility utilities and daemons (adbd, for example);
  • sys - sysfs is mounted here;
  • system - directory for mounting the system partition;
  • charger - application for displaying the charging process;
  • build.prop - system settings;
  • init - initialization system;
  • init.rc - initialization system settings;
  • ueventd.rc - settings of the uventd daemon included in init.

This is, so to speak, the skeleton of the system: a set of directories for connecting file systems from NAND memory partitions and an initialization system that will handle the rest of the work of booting the system. The central element here is the init application and its init.rc config, which I will talk about in detail later. In the meantime, I would like to draw your attention to the charger and ueventd.rc files, as well as the sbin, proc and sys directories.

The charger file is a small application whose only job is to display the battery icon. It has nothing to do with Android and is used when the device is connected to the charger in the off state. In this case, Android does not load, and the system simply loads the kernel, connects the RAM disk and starts the charger. The latter displays a battery icon, the image of which in all possible states is stored in ordinary PNG files inside the res directory.

The ueventd.rc file is a config that determines which device files in the sys directory should be created during system boot. In systems based on the Linux kernel, access to hardware is carried out through special files inside the dev directory, and the ueventd daemon, which is part of init, is responsible for their creation in Android. In a normal situation, it works in automatic mode, accepting commands to create files from the kernel, but some files need to be created independently. They are listed in ueventd.rc.

The sbin directory in stock Android usually does not contain anything except adbd, that is, the ADB daemon, which is responsible for debugging the system from the PC. It runs at an early stage of OS boot and allows you to identify possible problems during the OS initialization stage. In custom firmwares, you can find a bunch of other files in this directory, for example mke2fs, which may be required if partitions need to be reformatted to ext3/4. Also, modders often place BusyBox there, with which you can call hundreds of Linux commands.

The proc directory is standard for Linux; in the next stages of boot, init will connect to it procfs, a virtual file system that provides access to information about all processes on the system. The system will connect sysfs to the sys directory, which opens access to information about the hardware and its settings. Using sysfs you can, for example, put the device to sleep or change the power saving algorithm used.

The build.prop file is designed to store low-level Android settings. Later, the system will reset these settings and overwrite them with values ​​from the currently inaccessible system/build.prop file.


Takeaways from the text

  • Fastboot will remain in place even if, as a result of experiments, you erase the contents of all NAND memory sections from your smartphone
  • The recovery section is completely self-sufficient and contains a miniature operating system that is in no way related to Android
  • By slightly modifying the fstab file, we can force init to boot the system from the memory card

Step two, alternative. Recovery section

If the recovery boot flag in the misc section is set or the user turns on the smartphone with the volume down key held down, aboot will transfer control to the code located at the beginning of the recovery section. Like the boot partition, it contains the kernel and a RAM disk, which is unpacked into memory and becomes the root of the file system. However, the contents of the RAM disk are somewhat different here.

Unlike the boot partition, which acts as a transition link between different stages of loading the OS, the recovery partition is completely self-sufficient and contains a miniature operating system that is in no way connected with Android. Recovery has its own core, its own set of applications (commands) and its own interface that allows the user to activate service functions.

In a standard (stock) recovery there are usually only three such functions: installation of firmware signed with the key of the smartphone manufacturer, wipe and reboot. Modified third-party recoveries, such as ClockworkMod and TWRP, have much more functions. They can format file systems, install firmware signed with any keys (read: custom), mount file systems on other partitions (for OS debugging purposes) and include script support, which allows you to automate the firmware process and many other functions.

Using scripts, for example, you can make sure that after booting, recovery automatically finds the necessary firmware on the memory card, installs them and reboots into Android. This feature is used by the ROM Manager, auto-flasher tools, as well as the automatic update mechanism for CyanogenMod and other firmware.

Custom recovery also supports backup scripts located in the /system/addon.d/ directory. Before flashing the firmware, recovery checks for scripts and executes them before flashing the firmware. Thanks to such scripts, gapps do not disappear after installing a new firmware version.

fastboot commands

To access fastboot, you need to install the Android SDK, connect your smartphone to your PC using a cable and turn it on by holding both volume buttons. After this, you should go to the platform-tools subdirectory inside the SDK and run the command

Fastboot devices

The device name will be displayed on the screen. Other available commands:

  • fatsboot oem unlock- unlocking the bootloader on nexuses;
  • update file.zip- installation of firmware;
  • flash boot boot.img- flashing the boot partition image;
  • flash recovery recovery.img- flashing the recovery partition image;
  • flash system system.img- flashing the system image;
  • oem format- restoration of a destroyed partition table;

Step three. Initialization

So, having received control, the kernel connects the RAM disk and, after initializing all its subsystems and drivers, starts the init process, which begins the initialization of Android. As I already said, init has a configuration file init.rc, from which the process learns what exactly it must do to bring the system up. In modern smartphones, this config has an impressive length of several hundred lines and is also equipped with a trailer of several child configs that are connected to the main one using the import directive. However, its format is quite simple and is essentially a set of commands divided into blocks.

Each block defines a loading stage or, in Android developer parlance, an action. Blocks are separated from each other by an on directive followed by the name of the action, such as on early-init or on post-fs. The block of commands will be executed only if the trigger of the same name fires. As it boots, init will activate the early-init, init, early-fs, fs, post-fs, early-boot and boot triggers in turn, thus launching the corresponding command blocks.


If the configuration file pulls along several more configs listed at the beginning (and this is almost always the case), then the command blocks of the same name inside them will be combined with the main config, so that when the trigger fires, init will execute commands from the corresponding blocks of all files. This is done for the convenience of creating configuration files for several devices, when the main config contains commands common to all devices, and those specific to each device are written in separate files.

The most notable of the additional configs is named initrc.device_name.rc, where the device name is determined automatically based on the contents of the ro.hardware system variable. This is a platform-specific configuration file that contains device-specific command blocks. In addition to the commands responsible for tuning the kernel, it also contains something like this:

Mount_all ./fstab.device_name

It means that init should now mount all file systems listed in the file ./fstab.device_name, which has the following structure:

Device_name (partition) mount_point file_system fs_options other options

It usually contains instructions for mounting file systems from internal NAND partitions to the /system (OS), /data (application settings) and /cache (cached data) directories. However, by slightly modifying this file, we can force init to boot the system from the memory card. To do this, just divide the memory card into three 4 sections: 1 GB / ext4, 2 GB / ext4, 1 GB / ext4 and the remaining fat32 space. Next, you need to determine the names of the memory card partitions in the /dev directory (they differ for different devices) and replace them with the original device names in the fstab file.


At the end of the boot init block, it will most likely encounter the class_start default command, which will inform you that you should then start all the services listed in the config that are related to the default class. The description of services begins with the service directive, followed by the name of the service and the command that must be executed to start it. Unlike the commands listed in the blocks, services must be running all the time, so throughout the life of the smartphone, init will hang in the background and monitor this.

Modern Android includes dozens of services, but two of them have a special status and determine the entire life cycle of the system.

init.rc Commands

The init process has a built-in set of commands, many of which follow the standard Linux command set. The most notable of them:

  • exec /path/to/command- run an external command;
  • ifup interface- raise the network interface;
  • class_start class_name- start services belonging to the specified class;
  • class_stop class_name- stop services;
  • insmod /path/to/module- load the kernel module;
  • mount FS device directory- connect the file system;
  • setprop name value- set a system variable;
  • start service_name- start the specified service;
  • trigger name- enable the trigger (execute the specified block of commands);
  • write /path/to/file line- write a line to a file.

Step four. Zygote and app_process

At a certain stage of loading, init will encounter something like this block at the end of the config:

Service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server class default socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart media onrestart restart netd

This is a description of the Zygote service, a key component of any Android system that is responsible for initialization, starting system services, starting and stopping user applications, and many other tasks. Zygote is launched using a small application /system/bin/app_process, which is very clearly visible in the above piece of the config. The app_proccess task is to launch the Dalvik virtual machine, the code of which is located in the /system/lib/libandroid_runtime.so shared library, and then run Zygote on top of it.

Once all this is done and Zygote is in control, it begins building the Java application runtime by loading all the framework's Java classes (currently over 2000 of them). It then starts the system_server, which includes most of the high-level (written in Java) system services, including the Window Manager, Status Bar, Package Manager and, most importantly, the Activity Manager, which in the future will be responsible for receiving start and end signals applications.

After this, Zygote opens the socket /dev/socket/zygote and goes to sleep, waiting for data. At this time, the previously launched Activity Manager sends a broadcast intent Intent.CATEGORY_HOME to find the application responsible for creating the desktop and gives its name to Zygote via the socket. The latter, in turn, forks and runs the application on top of the virtual machine. Voila, we have a desktop on our screen, found by Activity Manager and launched by Zygote, and a status bar launched by system_server as part of the Status Bar service. After tapping on the icon, the desktop will send an intent with the name of this application, Activity Manager will receive it and send a command to start the application to the Zygote daemon

INFO

In Linux terminology, a RAM disk is a kind of virtual hard disk that exists only in RAM. Early in the boot process, the kernel extracts the disk contents from the image and mounts it as the root file system (rootfs).

During the boot process, Android displays three different boot screens: the first appears immediately after pressing the power button and is flashed into the Linux kernel, the second is shown during the early stages of initialization and recorded in the file /initlogo.rle (hardly used today), the last is launched using the bootanimation application and is contained in the file /system/media/bootanimation.zip.

In addition to standard triggers, init allows you to define your own triggers, which can be triggered by a variety of events: connecting a device to USB, changing the state of a smartphone, or changing the state of system variables.

Among other things, Activity Manager also kills background applications when there is low memory. Free memory threshold values ​​are contained in the file /sys/module/lowmemorykiller/parameters/minfree.

All this may look a little confusing, but the most important thing is to remember three simple things:

In many ways, Android is very different from other operating systems, and it’s hard to figure it out right away. However, if you understand how everything works, the possibilities are simply endless. Unlike iOS and Windows Phone, Google's operating system has a very flexible architecture that allows you to seriously change its behavior without having to write code. In most cases, it is enough to correct the necessary configs and scripts.

I started developing for Android relatively recently (3 months ago) and the first thing I encountered was a very small amount of “Russian-language” material on this topic, especially regarding issues such as thinking through the interface or using built-in features of the Android environment. Everything I found, for the most part, came down to either translations of articles from http://developer.android.com or examples that solved a specific problem.

I will say right away that I do not pretend to be the ultimate truth, and I only want to convey to beginning Android developers material that may help them in their future activities.

I intend to publish several articles, the purpose of which will be to reveal the essence of designing and developing applications for the Android platform.

Specifically, this article will talk about the software needed to start developing for Android, literature and a little about the structure of the application.

Fast start

To start development, you need 2 things: Android SDK (can be downloaded from http://developer.android.com/intl/zh-TW/sdk/index.html) and, in fact, the development environment.

The SDK is installed via the Internet (the installation module itself weighs a little, at the time I started it was about 10 MB). By launching the installation module (SDK Setup.exe), the repository will immediately be checked for API updates and other odds and ends; by default, your SDK is empty, and in any case, to get started, you will need to download something from the proposed selection of updates. Attention! There may be a problem connecting to the repository, in order to solve it you need to go to Settings and check the box next to "Force https: \\ something else..." and try connecting to the repository again.

The size of the downloaded content will depend on your choice (currently about 1 GB). In order to speed up loading, you can limit your choice to 1 - 2 modules (for example SDK Platform Android API 1.5 and 2.0). In general, it all depends on what version of Android you plan to develop for. Most popular on this moment API versions: 1.5, 1.6, 2.0. Personally, I downloaded everything...

Attention! Consider the fact that this is not your iPhone! The platform is constantly growing and developing, and what compiled well on Android API 1.5, under 2.0 you will get a warning that you are using outdated libraries or methods (eh, Java ;-)). Plus, in new versions of the API, methods are available that are not available in earlier ones; in order to clearly see which libraries this API supports, you can visit http://developer.android.com/intl/zh-TW/reference/android/app/Activity. html on the right top corner check the box next to "Filter by API level" and indicate the API version you are interested in (as of March 2010 - maximum 7).

You can see the loaded modules by clicking on the "Installed Packages" tab. You can update and delete them there.

So, you've downloaded the SDK... now you need to create emulators to debug your applications. In order to create an emulator, you need to go to the Virtual Device tab in the same loading module. In the window that opens, you will see a table (empty at first) with a list of created emulators. The window functionality allows you to create, delete, “repair” (I have never used this function), view information and run emulators. By clicking on the "New" button you will be taken to the emulator creation wizard.

In the wizard, you need to specify the name of the emulator, the target platform (Target drop-down list), the size of the SD memory card (note, by default, the size is in MB), skin (device screen type and resolution), as well as supported hardware: support for camera, battery life, GPS, etc. (by clicking on the "New" button you will be taken to the window for selecting the emulator property and its value).

To complete creating the emulator, you need to click on "Create AVD". Attention! Once an emulator is created, it is impossible to change its properties. If you need an emulator with other properties, you will have to create a new one. After creating the emulator, consider that half the way for a “quick” start has already been completed...

Now let's move on to the development environment. We have little choice here: either install the plugin for Eclipse/NetBeans (http://developer.android.com/intl/zh-TW/sdk/eclipse-adt.html and http://kenai.com/projects/nbandroid/ , respectively) or download an already assembled IDE (for example, MOTODEV Studio for Android 1.1 from the site http://developer.motorola.com/docstools/motodevstudio/). In principle, by installing the plugin for Eclipse, you will ultimately get, almost, MOTODEV Studio for Android 1.1, but do you need all this fuss??? As for the plugin for NetBeans, I don’t know what its status is now, but the version I had to work with did not have a visual UI editor, which, to put it mildly, slowed down the work.

Personally, my choice fell on the second option (MOTODEV Studio rules ;-))... You can easily find all the necessary information on installing and configuring the development environment by googling for half an hour.

Reading

Personally, I have not yet observed the presence of Russian-language literature on development for Android. Therefore, let's immediately move on to the English-language content... So, for me, Android became the Bible: Apress Beginning Android and Apress Pro Android.

These books quite popularly and clearly describe what, why and why, and also provide sufficient clear examples... It is worth noting that both books use the Android 1.5 platform as a base; versions of the books under 2.0 (Apress Beginning Android 2 and Apress Pro Android 2, respectively), although they are present on the publisher’s website, I have not yet come across for download.

A lot of reference material(though with partially non-working examples ;-)) is on the main project website (http://developer.android.com), it will be useful not only to read the abstracts and DevGuide, but also to watch video tutorials.

Structure

They will tell you how to create a HelloWorld application without me, so let’s move on to the structure. In principle, you can read everything that I am about to tell you from the reading material offered to you above, but I will try to save you a little time.

So, conditionally, an application for Android consists of 3 blocks:

  1. Manifest (AndroidManifest.xml) is an application file descriptor, a required element, which defines such scary things as: activities, content providers, services, intent receivers (they will be discussed in the following articles). And also in the manifest you can describe the “permissions” necessary for the operation of your application. I plan to describe the manifesto in more detail in future articles.
  2. Folder "src" - a folder containing all source program is mandatory.
  3. The "res" folder is the most delicious folder, it contains all the "resources" of the application;-) You don't know about it yet, but it will make your life much easier, moreover, I would say that it is the most EVERYTHING for an Android developer. This folder is required for the project.

Besides, The root folder The application may also contain an “assets” folder; this folder is optional and may contain various auxiliary resources (other folders and files).

And one more subtlety... You can drop the “libs” folder into the root of the application, into which you can later add native C/C++ libraries (we’ll also talk about them someday, but later).

During the application build process, a "gen" folder will appear with an attached package and an R.xml file - this is also very useful file, which contains resource descriptors, is generated by the development environment and it is highly not recommended to go into it manually.

Resources (except for graphic ones), as well as the manifest, are presented in the form of XML files. And those who understand something about Java EE will immediately find a lot of similarities for themselves, and they will be right... XML structure For various types I also plan to describe the resources in the following articles, but for now I’ll just briefly describe the contents of the “res” folder:

  1. drawable - a folder that contains files with graphic content as well as xml instructions for working with them, is optional.
  2. anim - a folder that contains xml files describing the animation.
  3. layout - folder, contains xml description layer for implementing the UI.
  4. values ​​- folder - container for such xml files as: strings, styles, colors, dimens, arrays (the content of the designated files corresponds to their name).
  5. xml - a folder containing various auxiliary xml files.
  6. raw - folder for storing non-XML data used in the application.

It would seem that, judging by the structure, everything is already clear... But I assure you - this is just the tip of the iceberg. By simple manipulations with these folders and their content, you can quite easily implement such things as internationalization and localization of your application, as well as implement approximately up to 80% of the work with your UI.

Summing up

While writing the article, I realized that I was “carried away”... and I still have to write a whole bunch of articles in order to pour out everything that has “boiled” about development for Android.

I hope someone finds it useful, and I, in turn, will try to publish a continuation as quickly as possible...

x86.

Originally developed by Android Inc., which was then (July, 2005) bought by Google. Subsequently (November 2007), Google initiated the creation of the Open Handset Alliance business alliance (it included Google, HTC, Intel, Motorola, Nvidia and other companies), which is now supporting and further developing the platform.

Since the release of the first version (September 2008), several system updates have occurred. These updates usually concern fixing detected errors and adding new functionality to the system. Each version of the system gets its own dessert-themed codename.

1.2. Developer Toolkit

Before you start creating Android applications, you need to select the appropriate development tools.

As a rule, Android application development is carried out in Java. Therefore, first of all, you need to install Java Development Kit(JDK). But first you need to understand what Java is.

Java is object oriented programming language. Java programs are translated into bytecode, executed by the Java Virtual Machine, which processes the bytecode and passes instructions to the hardware as an interpreter. The advantage of this method of executing programs is that the bytecode is completely independent of the operating system and hardware, which allows you to run Java applications on any device for which there is a corresponding virtual machine. Another important feature Java is a flexible security system due to the fact that program execution is completely controlled by the virtual machine. Any operations that exceed the program's established permissions (for example, an attempt to unauthorizedly access data or connect to another computer) cause an immediate interruption. It should be noted that in fact, the majority architectural solutions adopted when creating Java was dictated by the desire to provide a syntax similar to C/C++. Java uses almost identical conventions for declaring variables, passing parameters, and passing operators. Therefore, those who already have programming experience in C/C++ will be able to quickly get the hang of it and start writing Java applications.

JDK is a free Java application development kit that includes a Java compiler, standard libraries Java classes, examples, documentation, various utilities, and the Java Runtime Environment (JRE). The JDK does not include an integrated development environment(Integrated Development Environment). Therefore, after the JDK is installed, the IDE should be installed.

There are several popular development environments, but this course we will choose Eclipse IDE and the corresponding plugin for it Android Development Tools(ADT).

Android Software Development Kit(SDK) contains many tools and utilities for creating and testing applications. For example, using SDK Manager you can install the Android API of any version (Fig. 1.1), and also check the repository for available ones, but not yet installed packages and archives.


Rice. 1.1.

Android Native Development Kit(NDK) allows you to develop Android applications in C/C++. Why might this be needed? There are several reasons. For example, the need to use code that has already been written for the native platform, or speeding up the execution of critical pieces of code.

1.3. Android architecture

Let's look at the main components of the Android operating system (Fig. 1.2).

Applications. Android comes with a set of core apps, including a calendar, maps, browser, contact manager, and others. All listed applications are written in Java.

Application Framework. By providing open platform development, Android gives developers the ability to create flexible and innovative applications. Developers can leverage the device's hardware capabilities, get location information, run tasks in the background, set alerts, and more. The developers have full access to the same APIs that are used in the main applications.

The application architecture is designed to simplify reuse components; any application can "publish" its capabilities and any other application can then use those capabilities (subject to security restrictions). The same mechanism allows you to replace standard components with custom ones.


Rice. 1.2.

Libraries. Android includes a set of C/C++ libraries used by various system components. These features are available to developers in the context Android applications Application Framework. Some main libraries are listed below:

  • Media libraries – these libraries provide support for playback and recording of many popular audio, video and image formats, including MPEG4, MP3, AAC, AMR, JPG, PNG and others;
  • Surface Manager – controls access to the display subsystem of 2D and 3D graphic layers;
  • LibWebCore is a modern web engine on which the Android browser is built;
  • SGL – main 2D graphics engine;
  • 3D libraries – implemented based on OpenGL; libraries use either hardware 3D acceleration (if available) or are enabled in software;
  • FreeType – support for raster and vector fonts
  • SQLite is a database engine available to all applications.

Android Runtime. Android includes a set of core libraries that provide most of the functionality available in the Java libraries. Each Android application runs in its own process, with its own instance of the Dalvik virtual machine. Dalvik was written so that the device can work effectively with several virtual machines simultaneously.

Dalvik was designed specifically for the Android platform. Virtual machine optimized for low memory consumption and running on mobile hardware. Dalvik uses its own bytecode. Android applications are translated by the compiler into special machine-independent low-level code. And it is Dalvik that interprets and executes such a program when executed on the platform. In addition, using special utility included in the Android SDK, Dalvik is capable of translating Java bytecodes into codes own format and also perform them in your virtual environment.

Linux Kernel. Android is based on Linux versions 2.6 with basic system services- safety , memory management, process management and driver model. Android developers have modified the Linux kernel to add support for hardware, used in mobile devices and, most often, inaccessible on computers.

1.4. Overview of Java Interfaces

For application programmer Android is a set of interfaces in the Java language. Let's look at how it is organized. The set is based on packages included in

There are four standard blocks Android apps:

- Activity.

- Intent Receiver.

- Service.

- Content Provider.

Not every application needs to have all four blocks, but your application will be written with some combination of them.

Once you have decided which components you need for your application, you should list them in a file called AndroidManifest.xml. This - XML file, where you declare the components of your application and what their capabilities and requirements are. We'll soon discuss what AndroidManifest.xml is responsible for.

(This could have been written VERY crookedly. There is a lot of text and no pictures of examples. I recommend being patient and reading this theory, but then it will be clearer to you. Then everything is written much smoother, don’t worry)

Activity

Activity is the most common of the four building blocks of Android. The Activity is usually the only screen in your application. Each Activity is implemented as a single class that extends the base Activity class. Your class will display the user interface composed of Views and respond to events. Most applications consist of multiple screens. For example, a messaging app might have one screen that shows a list of contacts, a second screen to write a message to a selected contact, and other screens to review old messages or change a setting. Each of these screens would be implemented as an Activity. Moving to another screen is achieved by starting a new Activity. In some cases, an Activity may return the value of a previous Activity - for example, an Activity that allows the user to select a photo would return the selected photo to the calling program. When new screen opens, the previous screen is paused and placed on the history stack. The user can move back through previously open screens in chronology. Screens may also want to be removed from the history stack when it would be inappropriate for them to remain. Android saves history stacks for each application started from the beginning of the screen.

Intent and Intent filters

Android uses a special class called Intent to move from screen to screen. Intent describes what the application intends to do. The two most important parts of the Intent structure are the action and the data behind the action. Typical values ​​for the action are MAIN (main screen applications), VIEW, PICK, EDIT, etc. The data is expressed as a Uniform Resource Indicator (URI). For example, to view a website in a browser, you would create an Intent with a VIEW action and a data set - the site's address.

new Intent(android.content.Intent. VIEW_ACTION,ContentURI. create("http://anddev.org"));

There is a related class called IntentFilter. While an Intent is a request to do something, an IntentFilter is a description of what the Intent Activity (or intent receiver, see below) is capable of processing. An Activity that is able to display information for a person would publish an IntentFilter that says it knows how to process the activity's VIEW. The Activity publishes its IntentFilters in the AndroidManifest.xml file.

Navigation from screen to screen is achieved using Intent. To move forward, the Activity calls startActivity(myIntent). The system then looks at the IntentFilter for all installed applications and selects the Activity whose Intent myIntent is filtering. The new Activity is informed of an Intent, which causes it to begin. The Intent resolution process occurs when startActivity is called. The process offers two key benefits:

Activities can reuse functionality from other components simply by making a request in the Intent form.

Activities can be replaced at any time by a new Activity with an equivalent IntentFilter.

Intent Receiver

You can use IntentReceiver when you want code in your application to execute in response to an external event, for example, when the phone rings, or when the data network is available, or when it is midnight. Intent Receivers do not display a UI, although they can display Notifications to alert the user if something interesting has happened. Consumed receivers are also registered in AndroidManifest.xml, but you can also register them in code using Context.registerReceiver(). Your application should not be running for its Intent Receiver to be called; the system will launch your application, if necessary, when the Intent Receiver is called. Applications can also send their own Intent Receivers to others with Context.broadcastIntent().

Service

Service is code that is durable and runs without a UI. Good example This is a universal player that plays songs from a playlist. A universal player application would likely have one or more Activities that allow the user to select songs and play them. However, playing the music itself should not be handled by the Activity, because the user will expect the music to continue playing even after the player is minimized. In this case, the media player activity could start a Service using Context.startService() to run in the background and keep the music playing. Then the system will continue playing music until it closes itself. (You can learn more about the priority given to services on the system by reading Loop Life Applications Android). Note that you can bind to the Service (and start it if it's not already running) with the Context.bindService() method. When there is a connection to a Service, you can communicate with it through the interface exposed by the Service. For Service music, this might allow you to pause, rewind, etc.

Content Provider

Applications can store their data in files, a SQLite database, personalization settings, or any other mechanism that makes sense. Content Provider is, however, useful if you want your app data to be shared with other apps. Content Provider is a class that implements a standard set of methods to allow other applications to save and restore the type of data that is processed by another Content Provider.

Android user interfaces

User interfaces (UI) in Android can be created in two ways, through XML code or in java code. Creating a structure GUI user in XML is very preferable because, according to the principle of Model Viewer Control, the UI should always be separated from program logic. In addition, adapting the program from one screen resolution to another is much simpler. Defining a UI in XML is very similar to creating a generic HTML document, where you have that is such a simple file:

Page Title

The content of the body element.

It’s the same as in Android XML-Layouts. Everything is well structured and can be expressed in tree structures:

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello World"/>

HierarchyElementsScreen

Basic function module Android applications - Activity - an object of the android.app.activity class. An Activity can do a lot of things, but it doesn't have any screen presence on its own. To give your Activity screen presence and design its UI, you work with Views and Viewgroups - the basic units of user interface expression on the Android platform.

Views

View is an object that extends the base class android.view.view. This is a data structure whose properties store Layouts and content for a specific rectangular area of ​​the screen. The View object handles the dimension, its layout, drawing, center changes, scrolling, and keys/icons for the area of ​​the screen it represents. The View class serves base class for all graphic fragments - the entire row implemented subclasses that draw interactive screen elements. Graphic fragments handle their own dimension and drawing, so you can use them to create your UI more quickly. The list of available graphic fragments includes TextView, EditText, Button, RadioButton, Checkbox, ScrollView, etc.

Viewgroups

Viewgroup is an object of class android.view.viewgroup. Viewgroup - special type a View object whose function is to contain and manage a set of Views and Viewgroups. Viewgroups allow you to add structure to your UI and create complex screen elements that can be accessed as to a single object. The Viewgroup class serves as the base class for Layouts, a series of fully implemented subclasses that provide common types Screen layouts. Layouts give you a way to build in structure for a View series.

UI with tree structure

On the Android platform, you define a UI Activity using a View tree and Viewgroup nodes, as shown in the diagram below. The tree can be as simple or complex as you make it, and you can build it using sets of predefined graphics tiles and Android Layouts, or custom View types that you create yourself.

Android UI is a tree structure.

To attach the tree to the screen and render it, your Activity calls its setContentView() method and passes the information to the node's root object. Once the Android system receives information on the root object of a node, it begins to work directly with the node to measure and draw the tree. When your Activity becomes active and receives priority, the system registers your Activity and asks the root node to measure and draw the tree. The root node then asks its child nodes to draw themselves - in turn, each Viewgroup node in the tree is responsible for drawing it direct child nodes. As mentioned earlier, each View group has the responsibility of measuring its available space, the location of its child nodes, and calling draw() on each child node to allow them all to render themselves. Child nodes can request size and location in the parent, but the parent has the ultimate decision on where and how big each child can be.

Comparison of Android UI Elements to Swing UI Elements

Since some developers who are reading this may have found the UIs to be similar to Swing, there will now be few similarities between Android and Swing.

Activity in Android is almost a (J) Frame in Swing.

View in Android - (J) Component in Swing.

TextViews in Android - (J) TextField in Swing.

EditTexts in Android - (J) TextField in Swing.

Button in Android - (J) Button in Swing.

Setting listeners to Views in Android is almost the same as in Swing.

myView.setOnClickListener( new OnClickListener())( ...

myButton.addActionListener( new ActionListener()(...