Денис Колисниченко



Pdf просмотр
страница8/8
Дата05.11.2016
Размер5.05 Kb.
Просмотров1931
Скачиваний0
1   2   3   4   5   6   7   8




Глава 11. Потоки, службы и широковещательные приемники
207






Теперь нужно переопределить методы onCreate()
и onDestroy()
. Для этого щелкни- те правой кнопкой на файле класса в Eclipse и выберите команду Source |
Override/Implement Methods (рис.
11.3), после чего в открывшемся окне
(рис. 11.4) установите флажки напротив упомянутых методов.

Рис. 11.3. Меню Source
Метод onBind()
нужно переопределять в том случае, если новый компонент привя- зывается к этой службе после ее создания.
Запустите службу функцией startService()
. Остановить службу можно функцией stopService()
. Представим, что у нас есть деятельность
MainActivity с кнопками

208
Часть III. Профессиональное программирование
Start и Stop. Кнопка Start запускает сервис
MyService
, описанный в классе
MyService
(файл
MyService.java
). Обработчик нажатия этой кнопки будет выгля- деть так: startButton.setOnClickListener(new View.OnClickListener() { public void onClick(View view){ startService(new Intent(MainActivity.this,
MyService.class));
}
});

Рис. 11.4. Переопределяем методы onCreate()
и onDestroy()

Обработчик кнопки Stop будет таким: stopButton.setOnClickListener(new View.OnClickListener() { public void onClick(View v){ stopService(new Intent(MainActivity.this,
MyService.class));
}
});
В листинге 11.6 приведена расширенная «болванка» службы. Наша служба при за- пуске и останове выводит соответствующее уведомление.

Глава 11. Потоки, службы и широковещательные приемники
209
Листинг 11.6. Расширенная «болванка» службы (файл MyService.java) package com.samples.my_first_service; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.IBinder; import android.widget.Toast; public class MyService extends Service {
@Override public IBinder onBind(Intent arg0) { return null;
}
@Override public void onCreate() { super.onCreate();
Toast.makeText(this,"Service started...",
Toast.LENGTH_LONG).show();
}
@Override public void onDestroy() { super.onDestroy();
Toast.makeText(this, "Service destroyed...",
Toast.LENGTH_LONG).show();
}
}
Если служба разрешает другим приложениям связываться с собой, то привязка вы- полняется посредством следующих методов обратного вызова:
IBinder onBind(Intent intent)
; onUnbind(Intent intent)
; onRebind(Intent intent)
В метод onBind()
передают объект
Intent
, который был параметром в методе bindService()
, а в метод обратного вызова onUnbind()
— объект
Intent
, который передавали в метод unbindService()
. Если служба разрешает связывание, то метод onBind()
возвращает канал связи, который могут использовать клиенты, чтобы ра- ботать со службой. Метод onRebind()
может быть вызван после метода onBind()
, если со службой соединяется новый клиент.
В завершение повествования о службах приведу код, выводящий в лог (вывод можно просмотреть в Eclipse) список всех запущенных служб:

