初心者必見!10時間で作るはじめてのAndroidアプリ−前編

初心者必見!10時間で作るはじめてのAndroidアプリ−前編

カテゴリBLOG

初めまして!
7月よりエウレカにJOINしました、エンジニアの二川です。
エウレカではCouplesのAndroid開発を担当しています。

前職では、Android向けのゲーム開発を行っていました。それまでゲームしか作ったことが無かったので、エウレカに入社するにあたり、練習を兼ねて簡単なサービスアプリを開発しました。今日はそのアプリについて話をしたいと思います。

ある程度の開発経験があれば10時間程度で作れる、かなりシンプルなアプリです。

Androidアプリ開発に興味はあるけど、まだ作ったことはないという方、この夏なにか新しいことに挑戦しよう!と思っていたけどまだやっていない方、このアプリを作ってAndroidエンジニアデビューしてみませんか?

今回作るアプリの概要

今回作るのは、Dribbbleという世界中のデザイナーが作品を投稿するSNSサイトを閲覧するためのアプリです。
UIは、デフォルトの素材を活かし、とてもシンプルに作っています。

Screenshot_2014-08-19-22-47-28

Screenshot_2014-08-19-22-47-36

 

DribbbleのAPI(記事執筆時のAPIはDeprecatedになっています)を使い、Tab毎にカテゴリ分けしたListを表示しています。 Listのアイテムをタップすることでサムネイル画像をDialogで表示することができます。

今回のコードは、GitHubで公開していますので、この記事を見てAndroid開発に初めて挑戦する方は答え合わせに使ってみてください。 また、すでにバリバリAndroid開発を行っている方は、なんじゃこりゃ!な部分を修正し是非pull requestをお願いします!w

 

完成までの流れ

完成までの流れは大きく3つに分けています。

前編では2番目のAPIから受け取った値を保存するところまでを説明していきます。

  1. 開発環境の構築
  2. APIから受け取った値を保存する
  3. 保存した値を表示する

それでは開発を進めていきましょう!

AndroidStudioを使った環境構築

 

スクリーンショット 2014-08-10 17.30.38

アプリを作るにあたり、まずは開発環境を構築しましょう。
今までEclipseを使った開発しかしたことなかった私ですが、開発環境としてAndroidStudioを使いました。

AndroidStudioとはGoogleが提供するAndroidプラットフォーム開発用の統合開発環境(IDE)です。
これからAndroidアプリ開発を始めるのであれば、これを使わない手はないと思います。
なぜなら……カッコいいからです!(←重要)
※注:あくまで個人的な好みです。Eclipseがカッコ悪い、ということでは決してないです…ゴニョゴニョ

AndroidStudio

スクリーンショット 2014-08-19 23.40.02

 

Eclipse

スクリーンショット 2014-08-11 15.31.42

 

補足ですが、DeveloperサイトにてAndroid開発用のIDEとして、AndroidStudioが今後は公式になると書かれています。

Android Studio is a new Android development environment based on IntelliJ IDEA. It provides new features and improvements over Eclipse ADT and will be the official Android IDE once it’s ready.

また開発環境としてEclipseではなくAndroidStudioを使ったほうが良い理由はこちらで詳しく解説されています。
(参考:僕がEclipseをやめてAndroid Studioを使っている10の理由

AndroidStudioの導入やプロジェクトの作成方法はネット上で様々紹介されていますので、今回は割愛させていただきます。

面倒なことはライブラリー導入で解決

ネットワーク通信用ライブラリーVolley

環境構築ができたら、早速開発に入っていきます。

今回はDribbbleのAPIを使うのでネットワーク通信の機能が必須となります。 Androidでネットワーク通信の機能を書く場合、下記のことに意識する必要があります。

  • ネットワーク通信を伴う操作は遅延することもありえるので、UIスレッドでは行わない(UIスレッドでの通信はAndroidOS3.0以降エラーをはくようになっています)
  • 同様の理由でユーザーが通信をキャンセルすることができるようにする
  • キャッシュを行い、高速化をはかる

これらのことを一挙に解決してくれるライブラリーがVolleyです。 Volleyは昨年のGoogle I/Oで発表されたネットワーク通信用のライブラリーです。 Volleyという名前はa burst or emission of many things or a large amount at onceというイメージからきています。 まあ、ひと言でいえば「一度に色々できるよ!」ということです。

導入

Volleyをgitのsubmoduleとしてプロジェクトへ追加します。

$ cd traveling

$ git submodule add https://android.googlesource.com/platform/frameworks/volley libraries

 

追加したVolleyのフォルダをmoduleとして追加します。

traveling/settings.gradle

include ':app','libraries:volley'

dependenciesにvolleyを追加します。

traveling/app/build.gradle

dependencies { compile project(':libraries:volley') }

ここまでやってvolleyが使えるようになります。

使い方

Volleyを使ってJsonを取得するようなリクエストは下記のように書きます。 この場合dribbbleのAPIから返ってきたJson形式のresposeがonResponseに渡され、処理が行われます。

java String tagJsonObj = “json_obj_req;
mRequestQueue = Volley.newRequestQueue(context);

JsonObjectRequest jsonObjReq =new JsonObjectRequest(
             // HTTPメソッド名を設定する。GETかPOSTか等
             Request.Method.GET
             // リクエスト先のURLを設定する
            ,"http://api.dribbble.com/shots/everyone"
             // リクエストパラメーターを設定する
            ,null
             // 通信成功時のリスナーを設定する
            ,new Response.Listener() {
                    @Override
                    public void onResponse(JSONObject response) {
                        // 通信成功時の処理
                    }
                }
             // 通信失敗時のリスナーを設定する
            ,new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        // 通信失敗時の処理
                    }
                }
        );

