Как отправить HttpPost запрос в Андроид 4.4 и выше используя HttpURLConnection

Ответить
Аватара пользователя
admin
Администратор
Сообщения: 25
Зарегистрирован: 11 май 2020, 12:32

Как отправить HttpPost запрос в Андроид 4.4 и выше используя HttpURLConnection

Сообщение admin »

Чтобы отправить POST-запрос в андроид я сделал отдельный класс для упрощения самого запроса. Передача происходит используя класс HttpURLConnection.
Работает от андроид 4.4 (19) и выше.
Исходные файлы:

Файл MainActivity.java:

Код: Выделить всё

package ua.in.starcity.myhttpurlconnect;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

import java.util.HashMap;
import java.util.Objects;

public class MainActivity extends AppCompatActivity {

    private final Context context = MainActivity.this;
    MyHttpURLConnect myhp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        myhp = new MyHttpURLConnect(context);
        myhp.add("param1", "111");
        myhp.add("param2", "222");
        myhp.showdialog(true);
        new MyReqTask().execute("actiontest1");

    }

    private void MyReturn(HashMap<String, String> hmret) {
        String queryjson = hmret.get("query");
        String function = hmret.get("function");
        if (queryjson == null)
            Toast.makeText(MainActivity.this, getResources().getText(R.string.errorotvet), Toast.LENGTH_SHORT).show();
        else {
            switch (Objects.requireNonNull(function)) {
                case "actiontest1":
                    Toast.makeText(MainActivity.this, "actiontest1" + queryjson, Toast.LENGTH_SHORT).show();
                    break;
                case "actiontest2":
                    Toast.makeText(MainActivity.this, "actiontest2" + queryjson, Toast.LENGTH_SHORT).show();
                    break;
                default:
                    Toast.makeText(getApplicationContext(), getResources().getText(R.string.errorfunction1) + function + getResources().getText(R.string.errorfunction2) + queryjson, Toast.LENGTH_LONG).show();
                    break;
            }
        }
    }

    @SuppressLint("StaticFieldLeak")
    class MyReqTask extends AsyncTask<String, String, HashMap<String, String>> {
        protected HashMap<String, String> doInBackground(String... params) {
            HashMap<String, String> hmans = new HashMap<>();
            hmans.put("function", params[0]);
            hmans.put("query", myhp.query());
            return hmans;
        }

        protected void onPostExecute(HashMap<String, String> result) {
            super.onPostExecute(result);
            myhp.MyDialogStop();
            MyReturn(result);
        }

        protected void onPreExecute() {
            super.onPreExecute();
            myhp.MyDialogStart();
        }
    }

}
Файл MyHttpURLConnect.java:

Код: Выделить всё

package ua.in.starcity.myhttpurlconnect;

import android.app.ProgressDialog;
import android.content.Context;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class MyHttpURLConnect {
    private final Context context;
    private ProgressDialog dialog;
    private String params;
    private boolean showdialog = false;

    MyHttpURLConnect(Context context) {
        this.context = context;
    }

    void add(String name, String value) {
        params += "&" + name + "=" + value;
    }

    String query() {
        String myURL = context.getString(R.string.urlpost);
        byte[] data;
        InputStream is;
        String result = null;
        try {
            URL url = new URL(myURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestProperty("User-Agent", context.getString(R.string.useragent));
            conn.setRequestProperty("Content-Length", "" + params.getBytes().length);
            OutputStream os = conn.getOutputStream();
            data = params.getBytes(StandardCharsets.UTF_8);
            os.write(data);
            conn.connect();
            int responseCode = conn.getResponseCode();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            if (responseCode == 200) {
                is = conn.getInputStream();
                byte[] buffer = new byte[8192];
                int bytesRead;
                while ((bytesRead = is.read(buffer)) != -1)
                    baos.write(buffer, 0, bytesRead);
                data = baos.toByteArray();
                result = new String(data, StandardCharsets.UTF_8);
            } else
                return null;
        } catch (Exception ignored) {
        }
        return result;
    }

    void MyDialogStart() {
        if (showdialog) {
            dialog = new ProgressDialog(context);
            dialog.setMessage(context.getString(R.string.dowloadtext));
            dialog.setIndeterminate(true);
            dialog.setCancelable(true);
            dialog.show();
        }
    }

    void MyDialogStop() {
        if (showdialog)
            dialog.dismiss();
    }

    void showdialog(boolean b) {
        showdialog = b;
    }

}
Файл build.gradle (app):

Код: Выделить всё

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "ua.in.starcity.myhttpurlconnect"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
    }
}

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.13.1'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
Файл AndroidManifest.xml:

Код: Выделить всё

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="ua.in.starcity.myhttpurlconnect">

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

    <application
        android:allowBackup="true"
        android:fullBackupContent="@xml/backup_descriptor"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Myhttpurlconnect">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Файл activity_main.xml:

Код: Выделить всё

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Файл strings.xml:

Код: Выделить всё

<resources>
    <string name="app_name">MyHttpURLConnect</string>
    <string name="urlpost">https://www.starcity.in.ua/myhttpurlconnect.php</string>
    <string name="useragent">My user agent android</string>
    <string name="dowloadtext">Загружаю данные…</string>
    <string name="errorotvet">Ошибка сервера!</string>
    <string name="errorfunction1">Ошибка!\nФункция &lt;</string>
    <string name="errorfunction2">> не определена!\nОтвет сервера:\n</string>
</resources>
Файл myhttpurlconnect.php на сервере, к которому мы будем обращаться и получать ответ:

Код: Выделить всё

<?php
$ret=array();
$ret["my_p1"]=$_POST["param1"];
$ret["my_p2"]=$_POST["param2"];
$ret["my_http_user_agent"]=$_SERVER["HTTP_USER_AGENT"];
echo json_encode($ret);
?>
Суть процесса такова:
  1. В файл strings.xml записываем свой url, который будет обрабатывать наш POST-запрос.
    Если вы используете защищенное шифрование, то адрес обязательно должен содержать www

    Код: Выделить всё

        <string name="urlpost">https://www.starcity.in.ua/myhttpurlconnect.php</string>
    ну и добавляем еще несколько дополнительных переменных используемых в проетке.
  2. В MyHttpURLConnect.java переменная showdialog отвечает за показывание процесса загрузки во время запроса на сервер. Ей можно установить по умолчанию на true или false, но потом в процессе можно для каждого запроса изменять.
  3. В каждом активити создаем и не забываем изменять переменную context своего активити на свой класс, где она применяется, в данном случае это MainActivity.

    Код: Выделить всё

        private final Context context = MainActivity.this;
  4. Объявляем нашу переменную запроса:

    Код: Выделить всё

        MyHttpURLConnect myhp;
  5. Создаем наш POST-запрос:

    Код: Выделить всё

            myhp = new MyHttpURLConnect(context);
  6. Передаем POST-переменные и их значения, их может быть сколько угодно. К примеру:

    Код: Выделить всё

            myhp.add("param1", "111");
            myhp.add("param2", "222");
  7. Если необходимо изменить ход отображения процесса ожидания, то объявляем здесь или же можно вообще ничего не прописывать, тогда будет по умолчанию:

    Код: Выделить всё

            myhp.showdialog(true);
  8. Отправляем запрос и прописываем название функции, которая будет обрабатывать ответ от сервера:

    Код: Выделить всё

            new MyReqTask().execute("actiontest1");
  9. Метод MyReturn запускается сразу же после того как придет ответ от сервера и в нем запускается функция, название которой мы указали в предыдущем пункте.
    Ответ передается в переменную queryjson, далее собственно проделываем все необходимые нам операции в соответствующей функции.
  10. Кстати здесь можно передавать значение useragent, к примеру для браузера Google Chrome в Линукс по умолчанию это: Mozilla\/5.0 (X11; Linux x86_64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/87.0.4280.88 Safari\/537.36, но в данном примере мы его изменили вообще на любую свою фразу.

Ответить