210
Часть III. Профессиональное программирование
ActivityManager am = (ActivityManager) this
.getSystemService(ACTIVITY_SERVICE);
List services = am.getRunningServices(50); for (int i = 0; i < services.size(); i++) {
ActivityManager.RunningServiceInfo rsi = services.get(i);
Log.i("Service", "Process " + rsi.process + " with component "
+ rsi.service.getClassName());
}
11.3. Широковещательные приемники
Широковещательные приемники прослушивают широковещательные сообщения системы. Примеры таких сообщений: низкий заряд батареи; нажата кнопка камеры; установлено новое приложение.
Помимо системных событий, пользователь может создавать свои события, — на- пример, когда поток завершил вычисления или когда поток начал работу.
Широковещательный приемник — это объект класса
BroadcastReceiver или одного из его подклассов. Самый главный метод этого класса — onReceive()
, который вы- зывается, когда приемник получает сообщение.
Рассмотрим пример запуска службы на основании получения широковещательного сообщения
— нажатия кнопки камеры. Приемник прослушивает сообщения, фильтр намерения установлен на действие
Intent.ACTION_CAMERA_BUTTON
, которое соответствует нажатию кнопки камеры.
Зарегистрировать приемник можно функцией registerReceiver()
, а удалить его — функцией unregisterReceiver()
Итак, начнем создавать приложение. Код основной деятельности
MainActivity представлен в файле
MainActivity.java
(листинг 11.7).
Листинг 11.7. Код основной деятельности (файл MainActivity.java) package com.samples.my_receiver; import android.app.Activity; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; public class MainActivity extends Activity {
// Создаем объект iReceiver класса MyReceiver
MyReceiver iReceiver = new MyReceiver();

Глава 11. Потоки, службы и широковещательные приемники
211
/** Called when the activity is first created. */
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
// Создаем фильтр намерения
IntentFilter iFilter = new IntentFilter(Intent.ACTION_CAMERA_BUTTON);
//
Добавляем действие в фильтр iFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
// Регистрируем приемник registerReceiver(iReceiver, iFilter);
}
@Override protected void onDestroy() {
// Уничтожаем приемник при завершении приложения unregisterReceiver(iReceiver); super.onDestroy();
}
}
Разберемся, что здесь что. Первым делом мы объявили объект iReceiver класса
MyReceiver
. Этот класс будет описан позже. Затем мы создали фильтр намерения:
IntentFilter iFilter = new IntentFilter(Intent.ACTION_CAMERA_BUTTON); iFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
После этого нужно только зарегистрировать приемник с помощью функции registerReceiver()
. Первый параметр — это сам приемник, второй — фильтр на- мерений: registerReceiver(iReceiver, iFilter);
Теперь надо создать класс
MyReceiver
. Как это сделать с помощью Eclipse, вы уже знаете, поэтому привожу сразу код класса (листинг 11.8).
Листинг 11.8. Код класса MyReceiver (файл MyReceiver.java) package com.samples.my_receiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent;
// Класс MyReceiver является расширением класса BroadcastReceiver public class MyReceiver extends BroadcastReceiver {
// Переопределяем метод onReceive()
@Override public void onReceive(Context rcvContext, Intent rcvIntent) {
String action = rcvIntent.getAction();

212
Часть III. Профессиональное программирование
// Если действие = Intent.ACTION_CAMERA_BUTTON if (action.equals(Intent.ACTION_CAMERA_BUTTON)) {
// то запускаем сервис MyService rcvContext.startService(new Intent(rcvContext,
MyService.class));
}
}
}
Приемник анализирует полученное действие: если нажата кнопка камеры, то будет запущен сервис (служба)
MyService
, описанный в файле
MyService.java
. Код этого файла представлен в листинге 11.6. Вам нужно изменить только первую строчку — она должна выглядеть так: package com.samples.my_receiver;
В этой главе мы рассмотрели создание потоков, служб и широковещательных при- емников. А в следующей поговорим о создании анимации в Android-приложениях.



ГЛ А В А
12

Создание анимации
12.1. Анимация преобразований
В Android используются два подхода к созданию анимации: кадровая анимация
(Frame Animation) и анимация преобразований (Tween Animation). Сначала мы рас- смотрим анимацию преобразований, а затем — кадровую анимацию.
Анимация преобразований выполняется путем выполнения над изображением ряда преобразований: вращения, добавления прозрачности, изменения размера и т. д.
В пакете android.view.animationpackages находятся все необходимые для выполне- ния преобразований классы:
AnimationSet
(XML-элемент

) — представляет группу анимаций, которые запускаются вместе;
AlphaAnimation
(XML-элемент

) — управляет прозрачностью объекта;
RotateAnimation
(XML-элемент

) — управляет вращением объекта;
ScaleAnimation
(XML-элемент

) — управляет масштабированием (изме- нением размера) объекта;
TranslateAnimation
(XML-элемент

) — управляет позиционировани- ем объекта.
Анимацию преобразования можно создать как в XML-файле, так и в программном коде. Начнем с XML-файла. Файл анимации помещают в каталог res/anim
. В этом файле имеется единственный корневой элемент. Таким элементом может быть один из элементов преобразования:

