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

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

詳細はこちら
Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

HTTP

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

HTTPヘッダー

Hypertext Transfer Protocol(HTTP)の中のHTTPヘッダフィールドはHTTPの要求やレスポンスの機能しているパラメーターが含まれます。その要求もしくはレスポンスライン(メッセージの最初の一行)でメッセージヘッダを作ります。

Android

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

HTTP2

HTTP2は、Hypertext Transfer Protocolのバージョンの1つでWWWで用いられます。接続を多重化し複数のリクエスト処理でき、HTTP1.1との互換性を持たせています。

Q&A

解決済

1回答

1992閲覧

AndroidでHTTP通信が上手くいかない

takaradango

総合スコア8

Firebase

Firebaseは、Googleが提供するBasSサービスの一つ。リアルタイム通知可能、並びにアクセス制御ができるオブジェクトデータベース機能を備えます。さらに認証機能、アプリケーションのログ解析機能などの利用も可能です。

HTTP

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

HTTPヘッダー

Hypertext Transfer Protocol(HTTP)の中のHTTPヘッダフィールドはHTTPの要求やレスポンスの機能しているパラメーターが含まれます。その要求もしくはレスポンスライン(メッセージの最初の一行)でメッセージヘッダを作ります。

Android

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

HTTP2

HTTP2は、Hypertext Transfer Protocolのバージョンの1つでWWWで用いられます。接続を多重化し複数のリクエスト処理でき、HTTP1.1との互換性を持たせています。

0グッド

0クリップ

投稿2019/11/14 06:33

編集2019/11/14 09:04

前提、実現したいこと

指定したメッセージをandroidアプリから送り、その内容を他のandroidアプリにフォアグラウンド・バックグラウンドで通知させようとしています(コンソールからではないということ)。HTTP通信(POST)を利用してfirebaseのサーバーと通信して、通知のタイトルや内容を送ろうとしています。メッセージの形式はJSON形式で書いたものをオブジェクトに変換しています(ここがあっているかもわかりません)。

発生している問題・エラー

2019-11-14 15:02:30.573 21604-22307/com.webserva.wings.android.http_post E/PostAccess: 通信失敗 java.io.IOException: ステータスコード: 400 at com.webserva.wings.android.http_post.PostActivity$PostAccess.doInBackground(PostActivity.java:117) at com.webserva.wings.android.http_post.PostActivity$PostAccess.doInBackground(PostActivity.java:51) at android.os.AsyncTask$2.call(AsyncTask.java:304) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:761)

該当のソースコード

java

