Harrix Блог

  • Списки статей
    • Все статьи
    • IT
    • Qt
    • C++
    • Сложение двух чисел
    • Web программированиe
    • FAQ
    • Latex
    • Установка программ
    • Мифы
    • Видео
    • Про фото
  • Проекты
  • Harrix.org
  • RSS
  • Контакты

Сложение двух чисел в Android Studio с использованием HttpURLConnection и передачей параметров через POST (клиент-серверное приложение)

Учебный пример взаимодействия Android приложения с сервером.

05.05.2017 Leave a Comment 4 863 просмотров

Напишем приложение сложение двух чисел, где сложение двух чисел происходит на стороне сервера.

Эта статья из цикла статей Клиент-серверные приложения.

Статья из цикла «Сложение двух чисел». Для меня минимальное освоение любой системы программирования начинается с возможности создания такой программы. Если можно написать приложение, в которой пользователь может ввести два числа, считать их, провести с ними какие-то действия, а потом вывести результат, то, значит, базовое владение имеется. И много задач именно из области программирования, алгоритмики можно будет решать, зная, как в конкретной системе программирования запрограммировать такую программу.

В статье Сложение двух чисел в Android Studio (клиент-серверное приложение) приведен вариант с использованием устаревших классов. В данной статье используются классы, пришедшие на замену.

В статье показан вариант приложения для отправки GET параметров.

Содержание

  • Постановка задачи
  • Серверная часть
  • Создание Android проекта
  • XML разметка
  • Добавляем разрешения
  • Java код

Постановка задачи

В статье показан пример приложения под Android по сложению двух чисел. И там сложение двух чисел происходило в самом приложении, что логично. А в этом приложении мы из полей ввода считаем два числа и отправим их на сервер, который сложит два числа, отправит нам ответ, и мы этот ответ отобразим в текстовом поле.

На сервер поступает HTTP запрос с двумя переменными a и b. Переменные a и b передаются через POST параметры.

Серверная часть

У вас должен быть сервер, доступный из интернета, к которому можно обращаться.

В статье приведен пример серверной части на Java.

В статье приведен пример серверной части на PHP.

В статье буду использовать PHP скрипт, который я расположил по адресу http://demo.harrix.org/demo0012/ (при переходе по ссылке должно выдаваться error — и это правильно).

Создание Android проекта

Надеюсь, что вы сможете сами создать болванку приложения, так что закинул под сплойер.

XML разметка

Пусть разметка файла activity_main.xml будет такой.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:orientation="vertical" >
    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName" />
    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName" />
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

Есть два поля ввода чисел, кнопка и поле для вывода суммы чисел. Все элементы имеют свои идентификаторы android:id.

Добавляем разрешения

Приложение у нас будет обращаться в интернет. Поэтому нужно ей дать на это разрешение в AndroidMainfest.xml.

1
<uses-permission android:name="android.permission.INTERNET"/>

Java код

Был такой код файла MainActivity.java.

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.example.clientadding2numbers;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
 
public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}

Вначале объявим переменные кнопки, полей ввода и поля для вывода результата и соединим их с элементами из XML файла. Также назначим слушателя для клика кнопки.

1
2
3
4
5
6
7
8
9
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
package com.example.clientadding2numbers;
 
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
public class MainActivity extends AppCompatActivity {
 
    private TextView textView;
    private EditText editText;
    private EditText editText2;
    private Button button;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textView = (TextView)findViewById(R.id.textView);
        editText = (EditText)findViewById(R.id.editText);
        editText2 = (EditText)findViewById(R.id.editText2);
        button = (Button)findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
 
            }
        });
    }
}

Запросы к серверу по времени могут быть длительными. Поэтому обязательно делаем их в другом потоке. Для этого внутри класса MainActivity создадим класс-наследник от AsyncTask.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyAsyncTask extends AsyncTask<String, String, String> {
 
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
 
    @Override
    protected String doInBackground(String... params) {
        //Тут будет запрос к серверу
        return null;
    }
 
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
    }
}

В классе MyAsyncTask объявим переменные.

1
String a, b, answerHTTP;

А также определим переменную server, которая будет указывать на сервер, к которому мы будем осуществлять запрос. Если вы используйте свой сервер, то поменяйте значение.

1
String server = "http://demo.harrix.org/demo0012/";

В методе onPreExecute() считаем данные из полей ввода.

1
2
3
4
5
6
@Override
protected void onPreExecute() {
    a = editText.getText().toString();
    b = editText2.getText().toString();
    super.onPreExecute();
}

