LXF160:Android-программирование
|
|
|
[[Категория:Android]
» Программирование. С базами данных Android умеет работать и в облаках
Содержание |
Android:Базы данных в облаке
Джульетта Кемп показывает, как подключиться к облаку и заставить свое приложение взаимодействовать с сервером.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
В прошлом месяце мы работали с локальной базой данных Android. Ну, а если нужно связаться с удаленной базой данных? Есть несколько способов это сделать, но на нашем уроке мы рассмотрим вариант, при котором для общения с базой данных используются HTTP-запросы – это, пожалуй, самый простой способ. Этот вариант также является расширяемым: мы получаем информацию из базы данных, но с помощью тех же методов и API можно получить все, что готов предоставить web-сервер. Мы будем обрабатывать данные с помощью JSON и посмотрим, как делать это в фоне, чтобы основное приложение не зависало при ожидании подключения от сервера.
Этот код основан на коде для работы с локальной базой данных из предыдущей статьи; если вы ее не читали, возьмите полный код приложения с нашего диска.
Базовый запрос HTTP
Прежде чем начать писать код HTTP-запроса, приложению нужно предоставить права доступа к сети. Добавьте в манифест строку
<uses-permission android:name=”android.permission.INTERNET” />
Для выполнения HTTP-запроса существует два варианта API: HTTPClient и HttpURLConnection. Начиная с Android 2.3, Google советует использовать HttpURLConnection, но на практике многие еще предпочитают HTTPClient, и с ним легче получить советы или помощь. Чтобы продемонстрировать оба класса в действии, я воспользуюсь HTTPClient для написания простого метода получения данных с сервера, а HttpURLConnection — для простого метода отправки данных на сервер.
Разбор JSON
Для отправки данных туда и обратно вам понадобится формат хранения данных, который смогут понять и телефон, и web-сервер. Хороший вариант, которым мы здесь и воспользуемся – JSON, сокращение от “JavaScript Object Notation [Формат описания объектов JavaScript]”. Это легкий формат обмена данными, который понятен и для чтения/записи человеку, и для разбора/генерации компьютеру. Существует множество других форматов обмена данными, но JSON – хороший базовый формат для строковых данных, которые и хранятся в нашей базе.
Один JSONObject будет напоминать описание одного из заданий из таблицы заданий приложения ToDo:
{“_id”:1,”task”:”test task”, “duedate”:”2011-12-24”, “createdate”:1324660453756, “category_link”:2}
Прежде чем вступать во взаимодействие с настоящим сервером MySQL, рассмотрим простой пример на PHP, который воспроизводит эту строку вручную:
<?php
$output=array(
“_id” => 1,
“category” => ‘work’
); print(json_encode($output));
?>
Сохраните этот код на сервере в файле test.php, и теперь он готов ответить на запрос вашего телефона. Затем создайте новый класс Android в своем проекте RemoteTodoSync.java:
public class RemoteTodoSync extends Activity {
public static final String WEBADDRESS = “http://yourserver/test.php”;
private static final String TAG = “RemoteTodoSync”;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
retrieveData();
Intent i = new Intent();
setResult(RESULT_OK, i);
finish();
}
}
Добавьте его в AndroidManifest.xml, затем добавьте такие строки в ToDo.java для вызова Действия и обработки результата:
public void onCreate(Bundle savedInstanceState) {
...
startActivityForResult(new Intent(this.getBaseContext(),
RemoteTodoSync.class), SERVER_UPDATE_ID);
...
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent i) {
super.onActivityResult(requestCode, resultCode, i);
switch (requestCode) {
case SERVER_UPDATE_ID:
populateList();
default:
// do nothing; no other result expected
}
}
Метод retrieveData() класса RemoteTodoSync получит нашу тестовую строку (представляющую объект JSONObject) из файла test.php:
private void retrieveData() {
InputStream is = null;
try {
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(WEBADDRESS);
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
} catch (IOException e) {
Log.e(TAG, “IOException “ + e.toString());
e.printStackTrace();
}
try {
BufferedReader reader = new BufferedReader
(new InputStreamReader(is, “iso-8859-1”), 8);
String line = null;
while ((line = reader.readLine()) != null) {
JSONObject jo = new JSONObject(line);
Log.v(TAG, “id is: “ + jo.getInt(TodoDatabaseProvider.ID));
Log.v(TAG, “task is: “ + jo.getString(TodoDatabaseProvider.TASK));
}
is.close();
} catch (Exception e) {
Log.e(TAG, “Exception: “ + e.toString());
e.printStackTrace();
}
}
В первом блоке try создается HttpClient, отправляется запрос на URL, заданный в WEBADDRESS, и результат этого запроса сохраняется в InputStream. Во втором блоке производится разбор этого результата; сейчас результат просто выводится в лог-файл без дополнительных действий.
Посмотрев на код, вы увидите, что на самом деле считывается строка (String), которая затем вновь превращается в JSONObject. Так ее проще разобрать, поскольку можно воспользоваться методами разбора JSONObject, а не заниматься этим вручную. Как иллюстрируют приведенные здесь примеры получения целых чисел и строк, методами getX() из объекта JSONObject можно получить значения любых типов.
InputStreamReader преобразует байты входного потока (is) в символы с помощью преобразователя символов. BufferedReader буферизует результат в группах по восемь символов. С помощью этого примера можно посмотреть, что происходит (и убедиться, что все классы инициализированы правильно). Однако данные, полученные от настоящего сервера MySQL, будут представлены в виде JSONArray, который требует несколько большего разбора и выглядит так (квадратные скобки ограничивают массив):
[{“_id”:1,”task”:”test task”, “duedate”:”2011-12-24”, “createdate”:1324660453756, “category_link”:2}
{“_id”:2,”task”:”new work task”, “duedate”:”2011-12-31”, “createdate”:1324661242417, “category_link”:1}]
Вот простой пример PHP-кода для запуска на web-сервере (обратите внимание, здесь подразумевается, что база MySQL уже создана и заполнена данными, иначе никаких данных из запроса вы не получите):
<?php mysql_connect(“host”, “user”, “password”); mysql_select_db(“todo”);
$output;
$q = mysql_query(“select * from tasks”); while($e = mysql_fetch_assoc($q)) {
$output[] = $e;
} print(json_encode($output)); mysql_close();
?>
Новый улучшенный вариант разбора JSON выглядит так (первый блок try HttpClient остался без изменений):
try {
BufferedReader reader = new BufferedReader
(new InputStreamReader(is, “iso-8859-1”), 8);
String line = null;
while ((line = reader.readLine()) != null) {
JSONArray resultArray = new JSONArray(line);
for (int i = 0; i < resultArray.length(); i++) {
JSONObject jo = (JSONObject) resultArray.get(i);
Log.v(TAG, “id is: “ + jo.getInt(TodoDatabaseProvider.ID);
Log.v(TAG, “task is: “ + jo.getString(TodoDatabaseProvider.TASK));
}
}
is.close();
}
Сервер вернет одну строку для всего массива (хотя если он вернет несколько строк, наш код сумеет справиться с их обработкой), которую мы разбираем сначала в отдельные объекты JSONObject, а затем в необходимые компоненты. Опять же, возвращается строка, которая преобразуется в JSONArray – это упрощает разбор.
Работа с полученными данными
Конечно, в том чтобы просто вывести данные в лог-файл, проку мало. Нам нужна какая-то форма синхронизации с базой данных Android. На этом уроке я не буду говорить о синхронизации (это довольно сложная тема – логика ее работы и проблемы, которые нужно обсудить, заняли бы большую часть статьи). Вместо этого мы выполним простую проверку на дубликаты и затем скопируем данные с сервера на устройство Android. В следующем разделе мы займемся отправкой данных с устройства Android на сервер, но по тем же причинам экономии места и внимания мы не будем касаться серверного кода, необходимого для их сброса в MySQL на стороне сервера.
При изменении кода локальной базы данных для работы с сервером метод retrieveData() во многом останется прежним. Однако JSONArray todoDataFromServer станет переменной класса, и мы не будем разбирать ее в компоненты JSONObject. Вместо этого мы добавим вызов addTodosFromServer() в onCreate() после вызова retrieveData(). Это большой фрагмент кода, и мы поместили его на DVD в Листинге 1.
addTodosFromServer() просто перебирает объекты JSONObject, возвращенные сервером в массиве JSONArray, проверяет, есть ли объект в локальной базе данных, методом checkIfTaskExists() и добавляет его в базу данных, если его там нет.
checkIfTaskExists() получает строку «задания» из JSONObject и выполняет SQL-запрос, который ищет это значение в локальной базе данных. Если запрос не возвращает результатов, задания не существует локально, и его нужно добавить.
Наконец, метод insertTask() добавляет новую строку в базу данных, получает новые значений из JSONObject и затем обновляет новый URI этими значениями. Используемые здесь методы insert() и update() рассматривались в предыдущей статье (если вы ее пропустили, их код можно найти на DVD).