Intent - wl.unn.ru

advertisement
Платформа Android
Ведущий семинара: Максим Лейкин, компания «МЕРА НН»
План семинара
1. Android - FAQ
2. Инструменты Android-разработчика
3. Примеры приложений
• Жизненный цикл приложения + AsyncTasks,
Threads
• Простые ресурсы, размещения
• Элементы управления
• Хранилища данных
• Content Providers
• Intents, receivers
• Сервисы
• LBS-приложения
План семинара
Часть 1. Android - FAQ
1.Что такое Android?
2.Кто его разрабатывает?
3.Какие версии Android существуют?
4.Какие аппаратные платформы поддерживаются?
5.Под какой лицензией распространяется Android?
6.В чем ключевые особенности Android?
7.Из чего состоит Android?
8.Какова доля Android на рынке мобильных платформ?
9.Какие существуют устройства на платформе Android?
10.Что такое Google Play?
11.В чем преимущества и недостатки платформы Android?
Android Activity Lifecycle
В любой момент времени всякая активность может находиться в
одном из 4-х состояний:
1) Active – видна на экране и может взаимодействовать с
пользователем
2) Paused – видна на экране, но не может взаимодействовать с
пользователем (не имеет фокуса ввода), например по причине
перекрытия всплывающим окном. Состояние сохраняется.
Может быть уничтожена системой в случае серьезной нехватки
памяти
3) Stopped – запущена, но не видна пользователю и не может
взаимодействовать с ним. Состояние сохраняется. Может быть
уничтожена системой в случае нехватки памяти
4) Dead – активность не была запущена, либо была снята с
выполнения системой из-за нехватки ресурсов . Состояние не
сохраняется.
Android Activity Lifecycle
Foreground
lifetime
Entire
lifetime
Visible
lifetime
Android Activity Lifecycle
public class Activity extends ApplicationContext {
protected void onCreate(Bundle savedInstanceState);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();
}
Внимание! Сохранять состояние активности надо в методе onPause(),
а не в onSaveInstanceState(Bundle), последний может в некоторых
случаях не вызываться.
Android Activity Lifecycle
Intents
Intent – специальный объект, который используется для передачи
сообщений между компонентами как внутри одного приложения так
и между разными приложениями.
С помощью Intents системе передается намерение совершить какоелибо действие и данные, с которыми надо совершить это действие.
В ОС Android с помощью Intents можно делать следующее:
-
стартовать другие активности (явно или неявно)
-
передавать «широковещательные» сообщения операционной
системе
-
получать «широковещательные» сообщения от операционной
системы
Intents – рекомендованный способ взаимдействия между
компонентами даже внутри одного приложения.
Intents
Структура Intent
1) Обязательные параметры:
•
action – действие, которое нужно произвести, например
ACTION_VIEW, ACTION_EDIT, etc.
•
data – элемент данных, над которым надо произвести action,
задается с помощью Uri
Intents
Структура Intent
2) Необязательные параметры:
•
category – дополнительная информация о действии, которое
нужно произвести (например, CATEGORY_LAUNCHER,
СATEGORY_ALTERNATIVE)
•
type – позволяет явно указать MIME type данных,
поставляемых с Intent (обычно извлекается из data)
•
component - позволяет явно указать имя класса, для
выполнения Intent (обычно извлекается из action, data/type,
categories). Если указан – перекрывает действие всех
остальных атрибутов.
•
extras – дополнительные данные, в виде набора пар «ключзначение»
Intents: запуск активностей
Явно (explicitly):
Intent intent = new Intent(MyActivity.this, MyOtherActivity.class);
startActivity(intent);
Внимание! Вызываемая активность д.б. прописана в AndroidManifest.xml
Intents: запуск активностей
Неявно (implicitly):
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(“tel:555-2368”));
startActivity(intent);
Приложение SimpleCaller
/res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, SimpleCallerActivity!</string>
<string name="app_name">SimpleCaller</string>
<string name="call">Call</string>
<string name="number">Number:</string>
</resources>
Приложение SimpleCaller
/src/layout/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/number" />
<EditText
android:id="@+id/Number"
android:layout_width="103dp"
android:layout_height="wrap_content" />
<Button
android:layout_height="wrap_content"
android:text="@string/call"
android:layout_width="wrap_content"
android:id="@+id/btnCall">
</Button>
</LinearLayout>
Приложение SimpleCaller
/src/com/nnsu/mobileweek/SimpleCallerActivity.java:
package com.nnsu.mobileweek;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class SimpleCallerActivity extends Activity implements
OnClickListener{
/** Called when the activity is first created. */
Button btnCall;
EditText numberField;
Приложение SimpleCaller
/src/com/nnsu/mobileweek/SimpleCallerActivity.java:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnCall = (Button)findViewById(R.id.btnCall);
numberField = (EditText)findViewById(R.id.Number);
btnCall.setOnClickListener(this);
}
private void phoneCall() {
String phoneCallUri = "tel:" + numberField.getText().toString();
Intent phoneCallIntent = new Intent(Intent.ACTION_CALL);
phoneCallIntent.setData(Uri.parse(phoneCallUri));
startActivity(phoneCallIntent);
}
public void onClick(View v) {
phoneCall();
}
}
Приложение SimpleCaller
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nnsu.mobileweek"
android:versionCode="1"
android:versionName="1.0">
<application
android:label="@string/app_name"
android:debuggable="true">
<activity android:name=".SimpleCallerActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.CALL_PHONE" />
</manifest>
Приложение SimpleCaller
Приложение SimpleCaller
Intents: Intent Filters
Intent Filters предназначены для того, чтобы сообщить
операционной системе, что компонент (активность,
сервис) может принимать и обрабатывать Intents,
c параметрами определенного типа.
В приложении создается Intent, заполняются параметры action, data,
category. С помощью startActivity() этот Intent отправляется на поиски
подходящей Activity, которая сможет выполнить то, что определено
параметрами Intent. В системе есть разные приложения, и в каждом из
них несколько Activity. Для некоторых Activity определен Intent Filter т.д.),
для некоторых нет. Метод startActivity() сверяет набор параметров Intent
и наборы параметров Intent Filter для каждой Activity. Если наборы
совпадают – Activity считается подходящей. Если в итоге нашлась
только одна Activity – она и отображается. Если же нашлось несколько
подходящих Activity, то пользователю выводится список, где он может
сам выбрать какое приложение ему использовать.
Intents: Intent Filters
Для задания Intent Filter используется тег intent-filter в
файле AndroidManifest.xml:
<activity android:name=".TourViewActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="vnd.android.cursor.item/vnd.com.niit.android" />
</intent-filter>
</activity>
1) action – задает действие, которое надо свершить или компонент, который надо
запустить
2) category – определяет, при каких условиях надо совершить action
3) data – набор дополнительных данных, который используется при выборе
компонента, выполняющего Intent, и передается ему для обработки
Можно считать, что Intent – ключ, IntentFilter - замок
Intents: Resolution Rules
1) Собирается список всех доступных Intent Filters
2) Intent Filters, которые не соответствуют действию или категории
удаляются из списка.
a) Совпадение происходит только в том случае, если Intent Filter
содержит указанное действие (или если действие для него
вовсе не задано). Совпадения не произойдет, только если ни
одно из действий Intent Filter не будет эквивалентно тому,
которое задано в Intent
b) Для категорий процесс соответствия более строгий. Intent Filter
должен включать в себя все категории, заданные в полученном
Intent. Фильтр, для которого категории не указаны, может
соответствовать только таким же Intent без категорий.
3) Каждая часть пути URI из Intent сравнивается с тегом data Intent Filter.
Если в Intent Filter указаны схема (протокол), сервер/принадлежность,
путь или тип MIME, все эти значения проверяются на соответствие
пути URI из Intent. При любом несовпадении Фильтр будет удален из
списка. Если в Intent Filter не указано ни одного параметра data, его
действие будет распространяться на любые данные.
Intents: Resolution Rules
a) MIME — тип данных, который должен совпасть. При
сравнении типов данных вы можете использовать маски,
чтобы охватывать все подтипы (например, cats/*). Если в
Intent Filter указан тип данных, он должен совпасть с тем,
который значится в намерении, при отсутствии тега data
подойдет любой тип.
b) Схема — это протокольная часть пути URI, например http:,
mailto: или tel:.
c) Имя сервера (или принадлежность данных) — часть URI
между схемой и самим путем (например, www.google.com).
Чтобы совпало имя сервера, схема Intent Filter также должна
подойти.
d) После имени сервера идет путь к данным (например, /ig). Путь
пройдет проверку только после схемы и имени сервера,
содержащихся в теге.
4) Если вышеописанный процесс возвращает более одного
совпадения, пользователю выводится список со всеми вариантами
Sample 15
Intents: чтение Intent
Если активность была запущена в результате совпадения
Intent с IntentFilter, то она может получить Intent, с которым
ее вызывали:
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Intent intent = getIntent();
String action = intent.getAction();
Uri data = intent.getData();
}
Intents: передача Intent
Можно передать Intent в активность, следующую в списке
подходящих (предварительно выполнив
проверки\обработки):
Intent intent = getIntent();
if (isAfterMidnight) {
startNextMatchingActivity(intent);
}
Intents: возврат результата из активности
Основная активность:
private static final int SHOW_SUBACTIVITY = 1;
Intent intent = new Intent(this, MyOtherActivity.class);
startActivityForResult(intent, SHOW_SUBACTIVITY);
...
private static final int PICK_CONTACT_SUBACTIVITY = 2;
Uri uri = Uri.parse(“content://contacts/people”);
Intent intent = new Intent(Intent.ACTION_PICK, uri);
startActivityForResult(intent, PICK_CONTACT_SUBACTIVITY);
Intents: возврат результата из активности
Вспомогательная активность
Button okButton = (Button) findViewById(R.id.ok_button);
okButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
Uri data = Uri.parse(“content://vendors/” + vendor_id);
Intent result = new Intent(null, data);
result.putExtra(IS_INPUT_CORRECT, inputCorrect);
setResult(RESULT_OK, result);
finish();
}
});
Intents: возврат результата из активности
Обработка возвращенного результата:
public void onActivityResult(int requestCode,
int resultCode, Intent data)
- requestCode – код, с которым была запущена активность (переданный
в кач-ве второго параметра в startActivityForResult())
- resultCode – код, возвращенный из активности, обычно
Activity.RESULT_OK или Activity.RESULT_CANCELLED
- data – Intent, сорфмированный по результатам запуска sub-Activity
Intents: возврат результата из активности
private static final int SHOW_SUB_ACTIVITY_ONE = 1;
private static final int SHOW_SUB_ACTIVITY_TWO = 2;
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case (SHOW_SUB_ACTIVITY_ONE) :
if (resultCode == Activity.RESULT_OK) {
Uri vendor = data.getData();
boolean inputCorrect = data.getBooleanExtra(IS_INPUT_CORRECT, false); }
break;
case (SHOW_SUB_ACTIVITY_TWO) :
if (resultCode == Activity.RESULT_OK) {
// TODO: Handle OK click. }
break;
}
}
Отладка Android-приложений
Отладка из Eclipse:
- The Debug Perspective
- The DDMS Perspective
(Dalvik Debug Monitor Server )
Отладка Android-приложений: Breakpoints
Отладка Android-приложений: запуск в debug
Отладка Android-приложений: Debug Perspective
Variables – значения
переменных (работает если
есть установленные
breakpoints)
Debug – показывает
Breakpoints – расставленные
отлаживаемые приложения
точки останова
и выполняющиеся в данный
момент потоки
LogCat – Системные сообщения
платформы (в т.ч. exceptions)
Отладка Android-приложений: Debug Perspective
Отладка Android-приложений: DDMS Perspective
Threads –
выполняющиеся
потоки Tracker
Emulator
Allocation
Tracker
–
–
Allocation
– Control
выделение
эмулятором
памяти
выделениеуправление
памяти
Heap – использование
Devices – список
динамической памяти
подключенных
эмуляторов и
устройств
Android-приложения работающие с картами и GPS
Все устройства на платформе Android включают
датчик GPS и встроенные средства работы с данными
местоположения и картами.
Устройства на платформе Android позволяют
определять местоположение одним из 3-х способов:
- датчик GPS
- Cell-ID (триангуляция)
- Wi-Fi spots
Типовая задача:
1) Получить координаты с датчика GPS
2) Показать местоположение на карте Google Maps
Google API vs. Android API
Приложение LocationMaps
/res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, AndroidMapsActivity!</string>
<string name="app_name">AndroidMaps</string>
<string name="lat">Latitude</string>
<string name="lon">Longitude</string>
</resources>
Приложение LocationMaps
/src/layout/main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="@+id/bFindMe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Find Me!" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/lat" />
Приложение LocationMaps
<EditText
android:id="@+id/etLatitude"
android:layout_width="103dp"
android:layout_height="wrap_content" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/lon" />
<EditText
android:id="@+id/etLongitude"
android:layout_width="103dp"
android:layout_height="wrap_content" />
<Button
android:id="@+id/bShowMe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Show Me!" />
</LinearLayout>
Приложение LocationMaps
/src/com/nnsu/mobileweek/AndroidMapsActivity.java:
package com.nnsu.mobileweek;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
Приложение LocationMaps
/src/com/nnsu/mobileweek/AndroidMapsActivity.java:
public class AndroidMapsActivity extends Activity implements
LocationListener {
EditText lat, lon;
Button btnShow, btnFind;
LocationManager locMgr;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
Button btnShow=(Button)findViewById(R.id.bShowMe);
Button btnFind=(Button)findViewById(R.id.bFindMe);
lat=(EditText)findViewById(R.id.etLatitude);
lon=(EditText)findViewById(R.id.etLongitude);
Приложение LocationMaps
/src/com/nnsu/mobileweek/AndroidMapsActivity.java:
btnShow.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
String _lat=lat.getText().toString();
String _lon=lon.getText().toString();
Uri uri=Uri.parse("geo:"+_lat+","+_lon);
startActivity(new Intent(Intent.ACTION_VIEW, uri));
}
});
btnFind.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
getFix();
}
} );
}
Приложение LocationMaps
/src/com/nnsu/mobileweek/AndroidMapsActivity.java:
public void getFix() {
locMgr = (LocationManager)
this.getSystemService(Context.LOCATION_SERVICE);
locMgr.requestLocationUpdates
(LocationManager.GPS_PROVIDER, 0L, 0, this);
}
public void onLocationChanged(final Location location) {
this.runOnUiThread(new Runnable() {
public void run() {
lat.setText(new Double(location.getLatitude()).toString());
lon.setText(new Double(location.getLongitude()).toString());
}
} );
}
Приложение LocationMaps
/src/com/nnsu/mobileweek/AndroidMapsActivity.java:
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
Приложение LocationMaps
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nnsu.mobileweek"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="9" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".AndroidMapsActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
Приложение LocationMaps
Приложение LocationMaps
Download