,

,

,

или

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

преобразования выполняются одновременно.
Чтобы они выполнялись последовательно (в порядке описания в XML-файле), нужно использовать атрибут startOffset
, задающий задержку между выполнением преобразований в миллисекундах: android:startOffset="1000"


214
Часть III. Профессиональное программирование
У всех элементов преобразований есть общие атрибуты, описанные в табл. 12.1.
Таблица 12.1. Общие атрибуты элементов преобразований
Атрибут Описание duration
Продолжительность преобразования в миллисекундах startOffset
Время смещения перед выполнением заданного эффекта, в миллисекундах.
Можно использовать для задержки между преобразованиями fillBefore
Если равен true, преобразование анимации выполняется перед началом анимации fillAfter
Если равен true, преобразование выполняется после завершения анимации repeatCount
Определяет количество повторений анимации repeatMode
Позволяет задать режим повтора: 1 — анимация начинается заново с самого начала, 2 — анимация будет произведена в обратном порядке zAdjustment
Смещение по оси Z: 0 (обычное смещение, без изменений); 1 (вершина);
–1 (основание) interpolator
Позволяет указать интерполятор анимации. Имя интерполятора указывается в формате @[+][package:]type:name. Пример: android:interpolator="@android:anim/decelerate_interpolator

Теперь рассмотрим собственные атрибуты элементов преобразования.
У элемента

есть атрибут shareInterpolator
. Если он равен true
, то интер- полятор, заданный атрибутом interpolator для

, будет использоваться для всех дочерних элементов преобразования, входящих в этот элемент


У элемента

есть атрибуты fromAlpha и toAlpha
. Первый задает начальное значение прозрачности объекта, второй — конечное. Значения прозрачности на- ходятся в диапазоне от 0 до 1, где 0 — полная прозрачность объекта (объект почти невидим).
У элемента

, создающего вертикальную или горизонтальную анима- цию, атрибутов больше:
• fromXDelta
— начальное положение по оси X;
• toXDelta
— конечное положение по оси X;
• fromYDelta
— начальное положение по оси Y;
• toYDelta
— конечное положение по оси Y.
Атрибуты могут принимать либо абсолютное значение, либо значение в процен- тах: от –100 до 100 %. Можно также указывать процент относительно родителя: от
–100%p до
100%p

Элемент rotate служит для анимации вращения и поддерживает атрибуты:
• fromDegrees
— начальный угол вращения в градусах;
• toDegrees
— конечный угол вращения в градусах;

Глава 12. Создание анимации
215
• pivotX
— задает координату X центра вращения в пикселах;
• pivotY
— задает координату Y центра вращения в пикселах.
Элемент

управляет изменением размера объекта. Вы можете использо- вать следующие атрибуты:
• fromXScale
— начальный масштаб по оси X;
• toXScale
— конечный масштаб по оси X;
• fromYScale
— начальный масштаб по оси Y;
• toYScale
— конечный масштаб по оси Y;
• pivotX
— координата (X) закрепленного центра;
• pivotY
— координата (Y) закрепленного центра.
Вернемся к практике. Первым делом нужно создать XML-файл анимации в катало- ге res/anim
. В листинге 12.1 приведен простой файл анимации, содержащий только элемент

внутри элемента

. В листинге 12.2 приведена более сложная анимация, т. к. задано два анимационных эффекта.
Листинг 12.1. Файл res/anim/alpha.xml



Листинг 12.2. Файл res/anim/advanced.xml





