Fuelを使ってパラメータ付きPOSTリクエストを送信した

なんとかHTTPリクエストをAndroidのエミュレーターからローカルホストのLaravelサーバーに送信することができたので投稿します。

# ライブラリのインストール
`app/build.gradle`にインストールするライブラリを書いていきます。

```gradle:app/build.gradle
dependencies {
    // Fuel for HTTP Connections
    implementation 'com.github.kittinunf.fuel:fuel:2.2.0'
    implementation 'com.github.kittinunf.fuel:fuel-gson:2.2.0'

    implementation "com.squareup.moshi:moshi:1.5.0"
    implementation "com.squareup.moshi:moshi-kotlin:1.5.0"
}
```

HTTPリクエストを送信するための`Fuel`と，JSONのパラメータを作成するための`moshi`をインストールします。
（僕は最初，`app/build.gradle`じゃなくてルートのgradleに`implementation`を書いちゃって動きませんでした...。）

# パラメータのフォーマットを決める
JSONのパラメータのフォーマットを決めるためのクラス`SampleRequestFormat`クラスを作成します。

```kotlin:SampleRequestFormat.kt
class SampleRequestFormat(val kekey: String)
```

`kekey`という名前のキーを定義しました。

# Androidの画面作成
画面にボタンが一つ配置されているだけのものです。

<img width="310" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352824/dbd7d3c2-1b86-820a-4d6d-359298b6deef.png">


```xml:activity_debug.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

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

# リクエスト送信用のアクティビティを作成
POSTでLaravelのサーバーへリクエストをパラメータ付きで送るためのプログラムを作成します。

```DebugActivity.kt
import android.os.Bundle
import android.widget.Button
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.example.live_barcode_reader.request_format.SampleRequestFormat
import com.github.kittinunf.fuel.Fuel
import com.squareup.moshi.KotlinJsonAdapterFactory
import com.squareup.moshi.Moshi

class DebugActivity : AppCompatActivity() {
    private var button: Button? = null
    private val URL: String = "http://10.0.2.2:8000"
    private val domain: String = "/sample9999"

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_debug)
        val targetURL: String = URL + domain

        val moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
        val requestAdaper = moshi.adapter(SampleRequestFormat::class.java)

        button = findViewById(R.id.post_debug_button)
        button?.setOnClickListener {
            val header: HashMap<String, String> = hashMapOf("Content-Type" to "application/json")
            val sampleRequest = SampleRequestFormat(
                kekey = "from Android"
            )

            Fuel.post(targetURL)
                .header(header)
                .body(requestAdaper.toJson(sampleRequest))
                .response { _, response, result ->
                    println(response)
                    println(result)
                }

            //Toast.makeText(this, "PUSHED", Toast.LENGTH_SHORT).show()
        }
    }
}
```

このとき，`URL`の中身が`http://10.0.2.2:8000`であることを覚えておいてください！
最後に，HTTP通信の設定について`AndroidManifest.xml`に記述します。

# HTTP通信の設定
`network_security_config.xml`というファイルを作成し，HTTP通信できるドメインを指定して許可します。

```xml:network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config xmlns:android="http://schemas.android.com/apk/res/android">
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">10.0.2.2</domain>
    </domain-config>
</network-security-config>
```

その後，`AndroidManifest.xml`にも変更を加えます。

```xml:AndroidManifest.xml
<application
    ...
    android:networkSecurityConfig="@xml/network_security_config">
```

次はLaravelのサーバーです。

# サーバーサイド

```php:web.php
Route::post('/sample9999', 'TestController@sample9999');
```

`sample9999`というPOSTリクエストに反応して`TestController`の中の`sample9999()`という関数が反応するようにします。9999という数字は少し理由があって付けました。

```php:TestController.php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class TestController extends Controller
{
    public function sample9999(Request $request) {
        $json_string = file_get_contents('php://input');
        logger($json_string);
        $json_object = json_decode($json_string);
        logger(var_export($json_object, true));
        logger(gettype($json_object));

        logger($json_object->kekey);

        return 'got request';
    }
}
```

とりあえずこのコードで動作確認だけしてみました。

# 動作確認
Androidとサーバーを起動して，エミュレータのボタンを押すと，

```log:laravel.log
[2020-03-21 08:59:49] local.DEBUG: {"kekey":"from Android"}  
[2020-03-21 08:59:49] local.DEBUG: (object) array(
   'kekey' => 'from Android',
)  
[2020-03-21 08:59:49] local.DEBUG: object  
[2020-03-21 08:59:49] local.DEBUG: from Android  
```

Androidのログ↓

```
I/System.out: <-- 200 http://10.0.2.2:8000/sample9999
    Response : OK
    Length : -1
    Body : got request
    Headers : (11)
    Cache-Control : no-cache, private
    Connection : close
    Set-Cookie : laravel_session=eyJpdiI6IkVrR0RxK241U0xkWkRUbFhWWmhMSXc9PSIsInZhbHVlIjoicEF2d2h5dXVDVFdmVElDc09hLzNvMFJmNmM2bitBbTRrSFBBQjVucEN1elY5eGNUQy9ZZUFqVkExdkplTGEwWSIsIm1hYyI6IjAzMTBiZWEwN2FlYmYxODhlZWQ3OWY2MmU1YTBhMWQ2MWNiYzIzMGI3ZWY1NWM0NjlhYTNkMzkxMzJiZTgyYzIifQ%3D%3D; expires=Sat, 21-Mar-2020 10:59:49 GMT; Max-Age=7200; path=/; httponly; samesite=lax
    Date : Sat, 21 Mar 2020 08:59:49 GMT, Sat, 21 Mar 2020 08:59:49 GMT
    X-Android-Selected-Protocol : http/1.1
    X-Powered-By : PHP/7.3.11
    Content-Type : text/html; charset=UTF-8
    Host : 10.0.2.2:8000
    X-Android-Received-Millis : 1584781188564
    X-Android-Response-Source : NETWORK 200
    X-Android-Sent-Millis : 1584781188475
    [Success: [B@615227d]
```

HTTPリクエストが送られています！