mRequestQueue.add(jsonObjReq, tagJsonObj);

上記のリクエストをキャンセルしたい場合はaddした時に設定しているタグを指定することで可能です。

mRequestQueue.canceAll(tagJsonObj);

 

Cacheの利用は下記のように行います。

Cache cache = mRequestQueue.getCache();
Entry entry = cache.get("http://api.dribbble.com/shots/everyone");
if(entry != null){
    try {
        String data = new String(entry.data, "UTF-8");
        // dataをJsonに変換して処理を行う
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
        }
    }
}else{
    // Cacheがない場合の処理、再度リクエストを投げるような処理を書きます
}

これで、データの取得はできました。
次に、このデータを端末に保存していきましょう。

SQLiteDBをラップしてくれるライブラリーActiveAndroid

取得したデータもライブラリーを使って端末に保存します。
端末への保存方法には複数ありますが、今回作ったアプリではSQLiteDBを使います。

ActiveAndroidはDBを使っていることを意識せずにデータを扱えるようにしてくれるライブラリーです。

導入

GitHubからcloneしてjarファイルを作成します。

$ git clone https://github.com/pardom/ActiveAndroid.git 
$ cd ActiveAndroid
$ sh gradlew build

ActiveAndroid/buils/libs/activeandroid.jarが作成されます。 このjarファイルをtraveling/app/libs配下に配置します。 そしてdependenciesに下記を追加します。

traveling/app/build.gradle

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) }

初期設定

もう少し準備が必要です。 ライブラリーを使う宣言をAndroidManifest.xmlだけに書く方法とApplicationクラスを継承させたクラスにも書く方法がありますが、 先に紹介したVolleyと一緒に使うことを考えると必然的にApplicationクラスを継承させたクラスにも書く方法になります。

AppController.java

public class AppController extends Application {
        @Override
        public void onCreate(){
            super.onCreate();
            Configuration.Builder builder = new Configuration.Builder(getBaseContext());
            builder.setCacheSize(1024*1024*4);
            builder.setDatabaseName("sqlite.db");
            builder.setDatabaseVersion(1);
            ActiveAndroid.initialize(builder.create(), true);

            mInstance = this;
        }

        @Override
        public void onTerminate(){
            super.onTerminate();
            ActiveAndroid.dispose();
        }
    }

今回作成したアプリではShotsクラスを作成していますが、クラスに@Tableをつけることでテーブルの役割となります。 変数に@Columnのアノテーションを付けることでカラムの役割となります。

@Table(name = “Shots”) 
public class Shots extends Model {

public static final String TAG = Shots.class.getSimpleName();

@Column(name = "Shots_Id")
public String shotsId;

@Column(name = "Category")
public String category;

@Column(name = "Title")
public String title;

@Column(name = "Image_Url")
public String imageUrl;

@Column(name = "Image_Teaser_Url")
public String imageTeaserUrl;

@Column(name = "Player_Name")
public String playerName;

@Column(name = "Likes_Count")
public int likesCount;

public Shots() {
    super();
}

// クエリを使うことができます。

// idを指定してデータを取得します。
public static Shots getShots(String shotsId) {
    return new Select()
            .from(Shots.class)
            .where("Shots_Id = ?", shotsId)
            .executeSingle();
}

// categoryを指定してデータのリストを取得します。
public static List getCategoryList(String category) {
    return new Select()
            .from(Shots.class)
            .where("Category = ?", category)
            .orderBy("Shots_Id ASC")
            .execute();
    }
}

実際に通信で受け取ったJSONObjectからShotsへデータを保存する方法です。 今回はいったんDTOクラスにデータを格納し、そこからShotsへ保存を行いました。

ShotsDTO shotsDTO = new ShotsDTO();
JSONObject shots = jsonArray.getJSONObject(i);
JSONObject player = shots.getJSONObject("player");

shotsDTO.setShotsId(shots.getString("id"));
shotsDTO.setCategory("everyone");
shotsDTO.setTitle(shots.getString("title"));
shotsDTO.setImageUrl(shots.getString("image_url"));
shotsDTO.setImageTeaserUrl(shots.getString("image_teaser_url"));
shotsDTO.setPlayerName(player.getString("name"));
shotsDTO.setLikesCount(Integer.parseInt(shots.getString("likes_count")));

Shots shots = new Shots(shotsDTO);
shots.save();

データを取得するときは今までSQLiteを扱っていたようにクエリが使えます。 保存するときはDBであることを意識せずにsaveするだけで保存が可能です。

前編のまとめ

APIで取得したデータの保存までを書いてきました。

表示させる部分は後編でご紹介させていただきます!お楽しみに!
<2014/9/16 後編更新しました!>

興味が湧いた方、もしくはどんなクソコードか見てやるよ!という方は是非GitHubでソースを見ていただければと思います!cloneしてくればそのまま動かすことが可能です。

そして、pull requestも大歓迎です!

むしろpull requestしていただけたら喜びます!

というかpull requestしてください。

pull requestしろ。

(pull requestって何それ美味しいの?という方はこちらの記事がまとまっております→初めてのpull request @ GitHub

 

今回のアプリのように短時間でそれなりに動くものを作るには、ライブラリー郡をいかに効率よく活用するかで決まります。便利なライブラリーにはいつも助けられています。

今、開発を担当しているCouplesも、限られた時間の中で効果を最大化するために様々なライブラリーやツールを利用しています。エウレカでは、どんなライブラリーを使うのかや、開発を効率化するツールの導入などはエンジニアに任されています。
制約が無いぶん責任も重大ですが、最新のテクニックが使い放題、常に刺激的な開発ができる環境は、エンジニアとして遣り甲斐を感じられます。

自らの判断でスピード感ある開発を行いたいエンジニアの方、是非一緒に開発しましょう!