216
Часть III. Профессиональное программирование
Теперь займемся Java-кодом. Первым делом нужно подключить необходимые па- кеты. Далее — загрузить картинку, над которой будет производиться анимация.
Затем загрузить саму анимацию. Это можно сделать методом loadAnimation()
из
AnimationUtils
. После чего запустить анимацию методом startAnimation()
. Весь этот процесс описан в листинге 12.3.
Листинг 12.3. Создание анимации
// Подключаем необходимые пакеты import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Animation.AnimationListener;
// Загружаем картинку
ImageView image = (ImageView)findViewById(R.id.image);
// Загружаем анимацию из файла alpha.xml
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
// Запускаем анимацию image.startAnimation(animation);
Как видите, ничего сложного в анимации преобразования нет. Необходимо только подобрать нужный эффект (или группу эффектов).
12.2. Традиционная кадровая анимация
Традиционная кадровая анимация представляет собой последовательную смену различных изображений — подобно киноленте. Основой для этого типа анимации является класс
AnimationDrawable
Как и в случае с анимацией преобразований, начнем создавать анимацию с XML- файла, который, как обычно, нужно поместить в каталог res/anim
. В листинге 12.4 приведен пример такого файла.
Листинг 12.4. Файл res/anim/frames.xml







У нас есть пять кадров (
@drawable/frame1

@drawable/frame5
), длительность ото- бражения каждого кадра — 100 мс. Если параметр android:oneshot установлен в

Глава 12. Создание анимации
217 false
, то анимация будет циклической. Если же этот параметр принимает значение true
, то анимация отобразится только один раз, а после остановки будет показан последний кадр.
Код запуска анимации несложен:
// Находим область ImageView
ImageView image = (ImageView)findViewById(R.id.image);
// Загружаем анимацию из файла frames.xml image.setBackgroundResource(R.anim.frames);
AnimationDrawable myAnim = (AnimationDrawable)image.getBackground();
Запустить и остановить анимацию можно методами start()
и stop()
: myAnim.start(); myAnim.stop();
В листинге 12.5 приведен более полный код запуска анимации.
Листинг 12.5. Запуск кадровой анимации
// Подключаем необходимый пакет import android.graphics.drawable.AnimationDrawable;
// Находим область ImageView
ImageView image = (ImageView)findViewById(R.id.image);
// Загружаем анимацию из файла frames.xml image.setBackgroundResource(R.anim.frames);
AnimationDrawable myAnim = (AnimationDrawable)image.getBackground();
// Запускаем анимацию myAnim.start();
В случае с кадровой анимацией можно обойтись и без XML-файла. Сначала нужно заполучить кадры, которые мы будем использовать для анимации (файлы frame1.png
— frame5.png
):
BitmapDrawabie frame1 =
(BitmapDrawable)getResources().getDrawable(R.drawable.frame1);
BitmapDrawabie frame5 =
(BitmapDrawable)getResources().getDrawable(R.drawable.frame5);
Затем создать объект класса
AnimationDrawable
. Атрибут oneshot устанавливается методом setOneShot()
этого класса, а добавить кадры можно методом addFrame()
:
AnimationDrawable myAnim = new AnimationDrawable(); myAnim.setOneShot(false); myAnim.addFrame(frame1, 100); myAnim.addFrame(frame5, 100);

218
Часть III. Профессиональное программирование
Далее порядок действий тот же. Нужно установить анимацию в качестве фона для объекта класса
ImageView
(объект image
), сделать объект
AnimationDrawable види- мым и запустить анимацию: image.setBackgroundDrawable(MyAnim);
MyAnim.setVisible(true, true);
MyAnim.start();
Какой из способов выбрать — решать вам. XML-файлы удобно использовать для постоянной анимации (кадры которой не изменяются), а вот формирование кадров через метод addFrame()
полезно, когда производится загрузка файлов из внешнего источника, — например, из SD-карты устройства.



ГЛ А В А
13

