🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

5454閲覧

AndroidアプリからPOST送信したい Already connectet at エラーになる

old_dog

総合スコア51

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

POST

POSTはHTTPプロトコルのリクエストメソッドです。ファイルをアップロードしたときや入力フォームが送信されたときなど、クライアントがデータをサーバに送る際に利用されます。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2019/10/03 09:39

編集2019/10/03 10:39

■ 実現したいこと
AndroidアプリからPOST送信で返信したい。


■ 生じている問題
下記の<コード1>を実行すると、java.lang.IllegalStateException: Already connected at java.net.URLConnection.setDoOutputというエラーが現れて、目的のサイトと接続できません。

getRequestPriority()を記述すると、そちらに関しても、Already connect at…というエラーが発生します。


■ 試したこと
<コード2>のように、headerとcookieを取得する行を削除し、通信形式を"GET"に修正すると、目的のサイトと接続できました。


■ 知りたいこと

  1. Already connect atというエラーが発生してしまう理由
  2. <コード1>のように、目的にサイトからクッキーを取得した後に、POST送信できるようにするにはどうしたらいいか

という2点に関して、どうかご指導お願いします。


<コード1>

php:

1protected void onCreate(Bundle savedInstanceState) { 2 super.onCreate(savedInstanceState); 3 setContentView(R.layout.activity_main); 4 token = null; 5 new Thread(new Runnable() { 6 @Override 7 public void run() { 8 String site = "http://192.168.xxx.xxx"; 9 10 try { 11 HttpURLConnection connection = (HttpURLConnection) new URL(site).openConnection(); 12 13         // header と cookieを取得する 14 Map<String,List<String>> header = connection.getHeaderFields(); 15 List<String> cookies = header.get("cookie"); 16 17 connection.setRequestMethod("POST"); 18 connection.setDoOutput(true); 19 connection.connect(); 20 Log.d("\nSTATE:\n", String.valueOf(connection.getResponseCode())); 21 22 connection.disconnect(); 23 } catch (IOException e) { 24 e.printStackTrace(); 25 } 26 } 27 }).start(); 28}

<コード2>

php:

1protected void onCreate(Bundle savedInstanceState) { 2 super.onCreate(savedInstanceState); 3 setContentView(R.layout.activity_main); 4 token = null; 5 new Thread(new Runnable() { 6 @Override 7 public void run() { 8 String site = "http://192.168.xxx.xxx"; 9 10 try { 11 HttpURLConnection connection = (HttpURLConnection) new URL(site).openConnection(); 12 13 connection.setRequestMethod("GET"); 14 connection.setDoOutput(false); 15 connection.connect(); 16 Log.d("\nSTATE:\n", String.valueOf(connection.getResponseCode())); 17 18 connection.disconnect(); 19 } catch (IOException e) { 20 e.printStackTrace(); 21 } 22 } 23 }).start(); 24}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

多分ですが・・・
getHeaderFields()は、Response Headerを取得するメソッドなので、connect()の後で使用してください。
これ呼び出すと、connection.connectedがtrueになってしまったり変なことになっているんじゃないかと思います。

         // header と cookieを取得する Map<String,List<String>> header = connection.getHeaderFields(); List<String> cookies = header.get("cookie"); connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.connect(); Log.d("\nSTATE:\n", String.valueOf(connection.getResponseCode()));

connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.connect(); Log.d("\nSTATE:\n", String.valueOf(connection.getResponseCode()));          // header と cookieを取得する Map<String,List<String>> header = connection.getHeaderFields(); List<String> cookies = header.get("cookie");

投稿2019/10/03 11:32

Y.H.

総合スコア7918

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

old_dog

2019/10/03 22:11

Y.H.様、お忙しい中、早速のアドバイスをありがとうございました。 Y.H.様のコードでは、確かにAlready connectedエラーはでないようなのですが、目的としているサイトのcookieを取得して、取得したcookieをPOST送信しようとすると、どのようなコードになるのでしょうか?
old_dog

2019/10/04 00:07

Y.H.様のアドバイスをヒントに、cookieを取得するhttpURLConnectionオブジェクトは別に、getRequestPropertyに使うHttpURLConnectionオブジェクトを生成して利用してみましたら、Already connect at 系のエラーは出なくなったようです。しばらくはその方法で試してみて、また問題が生じるようなら再度質問をさせていただきます。Y.H.様の的確なアドバイスに感謝いたします。ありがとうございました。
Y.H.

2019/10/04 00:47

今のコードでは一切cookieが送信されないと思うのですが。。。 「cookieをPOST送信」するには、setRequestProperty()を使用してcookieをリクエストヘッダーに追加します。 > 目的としているサイトのcookieを取得して どこから取得しようとしているのかわかりませんが、一度リクエストを投げた結果からしかcookieは取得できませんよ。(Chrome,firefox,Edge,etc... のブラウザーのように通信した結果をDBなりファイルなりで保存しているのであればそれを利用することで可能ですが。。。) getRequestProperty()は、一度リクエスト(POSTやGETなど)を行い、その結果のサーバーから返されたレスポンスからレスポンスヘッダーを取得するメソッドです。 実際にリクエストされたときのリクエストヘッダーを見てみると何も送信されてないことが確認できると思います。 まずはHTTP通信の仕組みを理解されたほうが良いかと思います。
old_dog

2019/10/04 01:36

HttpURLConnection getCookieConnection = (...)new URL(site).openConnection(); // ここでクッキーを取得します getCookieConnection.disconnect(); HttpURLConnection postConnection = (...) new URL(site).openConnection(); ... getRequestProperty("cookie",getCookie); postConnection.connect(); postConnection.disconnect(); このコードで、取得したcookieは、postConnection.requestHeaders.nameAndValuesのArrayListに、'cookie',getCookieに格納されています。 なので、大丈夫なのかな?と考えていましたが、間違っていますでしょうか?
Y.H.

2019/10/04 01:54

> getCookieに格納されています。 中は確認しました?必要なcookieを取得できてますか? また、本リクエストする際に想定したcookieがきちんと送信されてますか? というか、単に空リクエストに対するレスポンスからcookie取得して、そのcookieを本リクエストに載せるだけなら、そんなcookie不要だと思うんですよね。。。
old_dog

2019/10/04 03:13

Y.H様。何度もアドバイスをありがとうございます。とても勉強になります。 getCookieには、取得したCookieが格納されていました。 実際のPOST送信先は、PHPフレームワークのLaravelアプリを想定しています。LaravelではPOST送信を受けるときに、csrf-tokenを必要とするので、最初にLaravelアプリのtokenを取得してから、リクエストヘッダーに取得したtokenを設定してPOST送信するらしいのです。tokenが設定されていないと、unknown error(419)が返されます。上記のコードを実行すると、internal server error (500)が返されてきてしまって、まだきちんと送信されているか確認できていません。get送信なら正常に接続されているようですので、まずはget送信し、Laravelから受信完了通知をandroid側に送信するようなコードを作って、HTTP通信ができるか確認してから、再度POST送信について試行錯誤してみようかなと考えています。今後、質問をさせていただくことが多々あると思いますが、どうかよろしくご指導をお願いいたします。 Y.H様には何度も本当にありがとうございます。心から感謝しております。
old_dog

2019/10/04 08:57

Y.H様のおっしゃるとおり、 ’一度リクエストを投げた結果からしかcookieは取得できませんよ’ ということで、500errorになっているようです。Laravelアプリからtokenを取得し、それをPOST送信に使うような方法を探す必要がありそうです。すこし試行錯誤してみます。本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問