В методе onPostExecute() выведем ответ сервера.

1
2
3
4
5
@Override
protected void onPostExecute(String result) {
    super.onPostExecute(result);
    textView.setText(answerHTTP);
}

В методе doInBackground() будем обращаться к серверу. Мы разнесем работу этого метода на два других метода, поэтому к методу doInBackground() вернемся попозже.

Во-первых, давайте параметры, которые мы хотим закинуть в POST, будем передавать в виде HashMap. Для этого нам будет нужна функция перевода HashMap в строку нужного нам вида.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private String getDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
    StringBuilder result = new StringBuilder();
    boolean first = true;
    for (Map.Entry<String, String> entry : params.entrySet()) {
        if (first)
            first = false;
        else
            result.append("&");
 
        result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
        result.append("=");
        result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
    }
 
    return result.toString();
}

Во-вторых, обработку запроса и получение ответа тоже перенесем в отдельный метод.

1
2
3
4
5
6
7
8
9
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
public String performPostCall(String requestURL,
                              HashMap<String, String> postDataParams) {
    URL url;
    String response = "";
    try {
        url = new URL(requestURL);
 
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(15000);
        conn.setConnectTimeout(15000);
        conn.setRequestMethod("POST");
        conn.setDoInput(true);
        conn.setDoOutput(true);
 
 
        OutputStream os = conn.getOutputStream();
        BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(os, "UTF-8"));
        writer.write(getPostDataString(postDataParams));
 
        writer.flush();
        writer.close();
        os.close();
        int responseCode = conn.getResponseCode();
 
        if (responseCode == HttpsURLConnection.HTTP_OK) {
            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            while ((line = br.readLine()) != null) {
                response += line;
            }
        } else {
            response = "";
 
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
 
    return response;
}

Тогда в методе doInBackground() будет достаточно составить HashMap с нужными параметрами, а потом вызвать performPostCall().

1
2
3
4
5
6
7
8
9
@Override
protected String doInBackground(String... params) {
    HashMap<String, String> postDataParams = new HashMap<String, String>();
    postDataParams.put("a", a);
    postDataParams.put("b", b);
    answerHTTP = performPostCall(server, postDataParams);
 
    return null;
}

В итоге получим такой код.

1
2
3
4
5
6
7
8
9
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package com.example.clientadding2numbers;
 
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
 
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
 
import javax.net.ssl.HttpsURLConnection;
 
public class MainActivity extends AppCompatActivity {
 
    private TextView textView;
    private EditText editText;
    private EditText editText2;
    private Button button;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textView = (TextView) findViewById(R.id.textView);
        editText = (EditText) findViewById(R.id.editText);
        editText2 = (EditText) findViewById(R.id.editText2);
        button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new MyAsyncTask().execute();
            }
        });
    }
 
    class MyAsyncTask extends AsyncTask<String, String, String> {
 
        String a, b, answerHTTP;
 
        String server = "http://demo.harrix.org/demo0012/";
 
        @Override
        protected void onPreExecute() {
            a = editText.getText().toString();
            b = editText2.getText().toString();
            super.onPreExecute();
        }
 
        @Override
        protected String doInBackground(String... params) {
            HashMap<String, String> postDataParams = new HashMap<String, String>();
            postDataParams.put("a", a);
            postDataParams.put("b", b);
            answerHTTP = performPostCall(server, postDataParams);
 
            return null;
        }
 
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            textView.setText(answerHTTP);
        }
    }
 
    public String performPostCall(String requestURL,
                                  HashMap<String, String> postDataParams) {
        URL url;
        String response = "";
        try {
            url = new URL(requestURL);
 
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);
 
 
            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));
 
            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();
 
            if (responseCode == HttpsURLConnection.HTTP_OK) {
                String line;
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                while ((line = br.readLine()) != null) {
                    response += line;
                }
            } else {
                response = "";
 
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        return response;
    }
 
    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");
 
            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }
 
        return result.toString();
    }
}

Всё. Можете запускать приложение и проверять работу.


Статьи по теме:

  1. Сложение двух чисел в Android Studio с использованием HttpURLConnection (клиент-серверное приложение)
  2. Сложение двух чисел в Android Studio с передачей параметров через POST (клиент-серверное приложение)
  3. Сложение двух чисел в Android Studio (клиент-серверное приложение)
  4. Сложение двух чисел в Android Studio с использованием Retrofit (клиент-серверное приложение)

Web программирование Andoid Studio, Java, Клиент-сервер, Программа сложения двух чисел, Сервер

© 2014 Harrix