1public class PostActivity extends AppCompatActivity { 2 3 private static final String ACCESS_URL = "https://fcm.googleapis.com/fcm/send"; 4 5 @Override 6 protected void onCreate(Bundle savedInstanceState) { 7 super.onCreate(savedInstanceState); 8 setContentView(R.layout.activity_post); 9 } 10 11 public void sendButtonClick(View view) { 12 EditText etName = findViewById(R.id.etName); 13 EditText etComment = findViewById(R.id.etComment); 14 TextView tvProcess = findViewById(R.id.tvProcess); 15 TextView tvResult = findViewById(R.id.tvResult); 16 17 tvProcess.setText(""); 18 tvResult.setText(""); 19 20 String name = etName.getText().toString(); 21 String comment = etComment.getText().toString(); 22 23 PostAccess access = new PostAccess(tvProcess, tvResult); 24 access.execute(ACCESS_URL, name, comment); 25 } 26 27 private class PostAccess extends AsyncTask<String, String, String> { 28 private static final String DEBUG_TAG = "PostAccess"; 29 private TextView _tvProcess; 30 private TextView _tvResult; 31 private boolean _success = false; 32 33 public PostAccess(TextView tvProcess, TextView tvResult) { 34 _tvProcess = tvProcess; 35 _tvResult = tvResult; 36 } 37 38 @Override 39 public String doInBackground(String... params) { 40 String urlStr = params[0]; 41 String title = params[1]; 42 String message = params[2]; 43 String postData = ""; 44 45 try { 46 JSONObject object = new JSONObject(); 47 object.put("to", "xxx"); 48 49 JSONArray array1 = new JSONArray(); 50 JSONObject object1 = new JSONObject(); 51 object1.put("title", title); 52 object1.put("body", message); 53 array1.put(object1); 54 55 JSONArray array2 = new JSONArray(); 56 JSONObject object2 = new JSONObject(); 57 object2.put("title", title); 58 object2.put("message", message); 59 array2.put(object2); 60 61 object.put("notification", array1); 62 object.put("data", array2); 63 64 postData = object.toString(); 65 66 } 67 catch (org.json.JSONException e) { 68 69 } 70 71 HttpURLConnection con = null; 72 InputStream is = null; 73 String result = ""; 74 75 try { 76 publishProgress(getString(R.string.msg_send_before)); 77 URL url = new URL(urlStr); 78 con = (HttpURLConnection) url.openConnection(); 79 con.setRequestMethod("POST"); 80 con.setConnectTimeout(5000); 81 con.setReadTimeout(5000); 82 con.setDoOutput(true); 83 // header用の記述 84 con.addRequestProperty("Content-Type", "application/json; charset=utf-8"); 85 con.addRequestProperty("Authorization", "key=" + "xxx"); 86 OutputStream os = con.getOutputStream(); 87 os.write(postData.getBytes()); 88 os.flush(); 89 os.close(); 90 int status = con.getResponseCode(); 91 if (status != 200) { 92 throw new IOException("ステータスコード: " + status); 93 } 94 publishProgress(getString(R.string.msg_send_after)); 95 is = con.getInputStream(); 96 97 result = is2String(is); 98 _success = true; 99 } 100 catch(SocketTimeoutException ex) { 101 publishProgress(getString(R.string.msg_err_timeout)); 102 Log.e(DEBUG_TAG, "タイムアウト", ex); 103 } 104 catch(MalformedURLException ex) { 105 publishProgress(getString(R.string.msg_err_send)); 106 Log.e(DEBUG_TAG, "URL変換失敗", ex); 107 } 108 catch(IOException ex) { 109 publishProgress(getString(R.string.msg_err_send)); 110 Log.e(DEBUG_TAG, "通信失敗", ex); 111 } 112 finally { 113 if (con != null) { 114 con.disconnect(); 115 } 116 try { 117 if (is != null) { 118 is.close(); 119 } 120 } 121 catch (IOException ex) { 122 publishProgress(getString(R.string.msg_err_parse)); 123 Log.e(DEBUG_TAG, "InputStream解析失敗", ex); 124 } 125 } 126 return result; 127 } 128 129 @Override 130 public void onProgressUpdate(String... values) { 131 super.onProgressUpdate(values); 132 String message = _tvProcess.getText().toString(); 133 if (!message.equals("")) { 134 message += "\n"; 135 } 136 message += values[0]; 137 _tvProcess.setText(message); 138 } 139 140 private String is2String(InputStream is) throws IOException { 141 BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); 142 StringBuffer sb = new StringBuffer(); 143 char[] b = new char[1024]; 144 int line; 145 while(0 <= (line = reader.read(b))) { 146 sb.append(b, 0, line); 147 } 148 return sb.toString(); 149 } 150 } 151}

補足

doInbackgroundの"to"は、Client AppのInstance ID Token(受信先の端末を指定するもの)。

java

1object.put("to", "xxx(Instance ID)");

doInbackground内の"Authorization"は、firebaseのサーバーキー。

java

1con.addRequestProperty("Authorization", "key=" + "xxx(apiキー)");

エラー以前に分かっていないこと

・firebaseにデータメッセージを送る際に、どのような形式で送ればいいのか

参考にしたサイト

https://qiita.com/etet-etet/items/bdd1c03d671a78a33e1d
https://qiita.com/toshiyuki_wada/items/a072ec557a49c6f8c00a
https://qiita.com/fezrestia/items/52e6162844ef1724af76
https://firebase.google.com/docs/cloud-messaging/http-server-ref
https://firebase.google.com/docs/cloud-messaging/
https://firebase.google.com/docs/cloud-messaging/http-server-ref

追記

補足にあるAuthorizationについての記述を以下のように変えるとエラーコードが400から401に変わりました。

java

1con.setRequestProperty("Authorization", "xxx");

firebase公式サイト(https://firebase.google.com/docs/cloud-messaging/http-server-ref)には以下のように書いてありました。

400 JSON リクエストに対してのみ適用されます。リクエストが JSON として解析できなかったか、リクエストに無効なフィールド(数値が期待されている場合に文字列が渡されているなど)が含まれていたことを示します。レスポンスには障害の理由が明記されており、リクエストを再試行する前に、問題に対処する必要があります。
401 送信者アカウントの認証エラーが発生しました。

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

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

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

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

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

dodox86

2019/11/14 08:45

ん? 結局今は、以下のエラーになっているのですよね。Authorization でセットするAPIキー?が不正なのでは。 > 401 送信者アカウントの認証エラーが発生しました。 ところで、APIキー?の値を載せてしまって良いのでしょうか。ダミーに書き換えた上、できれば無効化、再発行された方が良いと思います。
takaradango

2019/11/14 09:01

確かにそうですね!修正します。
guest

回答1

0

自己解決

JSONの記述が間違っており、それを修正したらうまくいきました。検討してくださった方々、ありがとうございました。

投稿2019/11/14 06:45

編集2019/11/15 04:42
takaradango

総合スコア8

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

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

takaradango

2019/11/15 04:42 編集

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問