almost 5 years ago

AndroidAnnotationsは、Androidアプリケーション開発のためのフレームワークです。このフレームワークを利用すれば、記述するコードの量を減らし、保守しやすいアプリケーション開発をすることができます。

セットアップ

1.jarのダウンロード

  1. androidannotations-X.X.X-api.jar を libsフォルダへ置きます。
  2. androidannotations-X.X.X.jar を compile-libsフォルダへ置きます。このフォルダがなければ作成してください。
  3. プロジェクト上で右クリックし "Properties"を開いてください。
  4. Java Compiler へ移動し、Compiler compliance level を1.6へセットします。
  5. Java Compiler > Annotation Processing の annotation processing を有効にします。
  6. Java Compiler > Annotation Processing > Factory Path へ androidannotations-X.X.X.jar. を追加します。
  7. ワークスペースがリビルドされることを確認してください。

Qiita API を叩く

サンプルアプリケーションとして Qiita API auth をたたくアプリケーションを作成します。このアプリケーションは、スタートボタンを押すとAPIリクエストが開始され、非同期でAPIリクエストが実行されます。成功レスポンスならTextViewへアカウント名とトークンを表示するというシンプルなアプリケーションです。

package com.example.annotationdemo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;

import android.app.Activity;
import android.widget.TextView;

import com.googlecode.androidannotations.annotations.Background;
import com.googlecode.androidannotations.annotations.Bean;
import com.googlecode.androidannotations.annotations.Click;
import com.googlecode.androidannotations.annotations.EActivity;
import com.googlecode.androidannotations.annotations.UiThread;
import com.googlecode.androidannotations.annotations.ViewById;
import com.googlecode.androidannotations.annotations.rest.RestService;

@EActivity(R.layout.activity_main)
public class MainActivity extends Activity {

    @ViewById(R.id.contents)
    TextView contents;

    @RestService
    MyRestClient myRestClient;

    @Bean
    MyInterceptor myInterceptor;

    @Click
    void start() {
        getToken();
    }

    @Background
    void getToken() {
        RestTemplate restTemplate = myRestClient.getRestTemplate();
        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
        interceptors.add(myInterceptor);
        restTemplate.setInterceptors(interceptors);
        HashMap<String, String> params = new HashMap<String, String>();
        params.put("url_name", "ynomoto@github");
        params.put("password", "*****************");
        QiitaAuth qiitaAuth = myRestClient.getToken(params);
        displayToken(qiitaAuth.getUrl_name(), qiitaAuth.getToken());
    }

    @UiThread
    void displayToken(String url, String token) {
        contents.setText(url + " ; " + token);
    }
}

このActivityにはonCreateがありません。なぜなら@EActivityが、setContentViewの代わりになり、また、@ViewByIdがfindViewByIdの代わりになります。また、@Clickはメソッド名=idのonClickコールバックメソッドを意味しています。@Backgroundは非UIスレッド、@UiThreadはUIスレッドを意味します。@Background/@UiThreadを使うことで複雑になりやすいスレッドの処理がとても簡単に書けることが分かると思います。

package com.example.annotationdemo;

import java.util.HashMap;

import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import com.googlecode.androidannotations.annotations.rest.Post;
import com.googlecode.androidannotations.annotations.rest.Rest;

@Rest(rootUrl = "https://qiita.com/api/v1", converters = { GsonHttpMessageConverter.class })
public interface MyRestClient {
    
    RestTemplate getRestTemplate();
    
    void setRestTemplate(RestTemplate restTemplate);

    @Post("/auth")
    QiitaAuth getToken(HashMap params);
    
}

これはRestクライアントです。コードだけ見ると非常にシンプルですが、利用するにはSPRING FOR ANDROIDを理解する必要があります。

AndroidAnnotationsはRestクライアントを書くためにSpring利用しています。Springは色々なフォーマットのデータをサポートしており、Message Body ConverterでJsonだけでなく、XMLをJavaオブジェクトとして受け取ることができます。ConverterはJsonならGson or Jackson。XML なら Simple をライブラリとしてアプリに組み込むことで利用できます。サンプルアプリではGsonHttpMessageConverterを使うのでGsonを別途組み込む必要があります。

package com.example.annotationdemo;

import java.io.IOException;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

import com.googlecode.androidannotations.annotations.EBean;

@EBean
public class MyInterceptor implements ClientHttpRequestInterceptor {

    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        HttpHeaders headers = request.getHeaders();
        headers.setUserAgent("android qiita client  0.1");
        return execution.execute(request, body);
    }
}

HttpHeaderなどの設定はClientHttpRequestInterceptorを経由して行うことができます。この例では、"android qiita client 0.1" というユーザエージェントを設定します。

package com.example.annotationdemo;

public class QiitaAuth {

    private String url_name;
    private String token;

    public String getUrl_name() {
        return url_name;
    }

    public void setUrl_name(String url_name) {
        this.url_name = url_name;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }
}

これはGsonの解析結果を格納するためのオブジェクトになります。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.annotationdemo"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.annotationdemo.MainActivity_"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

MainActivity ではなく MainActivity_ であることに注目してください。AndroidAnnotationsでコードを書くと実体が _ サフィックスが付いた状態で生成されるためです。.apt_generatedへ実体が作成されます。Eclipseを使っている場合はフィルター設定を変更すればこのフォルダを見ることができます。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/start"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="32dp"
        android:text="Start" />

    <TextView
        android:id="@+id/contents"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/start"/>

</RelativeLayout>

レイアウトファイルは今まで通り利用できます。

もっと詳しく知りたい

Cookbook に詳細な情報があります。

https://github.com/excilys/androidannotations/wiki/Cookbook

← Android Studio Androidアプリケーションのユニットテストを自動化 →