10
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

AndroidでWebAPIにGetとアクセスしてJson処理する(とりあえずJava)

AndroidはHttp通信、JSON処理もいろいろオプションがあるのでたまに使う人間にはつらい。。。
最近はOkHttpが流行ってるらしいので使ってみる。

前提

  • Http通信にはOkHttpを利用する
  • JsonのパースはJSONObjectで処理(簡単な処理しかしない+追加ライブラリいらないので)
  • 言語はJavaを利用する(大人の事情)
  • 開発環境はAndroid Studio 3.4.x on Mac

仕様

とりあえずボタンを押したらWebAPIをキックしてJson取得して、パースして、表示したい。

サーバ上に下記のJsonを返すプログラムを設置。

{"status":"OK","message":"Hello2019-05-31 07:06:23"}
  • ボタンクリックでJsonリクエスト
  • 取得したJsonからstatuを取り出し、上記画面に表示。

下記のようなイメージ。

スクリーンショット 2019-05-31 7.08.57.png

準備

実装前にいくつか準備。

INTERNETアクセスの許可

AndroidManifest.xmlに以下を追加。当たり前だが、当たり前過ぎて忘れている場合がある。

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

通信ドメインの許可(非https)

どうやらAndroid9.xからhttps以外の通信はエラーとなるよう。下記のようなエラーが出る。

java.io.IOException: Cleartext HTTP traffic to hoge.com not permitted

hoge.comはアクセスしたいドメイン、サブドメイン。

許可するためには設定ファイルが必要。めんどうだが対応する。

設定ファイルの設置

下記の内容を記したxmlファイルを容易する。
別にファイル名や場所はどこでもいいみたい(次の過程で明示的に指定するので)。

app/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">www.bluecode.jp</domain>
    </domain-config>
</network-security-config>

設定ファイルの指定

指定した設定ファイルをAndroidManifest.xmlで指定します。

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

    <application
+       android:networkSecurityConfig="@xml/network_security_config"
        android:allowBackup="true"
        ...

OkHttpの設定

GrandleのModule:appの方に追加してSync。

...
dependencies {
    ...
    implementation 'com.squareup.okhttp3:okhttp:4.0.0-alpha02'
}
...

準備は以上。

実装

いよいよ実装。もうずいぶん前から通信処理等はメインスレッドではできない。
別スレッドで起動し、かつ、非同期処理するというのが常識。OkHttpでは下記のように記述するみたい。

MainActivity.java

MainActivity.java
package jp.bluecode.http01;

import android.os.Handler;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import org.jetbrains.annotations.NotNull;
import org.json.JSONObject;

import java.io.IOException;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class MainActivity extends AppCompatActivity {

    //Widget宣言
    TextView txt01;
    Button btn01;


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

        //Widget初期化
        txt01 = findViewById(R.id.txt01);
        btn01 = findViewById(R.id.btn01);

        //ボタンクリック
        btn01.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //httpリクエスト
                try{
                    //okhttpを利用するカスタム関数(下記)
                    httpRequest("http://www.bluecode.jp/test/api.php");
                }catch(Exception e){
                    Log.e("Hoge",e.getMessage());
                }

            }
        });
    }

    void httpRequest(String url) throws IOException{

        //OkHttpClinet生成
        OkHttpClient client = new OkHttpClient();

        //request生成
        Request request = new Request.Builder()
                .url(url)
                .build();

        //非同期リクエスト
        client.newCall(request)
                .enqueue(new Callback() {

                    //エラーのとき
                    @Override
                    public void onFailure(@NotNull Call call, @NotNull IOException e) {
                        Log.e("Hoge",e.getMessage());
                    }

                    //正常のとき
                    @Override
                    public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {

                        //response取り出し
                        final String jsonStr = response.body().string();
                        Log.d("Hoge","jsonStr=" + jsonStr);

                        //JSON処理
                        try{
                            //jsonパース
                            JSONObject json = new JSONObject(jsonStr);
                            final String status = json.getString("status");

                            //親スレッドUI更新
                            Handler mainHandler = new Handler(Looper.getMainLooper());
                            mainHandler.post(new Runnable() {
                                @Override
                                public void run() {
                                    txt01.setText(status);
                                }
                            });


                        }catch(Exception e){
                            Log.e("Hoge",e.getMessage());
                        }

                    }
                });
    }
}

activity_main.xml

レイアウトはお好みでどう実装してもいい気がしますが、とりあえず参考まで。

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/txt01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="200dp"
        android:text="Hello World!"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn01"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="32dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/txt01" />

</android.support.constraint.ConstraintLayout>

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
10
Help us understand the problem. What are the problem?