Почему я не могу отправить JSON с Android с помощью этого кода?

Я хочу отправить JSON с Android на сервер с помощью HTTP (POST).

Но остановитесь на следующей строке:

OutputStreamWriter out = new OutputStreamWriter(con.getOutputStream());

Я использую поток для HTTP и добавил следующий манифест:

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

Но результаты не изменились.

public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();
    private String PostUrl = "http://localhost:3000";
    private String JSON = "{\"test\":\"100\"}";

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

    public void callPost()  {

        handler.post(new Runnable() {
            @Override
            public void run() {

                HttpURLConnection con = null;

                try{
                    URL url = new URL(PostUrl);
                    con = (HttpURLConnection) url.openConnection();
                    con.setRequestMethod("POST");
                    con.setDoOutput(true);
                    con.setRequestProperty("Content-Type","application/JSON; charset=utf-8");

                    Log.d("debug", "----- All right here -----");
                    OutputStreamWriter out = new 
OutputStreamWriter(con.getOutputStream());
                    Log.d("debug", "----- This message is not displayed -----");
                    out.write(JSON);
                    out.flush();
                    con.connect();

                } catch (Exception e){
                }
            }
        });
    }
}

Ошибки нет, а отображается только "----- All right here -----".

localhost:3000 указывает на текущее устройство, если явно не изменено, чтобы указать на удаленный хост. А для просмотра трассировки стека используйте e.printStackTrace();
Madhan Varadhodiyil 13.06.2019 17:01

Спасибо за ваш быстрый ответ. Я изменил "локальный: 3000" на IP-адрес сервера, но ситуация не изменилась. И когда я попробовал e.printStackTrace(); , отображалось «android.os.NetworkOnMainThreadException».

gyagyaw6 13.06.2019 17:19
Этот Может помочь вам решить эту проблему
Madhan Varadhodiyil 13.06.2019 17:23
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
3
96
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

1. Используйте IP-адрес:

вы не можете использовать локальный хост в эмуляторе, потому что эмулятор ссылается на локальный хост на себя, а не на ваш ноутбук. Вместо этого используйте IP-адрес вашего ноутбука, например http://100.100.10.1:3000. Подробнее здесь.

2. Проблема с открытым текстом:

вам нужно добавить URL-адрес вашего сервера (IP-адрес в вашем случае) в сетевой конфигурации открытого текста. для этого создайте файл res/xml/network_security_config.xml и добавьте свой IP-адрес вместо Ip.Adress.here.

<?xml version = "1.0" encoding = "utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted = "true">
        <domain includeSubdomains = "true">Ip.Adress.here</domain>
    </domain-config>
</network-security-config>

Затем добавьте этот файл в манифест тега приложения с помощью android:networkSecurityConfig = "@xml/network_security_config"

Ваш тег приложения в манифесте будет выглядеть так

<application
    android:allowBackup = "true"
    android:icon = "@mipmap/ic_launcher"
    android:label = "@string/app_name"
    android:networkSecurityConfig = "@xml/network_security_config"
    android:roundIcon = "@mipmap/ic_launcher_round"
    android:supportsRtl = "true"
    android:theme = "@style/AppTheme">

Подробнее здесь.

3. Сеть в основном потоке

Вы получите Network in main thread issue. Поскольку сетевые вызовы должны быть в фоновом режиме, для этого используйте асинхронную задачу. Ниже код работает нормально для меня, просто замените your.ip.address.here на ваш IP-адрес.

public class MainActivity extends AppCompatActivity {

private String PostUrl = "http://your.ip.address.here:3000";
private String JSON = "{\"test\":\"100\"}";

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

class PostTask extends AsyncTask<Void, Void, String> {

    @Override
    protected String doInBackground(Void... voids) {
        HttpURLConnection con = null;

        try {
            URL url = new URL(PostUrl);
            con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST");
            con.setDoOutput(true);
            con.setDoInput(true);
            con.setRequestProperty("Content-Type", "application/JSON; charset=utf-8");

            Log.d("debug", "----- All right here -----");
            OutputStream os = con.getOutputStream();
            Log.d("debug", "----- This message is not displayed -----");
            os.write(JSON.getBytes("UTF-8"));
            os.close();

            BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
            StringBuilder response = new StringBuilder();
            String responseLine = null;
            while ((responseLine = br.readLine()) != null) {
                response.append(responseLine.trim());
            }
            return response.toString();

        } catch (Exception e) {
            return e.getMessage();
        }
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (s!=null) {
            System.out.println(s);
        } else {
            System.out.println("Result not found");
        }
    }
}

}

Удачи. Если проблема не устранена, попробуйте опубликовать результат System.out из logcat.

Большое спасибо за ваши ответы. Но результаты не изменились.

gyagyaw6 13.06.2019 17:33

Извините, что опоздал с комментарием, и этот код позволил отправить JSON с Android! Спасибо большое.

gyagyaw6 15.06.2019 09:05

Переместите строку con.connect() сразу после строки con.setRequestProperty и закройте OutputStreamWriter после вызова метода flush.

Если вы получаете исключение NetworkOnMainThreadException, это связано с тем, что вы не можете выполнять сетевые вызовы в основном потоке, поэтому вам нужно использовать AsyncTask.

Я смог решить проблему с помощью нескольких советов. Спасибо.

gyagyaw6 15.06.2019 09:13

Другие вопросы по теме