База данных SQLite
13.1. Несколько слов о базах данных
В этой книге мы рассмотрели почти все основные способы хранения данных на
Android-устройстве. Осталось описать базы данных, которые используются для хранения более сложных структур данных.
Мы не станем изучать основы баз данных или основы языка запросов SQL. Пред- полагается, что вы уже знакомы с этими азами. Если это не так, то на полках книж- ного магазина, я уверен, вы найдете много книг, способных заполнить этот пробел в ваших знаниях.
В ОС Android используется система управления базами данных SQLite. Да, воз- можности SQLite относительно скромны. Но ведь Oracle в мобильном устройстве и не нужен. Зато SQLite на сегодняшний день — самая быстрая СУБД для неслож- ных запросов.
На Android-устройстве база данных хранится в каталоге
/data/data/<имя паке- та>/databases
. С помощью контент-провайдера несколько приложений могут ис- пользовать одну и ту же базу данных.
Основные этапы при работе с базой данных следующие:
1. Создание и открытие базы данных.
2. Создание таблицы.
3. Создание Insert-интерфейса (служит для вставки данных).
4. Создание Query-интерфейса (используется для выполнения запроса, обычно для выборки данных).
5. Закрытие базы данных.
Далее на примере создания приложения-блокнота будут продемонстрированы ос- новные приемы при работе с базой данных: вставка, удаление и выборка записей.
Наше простое приложение позволяет пользователю добавлять, удалять и просмат- ривать небольшие текстовые записи — заметки.


220
Часть III. Профессиональное программирование
13.2. Класс SQLiteOpenHelper
Класс
SQLiteOpenHelper управляет созданием базы данных. Мы создадим класс
MyDataHelper
, который является расширением класса android.database.sqlite.
SQLiteOpenHelper
. Задача нашего класса — подготовить базу данных mydatabase.db и создать таблицу table1
, которая будет хранить записи нашего блокнота.
Имя базы данных и таблицы задаются переменными: private static final String DATABASE_NAME = "mydatabase.db"; private static final String TABLE_NAME = "table1";
Структура нашей таблицы будет следующей:
CREATE TABLE table1 ( id INTEGER PRIMARY KEY, name TEXT
)
Таблица создается в методе onCreate()
: db.execSQL("CREATE TABLE " + TABLE_NAME + "(id INTEGER PRIMARY KEY, name
TEXT)");
Метод onUpgrade()
задает действие при обновлении таблицы. Мы сначала удаляем существующую таблицу, а потом создаем ее заново: db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db);
За выборку всех записей отвечает метод selectAll()
. Мы сначала с помощью мето- да query()
отправляем SQL-запрос, а затем читаем результат и возвращаем его в виде списка: public List selectAll() {
List list = new ArrayList();
Cursor cursor = this.db.query(TABLE_NAME, new String[] { "name" }, null, null, null, null, "name desc"); if (cursor.moveToFirst()) { do { list.add(cursor.getString(0));
} while (cursor.moveToNext());
} if (cursor != null && !cursor.isClosed()) { cursor.close();
} return list;
}
Полный код класса
MyDataHelper приведен в листинге 13.1.

Глава 13. База данных SQLite
221
Листинг 13.1. Код класса MyDataHelper (файл MyDataHelper.java) package com.samples.android_db; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteStatement; import java.util.ArrayList; import java.util.List; public class MyDataHelper {
// Имя базы данных private static final String DATABASE_NAME = "mydatabase.db"; private static final String TABLE_NAME = "table1"; private static final int DATABASE_VERSION = 1; private Context context; private SQLiteDatabase db; private static final String INSERT = "insert into "
+ TABLE_NAME + "(name) values (?)"; private SQLiteStatement insertStmt; public DataHelper(Context context) { this.context = context;
OpenHelper openHelper = new OpenHelper(this.context); this.db = openHelper.getWritableDatabase(); this.insertStmt = this.db.compileStatement(INSERT);
}
// Действие при вставке записи public long insert(String name) { this.insertStmt.bindString(1, name); return this.insertStmt.executeInsert();
} public void deleteAll() {
// Удаляем все записи в таблице this.db.delete(TABLE_NAME, null, null);
} public List selectAll() {
List list = new ArrayList();
Cursor cursor = this.db.query(TABLE_NAME, new String[] { "name" }, null, null, null, null, "name desc");

222
Часть III. Профессиональное программирование if (cursor.moveToFirst()) { do { list.add(cursor.getString(0));
} while (cursor.moveToNext());
} if (cursor != null && !cursor.isClosed()) { cursor.close();
} return list;
} private static class OpenHelper extends SQLiteOpenHelper {
OpenHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override public void onCreate(SQLiteDatabase db) {
// Запрос создания таблицы db.execSQL("CREATE TABLE " + TABLE_NAME + "(id INTEGER PRIMARY KEY, name TEXT)");
}
@Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// Запрос удаления таблицы db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME); onCreate(db);
}
}
}

