My Note Pad

エンジニアリングや日々の雑感を書いていきます

Androidで嵌った所(HTTP request編)

仕事が忙しくてなかなか進まないのですが、空いた時間を見つけてはmixiAndroidトレーニングを進めています。

現在は2.基礎編 9.ネットワーク通信のセクションです。
実習1の

  1. 画面のEditTextに入力されているURLを取得して、
  2. そのURLにGETリクエストを送り、
  3. レスポンスを画面のTextViewに表示する

だけの簡単なお仕事です(のはずでした)。

まずはAndroidManifest.xmlに、ネットワークのパーミッションを定義

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

今回は折角なのでOkHttpを使ってみました。

github.com

まずはbuild.gradleにOkHttpの依存関係を追加します。

dependencies {
    ~
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
}

続いて通信処理を書いていきます。
MainActivity#onCreateに書いてみたところ、NetworkOnMainThreadExceptionが発生してしまいました。
メインスレッドからネットワーク処理ができないようです。。

こちらの記事を参考にさせていただきました。

shirusu-ni-tarazu.hatenablog.jp

今回関係なさそうな所は省略していますが、以下のような感じになりました。

MainActivity.java

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

        // GetButton
        View buttonGet = findViewById(R.id.buttonGet);
        buttonGet.setOnClickListener(getButtonOnClickListener);
    }

    private View.OnClickListener getButtonOnClickListener = new View.OnClickListener() {

        @Override
        public void onClick(View view) {
            // EditTextからURLを取得
            EditText accessUrlText = (EditText) findViewById(R.id.accessUrl);
            final String accessUrl = accessUrlText.getText().toString();

            // Builderにセット
            Uri.Builder builder = new Uri.Builder();
            builder.path(accessUrl);

            // 別スレッドでリクエストを実行
            AsyncHttpRequest task = new AsyncHttpRequest(MainActivity.this);
            task.execute(builder);
        }
    };

AsyncHttpRequest.java

    private Activity mainActivity;

    public AsyncHttpRequest(Activity mainActivity) {
        // 呼び出し元のアクティビティ
        this.mainActivity = mainActivity;
    }

    // 非同期で呼ばれる処理
    @Override
    protected String doInBackground(Uri.Builder... builders) {

        Uri.Builder builder = builders[0];

        try {
            URL url = new URL(builder.build().getPath());
            Request request = new Request.Builder()
                    .url(url)
                    .build();

            OkHttpClient client = new OkHttpClient();
            Response response = client.newCall(request).execute();
            return response.body().string();

        // 例外処理は今回適当
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    // 非同期処理の後に呼ばれる処理
    // doInBackgroundのreturn値が引数で渡されます。
    @Override
    protected void onPostExecute(String result) {
        TextView responseText = (TextView) mainActivity.findViewById(R.id.responce);
        responseText.setText(result);
    }

嵌った所は以下のとおり

  • OnClickListener内でAsyncHttpRequestのコンストラクタにActivityをどうやって渡せば。。
    • new AsyncHttpRequest(MainActivity.this);でいけました。
  • Builderにpathをセットする際に、builder.addPath(url)でセットすると先頭に/がついてしましまう。
    • builder.path(url)でいけました。
  • request投げているのにresponseが帰ってこない
    • Genymotionを使っているのですが、MacをスリープしたりWi-Fiが切れたりすると駄目っぽい・・?
    • Genymotion再起動でうまく動きました。