Android応用
WebAPI 開発
トレーニングの目的
Android で WebAPI を利用し、アプリケーション開発に必要な知識
を身につける。
WebAPI にアクセスをする方法
非同期による表示方法
レスポンスデータの解析方法
JSON
XML

サービスを使う
演習を通して、上記事項が必要な理由を体験する
演習で習得した一連の技術を全て使った動画ダウンローダアプリケーシ
ョンを作成する

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ-2
トレーニングスケジュール
1日目
1章 トレーニング概要
2章 WebAPI開発知識
3章 チュートリアル
4章 ListViewの応用
5章 非同期処理

2日目
6章
7章
8章
9章
10章

Webサービスに接続する
JSON,XMLの解析
サービス
動画ダウンローダを作る
トレーニングのまとめ

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ-3
受講に必要なスキル
本セミナーを受講するにあたり、以下のスキルが必須となる。
Java 言語の経験があること
演習では、実際に Java でプログラミングを行う。
基本的な Java の言語仕様について理解していれば問題ない。

Eclipse を使用した経験があること
演習では、Eclipse を使用してプログラミングを実施する。
基本的な Eclipse の使用方法について理解していれば問題ない。

OESF公認Androidアプリケーション開発入門コースを受講済 ないし 同
等のスキルを有する。
Androidアプリケーションの基礎的なスキルを有する
複数画面からなる簡単なアプリケーション作成ができる

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ-4
1.

トレーニング概要
概要
演習で用いる開発環境
演習で用いるアプリケーション
演習概要

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ-6
開発環境
開発環境の説明
本トレーニングでは下記の開発ツールを用いる
トレーニング用マシンは既に開発環境は構築済みです
SDK付属のToolsに環境変数のパスが通っている
エミュレータ
演習で使用するエミュレータは、特段の指定がない限りWVGA800を用いる
こと
100M程度のSDカード領域を用意しておくこと
ソフトウェア

バージョン

Eclipse

Eclipse IDE with built-in ADT

Java SDK

JDK 1.6

Android Platform SDK

Android 2.3.3(API 10)

Android Plug-in

Android Development Tools (ADT) Ver.22.X.X

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ-7
演習概要
開発環境の説明
ディレクトリ構成
トレーニングに必要なファイルは全てandroid_traing_webapiに用意してあり
ます。
以下はandroid_traing_webapiのディレクトリ構成になります
パス(c:¥android_trainig_webapi以下)

内容

adt-bundle-windows-x86-[日付]¥sdk

AndroidSDK

adt-bundle-windows-x86-[日付]¥eclipse

eclipse

workspace

eclipseのワークスペース

gae_setup

GAEサーバ環境構築ツール

server¥webapi_server

WebAPIサーバ

datas

サンプル動画

answer_docs/html

実習の解答ドキュメント

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ-8
演習で用いるアプリケーション(1
)
演習では、動画ダウンロードアプリケーションを作成します。
動画ダウンローダの機能
画面遷移
WebAPIを使ったHTTP通信
バックグラウンドで動く処理
• Threadを使った描画
• サービスを使ったダウンロード機能
ListViewの応用技術
JSON、XMLの解析

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ-9
演習で用いるアプリケーション(2
)
動画ダウンローダーの画面構成

画面パーツ

サムネイル

サムネイル

動画のサムネイル画像を表示する

タイトル

動画に付けられているタイトルを表示
する

説明

タイトル

説明

動画の説明を表示する

説明

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 10
演習で用いるアプリケーション(3
)
明示的Intentに
よる画面遷移

WebAPIへの
接続

WebAPIサーバから検
索結果を取得する

SD Card
動画をSD Card
に保存
検索キーワード
を入力し、
「Serarch」ボタ
ンで遷移する

JSON・XMLの
解析処理

行をクリックして動
画をダウンロード

リストビュー
をカスタマイ
ズ

行をクリッ
クして再生

サービスを使っ
てダウンロード
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 11
演習の進め方(1)
プロジェクトの共通設定
演習で作成するプロジェクトは特に指定のない限り以下の設定になりま
す。
項目

設定値

Project name

演習毎に指定

Build Target

※講師の指示に従う

Application name

Project nameと同じ

Package name

jp.oesf.xxx
※xxxはプロジェクト名小文字が入
る

Create Activity

Project name + Activity

Min SDK Version

Build Targetと同じ

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 12
演習の進め方(2)
実習用プロジェクトをダウンロードする方法
各章ごとに完成プロジェクトとスケルトンプロジェクトを含んだプロジ
ェクトファイルがzip形式で用意しています
手順
「answer_docs/html/index.html」を開く
ファイルをダウンロードする(※キャプチャ参考)
例)解答 ListViewの応用
必要な実習プロジェクトは
各章の解答ページにありま
す。

「プロジェクトファイルのダウン
ロード」のダウンロードを選んで
This material is licensed under the Creative
ⅰ - 13
下さい
Commons License BY-NC-SA 4.0.
演習の進め方(3)
実習用スケルトンプロジェクトをEclipseにインポートする方法
トレーング実習ではあらかじめ用意してある、スケルトンプロジェクト
を使って実習をすることがあります。
例) HTTP通信のスケルトンプロジェクトをインポートする
ファイル名:HttpSample_skeleton01

「 File 」から「イン
ポート」を選し、「イ
ンポート」ダイアログ
を表示

「 General 」を選択し
「 Existing Projects into
Workspace 」を選択し
て「Next」をクリック

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

Browse」ボタンより
「HttpSample_skeleton01
」フォルダを選択

「Finish」をク
リック

ⅰ - 14
演習の進め方(4)
タスクビューの表示方法
スケルトンプロジェクトを使った実習では、修正箇所をタスクに登録し
ています
メニューの
「Window」から
「ShowView」の
「Tasks」を選択しま
す
「Tasks」を選択すると
Eclipseの下部にタス
クリストが表示されま
す

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 15
動画サーバ概要
サーバの概要
演習で使用する動画サーバは「Google App Engine Python(以下 GAEと
略称)」を使用しています
GAEはローカルでも起動することができ、GAEアカウントを持っていれ
ば誰でも簡単にデプロイすることができます。
GAE Pythonのセットアップに必要なもの
GAEセットアップツールフォルダ:「c:android_training_webapigae_setup」
• Python 2.5.X
• PIL(※必須ではないがイメージを扱う場合は必要になる)
• Google App Engine SDK for Python

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 16
動画サーバ構築手順(1)
構築手順
Python 2.5.4のインストール
python-2.5.4.msiを起動する
画面の指示に従い、「Next」をクリックして進める
※全ての画面でデフォルトの設定を適用します
最後に「Finish」をクリックして完了

PILのインストール
PIL-1.1.7.win32-py2.5.exeを起動する
画面の指示に従い、「次へ」をクリックして進める
※全ての画面でデフォルトの設定を適用します
最後に「完了」をクリックして完了

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 17
動画サーバ構築手順(2)
Google App Engine SDK for Pythonのインストール
1. GoogleAppEngine-1.6.1msiを起動する
2. 「I accept the terms in License Agreement」にチェックをいれ 「Next」
をクリック

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 18
動画サーバ構築手順(3)
3. 画面の指示に従い、 「Next」をクリックする
※全ての画面でデフォルトの設定を適用します

4. 以下の画面になったら「Install」をクリックする

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 19
動画サーバ構築手順(4)
5. 以下の画面になったら「Finish」を押して完了

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 20
GAEサーバを起動する(1)
起動手順
コマンドプロンプトを起動し、以下のコマンドを入力する
cd c:android_training_webapiserver
dev_appserver.py --address xx.xx.xx.xx webapi_server
※xx.xx.xx.xxは自分のIPアドレス

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 21
GAEサーバを起動する(2)
以下の画面になった場合は「y」を入力しEnterする
※表示されないこともあります

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 22
GAEサーバを起動する(3)
以下の画面になれば起動完了

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 23
GAEサーバを起動する(4)
ブラウザを起動しURL:「http://xx.xx.xx.xx:8080」を指定する
動画サーバ画面が表示される

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 24
2.

WebAPI開発知識
概要
WebAPI とは ?
非同期による画面表示の必要性
レスポンデータの解析
サービスの使いどころ

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 26
WebAPI とは ?
Web Application Programing Interface
Web 上にあるアプリケーションプログラムインタフェースのこと
基本的にはリクエストにパラメータを付与して、JSON・XML データの
やりとりを行う
代表的な物として、Yahoo API、 Google API、 Youtube API などがあ
る

Get/Post で送信

JSON・XML で送
信

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 27
非同期による画面表示の必要性
非同期処理の利点
表示処理に時間がかかる画面の場合、なかなか画面が表示されないと、
ユーザにストレスを感じさせてしまう
テキストと画像を表示する場合は、処理が分割できるので、最初にテキ
ストだけを表示させ、後から画像を表示することにより、ユーザのスト
レスを多少軽減させられる

非同期(別スレッ
ド)

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 28
レスポンデータの解析
レスポンデータの解析
WebAPIを使って通信を行うとレスポンデータが通常JSON,XMLなどの
形式で返ってくる
クライアント側では取得したデータを解析しなくてはいけない
そのため、AndroidでJSON,XMLの解析手段を知っておく必要がある

サービスの一例

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 29
レスポンデータの解析(JSON)
JSONとは
軽量のデータ記述言語
マークアップ言語ではないので、XMLの解析より高速に処理することが
可能
キー/バリューペアの集まりでデータ構造を記述している
文字コードは基本的にUTF-8のみ
AndroidではJSONの解析にorg.jsonを用いることができる

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 30
レスポンデータの解析(XML)
XMLとは
データをタグで囲んで、意味付けを行うフォーマット
タグの中に属性を持たせることができる
Androidでは以下の解析方法を用いることが可能
DOM
SAX
XMLPullparser

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 31
レスポンデータの解析(XML:DOM
)
DOM(ツリー構造型)
DOM ツリーとしてヒープに持つ。
パース時に XML の内容をすべてメモリ上に保持し、パース後にどの要
素にもいつでもアクセスできる。
すべてをメモリ上に保持するために、多くのメモリを消費するので、
Android が稼働するモバイル機器では問題がある。
XML 文書が小さい場合は DOM を使用すれば簡単に実装できる。

おそ~い

DO
M
消費メモリが多い

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 32
レスポンデータの解析(XML:SAX
)
SAX(イベント駆動型)
パーサがパースをしているアプリケーションを呼び出すようなイメージ
。
XML ドキュメントを頭から読んでいき、タグの開始や終了などに ぶつ
かると、決められたアプリケーション側のコールバックルーチンを コー
ルする。
アプリケーション側では DOMのようにXML ドキュメントの読み込みの
制御を行うことができない。
メモリの消費量は DOM よりも少ない。
Android には、従来の方法での SAX の使い方と、SAX の上に ラップさ
れたラッパーを使う方法が用意されている。
すげーはえー♪
!!!!!

ボクのほうが
扱いやすいもん・・・

SAX

DOM

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 33
レスポンデータの解析(XML:
XMLPullParser)
XMLPullParser(Pull 型)
JAVA でいうところの StAX と同じ機能を持つもの。
Android は StAX をサポートしていないので同じ機能を持
つ XMLPullParser が用意されている。
SAX と同じように XML ドキュメントを頭から読みこむが、読み込みの
制御をアプリケーション側で行い、必要に応じてパーサから情報を取得
することができる。
アプリケーション側から制御が行えるため、早い段階で構文解析を停止
させることができるので、構文解析に要する時間を大幅に短縮できる。
途中で止まれな
い!

いつでも止まれる♪

ボクも速い!

SAX

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 34
レスポンデータの解析(XMLまとめ
)
まとめ
DOM

SAX

XML
PullParser

パーサの
性質

ツリー構造

イベント駆動型
(制御不可)

イベント駆動型
(制御可能)

要素への
アクセス

ランダム

シーケンシャル

シーケンシャル

要素の取得

DOMツリーへの
アクセス

コールバック
ルーチン

イテレート時に
取得

XML書き出し

可能

不可能

可能

消費メモリ

多い

一番少ない

少ない

扱い易さ

扱いやすい

扱いにくい

扱いやすい

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 35
サービスの使いどころ
サービスを使う利点
サービスとは、ひと言で言えば常駐プログラムである
サービスの持つ機能の多くはスレッドでも実現可能だが、サービスでし
か出来なことも多い
スレッドとの違い
スレッドのような単発な機能だけでなく、一つのアプリケーションとしての役割を果たすケー
スが多い
全てのアプリケーションは同じサービスにアクセスすることができる
Activityとは別プロセスで実行することも可能で、プロセス間通信も行うことができる
Activity終了後に再起動しても同じサービスにアクセスすることもできる。
サービ
スレッ
ス
ド

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 36
サービスの使いどころ
スレッドとサービスの違いを意識し、サービスの使いどころを考える必
要がある
スレッドの使いどころ
Activityが消滅してしまうとアクセスすることが出来ないため主にUIに関わる処理
で使用する
• 画面に依存するI/O処理などで使用するケースが多い
ライフサイクルを意識し、適切なタイミングでキャンセルできるようにする必要
がある
例)
• 画面表示用の画像のダウンロード
• プログレスバーの表示
• DBやSDカードのアクセス

サービスの使いどころ
Activityのライフサイクルには依存しないため、完全に独立した処理で使用する
例)
• アラーム、タイマー
• ダウンロード
• 音楽再生

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 37
3.

チュートリアル
表示画面間でパラメータの受け渡し
アクティビティ間でパラメータを受け渡すには
仕組み
アクティビティ間でパラメータを受け渡すには、画面遷移の際に作成する
Intentオブジェクトに受け渡したいパラメータを設定する
パラメータはキー、値の組み合わせで作成する
遷移先画面は、アクティビティのメソッドを使用して送付されたIntentオブジ
ェクトを取得し、起動元画面がパラメータを設定する際に使用したキーを使
用して、Intentオブジェクトから値を取得する
アクティビティA

インテントにパラメータ
(キーと値)を詰める

アクティビティB

インテン
ト

インテン
ト

Android
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

• インテントからパラ
メータを取得する
• パラメータのキーを指
定して値を取り出す
ⅰ - 39
表示画面間でパラメータを渡す
インテントを使用してパラメータを渡す方法
起動元アクティビティ
1. 起動元アクティビティでIntentオブジェクトを生成する
2. IntentオブジェクトにIntent#putExtraメソッドを使用してパラメータを追加
する
• パラメータは「キー、値」のセットで設定する
3. Activity#startActivityメソッドを使用して、起動先アクティビティを呼び出す
サンプルコード(起動元アクティビティ)

public class SampleListActivity extends ListActivity {
・・・・・・・・
@Override
protected void onListItemClick(ListView listView, View view, int position,
long id) {
Intent intent = new Intent(this, NextActivity.class); ・・・1
intent.putExtra(“message”, “Android”);
・・・2
startActivity(intent);
・・・

3
}
}

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 40
表示画面間でパラメータを受け取る
インテントからパラメーターを受け取る方法
1. 起動されたアクティビティで、Activity#getIntentメソッドを使用して、イン
テントオブジェクトを取得する
2. データの型に応じたIntent#getExtraメソッドを使用して、Intentオブジェクト
に格納されているパラメータを取得する
• Integer型 ・・・ getIntegerExtra
• Long型 ・・・ getLongExtra
• String型 ・・・ getStringExtra

起動されたサンプルコード(onCreateでパラメータを取得する例)
public class NextActivity extends Activity {
・・・・・・・・
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
Intent intent = getIntent();
String message = intent.getStringExtra(”message”);

・・・1
・・・2

}
}

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 41
画面遷移アプリケーションの作成
(1)
実習1 (15分)
簡単な画面遷移アプリケーションを作成します

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 42
画面遷移アプリケーションの作成
(2)
アプリケーション概要
<プロジェクト設定>
項目

設定値

Project name

ActivitySample

Build Target

※トレーニングで指定したバージョン

Application name

ActivitySample

Package name

jp.oesf.activitysample

Create Activity

MainActivity

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 43
画面遷移アプリケーションの作成(
3)
手順
1. MainActivityの画面デザインを変更する
2. 遷移画面のレイアウトを作成
ファイル名:activity_next.xml

3. 遷移画面のActivityを作成
ファイル名:NextActivity.java

4. MainActivityにIntentにデータを格納する処理の追加
5. NextActivityにIntentからデータを取得する処理の追加
6. AndroidManifest.xmlにNextActivityを追加する

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 44
画面遷移アプリケーションの作成
(4)
リソースファイルの設定
<activity_main.xml>
ビュー
LinearLayout

階層構造
<LinearLayout>
<EditText />
<Button />
</LinearLayout>

プロパティ
android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical”

EditText

android:layout_height="wrap_content"
android:layout_width="match_parent”
android:id="@+id/edit_message"

Button

android:id=“@+id/Button01”
android:layout_width =“match_parent”
android:layout_height=“wrap_content”
android:text=“@string/next”
android:onClick=“onClickNextButton”

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 45
画面遷移アプリケーションの作成
(5)
リソースファイルの設定
<activity_next.xml>
ビュー

プロパティ

LinearLayout

階層構造

android:layout_width=“match_parent”
android:layout_height=“match_parent”
android:orientation=“vertical”

TextView

<LinearLayout>
<TextView />
<Button />
</LinearLayout>

android:text="@string/next_activity"
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

Button

android:id=“@+id/Button01”
android:layout_width =“match_parent”
android:layout_height=“wrap_content”
android:text=“@string/finish”
android:onClick=“onClickFinishButton”

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 46
画面遷移アプリケーションの作成
(6)
リソースファイルの設定
<string.xml>
項目

設定値

next

Next

finish

Fnish

main_activity

MainActivity

next_activity

NextActivity

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 47
画面遷移アプリケーションの作成
(7)
Main画面からNext画面へデータを渡す
MainActivity
public void onClickNextButton(View v){
EditText editMessage = (EditText)findViewById(R.id.edit_message);
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("message", editMessage.getText().toString());
startActivity(intent);
}

Intentからデータ取得
NextActivity
Intent intent = getIntent();
String message = intent.getStringExtra(“message");
TextView textView = (TextView)findViewById(R.id.text_title);
textView.setText(message);

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 48
画面遷移アプリケーションの作成
(確認)
確認
以下のように画面遷移することを確認する

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 49
画面遷移アプリケーションの作成
(解答1)
解答
MainActivity.java
package jp.oesf.activitysample;
import
import
import
import
import

android.os.Bundle;
android.view.View;
android.widget.EditText;
android.app.Activity;
android.content.Intent;

public class MainActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void onClickNextButton(View v) {
EditText editMessage = (EditText) findViewById(R.id.edit_message);
Intent intent = new Intent(this, NextActivity.class);
intent.putExtra("message", editMessage.getText().toString());
startActivity(intent);
}
}

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 50
画面遷移アプリケーションの作成(解答
2)
解答 (続き)
NextActivity.java
package jp.oesf.activitysample;
import
import
import
import
import

android.os.Bundle;
android.view.View;
android.widget.TextView;
android.app.Activity;
android.content.Intent;

public class NextActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
Intent intent = getIntent();
String message = intent.getStringExtra("message");
TextView textView = (TextView)findViewById(R.id.text_title);
textView.setText(message);
}
public void onClickFinishButton(View v){
finish();
}
}
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 51
画面遷移アプリケーションの作成
(解答3)
解答 (続き)
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<EditText
android:id="@+id/edit_message"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</EditText>
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClickNextButton"
android:text="@string/next" />
</LinearLayout>
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 52
画面遷移アプリケーションの作成
(解答4)
解答 (続き)
activity_next.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".NextActivity" >
<TextView
android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />

<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClickFinishButton"
android:text="@string/finish" />
</LinearLayout>

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 53
画面遷移アプリケーションの作成
(解答5)
解答 (続き)
string.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
<string
<string
<string
<string
<string
<string
<string

name="app_name">ActivitySample</string>
name="hello_world">Hello world!</string>
name="menu_settings">Settings</string>
name="title_activity_next">NextActivity</string>
name="finish">Finish</string>
name="next">Next</string>
name="main_activity">MainActivity</string>
name="next_activity">NextActivity</string>

</resources>

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 54
画面遷移アプリケーションの作成
(解答6)
解答 (続き)
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
〜略〜
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="jp.oesf.activitysample.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>
<activity android:name="jp.oesf.activitysample.NextActivity“ >
</activity>
</application>
</manifest>

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 55
4. ListViewの応用
概要
ListViewの使い方
ListViewにデータを表示する
ListViewを使ったサンプルアプリケーション
ListViewをカスタマイズする

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 57
ListViewの使い方
ListViewとは
ListViewはデータをリスト形式で表示するためのビューグループです
ListViewを使用するときは画面デザインと行デザインの2つのリソースフ
ァイルが必要
リスト形式で表示

画面デザイン

行デザイン

ⅰ - 58

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
ListViewの使い方
ListViewはアイテム内のレイアウトを変更することも可能です

ⅰ - 59

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
ListViewにデータを表示する
Adapterとは
ListViewなどのデータを一覧形式で表示するViewGroupのインタフェー
スとしてAdapterクラスが用意されています
Adapterによってデータ1件分を表示するViewを組み立てる役割を担当
しています
データとViewの繋
ぎ役をします

Adapter

データ