13.3. Разработка блокнота
Итак, каркас для нашего приложения создан. Теперь можно приступить к созданию самого приложения. Наше приложение будет хранить небольшие текстовые замет- ки. При запуске приложения заметки будут отображены в основной деятельности приложения, у пользователя будет возможность добавить новую заметку и удалить все заметки из таблицы.
Разработку приложения начнем с файла разметки, код которого представлен в лис- тинге 13.2.

Глава 13. База данных SQLite
223
Листинг 13.2. Файл разметки /res/layout/main





224
Часть III. Профессиональное программирование
Основной код приложения, устанавливающий реакции на нажатия кнопок, пред- ставлен в листинге 13.3. Код снабжен подробными комментариями, поэтому, преж- де чем перейти к практике, внимательно прочитайте этот листинг.
Листинг 13.3. Файл android_db.java (основной файл кода приложения) package com.samples.android_db; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import java.util.List; import com.samples.android_db.R; public class Main extends Activity {
// Наш класс MyDataHelper private MyDataHelper dh;

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
// Находим кнопки и устанавливаем обработчики
Button ButDel = (Button) findViewById(R.id.DeleteAll);
Button ButRef = (Button) findViewById(R.id.Refresh);
Button ButIns = (Button) findViewById(R.id.Insert);
ButDel.setOnClickListener(delete_all_action);
ButRef.setOnClickListener(refresh_action);
ButIns.setOnClickListener(insert_action);
// Находим текстовую область
TextView Rc = (TextView) findViewById(R.id.Records);

dh = getDataHelper();

// В реальном приложении нужно удалить четыре следующих

// оператора (удаление всех записей и добавление трех
// тестовых записей) dh.deleteAll(); dh.insert("Заметка 1"); dh.insert("Заметка 2"); dh.insert("Заметка 3");

// Загружаем данные из таблицы в буфер sb
List names = this.dh.selectAll();
StringBuilder sb = new StringBuilder(); sb.append("Записи в таблице:\n");

Глава 13. База данных SQLite
225 for (String name : names) { sb.append(name + "\n");
}
// Устанавливаем содержимое буфера sb в качестве

// значения текстовой области
Rc.setText(sb);
}
public DataHelper getDataHelper(){
return new DataHelper(this);
}
// Обработчик нажатия кнопки Удалить все private OnClickListener delete_all_action = new OnClickListener()
{ public void onClick(View v)
{ dh
= getDataHelper();


// Удаляем все записи

dh.deleteAll();

}
};
// Действие при нажатии кнопки Обновить private OnClickListener refresh_action = new OnClickListener() { public void onClick(View v) {
dh = getDataHelper();

// Находим текстовую область

TextView Rc = (TextView) findViewById(R.id.Records);

// Выборка всех записей

List names = dh.selectAll();

StringBuilder sb = new StringBuilder();
sb.append("Записи в таблице:\n");
for (String name : names) {
sb.append(name + "\n");

}

Rc.setText(sb);
}
};
// Обработчик нажатия кнопки Вставить private OnClickListener insert_action = new OnClickListener() { public void onClick(View v) {
dh = getDataHelper();

// Находим текстовое поле

