Руководство Android Services
1. Виды сервисов в Android
Что такое Сервис?
Сервис (Service) это фоновые процессы в системе выполняющие длительные операции и не нуждаются в взаимодействии с пользователем и работает даже при уничтожении приложения. Сервис имеет два состояния.
Состояние | Oписание |
Started
(Запущенный) | Сервис называется started (запущенный) когда компонент приложения, например Activity запускает его вызовом startService(). При вызове, этот сервис может работать в фоновом режиме в течении неограниченного времени, даже при уничтожении запущенного компонента.
Этот сервис так же называет непривязанным (Un Bounded Service). |
Bound
(Привязанный) | Сервис является привязанной (bound) когда компонент приложения привязывается к ней вызовом bindService().
Привязанный сервис предлагает интерфейс клиент-сервер client-server, который позволяет компонентам взаимодействовать со службой, отправлять запросы, получать результаты и даже делать это между разными процессами посредством межпроцессного взаимодействия Interprocess communication (IPC). |
В информатике, межпроцессное взаимодействие inter-process communication (IPC) это обмен данными между несколькими обычно специализированными коммуникационными протоколами. Приложения использующие IPC делятся на клиент (clients) и сервер (servers), когда клиент требует данные, сервер предоставляет данные по требованию клиента.
Сервис содержит методы обратного вызова жизненного цикла (life cycle callback methods) которые можно реализовать (implement) для контроля изменений состояния службы и выполнения работы в соответствующие моменты времени. Диаграмма ниже показывает жизненный цикл когда сервис создан с startService(), диаграмма справа показывает жизненный цикл когда сервис создан с bindService().
Чтобы создать сервис, создайте класс Java, который расширит класс Service или один из его подклассов. Класс Service определяет разные методы callback и самое главное описывается далее. Вам не нужно выполнять (implements) все методы callbacks. При этом, важно понять, что делает каждый метод и удостовериться, что приложение ведет себя так, как ожидает пользователь.
Помимо 2 сервисов выше, есть другой сервис, который называется IntentService. Intent Service используется при выполнении одного задания, т.е. при завершении задания сервис самоуничтожается.
Сравнение сервисов:
Unbound Service
(Непривязанный) | Bound Service
(Привязанный) | Intent
Service |
Unbounded Service используется для выполнения долгосрочных и повторяющихся заданий. | Bounded Service используется для выполнения заданий в фоновом режиме (background) и связанный с компонентом интерфейса | Intent Service используется для выполнения заданий 1 раз, т.е. при завершения задания сервис самоуничтожается. |
Unbound Service запускается при вызове startService(). | Bounded Service запускается при вызовеbindService(). | Intent Service запускается при вызове startService(). |
Unbound Service останавливется или уничтожается при точном вызове stopService(). | Bounded Service снимает ограничения или уничтожается при вызове unbindService(). | IntentService вызывается неточно stopself() для уничтожения |
Unbound Service независим от запускающего компонета. | Bound Service зависим от запускающего компонета. | Intent Service независим от запускающего компонета. |
Методы callback и описание:
Callback | Description |
onStartCommand() | The system calls this method when another component, such as an activity, requests that the service be started, by calling startService(). If you implement this method, it is your responsibility to stop the service when its work is done, by calling stopSelf() or stopService() methods. |
onBind() | The system calls this method when another component wants to bind with the service by calling bindService(). If you implement this method, you must provide an interface that clients use to communicate with the service, by returning an IBinder object. You must always implement this method, but if you don't want to allow binding, then you should return null. |
onUnbind() | The system calls this method when all clients have disconnected from a particular interface published by the service. |
onRebind() | The system calls this method when new clients have connected to the service, after it had previously been notified that all had disconnected in its onUnbind(Intent). |
onCreate() | The system calls this method when the service is first created using onStartCommand() or onBind(). This call is required to perform one-time set-up. |
onDestroy() | The system calls this method when the service is no longer used and is being destroyed. Your service should implement this to clean up any resources such as threads, registered listeners, receivers, etc. |
2. Unbounded Service
Unbound Service (или Started Service): В этом случае, компонент приложения запускает сервис вызывая startService(), и сервис будет работать в фоновом режиме (background), даже при уничтожении созданных компонентов. Например, при запуске, сервис играет фоновую музыку в неограниченном времени.
Метод onStartCommand() возврещает integer, значение которого может быть:
- START_STICKY
- START_NOT_STICKY
- TART_REDELIVER_INTENT
START_STICKY & START_NOT_STICKYОба значения имеют связь только когда память на телефоне кончается и уничтожает сервис перед завершением.START_STICKY говорит оперционной системе пересоздать сервис при наличии памяти и снова вызвать onStartCommand() с Intent null.START_NOT_STICKY говорит оперционной системе об отсутствии необходимости еще раз пересоздавать сервис.Есть так же третий код START_REDELIVER_INTENT, говорящий операционной системе пересоздать сервис и передать индентичный Intent для onStartCommand().
Пример сервиса музыки (Фоновый режим)
Создать новый "Empty Activity" project с названием PlaySongService
- Name: PlaySongService
- Package name: org.o7planning.playsongservice
Project создан.
Приготовить файл mp3:
Нажать правой мышью на папку res и выбрать:
- New > Folder > Raw Resources Folder
Скопировать и вставить аудиофайл mp3 в только что созданную вами папку 'raw'.
Интерфейс приложения:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/button_play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
android:text="Play"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="37dp"
android:text="Stop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_play" />
</androidx.constraintlayout.widget.ConstraintLayout>
Создать класс Service
Нажать на правую мышь java package, выбрать:
- New > Service > Service
Ввести название класса:
- PlaySongService
Вы можете увидеть что, PlaySongService был объявлен с AndroidManifest.xml:
** AndroidManifest.xml **
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.o7planning.playsongservice">
<application ...>
<service
android:name=".PlaySongService"
android:enabled="true"
android:exported="true"></service>
....
</application>
</manifest>
PlaySongService.java
package org.o7planning.playsongservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.media.MediaPlayer;
public class PlaySongService extends Service {
private MediaPlayer mediaPlayer;
public PlaySongService() {
}
// Return the communication channel to the service.
@Override
public IBinder onBind(Intent intent){
// This service is unbounded
// So this method is never called.
return null;
}
@Override
public void onCreate(){
super.onCreate();
// Create MediaPlayer object, to play your song.
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.mysong);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
// Play song.
mediaPlayer.start();
return START_STICKY;
}
// Destroy
@Override
public void onDestroy() {
// Release the resources
mediaPlayer.release();
super.onDestroy();
}
}
MainActivity.java
package org.o7planning.playsongservice;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.Intent;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button buttonPlay;
private Button buttonStop;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.buttonPlay = (Button) this.findViewById(R.id.button_play);
this.buttonStop = (Button) this.findViewById(R.id.button_stop);
this.buttonPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
playSong();
}
});
this.buttonStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopSong();
}
});
}
// This method is called when users click on the Play button.
public void playSong() {
// Create Intent object for PlaySongService.
Intent myIntent = new Intent(MainActivity.this, PlaySongService.class);
// Call startService with Intent parameter.
this.startService(myIntent);
}
// This method is called when users click on the Stop button.
public void stopSong( ) {
// Create Intent object
Intent myIntent = new Intent(MainActivity.this, PlaySongService.class);
this.stopService(myIntent);
}
}
OK теперь вы можете запусть свое приложение и насладиться песней.
3. Bouned Service
Далее, я стимулирую сервис предоставляющий информацию погоды на сегодня, с геолокацией (Hanoi, Chicago, ...), возвращает результат как дождь, солнечно ....
Создать project с названием WeatherService.
- Name: WeatherService
- Package name: org.o7planning.weatherservice
Дизайн интерфейса приложения:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="38dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="17dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:text="Location:"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/editText_location"
android:layout_width="0dp"
android:layout_height="47dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="23dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:ems="10"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView_weather"
android:layout_width="0dp"
android:layout_height="45dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="59dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editText_location" />
<Button
android:id="@+id/button_weather"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="35dp"
android:text="Show Weather"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView_weather" />
</androidx.constraintlayout.widget.ConstraintLayout>
Создать Сервис:
Нажмите на правую мышь java package, выбрать:
- New > Service > Service
Ввод:
- Class name: WeatherService
Класс WeatherService создан, это расширенный класс из класса android.app.Service.
Вы можете увидеть, что WeatherService был объявлен с AndroidManifest.xml:
** AndroidManifest.xml **
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.o7planning.weatherservice">
<application ...>
<service
android:name=".WeatherService"
android:enabled="true"
android:exported="true"></service>
...
</application>
</manifest>
WeatherService.java
package org.o7planning.weatherservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.Binder;
import android.util.Log;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class WeatherService extends Service {
private static String LOG_TAG = "WeatherService";
// Store the weather data.
private static final Map<String, String> weatherData = new HashMap<String,String>();
private final IBinder binder = new LocalWeatherBinder();
public class LocalWeatherBinder extends Binder {
public WeatherService getService() {
return WeatherService.this;
}
}
public WeatherService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.i(LOG_TAG,"onBind");
return this.binder;
}
@Override
public void onRebind(Intent intent) {
Log.i(LOG_TAG, "onRebind");
super.onRebind(intent);
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(LOG_TAG, "onUnbind");
return true;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(LOG_TAG, "onDestroy");
}
// Returns the weather information corresponding to the location of the current date.
public String getWeatherToday(String location) {
Date now= new Date();
DateFormat df= new SimpleDateFormat("dd-MM-yyyy");
String dayString = df.format(now);
String keyLocAndDay = location + "$"+ dayString;
String weather= weatherData.get(keyLocAndDay);
//
if(weather != null) {
return weather;
}
//
String[] weathers = new String[]{"Rainy", "Hot", "Cool", "Warm" ,"Snowy"};
// Random value from 0 to 4
int i= new Random().nextInt(5);
weather =weathers[i];
weatherData.put(keyLocAndDay, weather);
//
return weather;
}
}
MainActivity.java
package org.o7planning.weatherservice;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private boolean binded = false;
private WeatherService weatherService;
private TextView textViewWeather;
private EditText editTextLocation;
private Button buttonWeather;
ServiceConnection weatherServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
WeatherService.LocalWeatherBinder binder = (WeatherService.LocalWeatherBinder) service;
weatherService = binder.getService();
binded = true;
}
@Override
public void onServiceDisconnected(ComponentName name) {
binded = false;
}
};
// When the Activity creating its interface.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.textViewWeather = (TextView) this.findViewById(R.id.textView_weather);
this.editTextLocation = (EditText) this.findViewById(R.id.editText_location);
this.buttonWeather = (Button) this.findViewById(R.id.button_weather);
this.buttonWeather.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showWeather();
}
});
}
// When Activity starting.
@Override
protected void onStart() {
super.onStart();
// Create Intent object for WeatherService.
Intent intent = new Intent(this, WeatherService.class);
// Call bindService(..) method to bind service with UI.
this.bindService(intent, weatherServiceConnection, Context.BIND_AUTO_CREATE);
}
// Activity stop
@Override
protected void onStop() {
super.onStop();
if (binded) {
// Unbind Service
this.unbindService(weatherServiceConnection);
binded = false;
}
}
// When user click on 'Show weather' button.
public void showWeather() {
String location = this.editTextLocation.getText().toString();
String weather= this.weatherService.getWeatherToday(location);
this.textViewWeather.setText(weather);
}
}
Итак, теперь вы можете запустить приложение.
4. Сервис IntentService
Пример IntentService:
Иллюстрация показывает связь между Client (Activity) и IntentService, Клиент стартует сервис, отправляет запрос через Intent, сервис запускается и делает свою работу, одновременно отправляет информацию связанную с рабочей ситуацией, например, сколько процентов выполнено. С клиентом вы можете использовать ProgressBar, чтобы показать процентов работы выполнено.
IntentService смоделированы, чтобы автоматически stop (остановиться) естественно при завершенной работе и используется только один раз, поэтому вам стоит его использовать в таких ситуациях. Метод <context>.stopService(intentService) не будет работать с IntentService. Тем более, очень сложно для вас использовать UI приложения, чтобы взаимодействовать с IntentService.
Создать новый project SimpleIntentService.
- Name: SimpleIntentService
- Package name: org.o7planning.simpleintentservice
Дизай интерфейса:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="25dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="28dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView_percent"
android:layout_width="0dp"
android:layout_height="22dp"
android:layout_marginStart="16dp"
android:layout_marginLeft="16dp"
android:layout_marginTop="28dp"
android:layout_marginEnd="16dp"
android:layout_marginRight="16dp"
android:gravity="center"
android:text="(Percent)"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressBar" />
<Button
android:id="@+id/button_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="27dp"
android:text="Start"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView_percent" />
<Button
android:id="@+id/button_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="26dp"
android:text="Stop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_start" />
</androidx.constraintlayout.widget.ConstraintLayout>
Создать IntentService нажав на правую мышь в пакет и выбрать:
- New > Service > Service (IntentService)
Вы можете увидеть, что SimpleIntentService был объявлен с AndroidManifest.xml:
** AndroidManifest.xml **
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.o7planning.simpleintentservice">
<application ...>
<service
android:name=".SimpleIntentService"
android:exported="false"></service>
...
</application>
</manifest>
Класс SimpleIntentService создан, также зарегистрирован с AndroidManifest.xml, полученный код это подсказка для вас написать IntentService, вы можете удалить все полученные коды.
SimpleIntentService.java
package org.o7planning.simpleintentservice;
import android.app.IntentService;
import android.content.Intent;
import android.os.SystemClock;
public class SimpleIntentService extends IntentService {
public static volatile boolean shouldStop = false;
public static final String ACTION_1 ="MY_ACTION_1";
public static final String PARAM_PERCENT = "percent";
public SimpleIntentService() {
super("SimpleIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
// Create Intent object (to broadcast).
Intent broadcastIntent = new Intent();
// Set Action name for this Intent.
// A Intent can perform many different actions.
broadcastIntent.setAction(SimpleIntentService.ACTION_1);
// Loop 100 times broadcast of Intent.
for (int i = 0; i <= 100; i++) {
// Set data
// (Percent of work)
broadcastIntent.putExtra(PARAM_PERCENT, i);
// Send broadcast
sendBroadcast(broadcastIntent);
// Sleep 100 Milliseconds.
SystemClock.sleep(100);
if(shouldStop) {
stopSelf();
return;
}
}
}
}
MainActivity.java
package org.o7planning.simpleintentservice;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button buttonStart;
private Button buttonStop;
private TextView textViewPercent;
private ProgressBar progressBar;
private Intent serviceIntent;
private ResponseReceiver receiver = new ResponseReceiver();
// Broadcast component
public class ResponseReceiver extends BroadcastReceiver {
// On broadcast received
@Override
public void onReceive(Context context, Intent intent) {
// Check action name.
if(intent.getAction().equals(SimpleIntentService.ACTION_1)) {
int value = intent.getIntExtra(SimpleIntentService.PARAM_PERCENT, 0);
new ShowProgressBarTask().execute(value);
}
}
}
// Display value for the ProgressBar.
class ShowProgressBarTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... args) {
return args[0];
}
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
progressBar.setProgress(result);
textViewPercent.setText(result + " % Loaded");
if (result == 100) {
textViewPercent.setText("Completed");
buttonStart.setEnabled(true);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.textViewPercent = (TextView) this.findViewById(R.id.textView_percent);
this.progressBar = (ProgressBar) this.findViewById(R.id.progressBar);
this.buttonStart = (Button) this.findViewById(R.id.button_start);
this.buttonStop = (Button)this.findViewById(R.id.button_stop);
this.buttonStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
buttonStartClicked();
}
});
this.buttonStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
buttonStopClicked();
}
});
}
// On Resume of MainActivity
@Override
protected void onResume() {
super.onResume();
// Register receiver with Activity.
registerReceiver(receiver, new IntentFilter(
SimpleIntentService.ACTION_1));
}
// On Stop of MainActivity
@Override
protected void onStop() {
super.onStop();
// Unregister receiver with Activity.
unregisterReceiver(receiver);
}
// Method is called when the user clicks on the Start button.
public void buttonStartClicked( ) {
this.buttonStart.setEnabled(false);
this.serviceIntent = new Intent(this, SimpleIntentService.class);
startService(this.serviceIntent);
}
public void buttonStopClicked( ) {
if(this.serviceIntent!= null) {
// stopService(this.serviceIntent) does not work with IntentService(s).
// Mandatory stopping of an IntentService is not recommended.
SimpleIntentService.shouldStop = true;
}
}
}
Запуск приложения:
И вы можете увидеть правила работы пример выше на следующей иллюстрации:
Pуководства Android
- Настроить Android Emulator в Android Studio
- Руководство Android ToggleButton
- Создать простой File Finder Dialog в Android
- Руководство Android TimePickerDialog
- Руководство Android DatePickerDialog
- Что мне нужно для начала работы с Android?
- Установите Android Studio в Windows
- Установите Intel® HAXM для Android Studio
- Руководство Android AsyncTask
- Руководство Android AsyncTaskLoader
- Руководство Android для начинающих - основные примеры
- Как узнать номер телефона Android Emulator и изменить его?
- Руководство Android TextInputLayout
- Руководство Android CardView
- Руководство Android ViewPager2
- Получить номер телефона в Android с помощью TelephonyManager
- Руководство Android Phone Call
- Руководство Android Wifi Scanning
- Руководство Android 2D Game для начинающих
- Руководство Android DialogFragment
- Руководство Android CharacterPickerDialog
- Руководство Android для начинающих - Hello Android
- Использование Android Device File Explorer
- Включить USB Debugging на устройстве Android
- Руководство Android UI Layouts
- Руководство Android SMS
- Руководство Android SQLite Database
- Руководство Google Maps Android API
- Руководство Текст в речь на Android
- Руководство Android Space
- Руководство Android Toast
- Создание пользовательских Android Toast
- Руководство Android SnackBar
- Руководство Android TextView
- Руководство Android TextClock
- Руководство Android EditText
- Руководство Android TextWatcher
- Форматирование номера кредитной карты с помощью Android TextWatcher
- Руководство Android Clipboard
- Создать простой File Chooser в Android
- Руководство Android AutoCompleteTextView и MultiAutoCompleteTextView
- Руководство Android ImageView
- Руководство Android ImageSwitcher
- Руководство Android ScrollView и HorizontalScrollView
- Руководство Android WebView
- Руководство Android SeekBar
- Руководство Android Dialog
- Руководство Android AlertDialog
- Руководство Android RatingBar
- Руководство Android ProgressBar
- Руководство Android Spinner
- Руководство Android Button
- Руководство Android Switch
- Руководство Android ImageButton
- Руководство Android FloatingActionButton
- Руководство Android CheckBox
- Руководство Android RadioGroup и RadioButton
- Руководство Android Chip и ChipGroup
- Использование Image assets и Icon assets Android Studio
- Настройка SD Card для Android Emulator
- Пример ChipGroup и Chip Entry
- Как добавить внешние библиотеки в Android Project в Android Studio?
- Как отключить разрешения, уже предоставленные приложению Android?
- Как удалить приложения из Android Emulator?
- Руководство Android LinearLayout
- Руководство Android TableLayout
- Руководство Android FrameLayout
- Руководство Android QuickContactBadge
- Руководство Android StackView
- Руководство Android Camera
- Руководство Android MediaPlayer
- Руководство Android VideoView
- Воспроизведение звуковых эффектов в Android с помощью SoundPool
- Руководство Android Networking
- Руководство Android JSON Parser
- Руководство Android SharedPreferences
- Руководство Android Internal Storage
- Руководство Android External Storage
- Руководство Android Intents
- Пример явного Android Intent, вызов другого Intent
- Пример неявного Android Intent, откройте URL, отправьте email
- Руководство Android Services
- Использовать оповещения в Android - Android Notification
- Руководство Android DatePicker
- Руководство Android TimePicker
- Руководство Android Chronometer
- Руководство Android OptionMenu
- Руководство Android ContextMenu
- Руководство Android PopupMenu
- Руководство Android Fragment
- Руководство Android ListView
- Android ListView с Checkbox с помощью ArrayAdapter
- Руководство Android GridView
Show More