ブログ

  • WEBサーバーから取得したJSONデータを複数表示 手順1

    手順1、WEBサーバーからHTTP経由でjson形式の複数の記事データを取得する

    ・Hogehogeアクティビティを作る

    起動するアクティビティを作るよ。
    ファイル名は HogehogeActivity.java となるかとおもわれ。
    置き場所は hello/src/jp.example.hello 配下です。
    アクティビティとは http://example.jp/〇〇.php  の 〇〇.php にあたるものだ。多分。


    package jp.example.hello;


    import android.app.Activity;
    import android.os.Bundle;
    public class HogehogeActivity extends Activity {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.hogehoge);
        }
    }
    おぉ短い。

    ・res/layout/hogehoge.xmlをつくる

    アクティビティで setContentView(R.layout.hogehoge); とすると hogehoge.xml を作らないとエラーになります。
    エミュレーターが「アプリが予期せず停止しました。やり直してください。」等と言って起動してくれません。
    こういう「んん?」っていうエラーでツマヅキまくるんだよね。


    <?xml version=“1.0” encoding=“utf-8”?>

    <LinearLayout xmlns:android=“http://schemas.android.com/apk/res/android” android:id = “@+id/mainLayout”
    android:orientation=“vertical”
    android:layout_height=“fill_parent”
    android:layout_width=“fill_parent”
    >
    <ListView
        android:id=“@+id/list”
        android:layout_width=“fill_parent”
        android:layout_height=“wrap_content”
        android:fadeScrollbars=“false”/>
    </LinearLayout>

    ・AndroidManifest.xmlを修正

    まず、インターネットに接続しますよーというマニフェストをかかげるべく、AndroidManifest.xml に次の1行を追記します。


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



     次に、HogehogeActivity をアクティビティとして使いますよーというマニフェストを宣言すべく、AndroidManifest.xml に次の1行を追記します。


            <activity android:name=“HogehogeActivity”></activity>

    参考

    ・エミュレーターを起動し動作確認

    eclipseメニューの「実行」→「実行」でエミュレータを起動させて動作確認。

    はい。確認できましたね?さて次のステップに進みましょう。・・・みたいな感じの記事がばかりで困る!!
    なぜかエミュレーターが起動しないんだよー。
    筆者は様々なエラーでつまづく星の元に生まれたので、そのエラー例を以下に紹介します。

    ・パッケージ内のどれかで 構文エラー
    →解決策:eclipse 「パッケージ・エクスプローラー」内に 赤いバッテンのマーク がでている場合はそのファイルを開き、ソースコードの右側にあるバッテンをダブルクリックして解決策を読む。または自動的に保管してくれるeclipseの機能も多用する。

    ・R.javaが見つかりません。と言われている気がするエラー
    →解決策:eclipseのメニュー「プロジェクト」→「クリーン」してみる
    →解決策:layout/なんちゃら.xml でエラーしてる可能性があるので直す

    ・AndroidManifest.xmlに先ほど作成したHogehogeActivityの宣言が無くてエラー
    →解決策:解決策の参考

    ・主に画像ファイルを保存するdrawableディレクトリやdrawble-なんちゃらディレクトリに内のファイルのうち、大文字を含むファイル名のファイルが存在することによるエラー
    →解決策:ファイル名に大文字を使用せず、小文字とかアンダースコアだけにリネームしましょう

    ・Androidのプロジェクトビルドターゲットが違うことによるエラー
    →解決策:今回のアプリはandroid 2.3.3以上で利用出来るようにしたい。「パッケージ・エクスプローラー」内の該当のパッケージディレクトリツリー内にAndroid 2.3.3 というライブラリ(?)が有るか確認。無ければ「パッケージ・エクスプローラー」の該当のパッケージ名を右クリック→「ビルド・パス」→「ビルド・パスの構成」→「リソース」以下の「Android」をクリック「プロジェクト・ビルド・ターゲット」を「Android 2.3.3」にしてください。

    その他、起動しない方に助言できる事は、

    なんとかエミュレーターが起動して挙動が確認出来るまでガンガレ!!

    ここを乗り切れれば、自分で要領を得て色々と対処できるようになるかと思われ。

    ・jsonデータを取得してみる

    WEBサーバーからjsonデータを取得する。
    HogehogeActivity.javaを修正します。
    赤文字がHogehogeActivityに追記したところです。


    package jp.example.hello;

    import java.io.IOException;

    import org.apache.http.HttpResponse;
    import org.apache.http.HttpStatus;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.HttpClient;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;

    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.os.Bundle;
    import android.util.Log;

    public class HogehogeActivity extends Activity {

        private static final String LogTag = “HogehogeLog”;
        private ProgressDialog dialog;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.hogehoge);

            // jsonを取得して解析する
            LoadTask();
        }

        private String makeApiUrl(){
            return “http://akamako.com/blogger/sample.php”;
        }

        private void LoadTask(){
            // ProgressDialogを作成
            dialog = new ProgressDialog(this);
            dialog.setMessage(“Connect to Server.”);
            dialog.setCancelable(true);
            dialog.show();

            try{
                String apiUrl = makeApiUrl();

                // コンソールログに出力
                Log.d(LogTag+” apiUrl”,apiUrl);

                HttpGet get = new HttpGet(apiUrl);
                HttpClient DefaultHttpClient = new DefaultHttpClient();
                HttpResponse response = DefaultHttpClient.execute(get);

                // ステータスコード
                int status = response.getStatusLine().getStatusCode();
                Log.d(LogTag+” status”,String.valueOf(status));
                if (status != HttpStatus.SC_OK) {
                    throw new Exception(“Error!”);
                }

                // 結果を取得
                String source =    EntityUtils.toString(response.getEntity());

                Log.d(LogTag+” source”,source);
                DefaultHttpClient.getConnectionManager().shutdown();
            }
            catch (ClientProtocolException e){
                 Log.d(LogTag + ” ClientProtocolException”, e.getMessage());
            }
            catch (IOException e){
                Log.d(LogTag + ” IOException”, e.getMessage());
            }
            catch(Exception e){
                Log.d(LogTag + ” Exception”, e.getMessage());
            }
            if (dialog != null && dialog.isShowing()) {
                dialog.dismiss();
            }
        }
    }

    なんかいきなり長くなっちったな。

    ・動作確認

    エミュレータを起動して
    「ウインドウ」→「ビューの表示」→「その他」→「Android」以下の「LogCat」をクリックするとコンソールのようなものが開きます。開くかな? →ガンガレ!
    HogehogeActivityに記述した Log.d(LogTag+” source”,source); がLogCat内に表示されるのを確認してください。

    ===========================
    D/HogehogeLog source( 1466): {“count”:4,”items”:[{“id”:”1234″,”title”:”\u30bf\u30a4\u30c8\u30eb\u3068\u304b1234″,”detail”:”\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b1234″,”icon”:”http:\/\/akamako.com\/blogger\/pict\/1.jpg”,”image”:”http:\/\/akamako.com\/blogger\/pict\/2.jpg”},{“id”:”1235″,”title”:”\u30bf\u30a4\u30c8\u30eb\u3068\u304b1235″,”detail”:”\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b1235″,”icon”:”http:\/\/akamako.com\/blogger\/pict\/3.jpg”,”image”:”http:\/\/akamako.com\/blogger\/pict\/4.jpg”},{“id”:”1236″,”title”:”\u30bf\u30a4\u30c8\u30eb\u3068\u304b1236″,”detail”:”\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b1236″,”icon”:”http:\/\/akamako.com\/blogger\/pict\/5.jpg”,”image”:”http:\/\/akamako.com\/blogger\/pict\/6.jpg”},{“id”:”1237″,”title”:”\u30bf\u30a4\u30c8\u30eb\u3068\u304b1237″,”detail”:”\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b\u8a73\u7d30\u5185\u5bb9\u3068\u304b1237″,”icon”:”http:\/\/akamako.com\/blogger\/pict\/7.jpg”,”image”:”http:\/\/akamako.com\/blogger\/pict\/8.png”}]}
    ===========================

    キタコレ! 記事データがテキストで受け取れた!!

  • WEBサーバーから取得したJSONデータを複数表示 手順0

    手順0、WEBサーバーのAPIを用意する

    WEBサーバーにJSON形式で記事データを吐き出すスクリプトを設置します。

    ほいっとな

    こんな↑スクリプトを作成します。

    WEBエンジニア出身なのでこの行程は出来るんです。

    ここまでは、ここまではできるんだ・・

    何が分からないかって、このJSON記事データをAndroidアプリ上で表示するのやり方がよくわからなないのです。

    HTML5 + CSS3 + jQuery でAndroidアプリを作成する方法(ハイブリットアプリ)やツールもあるけど、今回はネイティブアプリを作ってみたいのです。

    次の行程へ

  • WEBサーバーから取得したJSONデータを複数表示


    筆者はPHPの非凡WEBエンジニアです。

    RSSリーダーみたいに非同期処理で複数の画像を読み込んだりテキストを表示するAndroidアプリを開発したい。

    WEBエンジニアならおなじみの処理なのにAndroidアプリの開発となると、なかなか出来ないんだなぁ。

    PHP? LAMP環境で色々できますよ。

    Javascript? jqueryで色々できそうです。

    Androidアプリ? WEBビューだけのアプリなら作れます。Googleプレイでしょ?


    Java? 名前は知ってます!(読めません・・ましてや書けません)

    そして家に帰ってからひっそり調べるのです。

    Google先生ぇ! 「Android開発 画像 読み込み 非同期」教えて!

    ・・・約100時間後

    苦ぅ! 調べども試せども、うまく動かない!

    こ、、これは、、センスがねぇ!

    Android開発の知識はついてきたけどもコーディングがおぼつかない。

    Githubの世界の素晴らしいエンジニアの素晴らしいソースコードを参考にさせてもらったりしたけど、、なんかうまくできない。

    そうじゃないんだよな、、多分ちゃんと自分でコーディングできる力が無いとダメだ。

    そりゃ落ちてるソースちょこちょこっといじって出来ましたー、とかってあり得ないよね。

    てか java書けないし、てか読めないし、そもそもビルドとかよく知らないしなぁ。

    完成系はイメージできても、コーディング手順がわからんのです。

    なので、

    シュミレーターでデバッグしながら、0からコーディング手順をまとめてみようかと思たよ、ワタシ!

    手順0、WEBサーバーのAPIを用意する

    手順1、WEBサーバーからHTTP経由でjson形式の複数の記事データを取得する

    手順2、手順1の通信でテキストデータは取得できてるので、TextViewでテキストだけ表示しちゃう

    手順3、画像 http://なんちゃら.jpg を表示するには数秒時間がかかるので、非同期処理でおこなう

    手順4、タイトルをクリックしたり画像をクリックしたらナニガシする

    手順5、レイアウトを綺麗にする

    という手順を コーディング→エミュレータで動作確認 を繰り返しながらよいアプリにしていくのが普通なんだと思います。

    いきなり完成系のソースコードを見ても、とても理解できる気がしませんよね汗泣


    以降の記事は起動アクティビティは既にできているものとして話を進めます。
    Androidプロジェクト名は jp.example.hello です。
    ターゲットSDKバージョンは2.3.3 APIレベルは10です。→参考
    開発環境はeclipse JUNOを日本語化してます。

  • Activityが増えちゃう、Activityファイルの行数が多くなってしまう

    WEBエンジニアは、サイト内の画面遷移 = 処理ファイルの移動 と認識する事が多い。

    WEBサイトの構築の仕方によりけりだが、最も簡単な画面遷移方法は、画面A(http://ほげ/a.php)から画面B(http://ほげ/b.php)に aタグでリンクをする方法でしょう。
    画面Aの処理の a.php 、画面Bの処理の b.php というようにファイルを2つに分ける方法が一般的だと思われます。
    (スマーティなどのテンプレートエンジンはもっと効率化されてますが)

    この考え方をそのままAndroidに適用すると、AaaActivity.java というアクティビティから Intent でBbbActivity.java に遷移する というやり方になりがちです。

    この方法だと1画面ごとに処理が記述でき、WEBエンジニアには分かりやすいかもしれませんがActivityが沢山増えてしまいます。

    じゃぁ画面遷移はどうやるの? という疑問が出てくるかもしれません。

    画面遷移というのはつまり、画面が切り替わるということなのでActivityを変える必要はありません。

    見た目に関しては View を切り替えると考えると良さそうです。

    呪文のようにActivityのonCreateで記述していた
    setContentView(R.layout.main);

    という一文は res/layout/main.xml を読み込み画面に表示するぞ という準備です。

    ということは ボタンをクリックしたときに、画面の見た目をhogehoge.xmlに変化させるには、OnClickの中に setContentView(R.layout.hogehoge); を記載すればよい

    また、IntentでActivityを遷移すると 「クリアボタン」 で戻ることができる画面遷移になり、いま見ているディスプレイの後ろにIntent遷移元の画面が隠れて居る状態なので、メモリを保持し続けなければならず、Intentを立ち上げすぎてメモリオーバーで「強制終了しました」のエラーが起こりえます。

    また、少し難しい処理をActivityにベタっと記述すると、Activityファイルがとても長いファイルになり可読性も落ちるので、Activityをextendsしない普通のクラスファイルに処理を記述するのが良さそうです。
    普通のクラスファイルの置き場もActivityと同じ場所におく事が普通です。

    例えば、helloというプロジェクトにの場合は
    hello/src/jp.example.hello/ 配下に Hogehoge.java というクラスを置く、と決めます。
    クラスファイルの頭文字は大文字が主流っぽいです。アッパーキャメルケースですね。
    例) hello/src/jp.example.hello/Hogehoge.java

    もしくは hello/src/jp.example.hello.hogehoge/ というディレクトリを作成し、そこにhogehogeという処理に関わるファイルを設置するというのも主流です。
    例) hello/src/jp.example.hello.hogehoge/LoadImageTask.java

    ちなみにhogehogeとかホゲホゲとは 抽象的な何々の〜の意味です。

    筆者は以下のように心がけて構築しようと思います。

    • Activityファイルは量産しない
    • IntentでのActivity間の画面遷移は必要最小限にする
    • Activityに処理を長々と書かず、クラスファイルに分ける
    • 共通の処理はクラスファイルに分ける

    これらの方法で 画面遷移 = アクティビティの切り替え というWEBエンジニアが陥りやすい構築方法を改善していきます。

    何かボタンを押した時に、WEBサイトでは URL が切り替わるというのが一般的です。

    最近のWEBでは何かボタンを押した時に Ajaxで処理ファイルAPIに通信し次の挙動を起こすという方法がありますが、古き良き時代のHTMLの構造では基本的にはURLを遷移し異なるページを閲覧させます。

    HTMLファイル や CGI が切り替わる仕組みが頭にあると、Android開発に置いても 画面が切り替わる = アクティビティが切り替わる と考えがちです。

    そうなると 30パターンの画面遷移があると 30個アクテビティが出来てしまいます。

    このような構築方法で開発し実際に実機でテストしてみると分かるのですが、遷移し続けてメモリオーバーで強制終了になることが多いです。

    どおやらこの方法は違うな?と気づいた頃にはアクティビティで溢れていることでしょう。

    WEBエンジニアの方でも、APIを多用しAjax通信で1枚の画面の中で完結するようなWEBサイトを作れる方は感覚をつかみやすいかも知れません。

    ・画像やボタンを表示される目に見えるHTML部分が「View」
    ・ボタンをおした時のjavascriptのAjax通信する部分を「イベント」
    ・通信されるAPIファイルが
    ・Ajax通信して帰ってきた値を処理する部分が「イベントリスナー」

    「イベント」はユーザーが画面をクリックやタッチやロングタップやダブルクリックや画面を傾けたり等をする事です。

    「イベントハンドラ」は「イベント」が起こったこらどうするかを判断(ハンドリング)する部分です。

    「イベントリスナー」のリスナーは「聞き手」という意味ですが、「ボタンが押されたので処理をお願いします」という意見を聞いて処理をする部分です。

    参考)http://www.edu.tuis.ac.jp/~yamasaki/mobileApp/Android_event.html