EditText memo = (EditText) findViewById(R.id.Edit);

// Получаем текст из поля и добавляем его в БД
dh.insert(memo.getText().toString());


}
};
}

226
Часть III. Профессиональное программирование
Вот теперь, когда прочитанный материал «разложен по полочкам», можно присту- пать к созданию проекта в Eclipse. Создайте файлы проекта и запустите его. Вы увидите приложение, тестовая таблица которого содержит три проверочные замет- ки (рис. 13.1).
Рис. 13.1. Приложение запущено
Рис. 13.2. Виртуальная клавиатура

Глава 13. База данных SQLite
227
Активируйте текстовое поле — появится виртуальная клавиатура (рис. 13.2). Чтобы ее скрыть, нажмите кнопку Назад на вашем устройстве (или на клавиатуре эмуля- тора). Во время ввода текста появится словарь для облегчения ввода (рис. 13.3).
Нажмите кнопку Вставить — в таблицу будет добавлена новая запись (рис. 13.4).
Рис. 13.3. Помощник при вводе
Рис. 13.4. Новая запись добавлена в таблицу


ГЛ А В А
14

Соединение с внешним миром
14.1. Отправка SMS
Для отправки SMS используется класс
SmsManager
. В ранних версиях Android этот класс был помещен в пакет android.telephony.gsm
, сейчас (начиная с версии 1.5) он находится в пакете android.telephony
Отправить SMS довольно просто. Первым делом нужно добавить в файл манифеста соответствующее разрешение:

Затем надо определить объект класса
SmsManager
— для этого используется стати- ческий метод getDefault()
. Далее следует определить получателя сообщения (его номер телефона) и текст самого сообщения: import android.telephony.SmsManager; import android.telephony.SmsMessage;
SmsManager sendSMS = SmsManager.getDefault();
String num = "номер получателя";
String msg = "My first SMS"; sendSMS.sendTextMessage(num, null, msg, null, null);
Отправляет SMS метод sendTextMessage()
. Обычно достаточно указать первый и третий его параметры. Первый параметр задает номер телефона получателя, тре- тий — текст сообщения. Второй параметр позволяет указать номер SMS-центра.
Если указано значение null
, будет использован номер SMS-центра, указанный в настройках устройства. Четвертый и пятый параметры служат для отслеживания факта отправки и доставки сообщения соответственно.
Разберемся, как использовать четвертый и пятый параметры:
// Определяем флаги отправки и доставки SMS
String SENT_SMS_FLAG = "SENT_SMS";
String DELIVER_SMS_FLAG = "DELIVER_SMS";


