В этом руководстве будет объяснено, помимо прочего, взаимодействие с внешним источником данных через приложение Android, которое будет использоваться при входе в веб-службу или резервном копировании данных на внешний источник.
Внешние данные могут храниться в любой из многочисленных баз данных, доступных сегодня, которые, в свою очередь, могут быть размещены в любой из доступных операционных систем. Имея это в виду, теория становится столь же важной, как и код.
Мы хотим иметь возможность отправлять информацию с одной платформы на другую совершенно отдельной платформой и наоборот. Звучит просто, но нужно преодолеть языковой барьер и не всегда существует решение. Нам нужен тип данных, с которым могут работать обе платформы, и некоторый код в середине для обработки запросов. Это API. Приведенная ниже диаграмма иллюстрирует это лучше, чем слова.
Для этого урока я буду использовать стандартный стек LAMP. Внешняя база данных будет MySQL, и я буду использовать PHP для создания API. Файл PHP будет записывать и читать в базу данных MySQL на основе запросов, полученных от приложения. Он также отправит результаты запросов обратно в приложение. Запросы и ответы будут в формате JSON, поскольку обе стороны понимают этот формат. Цель состоит в том, чтобы ввести имя человека из приложения Android и получить возраст человека из внешней базы данных. Я знаю, что это просто, но это широкая область, и это хороший способ проиллюстрировать процесс.
Также я не затрагиваю вопросы безопасности в этом уроке, я, скорее всего, расскажу об этом отдельно в дальнейшем.
Создание базы данных и таблицы MySQL
Подключитесь к своему экземпляру MySQL, как хотите, и выполните следующее.
1
2
|
create database android_remoteDB
use android_remoteDB
|
1
2
3
4
5
|
create table users(
_id int(10) primary key auto_increment,
user_name varchar(25) not null unique,
user_age int(2) not null
);
|
Вставьте тестовые данные
1
2
3
4
5
6
|
insert into users (user_name,user_age) values («green ranger»,27);
insert into users (user_name,user_age) values («red ranger»,24);
insert into users (user_name,user_age) values («blue ranger»,23);
insert into users (user_name,user_age) values («black ranger»,29);
insert into users (user_name,user_age) values («yellow ranger»,22);
insert into users(user_name,user_age) values («pink ranger»,21);
|
Создать API
В этом руководстве я буду использовать один файл PHP с именем android_api.php . Это должно быть размещено где-нибудь, где к нему можно получить доступ через HTTP-запрос. Он может находиться в каталоге www на локальной установке LAMP или WAMP или на размещенном сервере, к которому вы можете получить доступ.
Приложение отправит тег на эту страницу вместе с любыми дополнительными параметрами. API выполнит действие на основе содержимого тега. В этом базовом примере есть только один тег, один параметр и одно действие, поэтому в этом не было необходимости. Тем не менее, сделав это, вы поймете, как выполнять несколько задач из API.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
<?php
// check that the tag is present
if (isset($_POST[‘tag’]) && $_POST[‘tag’] != ») {
$tag = $_POST[‘tag’];
// Create a connection the the database and table
$error = ‘Could not connect to the database’;
//Depending on your setup you might need to change the below for your own credentials
mysql_connect(‘localhost’,’root’,») or die ($error);
mysql_select_db(‘remote_db’) or die ($error);
// check if tag = ‘getAge’
if ($tag == ‘getAge’) {
//Get name
$name = mysql_real_escape_string($_POST[‘name’]);
//Select records from the database
$find = mysql_query(«SELECT * FROM users WHERE user_name=’$name'»);
//check that records exist
if (mysql_num_rows($find)>0) {
while ($find_row = mysql_fetch_assoc($find))
{
//Get user age
$age = $find_row[‘user_age’];
}
//Return the response as a success, including age.
$response[«success»] = 1;
$response[«user»][«name»] = $name;
$response[«user»][«age»] = $age;
echo json_encode($response);
}
else {
//Return error
$response[«success»] = 0;
$response[«error»] = 1;
$response[«error_msg»] = «User could not be found»;
echo json_encode($response);
}
} else {
echo «No action for the tag»;
}
} else {
echo «Unknown error»;
}
?>
|
Создание приложения
В среде IDE создайте новый проект Android, выбрав « Файл» → «Создать» → «Проект приложения Android» . Далее назовите проект. Я пошел с RemoteDB . Начиная с этого момента, вы можете нажимать кнопку «Далее» на экранах, которые вам представлены.
Создание класса JSON
Чтобы создать новый класс, перейдите в новый проект и откройте папку src . Щелкните правой кнопкой мыши на пакете, разверните новый и выберите класс . Обязательно назовите его JSONParser .
Сам класс является довольно общим и широко используемым. Он отправляет запрос на указанный URL-адрес и преобразует ответ в формат JSON.
Затем откройте класс и вставьте следующее.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
package com.example.remotedb;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;
import android.util.Log;
public class JSONParser {
static InputStream is = null;
static JSONObject json = null;
static String outPut = «»;
// constructor
public JSONParser() {
}
public JSONObject getJSONFromUrl(String url, List<NameValuePair> params) {
// Making the HTTP request
try {
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
BufferedReader in = new BufferedReader(new InputStreamReader(
is, «iso-8859-1»), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = in.readLine()) != null) {
sb.append(line + «\n»);
}
is.close();
outPut = sb.toString();
Log.e(«JSON», outPut);
} catch (Exception e) {
Log.e(«Buffer Error», «Error converting result » + e.toString());
}
try {
json = new JSONObject(outPut);
} catch (JSONException e) {
Log.e(«JSON Parser», «Error parsing data » + e.toString());
}
// return JSON String
return json;
}
}
|
Создание файла макета
Откройте файл activity_main.xml в Res → Layout …
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
<?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=»wrap_content»
android:orientation=»vertical»
>
<!— User Name Label —>
<TextView
android:layout_width=»fill_parent»
android:layout_height=»wrap_content»
android:text=»User Name:»
android:padding=»10dip»
android:textColor=»#33B5E5″ />
<!— User Name Text Field —>
<EditText
android:id=»@+id/Enter»
android:hint=»Please Enter a Name»
android:layout_width=»fill_parent»
android:layout_height=»wrap_content» />
<!— Text View to display the returned age or a error message —>
<TextView android:id=»@+id/Results»
android:layout_width=»fill_parent»
android:layout_height=»wrap_content»
android:text=»User Age:»
android:textColor=»#99CC00″
android:padding=»10dip»
android:textStyle=»bold»/>
<!— Button to fire the getAge Method—>
<Button
android:id=»@+id/GetAge»
android:layout_width=»fill_parent»
android:layout_height=»wrap_content»
android:layout_marginTop=»10dip»
android:text=»Get Age» />
</LinearLayout>
|
Основное занятие
Теперь о основной деятельности, которая находится в Src → Packagename → MainActicity.java …
Опять же, это довольно просто. У нас есть метод getAge , который вызывается при нажатии кнопки. Он передает параметры, такие как URL и имя, в JSONParser и создает объект JSON из ответа. Затем он читается, и в текстовом окне результатов отображается либо возраст, либо сообщение об ошибке, в зависимости от того, был ли запрос успешным или нет.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
package com.example.remotedb;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
private JSONParser jsonParser;
//10.0.2.2 is the address used by the Android emulators to refer to the host address
// change this to the IP of another host if required
private static String ageURL = «http://10.0.2.2/android_api.php»;
private static String getAge = «getAge»;
private static String jsonResult = «success»;
String uname;
String age_res;
TextView Results;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Invoke the Json Parser
jsonParser = new JSONParser();
final EditText Enter = (EditText) findViewById(R.id.Enter);
Results = (TextView) findViewById(R.id.Results);
Button GetAge = (Button) findViewById(R.id.GetAge);
//Get Age Button
GetAge.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
//Get the contents of the edit text
uname = Enter.getText().toString();
//Pass the name to the JSON method and create a JSON object from the return
JSONObject json = getAge(uname);
// check the success of the JSON call
try {
if (json.getString(jsonResult) != null) {
Results.setText(«»);
String res = json.getString(jsonResult);
if(Integer.parseInt(res) == 1){
//If it’s a success create a new JSON object for the user element
JSONObject json_user = json.getJSONObject(«user»);
//Set the results text to the age from the above JSON object
Results.setText(«User Age: » + json_user.getString(«age»));
}else{
//If the user could not be found
Results.setText(«User could not be found»);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
//The below passes the tag and the user name over to the JSON parser class
public JSONObject getAge(String name){
List<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(«tag», getAge));
params.add(new BasicNameValuePair(«name», name));
JSONObject json = jsonParser.getJSONFromUrl(ageURL, params);
return json;
}
}
|
Добавить интернет-разрешение
Одним из требований приложения является разрешение android.permission.INTERNET . Это необходимо добавить в файл AndroidManifest.xml .
Линия это:
1
|
uses-permission android:name=»android.permission.INTERNET»
|
После добавления манифест должен выглядеть примерно так, как показано ниже.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<?xml version=»1.0″ encoding=»utf-8″?>
<manifest xmlns:android=»http://schemas.android.com/apk/res/android»
package=»com.example.remotedb»
android:versionCode=»1″
android:versionName=»1.0″ >
<uses-sdk
android:minSdkVersion=»8″
android:targetSdkVersion=»17″ />
<uses-permission android:name=»android.permission.INTERNET» />
<application
android:allowBackup=»true»
android:icon=»@drawable/ic_launcher»
android:label=»@string/app_name»
android:theme=»@style/AppTheme» >
<activity
android:name=»com.example.remotedb.MainActivity»
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>
</manifest>
|
Вы должны быть хороши, чтобы пойти на этом этапе. Попробуйте запустить приложение.
Вывод
Да, конечный результат крайне не впечатляет. Мы заставили номер появиться на экране. Хотя на самом деле мы сделали гораздо больше. Мы взяли информацию с одной платформы и отправили на совершенно чужую платформу. Зарубежная платформа смогла выполнить задачу на основе этой информации и извлечь информацию из базы данных, к которой исходная платформа не знала или не имела доступа к ней. Вторая платформа смогла отправить информацию обратно в оригинал, который затем смог отобразить информацию для пользователя.
Когда это звучит так, это звучит довольно круто и бесконечно полезно! Вы можете увидеть, как такие методы позволяют нескольким платформам обмениваться данными, и как можно комбинировать разные источники данных.
Простые текстовые объекты, такие как JSON, очень похожи на азбуку Морзе. Они превосходят другие языки и могут быть поняты повсеместно. Это делает их чрезвычайно полезными и универсальными. Это простые вещи, которые часто решают сложные проблемы.