向 LINE Notify 发送消息失败(使用 HttpsURLConnection POST)

Failed send message to LINE Notify (using HttpsURLConnection POST)

我是 Android 开发的新手,我正在尝试使用“身份验证方法 -> POST https://notify-api.line.me/api/notify" (LINE Notify API Document)[=17= 向 LINE 通知服务发送消息]

这是我的代码,我总是得到

Return status code: -1

。请帮我看看问题出在哪里?

LINENotify.java

package com.example.test3;

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;

public class LINENotify {

    private static final String strEndpoint = "https://notify-api.line.me/api/notify";
    private static final String tokenKEY = "ldO3dTIAjT5OpjWbeZAQtnXhq23poCXcEAvKoTwJHhn";

    public int sendMSG( String message ) {

        int statusCode;
        statusCode = -1;

        try {
            URL url = new URL( strEndpoint );
            HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();

            connection.setRequestMethod( "POST" );
            connection.addRequestProperty("Authorization",  "Bearer " + tokenKEY);
            connection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");

            connection.setConnectTimeout(15*1000);
            connection.setDoOutput( true );
            connection.setUseCaches( false );
            connection.connect();

            connection.setReadTimeout(15*1000);
            connection.setDoInput( true );

            OutputStream os = connection.getOutputStream();
            BufferedWriter writer = new BufferedWriter( new OutputStreamWriter( os, "UTF-8") );

            writer.write( "message=" + message );
            writer.flush();
            writer.close();

            os.close();

            statusCode = connection.getResponseCode();

            if ( statusCode == 200 ) {
                //
            } else {
                throw new Exception( "Error:(StatusCode)" + statusCode + ", " + connection.getResponseMessage() );
            }
            connection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return statusCode;
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:inputType="textPersonName"
        android:text="Name" />

    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />
</LinearLayout>

AndroidManifest.xml

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

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

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

</manifest>

MainActivity.java

package com.example.test3;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    EditText msg;
    Button send;

    LINENotify lineNotify;

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

        msg = (EditText) findViewById(R.id.editText);
        send = (Button) findViewById(R.id.button);

        lineNotify = new LINENotify();

        send.setOnClickListener(this);
    }// onCreate

    @Override
    public void onClick(View v) {
        switch( v.getId() ) {
            case R.id.button: {
                int statusCode = lineNotify.sendMSG( msg.getText().toString() );
                Toast.makeText(this, "Return status code: " + statusCode, Toast.LENGTH_LONG).show();
                break;
            }
        }
    }
}

我得到答案了!!感谢 google 以及 post 他们的经验和笔记的人。

我的失败是

Android Developers -> Docs -> Connect to the network
To avoid creating an unresponsive UI, don't perform network operations on the UI thread. By default, Android 3.0 (API level 11) and higher requires you to perform network operations on a thread other than the main UI thread;


因此,我尝试使用AsyncTask来解决问题。

MainActivity.java

package com.example.test3;

import androidx.appcompat.app.AppCompatActivity;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    EditText msg;
    Button send;

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

        msg = (EditText) findViewById(R.id.editText);
        send = (Button) findViewById(R.id.button);

        send.setOnClickListener(this);
    }// onCreate

    @Override
    public void onClick(View v) {
        switch( v.getId() ) {
            case R.id.button: {
                new LINENotify().execute(msg.getText().toString());
                break;
            }
        }
    }

    public class LINENotify extends AsyncTask<String, Integer, String> {

        private static final String strEndpoint = "https://notify-api.line.me/api/notify";
        private static final String tokenKEY = "ldO3dTIAjT5OpjWbeZAQtnXhq23poCXcEAvKoTwJHhn";
        String result = "";

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected String doInBackground(String... strings) {
            String message = strings[0];

            try {
                URL url = new URL( strEndpoint );
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();

                connection.setRequestMethod( "POST" );
                connection.addRequestProperty("Authorization",  "Bearer " + tokenKEY);
                connection.addRequestProperty("Content-Type", "application/x-www-form-urlencoded");

                connection.setConnectTimeout(15*1000);
                connection.setDoOutput( true );
                connection.setUseCaches( false );

                connection.setReadTimeout(15*1000);
                connection.setDoInput( true );

                OutputStream os = connection.getOutputStream();
                OutputStreamWriter writer = new OutputStreamWriter(os, "UTF-8");

                writer.write( "message=" + message );
                writer.flush();
                writer.close();
                os.close();

                connection.connect();

                result = connection.getResponseMessage();

                connection.disconnect();
            } catch (IOException error) {
                // Handles input and output errors
            }
            return result;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
        }
    }
}


一些参考链接:
How to fix 'android.os.NetworkOnMainThreadException'?
AsyncTask Android example
[Android] AsyncTask - 非同步任務
【Android】AsyncTask - Thread 外的另一選擇