表示するViewを組み立てます
ⅰ - 60

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
Adapterの役割
Viewの組み立ての仕組み
Adapterはデータとビューの連携を担っており、表示すべきビューをデー
タから組み立てるのが役割です
データ1件分をどのようなView構造で表示するかを決定するのが
getViewメソッドです
getViewメソッド
getViewメソッドは、新しいデータが表示されるタイミングで呼び出されます
ListViewの場合、画面をスクロールして、画面外から新しいデータが表示さ
れるタイミングで呼び出されます
戻り値

メソッド名

View

getView (int position, View contentView, ViewGroup parent)

ⅰ - 61

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
ArrayAdapter
ArrayAdapter
Androidにはデータの管理方法に適したAdapterクラスが複数用意されて
います
ArrayAdapterクラスは配列やListなどのデータ形式を管理するのに適した
Adapterです
ArrayAdapter<T>( Context context,
int textViewResourceId,
T[] objects)

ArrayAdapterのコンストラクタ
引数

説明

Context context

クラスのオブジェクトを指定します。

int textViewResourceId

行レイアウトのリソースIDを指定します。

T[] objects

表示データ配列のオブジェクト を指定

ⅰ - 62

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
ListViewのサンプルアプリケーシ
ョン 1 (1)
実習1
ListViewを使ったサンプルアプリケーションを作成する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 63
ListViewのサンプルアプリケーシ
ョン 1 (2)
プロジェクトの概要
項目

設定値

Project name

ListSample

Build Target

※トレーニングで指定したバージョン

Application name

ListSample

Package name

jp.oesf.listsample

Create Activity

ListSampleActivity

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 64
ListViewのサンプルアプリケーシ
ョン 1 (3)
手順
1. レイアウトファイルを修正する
ListViewを定義した画面デザインのレイアウトファイルを作成
ファイル名:activity_list_sample.xml

2. 行用のレイアウトファイルを作成する
ListView内で使用する、行デザインのレイアウトファイルを作成する
ファイル名:list_row.xml

3. 一覧表示のActivityを作成する
継承元をListActvitiyに変更する
ListActivityとAdapterを使用してデータをリストとして表示する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 65
ListViewのサンプルアプリケーシ
ョン 1 (4)
1. レイアウトファイルを修正する
ListViewを定義した画面デザインのレイアウトファイルを作成
ファイル名:activity_list_sample.xml
View

Property

LinearLayout

android:layout_width="match_parent"
android:layout_height="wrap_content"

ListView

android:id="@android:id/list" ※
android:layout_width="match_parent"
android:layout_height="wrap_content"

※ListActivityを使用する場合は必ずこのidにする

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 66
ListViewのサンプルアプリケーシ
ョン 1 (5)
2. 行用のレイアウトファイルを作成する
ListView内で使用する、行デザインのレイアウトファイルを作成する
ファイル名:list_row.xml
View

Property

TextView

xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"

※list_row.xmlではTextViewしか使用しません

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 67
ListViewのサンプルアプリケーシ
ョン 1 (6)
3. 一覧表示のActivityを作成する
ListSampleActivityクラスの継承元をListActvitiyに変更する
ListActivityとAdapterを使用してデータをリストとして表示する
ArrayAdapterをセットする
public class ListSampleActivity extends ListActivity {
・・・
public static final String[] ITEMS = { "柴犬", "北海道犬", "甲斐犬", "紀州犬", "土佐犬",
①
"四国犬", "秋田犬", "縄文犬", "琉球犬", "川上犬", "薩摩犬", "美濃柴", "山陰柴", "まめしば" };
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_sample);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.list_row, ITEMS);
setListAdapter(adapter);
・・・
}

・・・
②

③

}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 68
ListViewのサンプルアプリケーシ
ョン 1 (7)
実行結果
以下のようになることを確認

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 69
ListViewのサンプルアプリケーシ
ョン 1 (解答)
解答
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 70
1行選択を認識する
ListViewを選択する
ListViewの一行をタッチで選択するためには、
ListActivity#onListItemClickメソッドを実装します。
onListItemClickの定義
引数

意味

ListView listView

クリックされたListView

View view

クリックされたView

int position

リスト内の位置

long id

クリックされたアイテム
ID