Глава 14. Соединение с внешним миром
229
// Создаем соответствующие действия
// Действие, связанное с отправкой SMS
Intent sent_sms = new Intent(SENT_SMS_FLAG);
// Отложенная деятельность, связанная с sent_sms
PendingIntent spin = PendingIntent.getBroadcast(this,0,sent_sms,0);
// Аналогично для доставки:
Intent deliver_sms = new Intent(DELIVER_SMS_FLAG);
PendingIntent dpin = PendingIntent.getBroadcast(this,0,deliver_sms,0);
Теперь создаем объект
BroadcastReceiver
, необходимый для получения результата.
Такой
BroadcastReceiver нужно зарегистрировать для каждого отложенного дейст- вия:
// Получаем отчет об отправке
BroadcastReceiver sentReceiver = new BroadcastReceiver(){
@Override public void onReceive(Context c, Intent in) { switch(getResultCode()){ case Activity.RESULT_OK:
// SMS отправлено, выполняем какие-то действия break; default:
// Сбой break;
}
} };
// Получаем отчет о доставке
BroadcastReceiver deliverReceiver = new BroadcastReceiver(){
@Override public void onReceive(Context c, Intent in) { switch(getResultCode()){ case Activity.RESULT_OK:
// SMS доставлено, выполняем какие-то действия break; default:
// Сбой break;
}
} };
// Регистрируем BroadcastReceiver registerReceiver(sentReceiver, new IntentFilter(SENT_SMS_FLAG)); registerReceiver(deliverReceiver, new IntentFilter(DELIVER_SMS_FLAG));
В большинстве случаев SMS не должно превышать 140 символов. Для отправки более длинных сообщений служит метод divideMessage()
, разбивающий сообщения на фрагменты, равные максимальному размеру SMS-сообщения. Отправка такого сообщения осуществляется методом sendMultipartTextMessage()
, который исполь- зуется вместо метода sendTextMessage()
. Для получения отчета о доставке (или от-

230
Часть III. Профессиональное программирование правке) нужно задействовать уже не одно отложенное событие, а массив таких со- бытий. Количество элементов в таком массиве будет равно количеству частей, на которые было разбито исходное сообщение:
ArrayList multiSMS = sendSMS.divideMessage(msg);
ArrayList sent_sms = new ArrayList
();
ArrayList deliver_sms = new ArrayList
(); for(int i=0; i< multiSMS.size(); i++){ sentIns.add(sentIn); deliverIns.add(deliverIn);
} sendSMS.sendMultipartTextMessage(num, null, multiSMS, sentIns, deliverIns);
Ранее было сказано, что максимальная длина SMS составляет 140 байтов. Обратите внимание: именно байтов, а не символов. Когда вы отправляете SMS латинскими символами, то 140 байтов означает 140 символов. Когда же вы используете в SMS- сообщении символы национальных алфавитов — например, кириллицу, то макси- мальная длина сокращается до 70 символов. Для кодирования символов нацио- нальных алфавитов используется кодировка UCS-2, где каждый символ представ- лен двумя байтами (16-ю битами), поэтому количество символов, которые можно отправить в одной SMS, сокращается до 70. Помните об этом!
14.2. Работа с браузером
Запустить браузер для отображения заданной странички можно с помощью дейст- вия
ACTION_NEW
— сделать это достаточно просто:
Intent browser = Intent(Intent.ACTION_VIEW); browser.setData(Uri.parse("http://www.dkws.org.ua")); startActivity(browser);
Но запуск браузера нам мало интересен. Подумайте сами: напишете вы приложе- ние, запускающее браузер. И какой толк от него будет? Пользователю проще на- прямую запустить браузер.
Было бы гораздо интереснее создать свой браузер на основе класса
WebView
. Класс
WebView использует для отображения веб-страниц движок WebKit (открытый дви- жок браузера) — на этом же движке построен браузер Apple Safari и некоторые другие.
В файл манифеста для использования Интернета нужно добавить разрешение:

К приложению надо подключить два пакета: import android.webkit.WebView; import android.webkit.WebSettings;

Глава 14. Соединение с внешним миром
231
Есть два способа заполучить объект класса
WebView
. Первый заключается в исполь- зовании конструктора класса
WebView
, второй — в получении этого объекта из раз- метки приложения (предварительно его нужно поместить в разметку с помощью визуального редактора разметки):
// Первый способ
WebView browser = new WebView(this);
// Второй способ
WebView browser = (WebView) findViewById(R.id.webview);
После этого можно загрузить документ: browser.loadUrl("http://www.dkws.org.ua/");
При желании можно загружать HTML-код из строки:
String html = "

Hello


Каталог: images -> files
files -> Программа духовно-нравственного развития и воспитания обучающихся на уровне среднего общего образования
files -> Реклама на сайтерегистрация
files -> Вид: детский сад. Юридический адрес
files -> Рабочая программа по предмету по выбору«Общее фортепиано» Преподавателя Клюевой Т. А принята на заседании
files -> Рабочая программа по учебной дисциплине «Информатика» для детей 5-7 лет
files -> Использование информационных технологий в доу


Поделитесь с Вашими друзьями:
1   2   3   4   5   6   7   8


База данных защищена авторским правом ©nethash.ru 2019
обратиться к администрации

войти | регистрация
    Главная страница


загрузить материал