サンプル
public class ListSampleActivity extends ListActivity {
・・・・・・・・
@Override
protected void onListItemClick(ListView l, View v, int position, long id){
Log.v("ListSample", "position = " + position);
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 71
ListViewのサンプルアプリケーシ
ョン 2 (1)
実習2
前項で作成したプログラムを修正し、一覧形式で表示したデータを選択
すると
ログを出力するプログラムを作成する。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 72
ListViewのサンプルアプリケーシ
ョン 2 (2)
手順
ListActivity#onListItemClickの実装
onListItemClickメソッド内にログ出力
• tag :「ListSample」
• message :「position = [選択番号]」

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 73
ListViewのサンプルアプリケーシ
ョン 2 (3)
確認
リストの一行をタッチしたときにログが出力されることを確認する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 74
ListViewのサンプルアプリケーシ
ョン 2 (解答)
解答
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 75
ListViewをカスタマイズする
実習3
ListViewのカスタマイズ
ListViewをカスタマイズして、使いやすいユーザーインタフェースを作成す
る。
• <完成図>
サムネイル
タイトル

説明

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 76
ListViewをカスタマイズする
手順
1. 行レイアウトの作成
サムネイル、タイトル、説明の要素を追加する

2. カスタムAdapterの作成
RowModelの定義 <実装済>
TableAdapterクラスの作成
string-arrayの定義 <実装済>
※スケルトンプロジェクトを使用しても
よい
• 「ListSample_03_skeleton」

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 77
手順 1 行レイアウトの作成(1)
1. 行レイアウトの作成
1行に、「サムネイル」「タイトル」「説明」の3つの要素を表示できるよ
うにする
レイアウトファイルlist_row.xmlを編集する
• サムネイル=>ImageView
• タイトル、説明=>TextView
上記をLinearLayoutを駆使して以下のような並びになるようにする

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 78
手順 1 行レイアウトの作成(2
)
設定情報

View

Property

ImageView

android:id="@+id/image_thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"

LinearLayout(内側)

android:id="@+id/LinearLayout01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"

TextView(タイトル)

android:id="@+id/text_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedi
um"

TextView(詳細)

android:id="@+id/text_summary"
android:text="default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall
"

※外側のLinearLayoutは省略

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 79
手順 2. カスタムAdapterを作成す
る(1)
2. カスタムAdapterを作成する
1. 作成手順
<実装済>
1. データクラスRowModelを作成する
– メンバーに「サムネイル・タイトル・説明」を保持する

<未実装>
2. ArrayAdapterを継承してTableAdapterクラスを作成する
– getView()をオーバーライドし、必要な処理を実装する
– convertViewのnullチェック対応は必須
– 各項目のビューへ値を設定する

3. setListAdapterしているAdapterを変更する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 80
手順 2. カスタムAdapterを作成す
る(2)
1. RowModelを作成する
「src」フォルダ配下にパッケージ [jp.oesf.listsample.model]を作成する
RowModelクラスを作成する
「サムネイル タイトル 説明」 を保持するメンバ変数を定義する
各変数のgetter,setterメソッドを用意
public class RowModel {
private String title;
private Drawable thumbnailImage;
private String summary;
「

各変数のgetter setter を記載 」

}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 81
手順 2. カスタムAdapterを作成す
る(3)
2. ArrayAdapterを継承したTableAdapterクラスを作成する
ListSample.javaファイルにArrayAdapterを継承したTableAdapterクラスを作
成 ジェネリックにRowModelを指定する
getViewをオーバーライドしたメソッドを作成

※内部クラスとして定義す
る
class TableAdapter extends ArrayAdapter<RowModel> {
public TableAdapter(Context context) {
super(context, R.layout.list_row);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
RowModel item = getItem(position);
if (convertView == null) {
// Viewを作成する
LayoutInflater inflater = getLayoutInflater();
convertView = inflater.inflate(R.layout.list_row, null);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 82
手順 2. カスタムAdapterを作成す
る(4)
2. ArrayAdapterを継承したTableAdapterクラスを作成する<続き>
nullチェックを行い、Viewの生成と取得したItemをセットする
if (item != null) {
// Image
ImageView imageView = (ImageView) convertView.findViewById(R.id.image_thumbnail);
if (imageView != null) {
imageView.setImageDrawable(item.getThumbnailImage());
}
// Title
TextView textTitle = (TextView) convertView.findViewById(R.id.text_title);
if (textTitle != null) {
textTitle.setText(item.getTitle());
}
// summary
TextView textSummary = (TextView) convertView.findViewById(R.id.text_summary);
if (textSummary != null) {
textSummary.setText(item.getSummary());
}
}
return convertView;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 83
手順 2. カスタムAdapterを作成す
る(5)
3. Adapterと値のセット
MainActivityのonCreateメソッドでsetListAdapterでTableAdapterをセット
リソースからテキスト配列を取得する
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_sample);
TableAdapter adapter= new TableAdapter(this);
setListAdapter(adapter);
//RowModelの作成
String[] titles = getResources().getStringArray(R.array.titles);
String[] summaries =
getResources().getStringArray(R.array.summaries);
Drawable image =
getResources().getDrawable(R.drawable.ic_launcher);
int num = titles.length;

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 84
手順 2. カスタムAdapterを作成す
る(6)
3. Adapterと値のセット <続き>
取得した配列からRowModelの値をセット
RowModelをAdapterにセットする
for(int i = 0; i < num; i++){
RowModel row = new RowModel();
row.setTitle(titles[i]);
row.setSummary(summaries[i]);
row.setThumbnailImage(image);

adapter.add(row);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 85
文字列配列リソース(1)
string-arrayタグ
xmlファイルにデータを記載することで、アプリケーションから文字列
配列のデータを取得できるようになります。
構文
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="string_array_name">
<item>text_string</item>
<item>text_string</item>
</string-array>
</resources>

string-arrayの定義名を記載します。
リソースIDとして使用されます。

String-arrayの中に格納される
データを記載します。

◆値の取得方法
getStringArray(”定義名”)を使用することで<item></item>内の値を取得できます
String titles[] = getResources().getStringArray(R.array.string_array_name);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 86
文字列配列リソース(2)
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ListSample</string>
<string-array name="titles">
<item>柴犬</item>
<item>北海道犬</item>
<item>甲斐犬</item>
<item>紀州犬</item>
<item>土佐犬</item>
<item>四国犬</item>
<item>秋田犬</item>
<item>縄文犬</item>
<item>琉球犬</item>
<item>川上犬</item>
<item>薩摩犬</item>
<item>美濃柴</item>
<item>山陰柴</item>
<item>まめしば</item>
</string-array>

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 87
文字列配列リソース(3)
strings.xml(続き)
<string-array name="summaries">
<item>日本人の心。日本犬の中で唯一の小型犬。</item>
<item>別名アイヌ犬。純粋和犬とは別種とする考え方も</item>
<item>虎毛カコイー!中型と小型のあいだの大きさ</item>
<item>白が多い。巻尾より差し尾が多い</item>
<item>土佐闘犬。マスティフやブルドッグ、グレート・デーンなどを配し作られた犬
</item>
<item>ニホンオオカミと間違われることも!</item>
<item>日本犬唯一の大型犬。、「秋田マタギ」、マタギ犬。ハチー!</item>
<item>土着の日本犬</item>
<item>縄文時代以来の古い犬の形質を残すとされる</item>
<item>長野県の天然記念物</item>
<item>西郷隆盛の愛犬</item>
<item>美濃犬、飛騨柴とも</item>
<item>因幡犬がベース。差し尾、晩成型。飼えば飼うほど形が変わる?!</item>
<item>小型の柴犬の愛称。JKCや日本犬保存会には「豆柴」という血統書は存在しない
</item>
</string-array>
</resources>

リソースとして取得するコード

// getting resource array data
String titles[] = getResources().getStringArray(R.array.titles);
String summaries[] = getResources().getStringArray(R.array.summaries);
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 88
ListViewのカスタマイズ(確認)
実行結果
以下のようになることを確認

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 89
ListViewのカスタマイズ(解答)
解答
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 90
5. 非同期処理
概要
非同期について
Threadを使う
AsyncTaskの概要
実習

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 92
非同期による画面表示(1)
画面表示
表示処理に時間がかかる画面の場合、なかなか画面が表示されないと、
ユーザにストレスを感じさせてしまう。
テキストと画像を表示する場合は、処理が分割できるので最初にテキス
トだけを表示させ、後から画像を表示することにより、ユーザのストレ
スを多少軽減させられる。
非同期(別スレッド)

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 93
非同期による画面表示(2)
演習
まずは実行してみて、同期の状態を体感する。
プロジェクト:ListSample_async_skeleton

何も表示されない状態が続く

すべてのデータの読み込みが
終了すると画面が表示される94
ⅰ-

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
非同期による画面表示(3)
非同期で処理した場合
画像等のダウンロードに時間がかかる処理は、後から表示するようにな
り、
使用者のストレスを軽減させることができる。

すぐにローディン
グ
アイコンが表示さ
れる

完了

徐々にアイコン
が
表示される

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 95
Threadを使う
Thread
Threadはフォアグランドでは行いたくない時間のかかる処理を実行する
ときに良く使われます。
フォアグランドで時間のかかる処理を実行すると、画面UIの操作ができなく
なるため、Threadを使ったほうがよい。

Androidではフォアグランドで動いているThreadをメインスレッドまた
は、UIスレッドと呼びます。
AndroidでもThreadを使用することができますが、UIスレッド以外のス
レッドからは直接UIを操作できないという制限があります。
UIスレッド以外のスレッドからUIを操作する場合はHandlerクラスを使用
します。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 96
ThreadからUIを変更する
Handler
HandlerクラスはスレッドからのUIの操作を可能にします。
UIスレッド以外のスレッドからUIを変更しようとするとランタイムエラーが
発生し、アプリケーションが強制終了します。そのため、UIスレッド以外か
らUIの操作を実現するためにHandlerクラスというものが用意されています。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 97
Handlerの使い方(1)
Handlerの使い方
スレッドからUIを操作する際はHandler#postメソッドを呼び出します。
引数にRunnableの実装クラスを指定します。
HandlerインスタンスはUIスレッドで定義する必要があります。

実装例
※サンプルソースでは時間のかかる処理は行っていませんが、実際には時間
のかかる処理のあとにTextViewの表示文字列を操作を仮定したサンプルです

悪い例
Handlerを使っていない
class BadThread extends Thread{
@Override
public void run() {
// ・・・時間のかかる処理 ・・・
TextView tv = (TextView)findViewById(R.id.textView1);
tv.setText("Hello Thread");
}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 98
Handlerの使い方(2)
悪い例 2
HandlerインスタンスをUIスレッド以外で生成している
class BadThread2 extends Thread{
@Override
public void run() {
// ・・・時間のかかる処理 ・・・
//Threadで使用するのでfinal指定をする
final TextView tv = (TextView)findViewById(R.id.textView1);
//Handlerの定義
Handler handler = new Handler();
//Handler#postメソッドを呼び出すとrunメソッドの処理がUIスレッド上で実行される
handler.post(new Runnable() {
@Override
public void run() {
tv.setText("Hello Thread");
}
});
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 99
Handlerの使い方(3)
良い例
HandlerインスタンスをUIスレッドで定義し、postメソッド内でUIを操作して
いる
public class HandlerSample extends Activity {
// Handlerの定義
Handler mHandler = new Handler();
public void onClickThreadStart(View v) {
new GoodThread().start();
}
class GoodThread extends Thread {
@Override
public void run() {
// Threadで使用するのでfinalで指定する
final TextView tv = (TextView) findViewById(R.id.textView1);
// Handler#postメソッドを呼び出すとrunメソッドの処理がUIスレッドで実行される
mHandler.post(new Runnable() {
@Override
public void run() {
tv.setText("Hello Thread");
}
});
}
}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 100
ThreadからUIを変更する(1)
実習1
Handlerクラスを使って、UIをThreadから操作できることを確認する
HelloThreadという文字をThreadから表示する

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 101
ThreadからUIを変更する(2)
プロジェクト概要
項目

設定値

Project name

HandlerSample

Build Target

※トレーニングで指定したバージョン

Application name

HandlerSample

Package name

jp.oesf.handler

Create Activity

HandlerSample

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 102
ThreadからUIを変更する(3)
手順
1. レイアウトの修正
2. Threadを継承したクラスの作成
3. Button押下時の処理

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 103
ThreadからUIを変更する(4)
1. レイアウトの修正
strings.xmlにButtonラベルを追加する
name

value

string_thread_start

Thread Start

activity_handler_sample.xmlにTextViewとButtonを追加する
階層構造

<Linear
Layout
>

View

Property

TextView

android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"

Button

android:text="@string/string_thread_start"
android:id="@+id/button1"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:onClick="onClickThreadStart"

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 104
ThreadからUIを変更する(5)
2. Threadを継承したクラスの作成
Threadを継承したクラスを作成し、runメソッドをオーバライドします。
runメソッド内でTextViewの値を“Hello Thread”に設定します。
public class HandlerSample extends Activity {
// Handlerの定義
Handler mHandler = new Handler();
~略~
class GoodThread extends Thread {
@Override
public void run() {
// Threadで使用するのでfinalで指定する
final TextView tv = (TextView) findViewById(R.id.textView1);
// Handler#postメソッドを呼び出すとrunメソッドの処理がUIスレッドで実
行される
mHandler.post(new Runnable() {
@Override
public void run() {
tv.setText("Hello Thread");
}
ⅰ - 105
});
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
ThreadからUIを変更する(6)
3. Button押下時の処理
Button押下時にThreadを継承したクラスを実行します。

public void onClickThreadStart(View v){
new GoodThread().start();
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 106
ThreadからUIを変更する(確認
)
確認
Button押下時にTextViewに“Hello Thread”と表示されること

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 107
ThreadからUIを変更する(解答
)
解答
public class HandlerSample extends Activity {
// Handlerの定義
Handler mHandler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler_sample);
}
public void onClickThreadStart(View v) {
new GoodThread().start();
}
class GoodThread extends Thread {
@Override
public void run() {
// Threadで使用するのでfinalで指定する
final TextView tv = (TextView) findViewById(R.id.textView1);
// Handler#postメソッドを呼び出すとrunメソッドの処理がUIスレッドで実行される
mHandler.post(new Runnable() {

@Override
public void run() {
tv.setText("Hello Thread");
}
});
}
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 108
AsyncTask
AsyncTaskとは
Android は他のスレッドから UI スレッドにアクセスするための手段とし
てHandler以外にAsyncTaskというユーティリティクラスを提供していま
す。
ThreadでHandlerを使うことは、コードが冗長的になり、読みづらくな
ります。そのため、Androidで頻繁にUIを操作する場合はAsyncTaskを使
用します。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 109
AsyncTaskの使用例
AsyncTaskの使用例
Threadを使っていた処理をAsyncTaskに置き換えると以下のようになり
ます。
doInBackgroundで時間のかかる処理をおこない、onPostExecuteで
TextViewの表示文字列をHandlerを使わずに変更しています。

class MyAsyncTask extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(Void... params) {
// ・・・時間のかかる処理 ・・・
return null;
}

@Override
protected void onPostExecute(Void result) {
TextView tv = (TextView)findViewById(R.id.textView1);
tv.setText("Hello Thread");
}

}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 110
AsyncTaskの使い方
AsyncTaskを使う
AsyncTaskクラスを継承したクラスを定義します
AsyncTask のサブクラスでは、扱う型を指定する必要がある。
実行時引数(Params)
進捗単位(Progress)
処理結果(Result)
ジェネリック

説明

Params

doInBackgroundメソッドの引数

Progress

onProgressUpdateメソッドの引数

Result

onPostExecuteメソッドの引数
doInBackgroundメソッドの戻り値と一致
している必要がある

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 111
AsyncTaskを定義する
AsyncTaskを定義する

各メソッドの引数に対応し
た型を指定する

class MyAsyncTask extends AsyncTask<Params, Progress, Result>{
@Override
protected Result doInBackground(Params... params) {
return null;
}

}

doInBackgroundは
オーバライド必須

戻り値

メソッド名

説明

abstract Result

doInBackground(Params... params)

バックグラウンド実行処理

void

onPreExecute()

バックグラウンド実行を行う直前の処
理

void

onPostExecute(Result result)

バックグラウンド実行完了時の処理

void

onProgressUpdate(Progress... values)

バックグラウンド処理の進捗状況の更
新

void

onCancelled()

バックグラウンド処理のキャンセル

※ doInBackgroundとonProgressUpdateは可変長引数のため、配列以外で渡したときもparam[0]で参照する必要がある
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 112
AsyncTaskの実行
AsyncTaskを実行する
AsyncTaskのサブクラスのインスタンスを生成して実行する一般的な方
法
AsyncTaskを実行中にキャンセルすることができる
//AsyncTaskのインスタンスを取得する
MyAsyncTask task = new MyAsyncTask();
//AsyncTaskを実行する
task.execute("MyAsyncTask execute");

AsyncTaskのサブクラスのインスタンス生成時に実行する
実装コードが短いので非同期処理のキャンセルを行う必要がない場合などに
使われる
インスタンス
//AsyncTaskのインスタンス生成時に実行する
new MyAsyncTask().execute("args as doInBackground");

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 113
AsyncTaskのサンプル(1)
使用例
AsyncTaskで10秒カウントするプログラム。
カウント中は画面右上にインジケータアイコンを表示する

起動直後にカウント開始

インジケータアイコンを表示

カウント中

十秒後に終了
インジケータアイコンは消え

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 114
AsyncTaskのサンプル(2)
サンプルプログラム
public class AsyncSample extends Activity {
private TextView text;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//タイトルバーにインジケータを表示させる
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRES
S); ・・・①

setContentView(R.layout.activity_async_sample);
this.text = (TextView)findViewById(R.id.textView1);
this.text.setText("" + 0);
//AsyncTaskを実行する
new MyAsyncTask().execute("args as
doInBackground");
・・・②

}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 115
AsyncTaskのサンプル(3)
サンプルプログラム
class MyAsyncTask extends AsyncTask<String, Integer, Boolean>{
@Override
protected void onPreExecute()
{
・・・④
//onPreExecuteではHandlerを使わずにUIを変更できる
//インジケータを表示する
setProgressBarIndeterminateVisibility(true);
}
@Override
protected Boolean doInBackground(String... params) {
Log.v("MyAsyncTask", "param:" + params[0]);
for( int i = 0; i <= 10; i++){
try {
//進捗状況の更新通知
publishProgress(i);
・・・⑥ −1
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();under the Creative Commons License BY-NC-SA 4.0.
This material is licensed

・・・③

・・・⑤

ⅰ - 116
AsyncTaskのサンプル(4)
サンプルプログラム
@Override
protected void onPostExecute(Boolean result) {
・・・⑧-1
//onPostExecuteではHandlerを使わずにUIを変更できる
if( result ){
text.setText("完了");
}else{
text.setText("失敗");
}
//インジケータを非表示する
setProgressBarIndeterminateVisibility(false);
・・・⑧-2
}
@Override
protected void onProgressUpdate(Integer... values) { ・・・⑥−2
//onProgressUpdateではHandlerを使わずにUIを変更できる
text.setText("" + values[0]);
}

}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 117
サンプルプログラムの解説(1)
サンプルプログラムの解説
1. タイトルバーにインジケータを表示させる
Activity.requestWindowFeatureメソッドを使い画面タスクバーの状態を定義
する
インジケータアイコンを表示する場合は引数に
“Window.FEATURE_INDETERMINATE_PROGRESS”を指定します
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//タイトルバーにインジケータを表示させる
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS)
;
・・・①

2. AsyncTaskを実行する
AsyncTaskを実行するにはexecuteメソッドを呼び出す
executeメソッドの引数にはdoInBackgroundの引数の型と一致している必要
がある
//AsyncTaskを実行する
new MyAsyncTask().execute("args as doInBackground");
・・・②
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 118
サンプルプログラムの解説(2)
3. MyAsyncTaskクラスの作成
AsyncTask クラスのサブクラス“ MyAsyncTask “を定義し、ジェネリクスには
以下の型を指定する
• 実行時の引数の型 String
– AsyncTask実行時に出力するログメッセージを指定するため、引数
の型はStringで指定
• 進捗時の引数の型 Integer
– 現在のカウント状態を画面に表示するため引数の型はIntegerを指定
• 実行結果時の引数の型 Boolean
– 実行結果の成否を判定するため、引数の型はBooleanを指定

class MyAsyncTask extends AsyncTask<String, Integer, Boolean>{

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

・・・③

ⅰ - 119
サンプルプログラムの解説(3)
4. バックグラウンド実行直前の処理を行う
onPreExecuteメソッドでバックグラウンド実行直前の処理を記述する
このメソッドはAsyncTask#executeを実行した直後に呼び出される
ここでは、タスクバーにインジケータアイコンを表示している
• インジケータアイコンの表示・非表示は
setProgressBarIndeterminateVisibilityメソッドの引数で設定する

class MyAsyncTask extends AsyncTask<String, Integer, Boolean>{
@Override
protected void onPreExecute() {
//onPreExecuteではHandlerを使わずにUIを変更できる
//インジケータを表示する
setProgressBarIndeterminateVisibility(true);
・・・④
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 120
サンプルプログラムの解説(4)
5. バックグラウンドの処理を行う
doInBackgroundメソッドでバックグラウンドの処理を実装する
引数はAsyncTask#executeの引数で指定した値が入る
引数の型が可変長引数(Param… param)になっているため、参照する際は
必ず配列の要素番号を指定する
• (例) String s = param[0];
ここでは引数にAsyncTask開始時に出力するメッセージが入っていますので
、要素番号0を指定し、Logに出力している
@Override
protected Boolean doInBackground(String... params) {
Log.v("MyAsyncTask", "param:" + params[0]);

・・・⑤

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 121
サンプルプログラムの解説(5)
6. 進捗状況の更新通知
進捗毎の更新処理はAsyncTask#onProgressUpdateで行う
進捗状況を更新したいタイミングで publishProgressメソッドを呼び出すと、
AsyncTask#onProgressUpdateがコールバックされる
ここでは、ループ毎に、 publishProgress(ソース⑥-1の箇所)を呼び出し、
現在のカウント値を引数に指定する
onProgressUpdateメソッド(ソース⑥-2の箇所)では受けっ取ったカウント値
をTextViewにセットしている
通常メインスレッド以外でUIの設定を変更する場合はHandlerを使用し、明示
的にメインスレッドで実行指定するが、onProgressUpdateメソッド内ではUI
の変更にHandlerを使う必要はない

@Override
protected void onProgressUpdate(Integer... values) { ・・・⑥−2
//onProgressUpdateではHandlerを使わずにUIを変更できる
text.setText("" + values[0]);
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 122
サンプルプログラムの解説(6)
7. 実行結果を返す
バックグラウンドの処理で正常終了したときは”true”を返し、例外が発生した
ときは“false”を返す
返した値は、 onPostExecuteの引数で渡される
@Override
protected Boolean doInBackground(String... params) {
Log.v("MyAsyncTask", "param:" + params[0]);
for( int i = 0; i <= 10; i++){
try {
//進捗状況の更新通知
publishProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
・・・⑦−1
}
}
return true;
・・・⑦−2
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 123
サンプルプログラムの解説(7)
8. バックグラウンド処理完了時の処理
バックグラウンドの処理結果を引数で受け取り、TextViewに結果を表示する
(ソース⑧-1)
setProgressBarIndeterminateVisibilityメソッドでfalseを指定しインジケータ
アイコンを非表示にする(ソース⑧-2)
@Override
protected void onPostExecute(Boolean result) {
・・・⑧
//onPostExecuteではHandlerを使わずにUIを変更できる
if( result ){
text.setText("完了");
}else{
text.setText("失敗");
}
//インジケータを非表示する
setProgressBarIndeterminateVisibility(false); ・・・⑧
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 124
AsyncTaskの作成(1)
実習2
説明に使ったサンプルプログラムを作成する
プロジェクト概要
項目

設定値

Project name

AsyncSample

Build Target

※トレーニングで指定したバージョン

Application name

AsyncSample

Package name

jp.oesf.async.count

Create Activity

AsyncSample

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 125
AsyncTaskの作成(2)
確認
AsyncTaskで10秒カウント中に画面右上のインジケータアイコンが表示
されることを確認
カウントが完了した時、画面右上のインジケータアイコンが表示されな
くなることを確認

起動直後にカウント開始

インジケータアイコンを表示

カウント中

十秒後に終了
インジケータアイコンは消え
ⅰ - 126

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
AsyncTaskの作成(解答)
解答
解答ドキュメントを参照
※実習が終わったら、次のAsyncTaskの中断処理を確認する。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 127
AsyncTaskの中断
AsyncTaskの中断
AsyncTask#cancelメソッドを実行することでタスクを中断することがで
きる
このメソッドを実行するとisCancelメソッドはtrueを返す
onPostExecuteは呼び出されず、代わりにonCancelledメソッドが呼び出
される
cancelが実行されてもdoInBackground内の処理は中断されない
そのためdoInBackgroundなどでタスクが中断されているがどうかを常に
判定しなくてはいけない

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 128
AsyncTaskの中断の仕方
AsyncTaskを中断する方法
手順
1. AsyncTask#cancelメソッドを実行する
2. AsyncTask#onCancelledメソッドに中断時の処理を実装する
3. AsyncTask#doInBackgroundなどで中断処理を実装する
• キャンセル判定にはisCancelメソッドを使用する

キャンセルで扱うメソッド

戻り値

メソッド名

説明

boolean

cancel(boolean )

AsyncTaskを実行をキャンセルする
引数
boolean:実行しているスレッドに割り込む必要がある場合は、引数に
trueを指定する

戻り値
boolean:タスクの中断に失敗した場合はfalse、成功した場合はtrue
を返す

boolean

isCancel()

キャンセル判定

void

onCancelled()

キャンセルした時の処理を実装する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 129
AsyncTaskを中断する
1. AsyncTask#cancelメソッドを実行する
cancelメソッドを実行するにはAsyncTaskのインスタンスを用意しておく必
要がある。
//AsyncTaskのインスタンスを取得する
MyAsyncTask task = new MyAsyncTask();
//AsyncTaskを実行する
task.execute("MyAsyncTask execute");
//AsyncTaskをキャンセルする
task.cancel(true);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 130
AsyncTaskが中断されたときの処理
2. AsyncTask#onCancelledメソッドに中断時の処理を実装する
class MyAsyncTask extends AsyncTask<Void, Void, Void>{
@Override
protected void onCancelled() {
//インジケータを非表示にする
setProgressBarIndeterminateVisibility(false);
//TextViewに中止を設定
text.setText("中止");
}
}

3. AsyncTask#doInBackgroundに中断判定処理を実装する
class MyAsyncTask extends AsyncTask<Void, Void, Void>{
@Override
protected Void doInBackground(RowModel... arg0) {
if(isCancelled()){
//キャンセルした時の処理
}
}

}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 131
AsyncTaskの中断(1)
実習3
実習2で作成したサンプルプログラムにキャンセル処理を追加する
1. CancelButtonをクリックす
る

③

2. インジケータが表示されなくなる
3. カウント表示のTextViewに「中止」が表示され
る

②

①
①

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 132
AsyncTaskの中断(2)
手順
1.
2.
3.
4.

レイアウトの修正
AsyncTaskのサブクラスのインスタンスを生成して実行するように修正
Button押下時の処理にAsyncTask#cancel処理を実装
AsyncTaskのサブクラス内にAsyncTask#onCancelledメソッド内に中止
した時の処理を実装

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 133
AsyncTaskの中断(3)
1. レイアウトの修正
activity_async_sample.xmlにButtonを追加する
階層構造

View

Property

Button

android:id="@+id/button1"
android:text="Cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClickCancelButton"

<LinearLayout>
<TextView />
2. AsyncTaskのサブクラスのインスタンスを生成して実行するように修正
<Button />
</LinearLayout>
public class AsyncSample extends Activity {
private MyAsyncTask task;

@Override
public void onCreate(Bundle savedInstanceState) {
……… 省略 ………
//AsyncTaskを実行する
task = new MyAsyncTask();
task.execute("args as doInBackground");
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 134
AsyncTaskの中断(4)
3. Button押下時の処理にAsyncTask#cancel処理を実装
public class AsyncSample extends Activity {
……… 省略 ………
public void onClickCancelButton(View view){
task.cancel(true);
}
}

4. AsyncTaskのサブクラス内にAsyncTask#onCancelledメソッド内に中止
した時の処理を実装
onCancelledメソッドの実装
doInBackgroundでキャンセル判定処理の追加

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 135
AsyncTaskの中断(5)
public class AsyncSample extends Activity {
private TextView text;
……… 省略 ………
class MyAsyncTask extends AsyncTask<String, Integer, Boolean>{
……… 省略 ………
@Override
protected Boolean doInBackground(String... params) {
Log.v("MyAsncTask", "params:" + params[0]);
for (int i = 0; i < 10; i++) {
try {
if(isCancelled()){
break;
}
Log.v("MyAsyncTask", "i:" + i);
……… 省略 ………

}

@Override
protected void onCancelled() {
// インジケータを非表示にする
setProgressBarIndeterminateVisibility(false);
// TextViewに中止を設定
text.setText("中止");
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 136
AsyncTaskの中断(6)
確認
Cancelボタンをクリックして以下のようになることを確認
画面右上のインジケータアイコンが表示されなくなること
カウント表示のTextView部分に「中止」の文字列が設定されること
①

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 137
AsyncTaskの中断(解答)
解答
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 138
実習用スケルトンの非同期化(1
)
実習4

完成図

実習用スケルトンを非同期にする
AsyncTaskで画像の取得処理を行い、取得したタイミングで画面を更新
する。
画面右上にインジケータアイコンを表示する

すぐにローディング
アイコンが表示される

徐々にアイコンが
表示される

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

完了
ⅰ - 139
実習用スケルトンの非同期化(2
)
スケルトンプログラムの内容
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 140
実習用スケルトンの非同期化(3
)
非同期によるイメージ取得処理
イメージの取得処理を非同期にする
ListSampleクラスに内部クラス「LoadImageTask」が定義されています
。以下の処理を実装します
<手順>
1. onPreExecuteメソッドを実装する
2. doInBackgroundメソッドを実装する
3. onProgressUpdateメソッドを実装する
4. onPostExecuteメソッドを実装する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 141
実習用スケルトンの非同期化(4
)
メソッドの実装
1. onPreExecuteメソッドを実装する
onPreExecuteメソッドインジケータダイアログを表示する処理
protected void onPreExecute() {
//インジケータを表示する
setProgressBarIndeterminateVisibility(true);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 142
実習用スケルトンの非同期化(5
)
メソッドの実装
2. doInBackgroundメソッド
引数RowModel配列からデータを1件ずつ取得し、サムネイルを設定する。
• サムネイル画像はListSample#getImageメソッドで取得する
画像の取得が完了したら更新通知する
• publicProgressメソッドの実行

protected Void doInBackground(RowModel... arg0) {
//引数からデータを1件ずつ読み込み、RowModelのDrawableを設定する
for(RowModel rowModel : arg0){
if(isCancelled()){
Log.v("ListSample", "LoadImageTask#doInBackground() canceled.");
break;
}
// サムネイルイメージ取得
rowModel.setThumbnailImage(getImage());
//更新通知
publishProgress();
}
return null;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 143
実習用スケルトンの非同期化(6
)
メソッドの実装
3. onProgressUpdateメソッド
ListViewの画像を更新する
• ArrayAdpter#notifyDataSetChangedメソッドを実行し、ListViewにデー
タの変更通知をする
protected void onProgressUpdate(Void... values) {
//データの変更通知
adpter.notifyDataSetChanged();
}

4. onPostExecuteメソッド
インジケータダイアログを非表示する
protected void onPostExecute(Void result) {
//インジケータを非表示する
setProgressBarIndeterminateVisibility(false);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 144
実習用スケルトンの非同期化(7
)
メソッドの実装
ListSample.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//タイトルバーにインジケータを表示させる
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRES
S);
setContentView(R.layout.activity_list_sample);
adpter = new TableAdapter(this);
setListAdapter(adpter);
~略~
//非同期処理呼び出し
task = new LoadImageTask();
task.execute(models);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 145
実習用スケルトンの非同期化(7
)
確認
ローディングアイコンが表示されていること
ロード中に画面右上にインジケーターアイコンが表示されていることを
確認

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 146
実習用スケルトンの非同期化(解
答)
解答
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 147
実習用スケルトンの非同期化
(追加実習)
実習5
前項で作成したプログラムを最初から作成する

解答
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 148
6. HTTP通信
概要
Webサービスに接続する
レスポンスデータを取得する
WebAPIを使ったHTTP通信

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 150
Webサービスに接続する
Webサービスに接続する
ユーザはブラウザなどのクライアントを使ってHTTP通信をして外部の
Webサービスに接続する
Androidは常時接続が可能なため外部のWebサービスと連携したアプリケ
ーションを作成することが可能
特定のWebサービスに特化したアプリケーションを作成する場合は、プ
ログラム上で通信ロジックを組み込む必要がある

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 151
HTTP通信の仕方(1)
HTTP通信
AndroidにはHTTP通信を行うユーティリティとしてDefaultHttpClientク
ラスが用意されています。
DefaultHttpClientクラスを使ってHTTP通信を行う手順
1. DefaultHttpClientクラスを生成する。
2. リクエストメソッドの設定をする。
3. 指定したURLにリクエストを発行する。
4. レスポンスステータスをチェックする。
5. レスポンスデータから必要な情報をとりだす。

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 152
HTTP通信の仕方(2)
1. DefaultHttpClientクラスを生成する。
//DefaultHttpClientオブジェクトの生成
DefaultHttpClient client = new DefaultHttpClient();

1. リクエストメソッドの設定をする。
引数に接続先URLを指定する。
//接続先URL
String url = “http://www.oesf.jp/”;
//GETメソッドで接続するリクエストオブジェクトの生成
HttpGet get = new HttpGet(url);

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 153
HTTP通信の仕方(3)
3. 指定したURLにリクエストを発行する。
引数に2.で生成したリクエストオブジェクトを指定し、executeメソッドでリ
クエストを発行する。

4. レスポンスステータスをチェックする。
5. レスポンスデータから必要な情報をとりだす。
executeメソッドを実行するとResponseオブジェクトが取得できる。
取得したResponseオブジェクトからステータスコードの確認をする。
成功した場合、レスポンス情報を取り出す。
try {
//リクエストを発行してレスポンスを取得する
HttpResponse res = client.execute(get);
//ステータスコードのチェック
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
//レスポンス情報を取得する
HttpEntity entity = res.getEntity();
}
} catch (Exception e) {
e.printStackTrace();
}

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 154
HTTP通信の仕方(4)
サンプルコード
//接続先URL
String url = “http://www.oesf.jp/”;
//DefaultHttpClientオブジェクトの生成
DefaultHttpClient client = new DefaultHttpClient();
//GETメソッドで接続するリクエストオブジェクトの生成
HttpGet get = new HttpGet(url);
try {
//リクエストを発行してレスポンスを取得する
HttpResponse res = client.execute(get);
//ステータスコードのチェック
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
//レスポンス情報を取得する
HttpEntity entity = res.getEntity();
}
} catch (Exception e) {
e.printStackTrace();
}

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 155
HTTP通信をする(1)
実習1
GETメソッドでHTTP通信を行い、ステータスコードをチェックするプ
ログラムの作成

完成図

ログ

クリック
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 156
HTTP通信をする(2)
HTTP通信を使ったアプリケーションの作成
※スケルトンプロジェクトHttpSample_skeleton01をインポートする

項目

設定値

Project name

HttpSample

Build Target

※トレーニングで指定したバージョ
ン

Application name

HttpSample

Package name

jp.oesf.httpsample

Create Activity

HttpSample

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 157
HTTP通信をする(3)
サンプルプログラムの作成
<手順>
※スケルトンでは、いくつかの処理は実装済ため確認のみ行う
リソースファイルの修正(実装済)
• strings.xml
• activity_http_sample.xml
Activityの修正
• HTTP通信処理の追加
– 接続先“http://www.oesf.jp/”
– ネットワーク環境がない場合”http://[IPアドレス]:8080/oesf.html”
AndroidManifest.xmlの修正(実装済)
• インターネット通信のパーミッション追加する。

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 158
HTTP通信をする(4)
リソースファイルを修正する(実装済)
strings.xml
name

value

connect_http

HTTP通信

activity_http_sample.xml

階層
<Linear
構造
Layout>
<Button

View

Property

LinearLayout

android:orientation="vertical”
android:layout_width=“match_parent”
android:layout_height="match_parent"

Button

android:id="@+id/Button01”
android:layout_height="wrap_content”
android:text="@string/connect_http”
android:onClick="onClickButton”
android:layout_width="match_parent"

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 159
HTTP通信をする(5)
Activityクラスの修正
HTTP通信処理の追加する
onClickButtonメソッドの実装
DefaultHttpClientクラスを生成する。
リクエストメソッドの設定をする。
• HttpGetオブジェクトを生成する。
– 引数にurl:” http://www.oesf.jp/”を指定する
– ネットワークが環境がない場合”http://[IPアドレス]:8080/oesf.html”
指定したURLにリクエストを発行する。
レスポンスステータスをチェックする。
• ステータスが200ならログを出力する。
• 出力ログ:Log.v(TAG, "status ok");

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 160
HTTP通信をする(6)
AndroidManifest.xmlの修正(実装済)
インターネット通信のパーミッション追加
AndroidManifest.xmlファイルにインターネット接続を許可するパーミッショ
ンを追記します。
</activity>
</application>
<!-- インターネット接続の通信許可パーミッションを追加する -->
<uses-permission
android:name="android.permission.INTERNET">
</uses-permission>
<uses-sdk android:minSdkVersion="7" />
</manifest>

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 161
HTTP通信をする(7)
確認
GETメソッドでHTTP通信を行い、ログに“status ok”が出力されているこ
とを確認する

クリック
ログ
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 162
HTTP通信をする(解答)
解答
解答ドキュメント参照

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 163
レスポンスデータを取得する(1
)
実習2
実習1で作成したプログラムに、コンテンツ表示機能を追加する

完
成
図

ク
リ
ッ
ク

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 164
レスポンスデータを取得する(2
)
レスポンスデータを取得する
取得したレスポンスデータを文字列に変換するにはHttpEntitiyクラスと
EntityUtilsを使用する
<手順>
HttpResponseからHttpEntityを取得する
HttpEntityとEntityUtils#toStringメソッドにHttpEntityを引数に指定してコンテ
ンツを取得する

サンプル
HttpResponse res = client.execute(get);
String content = EntityUtils.toString(res.getEntity(), "EUC-JP");

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 165
レスポンスデータを取得する(3
)
手順
1. レイアウトファイルの修正
2. Activityクラスにレスポンスデータ取得処理を追加
3. 取得したデータを画面に表示

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 166
レスポンスデータを取得する(4
)
1. レイアウトファイルの修正
コンテンツデータを表示用のTextViewの追加
View

Property

TextView

android:id="@+id/text_content"
android:layout_width=“wrap_content“
android:layout_height="wrap_content“

階層構造

<Linear
Layout>
<Button

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 167
レスポンスデータを取得する(5
)
2. Activityクラスにレスポンスデータ取得処理を追加
HttpResponseからHttpEntityを取得する
HttpEntityとEntityUtils#toStringメソッドにHttpEntityを引数に指定してコンテ
ンツを取得する
String content = EntityUtils.toString(res.getEntity(), "EUC-JP");

3. 取得したデータを画面に表示
activity_http_sample.xmlに追加したTextViewにレスポンスデータを設定する

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 168
レスポンスデータを取得する(6
)
確認
取得したレスポンスデータがTextViewに表示されることを確認する。

クリック

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 169
レスポンスデータを取得する(解
答)
解答
解答ドキュメントを参照

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 170
WebAPI
WebAPIとは?
Web上にあるアプリケーションプログラムインタフェースのこと。
基本的にはURLにパラメータを付与して、XML/JSON データのやりとり
を行う。
代表的な物として、Yahoo API、 Google API、 Twitter API などがある
。

Get/Post で送信

JSON・XML で送信

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 171
WebAPIを使の使い方
WebAPIを使った通信の仕方
WebAPIには、リクエストにパラメータを付与してアクセスします。
リクエストは、各Web APIのURL(例 http://www.oesf.jp/modules/news)に
、パラメータ
(例 ?page=rss)を追加して作成します。
レスポンスはXML/JSONなどで返されます。(上記の例ではXMLが返さ
れます)
http://www.oesf.jp/modules/news?page=rss

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Open Embedded Software Foundation</title>
<link>http://www.oesf.jp/</link>
<description></description>
<lastBuildDate>Fri, 22 Jun 2012 02:09:57 +0000</lastBuildDate>
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 172
WebAPIパラメータ
WebAPIを使った通信の仕方
Key-ValueセットのWebAPIパラメータを作成する
?page=rss

key
value
page = rss

クエリパラメータからHttpGetオブジェクトを生成する
リクエストの送信
以降のリクエスト処理は実習2までの手順と同じ

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 173
WebAPIを使ったHTTP通信 (1)
WebAPIを使ったHTTP通信の実装方法
Key-ValueセットのWebAPIパラメータを作成する
1. コンストラクタを使ってUri.Builderオブジェクトを生成する
2. Builder#pathメソッドを使って接続先URLを設定する
3. Builder#appendQueryParameterメソッドを使用しWebAPIパラメータを設定
する
•

サンプル
// WebAPI用クエリパラメータのの作成
Builder builder = new Builder();
・・・①
builder.path(URL);
・・・②
builder.appendQueryParameter(“page”, “rss”);
・・・③

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 174
WebAPIを使ったHTTP通信 (2)
WebAPIを使ったHTTP通信の実装方法
クエリパラメータからHttpGetオブジェクトを生成する
Builder#buidメソッドを使用し、パラメータに基づいた Uriオブジェクトを生
成する
Uri#decodeメソッドを使用して、パラメータ付きの接続先URL文字列を生成
する
生成したURLを引数に指定し、HttpGetオブジェクトを生成する
// 作成したクエリパラメータからHttpGetオブジェクトを生成する

サンプル = Uri.decode(builder.build().toString());
String uri
HttpGet get = new HttpGet(uri);

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 175
WebAPIを使ったHTTP通信 (3)
WebAPIを使ったHTTP通信の実装方法
まとめると
// WebAPI用クエリパラメータのの作成
Builder builder = new Builder();
builder.path(URL);
builder.appendQueryParameter(“page”, “rss”);
// 作成したクエリパラメータからHttpGetオブジェクトを生成する
String uri = Uri.decode(builder.build().toString());
HttpGet get = new HttpGet(uri);

Builderクラスの主なメソッド
メソッド

機能

path

リソースを指定する。「/」 以外の文字は必要に応じてエ
ンコードされる

appendQueryParameter

KeyとValueを引数にとり、それぞれエンコードしてクエ
リ文字列に追加する

build

指定されたパラメータに基づいた Uri オブジェクトを生成
するThis material is licensed under the Creative
ⅰ - 176
Commons License BY-NC-SA 4.0.
WebAPIを使う(1)
実習3
実習2で作成したプログラムに、WebAPIを使った機能を追加する。

完成図
値を入力後クリック

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 177
WebAPIを使う(2)
WebAPIを使ったHTTP通信
<手順>
リソースファイルの修正
• strings.xmlの修正
• activity_http_sample.xmlの修正
Activityクラスの修正
• 接続先URLの変更
– 接続先 http://www.oesf.jp/modules/news/index.php
• WebAPIパラメータ対応
– URLのindex.php以降の値を付与してリクエストを投げる
• 接続先例
– http://www.oesf.jp/modules/news/index.php?page=rss

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 178
WebAPIを使う(3)
リソースファイルを修正する
strings.xml
• パラメータ用にKeyとValueを追加する
Name

Value

key

Key

value

Value

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 179
WebAPIを使う(4)
リソースファイルを修正する(続き)
activity_http_sample.xml
• “HTTP通信”ボタンの下に以下のViewを追加する

階層
<LinearL
構造
ayout>
<Button
/>

view

property

LinearLayout

android:layout_width="match_parent"
android:layout_height="wrap_content”

TextView

android:layout_width=”40dp"
android:layout_height="wrap_content"
android:text="@string/key”

EditText

android:id="@+id/editKey"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=”1”

LinearLayout

android:layout_width="match_parent"
android:layout_height="wrap_content”

TextView

android:layout_width=”40dp"
android:layout_height="wrap_content"
android:text="@string/view”

EditText

android:id="@+id/editValue"
android:layout_width="0dp"
android:layout_height="wrap_content"
This material is licensed under the Creative
android:layout_weight="1”
ⅰ - 180
Commons License BY-NC-SA 4.0.
WebAPIを使う(5)
ActivityクラスにHTTP通信処理の追加する
WebAPI用のパラメータを構築する。
パラメータからURLを作成する
作成したURLをコンストラクタの引数に指定しHttpGetオブジェクトを生成す
る
• ※実習 1,2で作成したHttpGetオブジェクトの処理はコメントアウトする

// TODO 【HTTP通信①】No.02 GETメソッドで接続するリクエストオブジェクトの生
成する
// HttpGet get = new HttpGet(URL);

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 181
WebAPIを使う(6)
確認
取得したレスポンスデータがTextViewに表示されることを確認する

パラメータには
以下のものが使用可
key

value

page

rss, archive

storytopic

1,2,3,4,5

値を入力後クリック

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 182
WebAPIを使う(解答)
解答
解答ドキュメントを参照

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 183
7. JSONの解析
概要
外部連帯概要
JSONの解析
JSONの解析 [実習]

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 185
外部連帯概要
Androidの特徴は外部連帯可能であること
ネットワークに常時接続できることを前提とし、Cloudサービス(サー
バーサイド)と連動したアプリケーションを作成することができる
Cloudサービスと端末間でのデータのやり取りは、XMLやJSONが用いら
れることが多い
端末側でXML、JSONを解釈できるようにする必要がある

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 186
外部連帯概要
サービスの一例
有名なサービスはXML、JSONいずれでも提供していることが多い

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 187
JSON
JSONとは
軽量のデータ記述言語
マークアップ言語ではないので、XMLの解析より高速に処理することが
可能
キー/バリューペアの集まりでデータ構造を記述している
文字コードは基本的にUTF-8のみ
型
Androidで扱う型
<JSONで扱えるデータ型>

数値

int,long,float,doubleなど

真偽値

boolean

文字列

String

配列

JSONArray

オブジェクト

JSONObject

null

null

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 188
解析の仕方
JSONの解析
<手順>
JSON文字列の構造を十分に把握し、ルートデータがJSONObjectなのか
、JSONArrayなのかを確認する
JSONObjectまたはJSONArrayのコンストラクタにJSON文字列を引数で
指定してオブジェクトを生成する
JSONObjectの場合
• { と } で囲まれたデータ
• 生成したJSONObjectからkeyを指定してデータを取得する
JSONArrayの場合
• [ と ] で囲まれたデータ
• 配列の数だけループし各要素のデータを取得する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 189
JSONを解析する
JSONObjectとJSONArrayからデータを取得する方法
JSONObjectとJSONArrayは型に応じたgetterメソッドが用意されていて
、キーまたは、要素番号を引数に指定してデータを取得する

<JSONObjectとJSONArrayの主なgetterメソッド>
getInt

getBoolean

getDouble

getJSONArray

getString

getJSONObject

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 190
JSON解析のサンプル
サンプルコード
以下のJSONを解析するサンプル
構成
ルートの型:JSONObject
• key:rootのJSONのObject
– key:nodeのJSONArray
– Stringの配列

{
"root": {
"node": [
"value1",
"value2"
]
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 191
JSON解析のサンプル
サンプルコード
1. JSON文字列からJSONObjectを生成する
2. JSONObjectから”root”をキーに指定しJSONObjectを生成する
3. 2で生成したJSONをObjectから”node”をキーに指定し、JSONArrayを生
成する
4. JSONArrayをforで繰り返し、要素番号を指定してn番目のデータを取得
ArrayList<String> values = new ArrayList<String>();
する
try {
JSONObject json = new JSONObject(strJson); ・・・ 1
JSONObject root = json.getJSONObject(“root”); ・・・ 2
JSONArray node = root.getJSONArray(“node”); ・・・ 3

for(int i = 0; i < node.length(); i++){
・・・ 4
values.add(node.getString(i));
}
} catch (JSONException e) {
Log.e("JsonSampleForDocActivity" , e.getMessage(), e);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

JSON文字列
{
"root": {
"node": [
"value1",
"value2"
]
}
}

ⅰ - 192
JSONの解析をする(1)
実習
JSONの解析を行う
完成図

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 193
JSONの解析をする(2)
JSONデータの構成
以下のJSONを、org.jsonパッケージを使って解析を行う
<sample.json> ※sample.jsonはassetsフォルダ以下に保存されています
{
"feed": {
"entries": [
{
"id": "hPzNl6NKAG0”,
"group": {
"description": "全てはより良い滑り込みのために。",
"thumbnail_url": "image/cat.jpg",
"title": "特訓するねこ。"
}
},
{
"id": ”xxxxxxxx”,
"group": {
“description”: “xxxxxxx",
"thumbnail_url": “xxxxxxxx”,
“title”: “xxxxxx"
}
}
]
}
}

※解析対象

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 194
JSONの解析をする(3)
スケルトンプロジェクトのインポート
実習用スケルトンプロジェクトをEclipseに取り込む
プロジェクト名:「JsonSample_skeleton」
項目

設定値

Project name

JsonSample

Build Target

※トレーニングで指定したバー
ジョン

Application name

JsonSample

Package name

jp.oesf.jsonsample

Create Activity

JsonSampleActivity

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 195
JSONの解析をする(4)
スケルトンプログラムについて
リソース定義情報
<activity_json_sample.xml>
View

Property

LinearLayo
ut

階層構造
<LinearLayout>
<Button />
<Button />
<TextView />
</LinearLayout>

android:orientation="vertical"
android:layout_width=“match_parent"
android:layout_height=“match_parent"

Button

android:id="@+id/button_clear"
android:text="Clear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClickClearButton"

Button

android:id="@+id/button_json“
android:text="JSON"
android:layout_width="match_parent “
android:layout_height="wrap_content"
android:onClick="onClickJsonButton"

TextView

android:id="@+id/text_result"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:inputType="textMultiLine"- 196
ⅰ

This material is licensed under the Creative Commons License BY-NC-SA 4.0.
JSONの解析をする(5)
スケルトンプログラムについて
クラス情報
RowModel
• JSONデータから以下の要素を取り出しデータクラス化したもの
– id
– description
– thumbnail_url
– title

<RowModel.javaの定義>
キー

メンバ変数

id

String id

title

String title

thumbnail_url

String thumbnailImageURL

description

String summary

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 197
JSONの解析をする(6)
スケルトンプログラムについて
クラス情報(続き)
JsonHelper
• JSONデータを解析するためのロジッククラス。
• 以下のメソッドを定義済
– public static ArrayList<RowModel> parseJson(String strJson)
– public static RowModel parseToModel(JSONObject json) throws
JSONException

<メソッド>
戻り値

メソッド

引数

説明

ArrayList<RowModel>

parseJson

String

JSON文字列を受け取り全体の解析を行う。

RowModel

parseToModel

JSONObject

parseJsonメソッドから呼び出される。
“entries”キーに定義されている各要素の情
報をデータクラス化する。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 198
JSONの解析をする(7)
手順
未実装の処理を実装し、プログラムを完成させる
<実装済>
Jsonボタン押下時にJsonHelper#parseJsonメソッドを呼び出し、解析後のデ
ータリストを取得。
TextViewに解析結果を表示する

<未実装>
JsonHelperクラスのparseJsonメソッドに以下の処理を実装する
• JSONを解析し、”entries”キーからJSONArrayを取得する
• 要素ごとに繰り返し、parseToRowModelを呼び出す

JsonHelperクラスのparseToModelメソッドに以下の処理を実装する
• 引数で受け取ったJSONObjectからデータを取り出し、値をRowModelに
セットする

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 199
JSONの解析をする(8)
実行結果

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 200
JSONの解析をする(解答)
解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 201
JSONの解析をする[実習補足]
実習[補足]
asset/sample.jsonを編集してentries内にデータを追加し、2つ以上のデ
ータクラスを取得できるようにする
sample.json
{
"feed": {
"entries": [
{
"id": "hPzNl6NKAG0”,
"group": {
"description": "全てはより良い滑り込みのために。",
"thumbnail_url": "image/cat.jpg",
"title": "特訓するねこ。"
}
},
{
※データを追加する
"id": ”xxxxxxxx”,
"group": {
“description”: “xxxxxxx",
"thumbnail_url": “xxxxxxxx”,
“title”: “xxxxxx"
}
}
]
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 202
[補足]XMLの解析
XML
XMLとは
データの意味や構造を記述するためのマークアップ言語のひとつ
マークアップ言語とは「タグ」と呼ばれる特定の文字列で文に情報の意
味や構造、装飾などを埋め込んでいく言語 ユーザーが独自のタグを指
定できる

種類

内容

説明

タグ

<id> ~ </id>

「<」と「>」で囲まれた部分をタグ
という、開始タグと終了タグがある

属性(アトリビュート)

<thumbnail url=" ~ ">

タグに対して付加情報を付け加えるた
めに使用される

値(バリュー)

<title> ~ </title>
<thumbnail url=" ~ ">

タグとタグで囲まれた文字列の子と、
属性の場合は「=」で指定した値

名前空間(ネームスペー
ス)

<feed xmlns:media=" ~
">
<media:group/>
</feed>

同じタグ名により衝突をするのを解決
するように使用、名前空間URIは必ず
ユニークである

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 204
実習用プロジェクト概要(1)
実習用スケルトンプロジェクトをEclipseに取り込む
プロジェクト名:XmlSample_skeleton01.zip

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 205
実習用プロジェクト概要(2)
スケルトンプログラムについて
XML解析の演習ではDOM、SAX、XMLPullparserを使ったサンプルを作
成します。
使用するスケルトンプロジェクトは以下の機能が実装されています
• XmlSample_skeleton01: 解析処理の実装なし
• XmlSample_skeleton02: DOMを使った解析処理が実装されています
• XmlSample_skeleton03: DOMとSAXを使った解析処理が実装されていま
す
– 各プロジェクトには演習で実装するタスクが記述されています。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 206
実習用プロジェクト概要(3)
スケルトンプログラムについて
リソース定義情報(Clearボタン部分)
XmlSample_skeleton01~XmlSample_skeleton03には以下の内容でリソ
ースが定義されています
階層構造
<LinearLayout>
<Button />
<LinearLayout>
<次のページ>
</LinearLayout>
</LinearLayout>

View

Property

LinearLayout

android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"

Button

android:id="@+id/button_clear"
android:text="Clear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClickClearButton"

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 207
実習用プロジェクト概要(4)
スケルトンプログラムについて
リソース定義情報(DOMボタン、SAXボタン、XMLPullparserボタン部分
)
View
Property
Button

android:id="@+id/button_dom"
android:text="DOM"
android:layout_weight="1"
android:layout_width="match_parent "
android:layout_height="wrap_content"
android:onClick="onClickDOMButton"

Button

android:id="@+id/button_sax"
android:text="SAX"
android:layout_weight="1"
android:layout_width="match_parent "
android:layout_height="wrap_content"
android:onClick="onClickSAXButton"

Button

android:id="@+id/button_xmlpullpaser"
android:text="XmlPullpaser"
android:textSize="12sp"
android:layout_weight="1"
android:layout_width="match_parent "
android:layout_height="wrap_content"
android:onClick="onClickXMLPullparserButton"

階層構造
<LinearLayout>
<Button />
<Button />
<Button />
<TextView />
</LinearLayout>

TextView

android:id="@+id/text_result"
android:inputType="textMultiLine"
android:layout_width="wrap_content"
android:layout_height="match_parent"
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 208
解析対象のデータ構造
XMLデータの解析
WebAPIを使ってHTTP通信をすると以下のようなデータが取得されます
以下のXML文書を使い、DOM・SAX・XMLPullparserでXMLの解析を行
う

property

<sample.xml> ※sample.xmlはassetsフォルダ以下に保存されています
<?xml version="1.0" encoding="UTF-8"?>
<feed>
<entry>
<id>hPzNl6NKAG0</id>
<group>
<description>全てはより良い滑り込みのために。</description>
<thumbnail url="image/cat.jpg"></thumbnail>
<title>特訓するねこ。</title>
</group>
</entry>
</feed>

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 209
XML構造のデータクラス
XMLの解析
取得したXMLから、以下の要素を解析して RowModelに変換する
id
description
thumbnail url属性
title

RowModelはjp.oesf.xmldomsample.model以下の”RowModel.java”ファイ
ルで定義済
タグ

属性

取得する値

id

なし

hPzNl6NKAG0

title

なし

特訓するねこ。

description

なし

全てはより良い滑り込み
のために。

thumbnail

url

image/cat.jpg

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 210
DOMとは
DOM(ツリー構造型)
XMLの内容をDOM ツリーとしてヒープに持つ
パース時に XML の内容をすべてメモリ上に保持し、パース後にどの要
素にもいつでもアクセスできる
すべてをメモリ上に保持するために、多くのメモリを消費するので
Android が稼働するモバイル機器では問題がある
XML 文書が小さい場合は DOM を使用すれば簡単に実装できる
おそ~い

DO
M
消費メモリが多い

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 211
DOMツリー
解析を行うXMLのDOMツリー
要素

<feed>

タグ
属性

<entry>

<id>
動画ID

説明

値

<group>
<description>

<thumbnail>

<title>

url
動画の説明

サムネイル画像
のURL

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

タイトル
ⅰ - 212
XMLの解析の仕方:DOM (1)
DOM を使ったXMLの解析
<手順>
1.
2.
3.
4.

XMLデータのDocumentオブジェクトを取得する
XMLデータのルート要素を取得する
DOMツリーをたどり、目的のノードを取得する
ノードが保持しているデータ(タグやテキストデータ)を取得する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 213
XMLの解析の仕方:DOM(2)
サンプルコード
以下のXML文書を解析するサンプル
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node1>Node Value</node1>
</root>

※実際は改行されていません

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 214
XMLの解析の仕方:DOM(3)
1. XMLデータのDocumentオブジェクトを取得する
DocumentBuilderFactoryオブジェクトを生成する
DOMパーサを作成する
XMLを解析しDOMツリーを構築する

// xmlファイルのストリームを取得
InputStream in = context.getAssets().open("sample.xml");
// No.01 ドキュメントビルダーファクトリを生成
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
dbfactory.setNamespaceAware(true);
// No.02 ドキュメントビルダーを生成
DocumentBuilder builder = dbfactory.newDocumentBuilder();

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 215
XMLの解析の仕方:DOM(4)
2. XMLデータのルート要素を取得する
3. DOMツリーをたどり、目的のノードを取得する
4. ノードが保持しているデータ(タグやテキストデータ)を取得する
InputStream in = null;
try {
// ドキュメントビルダーファクトリを生成
DocumentBuilderFactory dbfactory = DocumentBuilderFactory
.newInstance();
// ドキュメントビルダーを生成
DocumentBuilder builder = dbfactory.newDocumentBuilder();
// xmlファイルのストリームを取得
in = getAssets().open("sample.xml");
// パースを実行してDocumentオブジェクトを取得
Document doc = builder.parse(in);
// ルート要素を取得(タグ名:root)
Element root = doc.getDocumentElement();
// <node1>を取得
NodeList entryList = root.getElementsByTagName("node1");
// 最初の<node1>を取得
Element node1Element = (Element) entryList.item(0);
// <node1>の値を取得
String nodevalue = node1Element.getFirstChild().getNodeValue();
// 値を表示
Log.v(TAG, nodevalue);
} catch (Exception e) {
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 216
XMLの解析の仕方:DOM(5)
サンプルコード
InputStream in = null;
try {
// ドキュメントビルダーファクトリを生成
DocumentBuilderFactory dbfactory = DocumentBuilderFactory
.newInstance();
// ドキュメントビルダーを生成
DocumentBuilder builder = dbfactory.newDocumentBuilder();
// xmlファイルのストリームを取得
in = getAssets().open("sample.xml");
// パースを実行してDocumentオブジェクトを取得
Document doc = builder.parse(in);
// ルート要素を取得(タグ名:root)
Element root = doc.getDocumentElement();

// <node1>を取得
NodeList entryList = root.getElementsByTagName("node1");
// 最初の<node1>を取得
Element node1Element = (Element) entryList.item(0);
// <node1>の値を取得
String nodevalue = node1Element.getFirstChild().getNodeValue();
// 値を表示
Log.v(TAG, nodevalue);
} catch (Exception e) {

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 217
XMLの解析の仕方:DOM(6)
<サンプルコードで使用するクラス>
クラス名

説明

DocumentBuilderFactory

アプリケーションで XML ドキュメン
トから DOM オブジェクトツリーを生
成するパーサを取得できるファクトリ

API を定義
DocumentBuilder

XMLドキュメントから DOM
Document インスタンスを取得する
API を定義

Document

HTML文書または XML 文書全体を
表す

Element

HTML文書または XML 文書内の要
素を表す

NodeList

順序付けられたノード(*1)のコレク
ションを提供する

Node

文書ツリー内の単一のノード(*1)を
表す

*1 ノードとはXML文書を構成する要素や属性のことを指す

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 218
XMLの解析の仕方:DOM(7)
<サンプルコードで使用するメソッド>
戻り値

クラス名

メソッド名

説明

DocumentBuilde
r

DocumentBuilderFactor
y

newDocumentBuilder()

DocumentBuilder の新しいインスタンス
を作成

Document

DocumentBuilder

parse(InputStream is)

指定された InputStream の内容を XML ド
キュメントとして構文解析し、新しい
DOM オブジェクトを返却
パラメータ
• InputStream - 構文解析されるコンテン
ツを含むInputStream

Element

Document

getDocumentElement()

文書要素になっている子ノードへの直接
アクセスを可能にする

NodeList

Element

getElementsByTagName(String
name)

指定のタグ名とともに、すべての子孫
Elements の NodeList を文書順に返却

Node

NodeList

item(int index)

コレクション内の index 番目の項目を返
却
パラメータ
・index – コレクション内のindex 番目を
指定

Node

Node

getFirstChild()

ノードの最初の子ノードを返却

String

Node

getNodeValue

ノードの値を返却

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 219
XMLの解析:DOM (1)
実習 1
DOMを使ったXMLの解析を行う
完成図

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 220
XMLの解析:DOM (2)
<手順>
XmlHelperクラスのparseDomメソッドに以下の処理を実装する
XMLデータのDocumentオブジェクトを取得する
DOMパーサを作成する
XMLを解析しDOMツリーを構築する
RowModelに値をセットする

ActivityクラスにonClickDOMButtonの実装
XmlHelper#parseDomメソッドを呼び出し整形データRowModelを取得する
• ※XmlHelperのインスタンスはメンバ変数”xmlHelper”で定義されている
TextViewに解析結果を表示する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 221
XMLの解析:DOM (3)
XmlHelperクラスのparseDomメソッドの実装
XMLデータのDocumentオブジェクトを取得する
DOMパーサを作成する
XMLを解析しDOMツリーを構築する

<XMLHelper.java>
// TODO 【DOM】 No.01 ドキュメントビルダーファクトリを生成
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
dbfactory.setNamespaceAware(true);
// TODO 【DOM】 No.02 ドキュメントビルダーを生成
DocumentBuilder builder = dbfactory.newDocumentBuilder();
// xmlファイルのストリームを取得
in = context.getAssets().open("sample.xml");
// TODO 【DOM】
Document doc =
// TODO 【DOM】
Element root =

No.03 パースを実行してDocumentオブジェクトを取得
builder.parse(in);
No.04 ルート要素を取得(タグ名:message)
doc.getDocumentElement();

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 222
XMLの解析:DOM (4)
XmlHelperクラスのparseDomメソッドの実装
RowModelに値をセットする
• idをセット
// <entry>を取得
NodeList entryList = root.getElementsByTagName("entry");
// 最初の<entry>を取得
Element entryElement = (Element) entryList.item(0);
/* <id>の処理 */
// TODO 【DOM】 No.05 取得した<entry>から<id>を取得
Element idElement = (Element) entryElement.getFirstChild();
// TODO 【DOM】 No.06 取得した<id>からTextデータを取得
String id = idElement.getFirstChild().getNodeValue();
// 値をRowModelにセット
rowModel.setId(id);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 223
XMLの解析:DOM (5)
XmlHelperクラスのparseDomメソッドの実装
RowModelに値をセットする
• descriptionをセット
/* <description>の処理 */
// 取得した<entry>から<description>を取得
NodeList desriptionList =
entryElement.getElementsByTagName("description");

// Nodeからテキスト情報を取得。
String summary = desriptionList.item(0).getFirstChild().getNodeValue();
// 20文字以降をカットする。
if (summary != null && 0 < summary.length()) {
if (20 < summary.length()) {
summary = summary.substring(0, 20);
}
}
// 値をRowModelにセット
rowModel.setSummary(summary);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 224
XMLの解析:DOM (6)
XmlHelperクラスのparseDomメソッドの実装
RowModelに値をセットする
• thumbnailをセット
/* <thumbnail>の処理 */
// <thumbnail>を取得
NodeList thumbnailList = entryElement
.getElementsByTagName("thumbnail");
// 最初の<thumbnail>を取得
Element thumbnailElement = (Element) thumbnailList.item(0);
// TODO 【DOM】 No.07 <thumbnail>から"url"属性の値を取得
String thumbnail = thumbnailElement.getAttribute("url");
// 値をRowModelにセット
rowModel.setThumbnailImageURL(thumbnail);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 225
XMLの解析:DOM (7)
XmlHelperクラスのparseDomメソッドの実装
RowModelに値をセットする
• titleをセット
/* <title>の処理 */
// <title>を取得
NodeList titleList = entryElement.getElementsByTagName("title");
// Nodeからテキスト情報を取得
String title = titleList.item(0).getFirstChild().getNodeValue();
// 値をRowModelにセット
rowModel.setTitle(title);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 226
XMLの解析:DOM (8)
ActivityクラスにonClickDOMButtonの実装
XmlHelper#parseDomメソッドを呼び出し整形データRowModelを取得する
• ※XmlHelperのインスタンスはメンバ変数”xmlHelper”で定義されている
TextViewに解析結果を表示する
public void onClickDOMButton(View v) {
RowModel rowModel = null;
// TODO 【DOM】 No.08 XmlHelper#parseDomの呼び出しRowModelを取得する
rowModel = this.xmlHelper.parseDom(this, this.xml);
if( rowModel == null){
this.textResult.setText("データを取得できませんでした。");
}else{
// TODO 【DOM】 No.09 TextViewにrowModelの内容を表示する
this.textResult.setText(rowModel.toString());
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 227
XMLの解析:DOM (9)
実行結果

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 228
XMLの解析:DOM (解答)
解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 229
SAXとは
SAX(イベント駆動型)
パーサがパースをしているアプリケーションを呼び出すようなイメージ
。
XML ドキュメントを頭から読んでいき、タグの開始や終了などに ぶつ
かると、決められたアプリケーション側のコールバックルーチンを コー
ルする。
アプリケーション側では DOMのようにXML ドキュメントの読み込みの
制御を行うことが できない。
メモリの消費量は DOM よりも少ない。
すげーはえー♪
Android には、従来の方法での SAX の使い方と、SAX の上に ラップさ
れたラッパーを使う方法が用意されている。
ボクのほうが
!!!!!

扱いやすいもん・・・

SAX
DOM

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 230
XMLの解析の仕方:SAX (1)
SAXを使ったXMLの解析
<手順>
SAXパーサからのコールバックを受けるイベントハンドラクラスの作成する
SAXパーサファクトリを作成し、SAXパーサを取得する
SAXパーサに1で作成したイベントハンドラクラスを設定する
XMLのパースを開始する
イベントが発生したタイミングで1で作成したイベントハンドラにコールバ
ックされる

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 231
XMLの解析の仕方:SAX (2)
SAXパーサからのコールバックを受けるイベントハンドラクラスの
作成する
DefaultHandlerクラスを継承したサブクラスを作成する
各イベントに対応した処理を実装
タグ開始時のイベントの実装
タグ終了時のイベントの実装
要素内のテキストのイベントの実装

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 232
XMLの解析の仕方:SAX (3)
<オーバライドするメソッド>
戻り値

メソッド名

説明

void

startElement(String uri,
String localName,
String qName,
Attributes attributes)

要素の開始通知を受け取る
パラメータ
•uri - 名前空間 URI
•localName - 前置修飾子を含まないローカル名
•qName - 接頭辞を持つ修飾名
•attributes - 要素に付加された属性

void

endElement(String uri,
String localName,
String qName)

要素の終了通知を受け取る
パラメータ
•uri - 名前空間 URI
•localName - 前置修飾子を含まないローカル名
•qName - 接頭辞を持つ修飾名

void

void characters(char[] ch,
int start,
int length)

要素内の文字データの通知を受け取る
パラメータ
•ch - 文字
•start - 文字配列内の開始位置
•length - 文字配列から使用される文字数

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 233
XMLの解析の仕方:SAX (4)
サンプルコード
以下のXML文書を解析するサンプル
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node1>Node Value</node1>
</root>
※実際の文書は改行・空白はありません

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 234
XMLの解析の仕方:SAX (5)
サンプルコード
// 解析対象のストリームを取得する
InputSource is = new InputSource(new StringReader(xml));
SAXパーサ作成

// パーサのFactoryを作成
SAXParserFactory saxParaser = SAXParserFactory.newInstance();
try {
/* パーサを取得 */
SAXParser sp = saxParaser.newSAXParser();
/* イベントハンドラを作成 */
SaxHandler sh = new SaxHandler();

XMLの解析

/* イベントハンドラに入力データとイベントハンドラを渡す */
sp.parse(is, sh);
} catch (Exception e) {
e.printStackTrace();
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 235
XMLの解析の仕方:SAX (6)
class SaxHandler extends DefaultHandler {
//タグ開始フラグ
boolean isNode1;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if ("node1".equals(localName)) {
// node1 タグの開始
isNode1= true;
}
}

タグ開始時の処理

@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("node1".equals(localName)) {
// node1 タグの開始
isNode1= false;
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
//node1タグが開始されていたら、文字列をログに出力
if (isNode1) {
String nodevalue = new String(ch, start, length);
Log.v(TAG, nodevalue);
}
}
}

タグ終了時の処理

テキストイベントの処理

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 236
XMLの解析:SAX (1)
実習 2
SAXを使ったXMLの解析を行う
完成図

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 237
XMLの解析:SAX (2)
<手順>
XmlHelperクラスにDefaultHandlerクラスを継承したサブクラスを作成す
る
startElement, characters, endElementメソッドを実装する

XmlHelperクラスのparseSaxメソッドに以下の処理を実装する
SAXパーサオブジェクトの作成
XMLの解析開始

ActivityクラスにonClickSAXButtonの実装
XmlHelper#parseSaxメソッドを呼び出し整形データRowModelを取得する
•
※XmlHelperのインスタンスはメンバ変数”xmlHelper”で定義されてい
る
TextViewに解析結果を表示する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 238
XMLの解析:SAX (3)
XmlHelperクラスにDefaultHandlerクラスを継承したサブクラスを作
成する
class SaxHandler
サブクラスの定義 extends

DefaultHandler {

RowModel rowModel = new RowModel();
//タグ開始フラグ
boolean isEntry;
boolean isId = false;
boolean isSummary = false;
boolean isTitle = false;
boolean isThumbnail = false;
String id = null;
String summary = null;
String thumbnail = null;
String title = null;

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 239
XMLの解析:SAX (4)
XmlHelperクラスにDefaultHandlerクラスを継承したサブクラスを作
成する
class SaxHandler extends DefaultHandler {
startElement, characters, endElementメソッドを実装する
~略~
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
~略~
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
~略~
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
~略~
}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 240
XMLの解析:SAX (5)
startElementメソッドを実装する
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if ("entry".equals(localName)) {
//TODO 【SAX】 No.01 entryタグの場合はisEntryをtrueにする
//if (条件判定) {
// Entry タグの開始
isEntry = true;
}
//entryタグの中にいるか判定
if (isEntry) {
if ("id".equals(localName)) {
isId = true;
}
if ("description".equals(localName)){
isSummary = true;
}
if (!isThumbnail && "thumbnail".equals(localName)){
// TODO 【SAX】 No.02 thumnailタグのurl属性を取得する
thumbnail = attributes.getValue("url");
isThumbnail = true;
}
if ("title".equals(localName)){
isTitle = true;
}
}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 241
XMLの解析:SAX (5)
charactersメソッドを実装する
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (isEntry) {
if (isId) {
//idを取得する
id = new String(ch, start, length);
isId = false;
}
if (isSummary) {
//descriptionを取得する
summary = new String(ch, start, length);
if (summary != null && 0 < summary.length()) {
if (20 < length) {
summary = summary.substring(0, 20);
}
}
isSummary = false;
}
if (isTitle) {
// TODO 【SAX】 No.04 titleを取得する
title = new String(ch, start, length);
isTitle = false;
}
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 242
XMLの解析:SAX (6)
endElementメソッドを実装する
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("entry".equals(localName)) {
// TODO 【SAX】 No.03 rowModelに値を設定する
rowModel.setId(id);
rowModel.setSummary(summary);
rowModel.setThumbnailImageURL(thumbnail);
rowModel.setTitle(title);
//値をクリア
id = null;
summary = null;
thumbnail = null;
title = null;
isThumbnail = false;
isEntry = false;
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 243
XMLの解析:SAX (7)
ActivityクラスにonClickSAXButtonの実装
XmlHelper#parseSaxメソッドを呼び出し整形データRowModelを取得す
る
※XmlHelperのインスタンスはメンバ変数”xmlHelper”で定義されている

TextViewに解析結果を表示する
public void onClickSAXButton(View
<XmlSample.java> = null;
RowModel rowModel

v) {

// TODO 【SAX】 No.08 XmlHelper#parseSaxの呼び出しRowModelを取得する
rowModel = this.xmlHelper.parseSax(this, this.xml);
if( rowModel == null){
this.textResult.setText("データを取得できませんでした。");
}else{
// TODO 【SAX】 No.09 TextViewにrowModelの内容を表示する
this.textResult.setText(rowModel.toString());
}

}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 244
XMLの解析:SAX (8)
実行結果

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 245
XMLの解析:SAX (解答)
解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 246
XmlPullpaserとは
XmlPullparser(Pull 型)
SAX と同じように XML ドキュメントを頭から読みこむが、読み込みの
制御をアプリケーション側で行い、必要に応じてパーサから情報を取得
することができる。
アプリケーション側から制御が行えるため、早い段階で構文解析を停止
させることができるので、構文解析に要する時間を大幅に短縮できる。
途中で止まれな
い!

いつでも止まれる♪

ボクも速い!

SAX

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 247
XMLの解析の仕方:XmlPullpaser (
1)
XmlPullpaserを使ったXMLの解析
<手順>
XmlPullParserオブジェクトを生成する
パーサにパースする文字列を渡す
XMLイベントを1つずつ取得し、解析する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 248
XMLの解析の仕方:XmlPullpaser (
2)
サンプルコード
以下のXML文書を解析するサンプル
<?xml version="1.0" encoding="UTF-8"?>
<root>
<node1>Node Value</node1>
</root>
※実際の文書は改行・空白はありません

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 249
XMLの解析の仕方:XmlPullpaser (
3)
サンプルコード
InputStream in = null;
try {
// 解析対象のストリームを取得する
is = getAssets().open("samplea.xml");
// XmlPullParser XmlPullParserを定義する
XMLPullParserパーサ作成
final XmlPullParser parser = Xml.newPullParser();
// XmlPullParser パースする文字列のストリームを渡す
パーサにパースする文字列を渡す
parser.setInput(new InputStreamReader(is));
parser.next(); // rootタグ
parser.next(); // node1タグ
// XmlPullParser タグの名前を取得する
String tag = parser.getName();
XMLイベントを一つずつ取得し解析する
// XmlPullParser タグの名前が“node1"なら、
if ("node1".equals(tag)) {
parser.next();
String nodevalue = parser.getText();
Log.v(TAG, nodevalue);
}
} catch (Exception e) {

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 250
XMLの解析の仕方:XmlPullpaser (
4)
< XmlPullParserのメソッド>
戻り値

メソッド名

説明

void

setInput(Reader in)

引数の入力ソースをパーサーに渡す
パラメータ
•in – 入力ソース

int

next()

パーサーからXMLを1行送りする

String

getName()

XMLタグ名を取得する

String

getText()

XMLの要素を取得する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 251
XMLの解析:XmlPullpaser (1
)
実習 3
XmlPullpaserを使った解析を行う
完成図

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 252
XMLの解析の仕方:XmlPullpaser
(2)
<手順>
XmlHelperクラスにparseXmlPullparserメソッドに以下の処理を実装する
XmlPullParserを定義する
パースする文字列のストリームを渡す
While文で一つずつ処理を行う。
<entry>の中の<id>タグの値を取得し、RowModelに値をセットする
<thumbnail>から“url”属性の値を取得し、RowModelに値をセットする

ActivityクラスにonClickXMLPullparserButtonの実装
XmlHelper#parseXmlPullparserメソッドを呼び出し整形データRowModelを
取得する
• ※XmlHelperのインスタンスはメンバ変数”xmlHelper”で定義されている
TextViewに解析結果を表示する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 253
XMLの解析の仕方:XmlPullpaser
(3)
XmlHelperクラスにparseXmlPullparserメソッドに以下の処理を実装
する
XmlPullParserを定義する
RowModel parseXmlPullparser(Context context, String
パースする文字列のストリームを渡す

public
RowModel rowModel = null;
InputStream is = null;
try {
// 解析対象のストリームを取得する
is = context.getAssets().open("sample.xml");

xml) {

// TODO 【XMLPull】 No.01 XmlPullParserを定義する
final XmlPullParser parser = Xml.newPullParser();
// TODO 【XMLPull】 No.02 パースする文字列のストリームを渡す
parser.setInput(new InputStreamReader(is));
int eventType;
// XmlPullParser パースしている階層を取得
final int depth = parser.getDepth();
// XmlPullParser パースの終了条件
// TODO 【XMLPull】 No.03 while文で一つずつ処理をする
while (((eventType = parser.next()) != XmlPullParser.END_DOCUMENT || parser
.getDepth() > depth)) {
~次ページで説明~
}
} catch (Exception e) {
~略~
return rowModel;
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 254
XMLの解析の仕方:XmlPullpaser
(4)
while文で一つずつ処理を行う。
// TODO 【XMLPull】 No.03 while文で一つずつ処理をする
while (((eventType = parser.next()) != XmlPullParser.END_DOCUMENT
|| parser.getDepth() > depth)) {
// XmlPullParser eventTypeが開始タグか判定
if (eventType == XmlPullParser.START_TAG) {
// XmlPullParser タグの名前を取得する
String tag = parser.getName();
// XmlPullParser タグの名前が"entry"なら、parseToRowModelを呼び出す
if ("entry".equals(tag)) {
rowModel = parseToRowModel(parser);
break;
}
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 255
XMLの解析の仕方:XmlPullpaser
(5)
<entry>の中の<id>タグの値を取得し、RowModelに値をセットする
<thumbnail>から“url”属性の値を取得し、RowModelに値をセットする
private RowModel parseToRowModel(XmlPullParser parser) throws XmlPullParserException, IOException {
RowModel rowModel = new RowModel();
~略~
// パースの終了条件
while (((eventType = parser.next()) != XmlPullParser.END_DOCUMENT || parser
.getDepth() > depth)) {
// eventTypeが開始タグか判定
if (eventType == XmlPullParser.START_TAG) {
tag = parser.getName();
// TODO 【XMLPull】 No.04 <entry>の中の<id>タグの値を取得し、RowModelに値をセットする
if ("id".equals(tag)) {
// 次に移動する。
parser.next();
// parserからテキスト情報を取得し、rowModelのURLにセットする。
rowModel.setId(parser.getText());
} else if ("description".equals(tag)) {
~略~
} else if ("thumbnail".equals(tag)) {
// TODO 【XMLPull】 No.05 <thumbnail>から”url”属性の値を取得し、RowModelに値をセットするる
if (rowModel.getThumbnailImageURL() == null) {
rowModel.setThumbnailImageURL(parser.getAttributeValue(
null, "url"));
}
} else if ("title".equals(tag)) {
~略~
}
}
return rowModel;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 256
XMLの解析の仕方:XmlPullpaser
(6)
実行結果

クリック

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 257
XMLの解析の仕方:XmlPullpaser
(解答)
解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 258
XMLパーサのパフォーマンス測定
Traceview とは
処理の実行時間を計測するツール
実行時間を計測し、ファイルに出力する
出力したファイルはTraceViewを使って計測結果を確認することができ
る

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 259
XMLパーサのパフォーマンス測定
TraceViewを使ってXMLパーサの実行時間を計測する
Traceview
処理の実行時間を計測するツール
実行時間を計測し、ファイルに出力する
出力したファイルはTraceViewを使って計測結果を確認することができる

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 260
XMLパーサのパフォーマンス測定
TraceViewの使い方
計測したい処理の前後に以下のメソッドを追加する
Debug.startMethodTracing("出力ファイル名");
• 計測を開始するメソッド。引数に出力ファイル名を指定する
Debug.stopMethodTracing();
• 計測終了のメソッド

AndroidManifestファイルにSDカード書き込み権限を追加する
traceファイルはsdカードに出力されるため、書き込み権限の追加が必要にな
る
Debug.startMethodTracing(“xml”);// 測定開始箇所
例)
tableData = xmlHelper.parseTableModel(entity); //測定箇所
Debug.stopMethodTracing(); // 測定終了箇所

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

AndroidManifest.xml

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 261
XMLパーサのパフォーマンス測定
TraceViewで計測結果を確認する
<手順>
出力した trace ログファイルを DDMS を使って PC に格納する。
コマンドプロンプトより traceview [ファイル名] として実行する。
※AndroidSDKのバージョンが12以前では[ファイル名]はフルパスで指定する
必要がある。以下の例ではC:work時間計測xml.traceとなっている

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 262
XMLパーサのパフォーマンス測定
TraceViewで計測結果を確認する(続き)
コマンドを実行すると以下のようなViewが起動する
Incl %

Inclusive 時間の
トータルタイムから
の
パーセンテージ

Inclusive

そのメソッドと、
その
メソッドから呼ば
れた
メソッドの実行時
間

Excl %

Exclusive

Time/Call

そのメソッド メソッドの実行時
の
間
実行時間
(msec)

Exclusive 時間の
トータルタイムか
らの
パーセンテージ

Cals+RecurCalls/Total

このメソッドが何回呼ばれた
か/再帰で何回呼ばれたか

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 263
XMLパーサのパフォーマンス測定
計測結果(一例)
YouTubeサービスの動画検索APIを利用した場合、パース処理計測では
以下のような結果になった
検索データは動画30件分を取得
XMLは最初から最後までパースする必要がある
URL例:
• http://gdata.youtube.com/feeds/api/videos?category=bass%2Cfishing&v
=2
0
•
•
•

250

500

750

1000 ms

XmlPullparser 1134.704 ms
SAX
388.794 ms
DOM
計測不可能
※DOMではあまりに遅すぎて測定することが出来なかった

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 264
8. サービス
サービス
サービスとは?
サービスは長時間バックグラウンドで動き続けるUIを持たないAndroidコ
ンポーネントである
ユーザがアプリケーションを切り替えたり、終了してもサービスは起動
し続けることができる
常にバックグラウンドで動き続けるため常駐プログラムとして使用する
ことができる
サービスの例
音楽再生
ダウンロード
タイマー、アラーム
ロケーション情報
センサー情報

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 266
サービスの使いどころ
サービスの使いどころ
ダウンロードのように中断したくない処理は、サービス化したほうが良
い。
サービス化することで、途中で中断することなく処理を完了することが
できる
Activityのライフサイクルには依存しないため、完全に独立した処理で使用す
る
別プロセスで起動することもできるためActivityの終了や割り込みなどが起き
ても処理を継続することができる
例)
•
「戻る」ボタンを間違えて押してしまった場合
•
他のプログラムが実行された場合
– 電話がかかってきた
– メールが通知された
• などの割り込み処理が発生しても処理を継続

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 267
サービスの作成
サービスを実装する方法
サービスのクラスを新規作成する
基底クラスとなるServiceクラスを継承したクラスを作成する
onBindメソッドは抽象メソッドのため実装する必要がある。
ここではバインドを用いないためnullを返すようにしておく。
※バインドについては後述

サンプルコード
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
public class SampleService extends Service {
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 268
サービスのライフサイクル
必要に応じてコールバックメソッドを実
装する
onCreate, onStartCommand, onDestroyの3
つのメソッドがある
ライフサイクルを意識し、適切に実装をす
る
onStartCommandは起動される度に呼び出
される
他の2つのメソッドはオブジェクトの生成
イベント名
内容
と 破棄の際に1回だけ呼び出される
onCreate

サービスが起動される前に発生する
イベント

onDestroy

onCreate()

onStartCommand()

実行中
・停止命令

最初の起動時に発生するイベント

onStartCommand

Service起動

サービスが破棄される前に発生する
イベント

・

onDestroy()

状態遷移方向
状態

Activityのイベン
ト

Service破棄

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 269
サービスの起動(1)
Service#onStartCommandメソッド
戻り値

メソッド名

説明

int(※2)

onStartCommand(Intent intent, int
flags, int startId)

startServiceメソッドによって呼び出され、
サービスを開始する
パラメータ
•intent – サービスを開始する時に宣言した
Intentのインスタンスを設定
•flags(※1) – 開始要求に関する追加データを
設定
•startId – 開始要求を表す一意の整数である。
stopSelfResultメソッドの引数に指定して
サービスを停止する場合に使用

–

※1,※2に

ついては後述

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 270
サービスの起動(2)
onStartCommandメソッドの第2引数として以下の2つの定数が用意され
ている
定数

説明

START_FLAG_REDELIVERY

既にサービスを開始する時のインテントがある場合、
START_FLAG_REDELIVERYが設定される

START_FLAG_RETRY

サービスを開始する時のインテントがまだない場合、
START_FLAG_RETRYが設定される

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 271
サービスの起動(3)
onStartCommandメソッドの戻り値として以下の4つの定数が用意されて
いる

戻り値

説明

START_NOT_STICKY

サービスを起動するペンディングインテントが存在しない限
りサービスは再起動されない。強制終了によりサービスが終
了した場合、勝手な再起動を防ぐ場合に使用する

START_STICKY

システムはサービスを新たにインスタンス化し、サービスの
再起動を行う。
サービスを起動するペンディングインテントが存在しない場
合、システムはIntentをnullにしてonStartCommandを呼び出
す。
startServiceによりサービスを複数回起動していたとしても再
起動は1度しか行われない。

START_REDELIVER_INTENT

システムはサービスを新たにインスタンス化し、サービスの
再起動を行う。
再起動時のonStartCommandには強制終了前と同じ内容の
Intentが渡される。
再起動手順が強制終了前の起動手順と同じ。(A=>Bで起動し
た場合、A=>Bで再起動)
startServiceによりサービスを複数回起動していい多場合は、
起動した回数分onStartCommandが呼ばれる

START_STICKY_COMPATIBILIT システムに再起動される保証がない。START_STICKYとの互
換性のために用意されている。このモードが指定された場合、
ⅰ - 272
Y
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
onStartCommandの引数Intentにはnullは格納されない。
サービスのサンプル
サンプルコード
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId){
Toast.makeText(this, "Service Start", Toast.LENGTH_SHORT).show();
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
Log.v(getClass().getSimpleName(), "i:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
return START_STICKY;
}
@Override
public void onDestroy() {
Toast.makeText(this, "Service end", Toast.LENGTH_SHORT).show();
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
}

ⅰ - 273
サービスの作成(1)
実習1
サービスを使ったプログラムを作成する

ログ

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 274
サービスの作成(2)
プロジェクトのインポート
プロジェクト名: ServiceSample_skeleton
項目

設定値

Project name

ServiceSample

Build Target

※指定したバージョンを使用すること

Application name

ServiceSample

Package name

jp.oesf.servicesample

Create Activity

ServiceSampleActivity

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 275
サービスの作成(3)
手順
1.
2.
3.
4.

レイアウトの修正
Serviceの作成
ServiceSampleActivityの修正
AndroidManifestファイルの修正

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 276
サービスの作成(4)
手順詳細
1. レイアウトの修正
activity_service_sample.xmlファイルを修正する
strings.xmlファイルを修正する

2. Serviceの作成
Serviceクラスの継承
サービス起動時と終了時にトーストを起動する
サービス起動時に一秒毎にログを出力する

3. ServiceSampleActivityの修正
前ページで作成したSeviceクラスを定義
ToggleButtonが押されたときの処理を追加

4. AndroidManifestファイルの修正
Serviceタグを追加し、使用するサービスを指定する
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 277
サービスの作成(5)
スケルトンプログラムの内容
<ServiceSampleActivity.java>
public void onClickServiceButton(View v){
ToggleButton tb = (ToggleButton)v;
if( tb.isChecked()){
// TODO No.01 サービスを開始する
Intent intent = new Intent(this, ServiceSampleService.class);
startService(intent);
}else{
// TODO No.02 サービスを終了する
Intent intent = new Intent(this, ServiceSampleService.class);
stopService(intent);
}
}

トグルボタンが押された
ときの処理

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 278
サービスの作成(6)
スケルトンプログラムの内容
<ServiceSampleService.java>
public class ServiceSampleService extends Service {
AtomicBoolean running = new AtomicBoolean(false);
LogThread thread = new LogThread();

スレッドランニングフラグ

@Overrid
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//TODO No.03 Toastを表示する
Toast.makeText(this, “Service Start”, Toast.LENGTH_SHORT).show();
サービス開始時の処理
//TODO No.04 runnigフラグの変更
running.set(true);
//TODO No.05 Threadの開始
thread.start();
return START_STICKY;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 279
サービスの作成(7)
スケルトンプログラムの内容
<ServiceSampleService.java>
@Override
public void onDestroy() {
//TODO No.06 running1フラグの変更
running.set(false);
サービス終了時の処理
//TODO No.07 Toastの表示
Toast.makeText(this, "Service end", Toast.LENGTH_SHORT).show();
}
/**
* 1秒毎にログを出力するThread
*
*/
class LogThread extends Thread{
@Override
public void run() {
for (int i = 0; running.get(); i++) {
//TODO No.08 Logの出力

Log.v(getClass().getSimpleName(), "i:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

1秒毎にログを出力するThread

}
}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 280
サービスの作成(8)
1. レイアウトファイルの修正
strings.xml
name

value

service_off

Service Off

service_on

Service On

activity_service_sample.xml

階層構造

<LinearLayout>
<ToggleButton />
</LinearLayout>

View

Property

ToggleButton

android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/button_service"
android:onClick="onClickServiceButton"
android:textOff="@string/service_off"
android:textOn="@string/service_on

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 281
サービスの作成(9)
2. Serviceの作成
追加Serviceクラス
継承元クラス

クラス名

Serviceクラス

ServiceSampleService

実装するメソッドと処理内容
メソッド

処理

onStartCommand

・Toastの表示
メッセージ:"Service Start"
・ LogThreadの実行
runningフラグの変更
Thread#startで開始

onDestroy

・ LogThreadの終了
runningフラグの変更
・ Toastの表示
メッセージ:"Service Stop"

LogThread#run

・ 1秒毎にLog出力

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 282
サービスの作成(10)
3. Activityの修正
Activityクラスにサービスの起動・終了の処理を追加
ToggleButtonをクリックした時の処理を実装する
• isCheckedメソッドでToggleButtonの状態を取得できる
• トグルボタンがONの場合はサービスを起動する
• トグルボタンがOFFの場合はサービスを終了する
public void onClickServiceButton(View v){
ToggleButton tb = (ToggleButton)v;
if( tb.isChecked()){
//サービスを開始する
Intent intent = new Intent(this, ServiceSampleService.class);
startService(intent);
}else{
//サービスを終了する
Intent intent = new Intent(this, ServiceSampleService.class);
stopService(intent);
}
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 283
サービスの作成(11)
4. AndroidManifest.xmlの修正
マニフェストファイルにサービスを登録する
~略~
<service android:name=".ServiceSampleService" />
</application>
~略~

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 284
サービスの作成(12)
確認
サービスが起動時にToastが表示される (メッセージ”Service Start”)
サービス起動中にログが出力される
終了時にToastが表示される (メッセージ”Service End”)
サービス起動時

サービス終了時

ログ

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 285
サービスの作成(解答)
解答
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 286
サービスの作成(追加実習)
実習2
前項で作成したアプリケーションをスケルトンを使わずに最初から作成
する
解答ドキュメントを参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 287
サービスの作成 [補足実習 1]
実習2 補足1
実習2で作成したアプリケーションには以下のバグが存在するので修正
する

ToggleButtonをクリックし
てServiceを起動する

「ServiceSample」アプリ
ケーションを起動する

ToggleButtonをクリックし
てServiceを起動する

①

エラーが発生する

③

バックキー
を押下する

②

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

④

ⅰ - 288
サービスの作成 [補足実習 1]
バグの原因
バグの原因はサービス内で、既に実行中のThreadを起動することが原因
です
バグを修正するには以下の2つの方法が考えられます
ActivityのonPause()メソッド内でサービスを明示的に終了する
サービス内のThreadが既に実行されているか条件分岐する

解答
解答ドキュメントを参照 「Service実習2 補足1 解答」

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 289
サービスの作成 [補足実習 2]
実習2 補足2
実習2 補足1の解答例ではThreadの複数起動ができませんでした。
実習2で作成したアプリケーションにThreadの複数起動処理に対応した
修正をしてエラーが発生しないことを確認してください

解答
解答ドキュメントを参照 「第11章 Service

実習2 補足2 解答」

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 290
サービスに接続する
サービスに接続する
サービスのバインド
サービスが提供する機能を呼び出すために、アプリケーションがサービスに
接続することを”バインド”といいます

アプリケーションをサービスから切断することを“アンバインド”といい
ます
ActivityはServiceConnectionインタフェースを使うことで、サ
ービスからデータを取得したり、データを設定したりすることができる
。
aidlファイルを使うことでサービスとActivityのプロセス間通信が可能に
なります
※aidlファイル、ServiceConnectionインタフェースについては後述

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 291
サービスに接続する
サービスに接続する方法
サンプルプログラムを使って説明
①

④

②

Toastボタン
をクリック

③
サービス側で
Toastを表示

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 292
サービスに接続する手順
手順
サービスに接続するインタフェースを作成する
aidlファイルの作成

Serviceの修正
自動生成されたインタフェースのStubクラスのサブクラスを定義する
onBindメソッドでサブクラスを返す

Activityの修正
Serviceに接続するためのインタフェースクラスを作成
• ServiceConnectionインタフェースの実装クラスを定義する
Serviceに接続する処理を追加
• bindServiceメソッドを使ってサービスに接続する
Serviceと通信する
• Binderインタフェースを使ってサービスに定義されているメソッドを呼
び出す
Serviceの接続を解除する処理を追加
• unbindServiceメソッドを使ってサービスから切断する
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 293
手順 1. サービス接続インタフェ
ースの作成(1)
サービスに接続するインタフェースを作成する
aidlファイルの作成
• メニューの[File] → [New]→[File]から”[インタフェース名].aidl”というファ
イルを作成(ここでは「IServiceSampleService.aidl」)

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 294
手順 1. サービス接続インタフェース
の作成(2)
 aidlファイルとは
サービスに実装するメソッドを定義したインターフェイスファイル
aidlで記述されたファイルの拡張子は.aidl
aidlファイルにサービスに実装させたいインターフェースを記述する
aidlファイルにはjavaの構文をそのまま使える
aidlファイルを使うことで、Activityから、サービスに実装されているインタ
フェースを経由してpublicメソッドを呼び出すことができる

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 295
手順 1. サービス接続インタフェース
の作成(3)
1. aidlファイルの作成 (続き)
メソッドを定義する
package jp.oesf.servicesample;
interface IServiceSampleService{
void showToast();
}

自動生成されたjavaファイルの確認
• ソースコードと同じディレクトリにaidlファイルを保存すると、
Eclipseが自動的にコンパイルし、Javaのインターフェースが生成される
– gen/aidlファイル名.javaファイルが作成される

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 296
手順 1. サービス接続インタフェース
の作成(4)
 自動作成されたjavaファイルについて
作成されたインターフェースの中には、Stubと呼ばれる抽象クラスが作成さ
れている。
• [インタフェース名].Stubインタフェースで作成される
• aidlに定義したメソッドがオーバライドされている
Stubクラスを使用することによってプロセス間でメソッドの呼び出しが可能
になる。
public interface IServiceSampleService extends android.os.IInterface {
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements
jp.oesf.servicesample.IServiceSampleService {
private static final java.lang.String DESCRIPTOR =
"jp.oesf.servicesample.IServiceSampleService";
/** Construct the stub at attach it to the interface. */
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
~略~
public void showToast() throws android.os.RemoteException;
}
※実際のファイルはインデントされていません。
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 297
手順 2. Serviceの修正
2. Serviceの修正
① 自動生成されたインタフェースのStubクラスのサブクラスを定義する
② サブクラス内でインタフェースに定義したメソッドをオーバライドする
③ onBindメソッドのオーバライド
• 戻り値を定義したStubインタフェースにする

public class ServiceSampleService extends Service {
//サービスStubを定義する
private IServiceSampleService.Stub binder = new IServiceSampleService.Stub() {
・・・①
@Override
public void showToast() throws RemoteException {
・・・②
Toast.makeText(getApplicationContext(), "Service Running", Toast.LENGTH_SHORT).show();
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
・・・③
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 298
手順 3. Activityの修正(1)
3. Activityの修正
Serviceに接続するためのインタフェースクラスを作成
• ServiceConnectionインタフェースの実装クラスを定義する
Serviceに接続する処理を追加
• bindServiceメソッドを使ってサービスに接続する
Serviceと通信する
• Binderインタフェースを使ってサービスに定義されているメソッドを呼
び出す
Serviceの接続を解除する処理を追加
• unbindServiceメソッドを使ってサービスから切断する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 299
手順 3. Activityの修正(2)
 ServiceConnectionインタフェースとは
サービス接続した時と異常終了した時のコールバックメソッドが定義されて
いる。
• サービス接続時:onServiceConnected
– Context#bindServiceを使ってサービスにバインドする
– バインドすると、ServiceConnection#onServiceConnected がコー
ルバックされる。
– onServiceConnectedメソッドの引数でStubインタフェースを取得
– このStubインタフェースを使ってサービスに定義してあるメソッド
を呼び出すことができる
• 異常終了時:onServiceDisconnected
– サービスがクラッシュしたり強制終了などのときにAndroidシステ
ムよりonServiceDisconnectedメソッドがコールバックされる
– Context#unbindServiceを使ってサービスからアンバインドしても
呼び出されることはない

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 300
手順 3. Activityの修正(3)
3. Activityの修正
Serviceに接続するためのインタフェースクラスを作成
• ① aidlより自動生成されたインタフェースをメンバ変数で定義
• ② ServiceConnectionインタフェースの実装クラスを定義する
• ③ 抽象メソッドをオーバライドする
– onServiceConnected
– 引数を使って1で定義したインターフェースを取得する

– onServiceDisconnected
– インタフェースの参照を外す
private IServiceSampleService service;

・・・①

private ServiceConnection connection = new ServiceConnection() {

・・・②

@Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
service = IServiceSampleService.Stub.asInterface(ibinder);
}
};

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

・・・③

・・・③
ⅰ - 301
手順 3. Activityの修正(4)
3. Activityの修正
Serviceに接続するためのインタフェースクラスを作成
• ServiceConnectionインタフェースの実装クラスを定義する
Serviceに接続する処理を追加
• bindServiceメソッドを使ってサービスに接続する
Serviceと通信する
• Binderインタフェースを使ってサービスに定義されているメソッドを呼
び出す
Serviceの接続を解除する処理を追加
• unbindServiceメソッドを使ってサービスから切断する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 302
手順 3. Activityの修正(5)
3. Activityの修正
2. Serviceに接続する処理を追加
• bindServiceメソッドを使ってサービスに接続する
– 第1引数にIntentを指定する
– 第2引数にServiceConnectionインタフェースの実装クラスを指定す
る
– ※第3引数については後述
Intent intent = new Intent(this, ServiceSampleService.class);
startService(intent);
//サービスに接続する
bindService(intent, connection, BIND_AUTO_CREATE);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 303
手順 3. Activityの修正(6)
 Context#bindServiceメソッド
戻り値

メソッド名

説明

boolean

bindService(
Intent service,
ServiceConnection
conn,
int flags)

ServiceConnectionインタフェースを利
用してサービスに接続する

<引数>
・ service
サービスを開始する時に宣言したIntent
のインスタンスを設定
・ conn
ServiceConnectionのインスタンスを設
定
・ flags(※下記参照)
サービスをバインドする時の操作オプ
ション
bindServiceメソッドの第3引数で指定する定数

flags

説明

BIND_AUTO_CREATE

バインドが存在している間は、自動的にサービスを生成する
通常、 BIND_AUTO_CREATEを指定する

BIND_DEBUG_UNBIND

不正なアンバインドが呼び出された場合のデバッグを補助する

対象となるサービスのプロセスをフォアグラウンドのスケジュー
BIND_NOT_FOREGRO
リング
ⅰ - 304
UND
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
優先順位に上げない
手順 3. Activityの修正(7)
3. Activityの修正
2. Serviceに接続する処理を追加(続き)
• bindServiceを実行すると、Service#onBindメソッドが呼び出され、
ServiceConnection#onServiceConnectedがコールバックされる
• onServiceConnectedの第2引数IBinderでonBindの戻り値で指定したイン
タフェースが取得できる

private ServiceConnection connection = new ServiceConnection() {
〜略〜
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
service = IServiceSampleService.Stub.asInterface(ibinder);
}
};

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 305
手順 3. Activityの修正(8)
サービスに接続するまでの流れ
① aidlファイルを作成

interface IServiceSampleService{
void showToast();
}

② javaインタフェース
が自動生成される

③ インタフェースの実装とonBindのオーバライド
//サービスStubを定義する
private IServiceSampleService.Stub binder = new IServiceSampleService.Stub() {
@Override
public void showToast() throws RemoteException {
Toast.makeText(getApplicationContext(), "Service Running", Toast.LENGTH_SHORT).show();
}
};
@Override
public IBinder onBind(Intent intent) {
return binder;
・・・③
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 306
手順 3. Activityの修正(9)
サービスに接続するまでの流れ(続き)
④ ServiceConnectionインタフェースの実装クラスを定義
private IServiceSampleService service;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
service = IServiceSampleService.Stub.asInterface(ibinder);
}
};

⑤ サービスに接続する
Intent intent = new Intent(this, ServiceSampleService.class);
startService(intent);
//サービスに接続する
bindService(intent, connection, BIND_AUTO_CREATE);
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 307
手順 3. Activityの修正(10)
サービスに接続されたときの流れ
① サービスに接続する
//サービスに接続する
bindService(intent, connection, BIND_AUTO_CREATE);

② Service#onBIndが呼び出される
@Override
public IBinder onBind(Intent intent) {
return binder;
}

③ ServiceConnection#onServiceConnectedが呼び出される
private IServiceSampleService service;

private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
service = IServiceSampleService.Stub.asInterface(ibinder);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 308
手順 3. Activityの修正(11)
3. Activityの修正
Serviceに接続するためのインタフェースクラスを作成
• ServiceConnectionインタフェースの実装クラスを定義する
Serviceに接続する処理を追加
• bindServiceメソッドを使ってサービスに接続する
Serviceと通信する
• Binderインタフェースを使ってサービスに定義されているメソッドを呼
び出す
Serviceの接続を解除する処理を追加
• unbindServiceメソッドを使ってサービスから切断する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 309
手順 3. Activityの修正(12)
3. Activityの修正
3. Serviceと通信する
• Binderインタフェースを使ってサービスに定義されているメソッドを呼
び出す
try {
// サービスのメソッドを呼び出す
service.showToast();
} catch (RemoteException e) {
Log.e("ServiceSampleActivity", e.getMessage(), e);
}

• サービスに定義しているメソッドが呼び出される
private IServiceSampleService.Stub binder = new IServiceSampleService.Stub() {
@Override
public void showToast() throws RemoteException {
Toast.makeText(getApplicationContext(), "Service Running",
Toast.LENGTH_SHORT).show();
}
};

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 310
手順 3. Activityの修正(13)
3. Activityの修正
Serviceに接続するためのインタフェースクラスを作成
• ServiceConnectionインタフェースの実装クラスを定義する
Serviceに接続する処理を追加
• bindServiceメソッドを使ってサービスに接続する
Serviceと通信する
• Binderインタフェースを使ってサービスに定義されているメソッドを呼
び出す
Serviceの接続を解除する処理を追加
• unbindServiceメソッドを使ってサービスから切断する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 311
手順 3. Activityの修正(14)
3. Activityの修正
4. Serviceの接続を解除する処理を追加
• unbindServiceメソッドを使ってサービスから切断する
// サービスの接続を解除する
unbindService(connection);

• Context#unbindServiceメソッド
戻り
値

メソッド名

説明

void

unbindService(ServiceConnection
conn)

サービスの接続を解除する
パラメータ
•conn : ServiceConnectionのイ
ンスタンスを設定

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 312
手順 3. Activityの修正 まとめ (1)
 Activityの修正
1〜4の手順をまとめるたソースコード
public class ServiceSampleActivity extends Activity {
// TODO No.03 IServiceSampleService service;
private IServiceSampleService service;
// TODO No.04 Toast表示ボタンの定義(main.xmlにButtonを追加しておくこと)
private Button buttonToast;
// TODO No.05 ServiceConnectionの定義 とメソッドのオーバライド
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
service = IServiceSampleService.Stub.asInterface(ibinder);
}
};
〜略〜
public void onClickToastButton(View v) {
try {
// TODO No.12 Toastを表示する
service.showToast();
} catch (RemoteException e) {
Log.e("ServiceSampleActivity", e.getMessage(), e);
}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 313
手順 3. Activityの修正 まとめ (2)
Activityの修正
1〜4の手順をまとめるたソースコード (続き)
public void onClickServiceButton(View v) {
ToggleButton tb = (ToggleButton) v;
if (tb.isChecked()) {
// サービスを開始する
Intent intent = new Intent(this, ServiceSampleService.class);
startService(intent);
// TODO No.08 サービスに接続する
bindService(intent, connection, BIND_AUTO_CREATE);
// TODO No.09 Toastボタンを有効にする
this.buttonToast.setEnabled(true);
} else {
// TODO No.10 サービスの接続を解除する
unbindService(connection);
// サービスを終了する
stopService(new Intent(this, ServiceSampleService.class));
// TODO No.11 Toastボタンを無効にする
this.buttonToast.setEnabled(false);
}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 314
サービスに接続するプログラムの
作成(1)
実習3
サービスに接続するプログラムを作成する
スケルトンプロジェクト:ServiceSample_bind_skeleton
④

①
②

Toastボタ
ン
をクリック

③
サービス側で
Toastを表示

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 315
サービスに接続するプログラムの
作成(2)
手順
1.
2.
3.
4.

aidlファイルの作成
Serviceクラスの修正
レイアウトファイルの修正
Activityクラスの修正

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 316
サービスに接続するプログラムの
作成(3)
1. aidlファイルの作成
ファイル名:IServiceSampleService.aidl
Toastを表示するメソッドの定義
メソッド:void showToast()
genフォルダ以下にStubが自動作成されていることを確認

<IServiceSampleService.aidl>
package jp.oesf.servicesample;
interface IServiceSampleService {
void showToast();
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 317
サービスに接続するプログラムの
作成(4)
2. Serviceクラスの修正
自動作成されたStubクラスのサブクラスを定義
インタフェースで定義されているメソッドの実装
• showToastメソッドの実装
onBindメソッドの戻り値の修正
• 上記で定義したサブクラス

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 318
サービスに接続するプログラムの
作成(5)
3. レイアウトファイルの修正
Toastボタンの追加
<Toastボタン>
View

Property

Button

android:layout_height="wrap_content"
android:layout_width="match_parent"
android:onClick="onClickToastButton"
android:text="@string/toast"
android:id="@+id/button_toast"

階層構造

<LinearLayout>
<ToggleButton />
<Button />
</LinearLayout>
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 319
サービスに接続するプログラムの
作成(6)
4. Activityクラスの修正
ServiceConnectionクラスの定義
Serviceボタン押下時に接続、接続解除の処理
Toastボタンの有効・無効
• setEnabled(boolean)
Toastボタン押下後の処理を追加
• aidlファイルで定義したメソッドを呼び出す

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 320
サービスに接続するプログラムの
作成(7)
スケルトンプログラムの内容
<ServiceSampleActivity.java>
// TODO No.03 IServiceSampleService service;
private IServiceSampleService service;
// TODO No.04 Toast表示ボタンの定義(activity_service_sample.xmlにButtonを追加しておくこと)
private Button buttonToast;
// TODO No.05 ServiceConnectionの定義 とメソッドのオーバライド
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
service = null;
}

•IServiceSampleServi
•Toastボタンの定義
•ServuceConnectionクラスの定義

@Override
public void onServiceConnected(ComponentName name, IBinder ibinder) {
service = IServiceSampleService.Stub.asInterface(ibinder);
}
};

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 321
サービスに接続するプログラムの
作成(8)
スケルトンプログラムの内容
<ServiceSampleActivity.java>
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_sample);
// TODO No.06 Toastボタンのインスタンス生成
this.buttonToast = (Button) findViewById(R.id.button_toast);
// TODO No.07 Toastボタンを無効にする
this.buttonToast.setEnabled(false);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 322
サービスに接続するプログラムの
作成(9)
スケルトンプログラムの内容
<ServiceSampleActivity.java>
public void onClickServiceButton(View v) {
ToggleButton tb = (ToggleButton) v;
if (tb.isChecked()) {
// TODO No.08サービスを開始する
Intent intent = new Intent(this, ServiceSampleService.class);
startService(intent);
// TODO No.09サービスに接続する
bindService(intent, connection, BIND_AUTO_CREATE);
// Toastボタンを有効にする
this.buttonToast.setEnabled(true);
} else {
// TODO No.10サービスの接続を解除する
unbindService(connection);
// サービスを終了する
stopService(new Intent(this, ServiceSampleService.class));
// TODO No.11 Toastボタンを無効にする
this.buttonToast.setEnabled(false);
}

サービスを開始する

サービスを終了する

}
public void onClickToastButton(View v) {
try {
// TODO No.12 Toastを表示する
service.showToast();
} catch (RemoteException e) {
e.printStackTrace();
}
}

Toastボタンが
押されたときの処理

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 323
サービスに接続するプログラムの
作成(10)
スケルトンプログラムの内容
<ServiceSampleService.java>
public class ServiceSampleService extends Service{
AtomicBoolean running = new AtomicBoolean(true);

スレッドランニングフラグ

// TODO No.01 IServiceSampleService.Stubのサブクラスを定義とshowToastメソッドのオーバライド
private IServiceSampleService.Stub binder = new IServiceSampleService.Stub() { IServiceSampleService.Stub
のサブクラスを定義
@Override
public void showToast() throws RemoteException {
Toast.makeText(getApplicationContext(), "Service Running",
Toast.LENGTH_SHORT).show();
}
};
@Override
public IBinder onBind(Intent intent) {
//TODO No.02 No.01で定義したStubクラスを返す
return binder;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 324
サービスに接続するプログラムの
作成(11)
スケルトンプログラムの内容
<ServiceSampleService.java>
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "Service Start", Toast.LENGTH_SHORT).show();
running.set(true);
new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; running.get(); i++) {
Log.v(getClass().getSimpleName(), "i:" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
return START_STICKY;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 325
サービスに接続するプログラムの
作成(12)
スケルトンプログラムの内容
<ServiceSampleService.java>
@Override
public void onDestroy() {
Log.v(getClass().getSimpleName(), "onDestroy");
running.set(false);
Toast.makeText(this, "Service end", Toast.LENGTH_SHORT).show();
}
}

サービス終了時の処理

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 326
サービスに接続するプログラムの
作成(13)
確認
①

ToastボタンをクリックしてToastが表示されることを確認
④

②

Toastボタ
ン
をクリック

③
サービス側
で
Toastを表示

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 327
サービスに接続するプログラムの
作成(解答)
解答
解答ドキュメントを参照

実習4
実習3で作成したアプリケーションをスケルトンを使わずに最初から作
成する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 328
9.

動画ダウンローダの作成
アプリケーション概要
明示的Intentに
よる画面遷移

WebAPIへの
接続

WebAPIサーバから検
索結果を取得する

SD
Card

動画をSD Card
に保存
検索キーワード
を入力し、
「Serarch」ボタ
ンで遷移する

JSON・XMLの
解析処理

行をクリックして動
画をダウンロード

リストビュー
をカスタマイ
ズ

行をクリッ
クして再生

サービスを使っ
てダウンロード

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 330
スケルトンプロジェクト概要
実習用スケルトンプロジェクトをEclipseに取り込む
プロジェクト名:MediaDownloader_skeleton01

スケルトンプロジェクトの説明
スケルトンプロジェクトはMediaDownloaderSkeleton01~
MediaDownloaderSkeleton04の4つ用意されています
各プロジェクトは以下のような違いがあります
MediaDownloaderSkeleton01:未実装
MediaDownloaderSkeleton02:HTTP通信が実装済
MediaDownloaderSkeleton03:HTTP通信とJSON,XML解析が実装済
MediaDownloaderSkeleton04:HTTP通信とJSON,XML解析と非同期処理が
実装済

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 331
動画データの登録(1)
動画データの登録
動画サーバに動画データを登録する必要があります
動画データはandroid_trainig_webapidatasにサンプルが用意してありま
す

サーバ起動手順
「1.8 GAEサーバを起動する」を参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 332
動画データの登録(2)
手順
コマンドプロンプトから以下のコマンドを入力しGAEサーバを起動する
”dev_appserver.py --address [IPアドレス] webapi_server”

ブラウザを起動しURLに”http://[IPアドレス]:8080”を指定する
新規作成リンクを選択する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 333
動画データの登録(3)
タイトル、詳細、Searchword、サムネイル、動画ファイルを設定し「実
行ボタン」をクリック
作成するMediaDownloaderは以下のフォーマットが対応しています
画像:jpg
動画:mp4
※非対応のフォーマットを指定した場合正しく動作しませんので注意してください。
※Searchwordは単語一つのみ対応しています。複数指定することはできません。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 334
動画データの登録(4)
確認
一覧画面に遷移し、動画が登録されていることを確認する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 335
動画ダウンローダの作成
前章までに作成したサンプルプログラムを元に必要な機能を実装す
る
<手順>
HTTP通信の実装
• 接続先ホストの指定
• DefaultHttpClientのサブクラスを作成する。
• WebAPIパラメータを生成する
JSON, XML解析の実装
• JSONの解析処理を実装する
• [補足]XML解析は計測結果で最もパフォーマンスの良かったSAXパーサ
を使う
非同期処理
• 一覧表示の際に画像の読み込み処理をAsncTaskを使って非同期化する
。
サービス化
• 動画データをダウンロード処理をサービス化する。
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 336
HTTP通信の実装(1)
実習1
MediaDownloaderにHTTP通信処理を実装する
完成図

以下のログが出力される
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 337
HTTP通信の実装(2)
用意してあるTODO
【HTTP通信】No.00 (PCのIPアドレスを設定する)
【HTTP通信】No.01 Http通信を実装する (executを実行しresponseを返
す)
【HTTP通信】No.02 responseからStatusLineを取得し、更にそこから
StatusCodeを取得する。

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 338
HTTP通信の実装(3)
HTTP通信の実装
<手順>
接続先ホストの設定
•

SearchListアクティビティで定義されているHOST_URLを変更する
–

値:PCのIPアドレス
例 HOST_URL = “192.168.1.3”

DefaultHttpClientのサブクラスを修正する
クラス名

親クラス

HttpHelper

DefaultHttpClient

HttpHelperクラスにHttp通信処理を実装する
戻り値

メソッド名

説明

HttpEntity

getResponseContent(HttpHost httpHost,
HttpGet httpGet)

HTTP通信を行いレスポンス情報を取得
する

HttpEntity

statusCheck(HttpResponse response)

ステータスコードをチェックし、
HttpEntityクラスを作成する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 339
HTTP通信の実装(4)
WebAPIパラメータの生成
SearchListに定義されているSearchTaskクラスの処理を確認する
1. WebAPIパラメータの生成
• SearchList.SearchTask#doInBackgroundメソッドに処理を追加
• android.net.Uri.Builderクラスを使い、URLパラメータ情報を付加する
2. HttpHelperクラスに接続処理を依頼
@Override
protected List<RowModel> doInBackground(final Object... params) {
final String query = (String) params[0];
Builder builder = new Builder();
builder.path(FEED_URL);
builder.appendQueryParameter(PARAM_QUERY, query);
builder.appendQueryParameter(PARAM_TYPE, PARAM_TYPE_JSON);

・・・①

HttpHelper httpHelper = HttpHelper.getInstance();
final HttpGet httpGet = new HttpGet(builder.build().toString());
final HttpHost httpHost = new HttpHost(HOST_URL, PORT, "http");
// String url = "http://xx.xx.xx.xx:xxxx/_api?searchword=" + query;
try {
HttpEntity entity = httpHelper.getResponseContent(httpHost,
httpGet);

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

・・・②

ⅰ - 340
HTTP通信の実装(5)
スケルトンの内容
HttpHelper.java
public HttpEntity getResponseContent(HttpHost httpHost, HttpGet httpGet) throws HttpHelperException {
HttpResponse response = null;
try {
// TODO 【HTTP通信】No.01 Http通信を実装する (executを実行しresponseを返す)
response = execute(httpHost, httpGet);

HttpResponse

} catch (Exception exception) {

を取得する

throw new HttpHelperException(exception);
}
return statusCheck(response);
}
private HttpEntity statusCheck(HttpResponse response) throws HttpHelperException {
int statusCode = 0;
// TODO 【HTTP通信】No.02 responseからStatusLineを取得し、更にそこからStatusCodeを取得する。
int statusCode = response.getStatusLine().getStatusCode();
// 200 OK and 201 CREATED
if (HttpStatus.SC_OK == statusCode
|| HttpStatus.SC_CREATED == statusCode) {
try {
Log.v("HttpHelper", "Suceeded in retriving the InputStream");
return response.getEntity();
} catch (IllegalStateException e) {
throw new HttpHelperException(e);
}
} else {
Log.e("HttpHelper", "Connection Failed");
Log.e("HttpHelper", "Status code = " + statusCode);
throw new HttpHelperException("Connection Failed");
}

ステータスコー
ド
からエラーの判
別

}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 341
HTTP通信の実装(確認)
確認
ログが出力されていること
HttpHelper#statusCheckメソッド 85行目付近のログ出力処理が実行されるこ
と
try {
Log.v("HttpHelper", "Suceeded in retriving the InputStream");
return response.getEntity();
} catch (IllegalStateException e) {

※実習1ではJSON,XMLの解析処理が未実装のためエラーレベルのログが出力されるが、ここでは無視する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 342
HTTP通信の実装(解答)
HTTP通信 解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 343
JSON解析の実装(1)
実習2
MediaDownloaderにJSON解析処理を実装する
完成図

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 344
JSON解析の実装(2)
用意してあるTODO
【JSON解析】No.1 JSON文字列の解析を行う
【JSON解析】No.2 キー"entries"毎にRowModelにセットする
【JSON解析】No.3 キー"entries"のデータをセットする

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 345
JSON解析の実装(3)
JSONデータの解析
WebAPIを使ってHTTP通信をすると以下のようなJSONデータが取得で
きる
以下のJSONをの解析を行う

{

http://xx.xx.xx.xx:xxxx/_api?searchword=[サーチワード]&type=json にリ
クエストを投げると以下のようなjsonが返ってきます
"feed": {
"entries": [
{
"description": "全てはより良い滑りのために。(ただ遊んでいるだけです)",
"id": 2,
"thumbnail_url": "img/full?image_key=UQWle82pGtOnvMPQn3vN3w==",
"title": "特訓するねこ。",
"video_url": "video/dl?video_key=7Ye5LdAYDZeYKn2Res5R1A=="
}
]
}

}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 346
JSON解析の実装(4)
手順

1. スケルトンコードの確認

Json解析処理が呼び出されるまでの流れを把握する

2. JsonHelperクラスの修正

toModelsメソッドにJson解析処理を追加する。
patseToModelメソッドにJsonオブジェクト→RowModel変換処理を追加する

戻り値

メソッド名

説明

List<RowModel>

toModels(String strJson)

JSONデータを解析し、
RowModelのListを返す

RowModel

parseToModel(JSONObject json)

“entities”キーのデータから
RowModelに値をセットする

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 347
JSON解析の実装(5)
スケルトンコードの確認
SearchList$SearchTask#doInBackground
非同期によるHTTP通信処理の後にSearchList#parseJsonメソッドを呼び出す
@Override
protected List<RowModel> doInBackground(final Object... params) {
final String query = (String) params[0];
〜略〜
try {
HttpEntity entity = httpHelper.getResponseContent(httpHost,
httpGet);
parseJson(entity);
// TODO 【XML解析】以下のコメントアウトを解除する
// parseXml(entity);
} catch (Exception e) {
Log.e(TAG, "", e);
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 348
JSON解析の実装(6)
スケルトンコードの確認(続き)
SearchList#parseJson
メソッド内でJsonHelper#toModelsメソッドを呼び出す
JsonHelper#toModels以降が今回の実習のターゲットになる
<SearchList#parseJson>
private void parseJson(HttpEntity entity) throws Exception {
String strJson = EntityUtils.toString(entity);
mTableData = JsonHelper.toModels(strJson); ・・・修正ターゲット
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 349
JSON解析の実装(7)
JsonHelperクラスの修正
toModels(String strJson)
引数でjson文字列を取得する
JSONデータを解析し、RowModelのListを返す
<JsonHelper#toModels>
public static ArrayList<RowModel> toModels(String strJson) throws JSONException {
ArrayList<RowModel> list = new ArrayList<RowModel>();
// TODO 【JSON解析】No.1 JSON文字列の解析を行う
try {
JSONObject json = new JSONObject(strJson);
JSONObject feed = json.getJSONObject("feed");
JSONArray entries = feed.getJSONArray("entries");
// TODO 【JSON解析】No.2 キー"entry"毎にRowModelにセットする
for (int i = 0; i < entries.length(); i++) {
JSONObject entry = entries.getJSONObject(i);
list.add(parseToModel(entry));
}
} catch (Exception e) {
Log.e("JsonHelper", e.getMessage(), e);
}
return list;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 350
JSON解析の実装(8)
JsonHelperクラスの修正(続き)
parseToModel(JSONObject json)
引数でJSONObjectを取得する
JSONObjectからデータを取得し、RowModelにセットする
<JsonHelper#parseToModel>
public static RowModel parseToModel(JSONObject json) throws JSONException {
// TODO 【JSON解析】No.3 キー"entry"のデータをセットする
RowModel model = new RowModel();
model.setTitle(json.getString("title"));
model.setUrl(json.getString("video_url"));
model.setSummary(json.getString("description"));
model.setThumbnailImageURL(json.getString("thumbnail_url"));
Log.v("JsonHelper", model.toString());
return model;
}

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 351
JSON解析の実装(確認)
確認
一覧が表示されることを確認する
※まだ、サムネイルは表示されない

完成図

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 352
JSON解析の実装(解答)
解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 353
[補足] XML解析の実装(1)
実習2[補足]
MediaDownloaderにXML解析処理を実装する

完成図

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 354
[補足] XML解析の実装(2)
用意してあるTODO
【XML解析】No.1 イベントハンドラを作成する
【XML解析】No.2 パーサにイベントハンドラと入力データを渡す
【XML解析】No.3 各フラグをみて、フラグがtrueであれば各変数に値を
入れる
その他複数の箇所でコメントアウトの解除

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 355
[補足] XML解析の実装(3)
XMLデータの解析
WebAPIを使ってHTTP通信をすると以下のようなデータが取得されます
以下のXML文書を使い、DOM・SAX・XMLPullparserでXMLの解析を行
う

http://xx.xx.xx.xx:xxxx/_api?searchword=[サーチワード]にリクエストを
投げると以下のようなxmlが返ってきます
<?xml version="1.0" encoding="UTF-8"?>
<feed>
<entry>
<id>4</id>
<video url="video/dl?video_key=uh-LLppl4DiGfv5hp2uM1A=="></video>
<description>全てはより良い滑りのために。(ただ遊んでいるだけです)
</description>
<thumbnail
url="img/full?image_key=TeTgNSQrLuvhVH_uM6CTCw=="></thumbnail>
<title>特訓するねこ。</title>
<searchword>cat</searchword>
</entry>
</feed>

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 356
[補足] XML解析の実装(4)
手順

1. XmlHelperクラスの修正
2. SaxHandlerクラスの修正

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 357
[補足] XML解析の実装(5)
1. XmlHelperクラスの修正

• parseTableModelSaxメソッドにXML解析処理を追加する。

戻り値

メソッド名

説明

HttpEntity

getResponseContent(HttpHost httpHost,
HttpGet httpGet)

HTTP通信を行いレスポンス情報を
取得する

HttpEntity

statusCheck(HttpResponse response)

ステータスコードをチェックし、
HttpEntityクラスを作成する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 358
[補足] XML解析の実装(6)
2. SaxHandlerクラスの修正
•
•

DefaultHandlerクラスを継承したサブクラスを作成する
startElement, characters, endElementメソッドを実装する

戻り値

メソッド名

説明

void

startElement(String uri, String localName,
String qName, Attributes attributes)

要素の開始タグ読み込み時

void

characters(char[] ch, int offset, int length)

テキストデータ読み込み時

void

endElement(String uri, String localName,
String qName)

要素の終了タグ読み込み時

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 359
[補足] XML解析の実装(7)
スケルトンの内容
XMLHelper.java

public List<RowModel>
parseTableModelSax(final
HttpEntity entity) throws
IllegalStateException,
IOException,
ParserConfigurationExcept
ion, SAXException {
SAXパーサの作成

作成したイベントハン
ドラ
から結果を受け取る

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 360
[補足] XML解析の実装(8)
スケルトンの内容
XMLHelper.javaの続き
private class SaxHandler extends DefaultHandler {
[ 変数の定義 ]
/**
* 要素の開始タグ読み込み時
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) {
if ("entry".equals(localName)) {
// Entry タグの開始
isEntry = true;
}
if (isEntry) {
if (!isVideo && "video".equals(localName)) {
url = attributes.getValue("url");
isVideo = true;
}
if ("description".equals(localName)) {
isSummary = true;
}
if (!isThumbnail && "thumbnail".equals(localName)) {
thumbnail = attributes.getValue("url");
isThumbnail = true;
}
if ("title".equals(localName)) {
isTitle = true;
}
}
}

IDのフラグを立
てる
サマリーのフラグを立てる
サムネイルは取得す
る。
タイトルのフラグを立てる

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 361
[補足] XML解析の実装(9)
スケルトンの内容
XMLHelper.javaの続き
/**
* テキストデータ読み込み時
*/
@Override
public void characters(char[] ch, int offset, int length) {
// TODO 【XML解析】No.2 各フラグをみて、フラグがtrueであれば各変数に値を入れる。
}
/**
* 要素の終了タグ読み込み時
*/
@Override
public void endElement(String uri, String localName, String qName) {
if ("entry".equals(localName)) {
// Entry タグの終了
RowModel rowModel = new RowModel();
rowModel.setUrl(url);
rowModel.setSummary(summary);
rowModel.setThumbnailImageURL(thumbnail);
rowModel.setTitle(title);

各フラグから、対応する変数に
値を入れた後、対象フラグを
Falseに変更

各データをセットする

result.add(rowModel);
url = null;
summary = null;
thumbnail = null;
title = null;
isThumbnail = false;

全フラグをクリアする

}
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 362
[補足] XML解析の実装(確認)
確認
一覧が表示されること

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 363
[補足] XML解析の実装(解答)
解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 364
非同期処理の実装(1)
実習3
MediaDownloaderに画像読み込み処理を実装する
完成図

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 365
非同期処理の実装(2)
用意してあるTODO
【非同期】No.1 右上にインジゲータの表示
【非同期】No.2 URLの生成。rowModel.getThumbnailImageURL()を利用
する
【非同期】No.3 tableAdapterにデータが変わったことを通知
【非同期】No.4 右上のインジゲータを止める

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 366
非同期処理の実装(3)
非同期処理
<手順>
AsncTaskを使って画像の読み込み処理を非同期化する
• SearchList. LoadImageTaskクラスの作成
• 下記の処理をメソッドに追加
メソッド

処理

onPreExecute

Progressbarの表示

doInBackground

画像の読み込み処理

onProgressUpdate

ListViewの再描画

onPostExecute

Progressbarを非表示

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 367
非同期処理の実装(4)
スケルトンの内容
SearchList. java
class LoadImageTask extends AsyncTask<RowModel, Void, Void> {
※一部にXmlHelperを使っているがXML解析とは関係ないイメージの組み立て処理も担当している
@Override
protected void onPreExecute() {
// TODO 【非同期】No.1 右上にインジゲータの表示
setProgressBarIndeterminateVisibility(true);
}

インジゲータの表示

@Override
protected Void doInBackground(final RowModel... params) {
for (final RowModel rowModel : params) {
if (isCancelled()) {
Log.d(TAG, "LoadImageTask#doInBackground() cancelled.");
break;
}
if (!TextUtils.isEmpty(rowModel.getThumbnailImageURL())) {
XmlHelper xmlHelper = XmlHelper.getInstance();
StringBuffer url = new StringBuffer();
url.append("http://");
url.append(HOST_URL + ":" + PORT);
url.append(FEED_DATA_URL);

キャンセルされた場合
は終了する

サムネイルのURLを生成

// TODO 【非同期】No.2 URLの生成。rowModel.getThumbnailImageURL()を利用する
url.append(rowModel.getThumbnailImageURL());
final Bitmap bitmap = xmlHelper.loadImageBitmap(url.toString());
if (bitmap != null) {
rowModel.setThumbnailImage(bitmap);
}
publishProgress();
}

画像の取得処理を実装する

Bitmap情報を取得する

}
return null;
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 368
非同期処理の実装(5)
スケルトンの内容
SearchList. Javaの続き

/**
* 取得時にテーブル情報を更
新します。
*
* @param values
*/
@Override

テーブルを更新する

インジゲータを止める

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 369
非同期処理の実装(確認)
確認
一覧が表示され、サムネイルが表示されること

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 370
非同期処理の実装(解答)
非同期処理 解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 371
サービスの実装(1)
実習4
MediaDownloaderのサービスを実装する
ダウンロードの処理をサービス化する
完成図

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 372
サービスの実装(2)
用意してあるTODO
【サービス】No.1 IDownloadService.Stub.asInterfaceメソッドから
downloadServiceIfを作成する
【サービス】No.2 downloadServiceIfにnullを入れてコネクションを外す
【サービス】No.3 bindServiceにintent, downloadServiceConn,
BIND_AUTO_CREATEを渡して接続処理を追加する

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 373
サービスの実装(3)
サービス化
<手順>

aidlファイルの作成

※スケルトンでは実習の都合上すでに作成済みだが、実習4の演習では削除してから再度作成
する

Serviceクラスの修正
Activityクラスの修正

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 374
サービスの実装(4)
aidlファイルの作成
1. IDownloadService.aidl
download開始メソッドの定義
• String downloadFile()
genフォルダ以下にStubが自動作成されていることを確認

package
biz.oesf.app.mediadownload
er.service;
/**
* サービスのインターフェ
DownloadFileメソッドの
追加

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 375
サービスの実装(5)
サービスクラスの修正
サービスクラス「DownloadService.java」に以下の処理を加える
1. 自動作成されたStubクラスのサブクラスを定義
• 変数名:downloadServiceIf
2. インタフェースで定義されているメソッドの実装
• downloadFileメソッドの実装
3. onBindメソッドの戻り値の修正
• 戻り値:downloadServiceIf

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 376
サービスの実装(6)
サービスクラスの修正
1. 自動作成されたStubクラスのサブクラスを定義
• 変数名:downloadServiceIf
2. インタフェースで定義されているメソッドの実装
• downloadFileメソッドの実装
DownloadService.java

private final
IDownloadService.Stub
downloadServiceIf = new
IDownloadService.Stub()
{ ・・・①
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 377
サービスの実装(7)
サービスクラスの修正(続き)
3. onBindメソッドの戻り値の修正
• 戻り値:downloadServiceIf

DownloadService.java
public IBinder onBind(Intent intent) {
// IDownloadService
return downloadServiceIf;
}

・・・③

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 378
サービスの実装(8)
スケルトンの内容
downloadFileメソッド
ダウンロード時と完了時にnotificationの表示
ダウンロード処理の開始
private final IDownloadService.Stub downloadServiceIf = new IDownloadService.Stub() {
/**
* ファイルのダウンロードを行います。
*
* @param url
*
ダウンロードするURL
*/
@Override
public String downloadFile(String url, String title) throws RemoteException {
Notification notification = new Notification();
notification.icon = android.R.drawable.btn_default;
notificationの設定
notification.tickerText = "Download start...";
notification.when = System.currentTimeMillis();
ダウンロード中の
notification.setLatestEventInfo(getApplicationContext(),
notification
"AppDownloader", "Download start...", dammyIntent());
int notificationId = createNotificationId();
notificationManager.notify(notificationId, notification);
String filename = download(url, title);
・・・ダウンロード処理
notification.tickerText = "Download end.";
notification.setLatestEventInfo(getApplicationContext(),
"AppDownloader", "Download end.", pendingIntent(mFileName));
notificationManager.notify(notificationId, notification);

notificationの設定
ダウンロード完了の
notification

return filename;
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 379
サービスの実装(9)
Activityクラスの修正
SearchList.javaに以下の処理を追加する
1. ServiceConnection実装クラスの定義
• downloadServiceConn
2. メソッドのオーバライド
• onServiceConnected
• onServiceDisconnected
3. サービスの接続処理の追加
• SearchList#onCreateメソッドの最後に追加
• 動画データのダウンロード開始処理の追加

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 380
サービスの実装(10)
Activityクラスの修正
1. ServiceConnection実装クラスの定義
• downloadServiceConn
2. メソッドのオーバライド
• onServiceConnected
• onServiceDisconnected
SearchList.java

private final
ServiceConnection
downloadServiceConn =
new ServiceConnection()
{
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 381
サービスの実装(11)
Activityクラスの修正(続き)
3. サービスの接続処理の追加
• SearchList#onCreateメソッドの最後に追加
• 動画データのダウンロード開始処理の追加
SearchList.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.list);
〜略〜
Log.d(TAG, "search task start. query=" + query);
task = new SearchTask().execute(new Object[] { query });
// Intent intent = new Intent(IDownloadService.class.getName());
Intent intent = new Intent(this, DownloadService.class);
// TODO 【サービス】No.3 bindServiceにintent, downloadServiceConn,
サービス
// BIND_AUTO_CREATEを渡して接続処理を追加する
bindService(intent, downloadServiceConn, BIND_AUTO_CREATE);
に接続
}
This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 382
サービスの実装(確認)
確認
ダウンロードが実行できる

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 383
サービスの実装(解答)
解答
別ドキュメント参照

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 384
まとめ
トレーニングの振り返り
1日目
章

タイトル

内容

1章

トレーニング概要

開発環境の構築
演習で用いるアプリケーション
動画サーバの構築方法

2章

WebAPI開発知識

非同期による画面表示の必要性

レスポンスデータの解析
サービスの使いどころ
3章

チュートリアル

画面感でのパラメータの受け渡
し

4章

ListViewの応用

ListViewの使い方
ListViewのカスタマイズ

5章

非同期処理

非同期による画面表示
Handlerの使い方
AsyncTaskの使い方
AsyncTaskの中断

This material is licensed under the Creative Commons License BY-NC-SA

ⅰ - 386
トレーニングの振り返り
2日目
章

タイトル

概要

6章

HTTP通信

Webサービスに接続する

WebAPIを使ったHTTP通信
WebAPIを使ったHTTP通信
7章

JSONの解析

JSONの解析の仕方

7章

[補足]XMLの解析

XMLの解析の仕方:DOM
XMLの解析の仕方:SAX
XMLの解析の仕方:XMLPullparser

8章

サービス

サービスの使いどころ

サービスの使い方
サービスに接続する
9章

動画ダウンローダの作成

習得した一連の技術を全て使ったアプ
リケーション作成

ⅰ - 387
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
Androidに関する情報提供元
インターネット
wiki
Google Androidに関する情報のまとめwiki
• http://www29.atwiki.jp/android/
Android Wiki
• http://wikiwiki.jp/android/

サンプル
android developersが公開しているサンプル
• http://developer.android.com/intl/ja/guide/samples/index.html
apps-for-android
• http://code.google.com/p/apps-for-android/

ⅰ - 388
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
Androidに関する情報提供元
書籍
タイトル

著者

出版社

Androidプラットフォーム開発
入門

橋爪香織、小林明
大・・・他

技術評論社

Google Android
プログラミング入門

株式会社豆蔵
江川 崇 …他

アスキー・
メディアワーク
ス

入門 Android 2 プログラミング Mark Murphy
株式会社クイープ (監
修)

翔泳社

Android Hacks
プロが教えるテクニック &
ツール

オライリージャ
パン

株式会社
ブリリアントサービス

Android SDK逆引きハンドブッ 中西葵 ・・・他
ク

シーアンドアー
ル研究所

ⅰ - 389
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
OESF公認Androidトレーニング
アプリケーション開発
Anroidプログラミング入門(難易度:★☆☆☆☆)
Anroidアプリケーション開発入門(★★☆☆☆)
Anroidアプリケーション開発応用(★★★★☆)
Android応用 WebAPI開発(★★★★★)
Android応用 タブレットアプリケーション開発入門(★★★★☆)
AnroidUIデザイン入門(★☆☆☆☆)
品質向上! Androidアプリケーションテスト(★★★☆☆)

組み込み
Android組み込み開発 基礎コース - Armadillo-440 編 –

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 390
Anroidプログラミング入門
基本的なアプリケーション開発に必要なプログラミング技術を習得する
ユーザインタフェースの使い方や画面遷移の仕方
NextActivity

MainActivity

RequestCode:12
3

ResultCode:RESULT_OK

NextActivity2
ダイアログ表示
From
Result
Request

RequestCode:456

ResultCode
RESULT_OK
RESULT_CANCEL

or

RESULT_OK
RESULT_CANCEL

or

Result Cancelⅰ - 391
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
Anroidアプリケーション開発入門
Androidの基本的な知識から本格的なアプリケーション開発

インターネットからRSS
フィードを取得する

メニュー
画面

インターネッ
ト

データベースに
RSSフィードを登
録

データベース

データベースからRSS
フィードを検索
データベースへ登録
が完了した後、ダイ
アログを表示する

一覧画面
一覧表示ボタンをク
リックする
This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

詳細画面
一覧データを
選択する
ⅰ - 392
Anroidアプリケーション開発応用
入門編で作成したアプリケーションに手を加え、より快適なものに仕上
げる
Activityのタスク管理やプロファイリングなど開発における高度なサイド
技術の習得

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 393
Android応用 WebAPI開発
非同期処理、プロセス間通信など開発において重要で難易度の高い技術
の習得
GAEサーバを使用した動画ダウンロードアプリケーションの開発

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 394
Androidタブレット開発コース
タブレット基本的な知識、新機能、開発手法のベストプラクティスの習
得
ActionBar、Fragmentなどを駆使して画像ビューアを作成する

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 395
AndroidUIデザイン入門
Androidで独自UIを実現させるためのカスタマイズ手法を習得する
UI単体のカスタマイズからアプリケーション全体で統一されたデザインの実
現
ソースコードの修正は殆ど無いため、デザイナも受講生対象

実習用アプリケーションをGooglePlayで配布中
https://play.google.com/store/apps/details?id=biz.oesf.pochipochinyanko
Android標準UI

Buttonカスタマイズ
&アニメーション

統一されたアプリケーションデザ
イン

Dialogカスタマイズ

This material is licensed under the Creative Commons License BY-NC-SA 4.0.

ⅰ - 396
品質向上! Androidアプリケーショ
ンテスト
Androidで動作するアプリケーション開発に必要なテスティング技法を習
得する
JUnitベースのテストや、Android特有のテスティングフレームワークAPI
と、各種テスト(ストレステスト、シナリオテスト、カバレッジテスト
、など)の効率的な使い方を習得する

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 397
Android組み込み開発 基礎コース
- Armadillo-440 編 –
Armdillo-440を使ったシリアルデバイスアプリケーション作成
シリアル

Armadillo-440 ACアダプ クロスケーブル
タ
( Android 2.2)

給電用USB

開発用
PC

読み取ったコードは3番で
す

USB-RS232C
変換ケーブル
USB

Grid OnputⓇ

G2スキャナ

RS232C

LANケーブル

②Toast表示

①メニューをタッ
チ!

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

メニューの写真に
グリッドマークを
埋め込んだメニュー

③

ⅰ - 398
Adapter Tips
Adapter#getViewの仕組み
ListViewの特定の位置に表示されているViewを作成することができる
レイアウトファイルまたは独自コーディングで作成することができる
呼び出されるタイミング
List画面のスクロールなどで新しい行が表示されるときに呼び出される

Adapter#getViewでリソースを再利用する
Adapter#getViewとView#getTagを使って行の描画情報を再利用する
表示毎にViewをnewする必要がないためパフォーマンスが向上する

ⅰ - 399
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
Adapter Tips
<サンプルコード page1>
public class MyAdapter extends BaseAdapter {
//表示データ
ArrayList<String> arStr = new ArrayList<String>();
private String[] data = {
"Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi",
"Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale",
"Aisy Cendre", "Allgauer Emmentaler", "Alverca", "Ambert", "American Cheese",
"Ami du Chambertin", "Anejo Enchilado", "Anneau du Vic-Bilh", "Anthoriro",
"Appenzell",
"Aragon", "Ardi Gasna", "Ardrahan", "Armenian String", "Aromes au Gene de Marc",
"Asadero", "Asiago"};
private LayoutInflater inflater;
//1行に表示するView情報クラス
static class ViewHolder {
TextView textName;
}

ⅰ - 400
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
Adapter Tips
<サンプルコード page2>
public MyAdapter(Context context) {
super();
for(String s : data){
arStr.add(s);
}
this.inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return arStr.size();
}
@Override
public Object getItem(int position) {
return this.arStr.get(position);
}
@Override
public long getItemId(int position) {
return position;
}

ⅰ - 401
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
Adapter Tips
<サンプルコード page3>
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder viewHolder;
//Rowデータの作成
if (row == null) {
//Rowデータが存在しない場合は作成する
row = this.inflater.inflate(R.layout.list_row, null);
viewHolder = new ViewHolder();
viewHolder.textName = (TextView) row.findViewById(R.id.TextViewName);
//作成したRow情報をTagに設定する
row.setTag(viewHolder);
} else {
//Row情報が存在する場合は再利用する
viewHolder = (ViewHolder) row.getTag();
}
//表示データを更新する
viewHolder.textName.setText(data[position]);
return row;
}
}

ⅰ - 402
This material is licensed under the Creative Commons License BY-NC-SA 4.0.
本ドキュメントは株式会社リーディング・エッジ社が作成して
います。

http://www.leadinge.co.jp/

本ドキュメントは株式会社リーディング・エッジ社及び株式会社カサレアルが
バージョンアップ対応のために改変しています。
http://www.leadinge.co.jp/
http://www.casareal.co.jp/
このドキュメントの内容の一部は、Google が作成、提供しているコンテンツをベースに変更したもので、クリエイティブ・コモンズの表示 3.0 ライセンスに記載の条件に
従って使用しています。

This material is licensed under the Creative
Commons License BY-NC-SA 4.0.

ⅰ - 403

Androidアプリケーション応用 WebAPI開発