diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd
index 80ad7b8..f965966 100644
--- a/docs/html/guide/topics/ui/declaring-layout.jd
+++ b/docs/html/guide/topics/ui/declaring-layout.jd
@@ -65,7 +65,7 @@ example, the EditText element has a text
attribute that corresponds
Tip: Learn more about different layout types in Common
Layout Objects. There are also a collection of tutorials on building various layouts in the
-Hello Views tutorial guide.
+Hello Views tutorial guide.
Write the XML
diff --git a/docs/html/guide/topics/ui/dialogs.jd b/docs/html/guide/topics/ui/dialogs.jd
index 4e4ca14..fa2d916 100644
--- a/docs/html/guide/topics/ui/dialogs.jd
+++ b/docs/html/guide/topics/ui/dialogs.jd
@@ -47,10 +47,10 @@ for notifications and short activities that directly relate to the application i
See Creating a ProgressDialog below.
- {@link android.app.DatePickerDialog}
- A dialog that allows the user to select a date. See the
- Hello DatePicker tutorial.
+ Hello DatePicker tutorial.
- {@link android.app.TimePickerDialog}
- A dialog that allows the user to select a time. See the
- Hello TimePicker tutorial.
+ Hello TimePicker tutorial.
If you would like to customize your own dialog, you can extend the
diff --git a/docs/html/guide/topics/ui/layout-objects.jd b/docs/html/guide/topics/ui/layout-objects.jd
index bb13a18..345e9b3 100644
--- a/docs/html/guide/topics/ui/layout-objects.jd
+++ b/docs/html/guide/topics/ui/layout-objects.jd
@@ -19,7 +19,7 @@ parent.link=index.html
This section describes some of the more common types of layout objects
to use in your applications. Like all layouts, they are subclasses of {@link android.view.ViewGroup ViewGroup}.
-Also see the Hello Views tutorials for
+
Also see the Hello Views tutorials for
some guidance on using more Android View layouts.
FrameLayout
@@ -83,7 +83,7 @@ neighboring elements. This can be turned off by setting
android:baselineAligned="false"
in the layout XML.
To view other sample code, see the
-Hello LinearLayout tutorial.
+Hello LinearLayout tutorial.
TableLayout
@@ -138,7 +138,7 @@ result, with cell borders displayed as dotted lines (added for visual effect). <
fits the screen. See the {@link android.widget.TableLayout TableLayout reference}
documentation for more details.
-To view sample code, see the Hello
+To view sample code, see the Hello
TableLayout tutorial.
@@ -208,7 +208,7 @@ refer to the ID using the syntax of a relative resource
For example, assigning the parameter toLeft="my_button"
to a TextView would place the TextView to
the left of the View with the ID my_button (which must be written in the XML before the TextView).
-To view this sample code, see the Hello
+To view this sample code, see the Hello
RelativeLayout tutorial.
diff --git a/docs/html/guide/topics/ui/menus.jd b/docs/html/guide/topics/ui/menus.jd
index bae94ca..bad8d65 100644
--- a/docs/html/guide/topics/ui/menus.jd
+++ b/docs/html/guide/topics/ui/menus.jd
@@ -180,7 +180,7 @@ Then, register a {@link android.view.ContextMenu} for the View, with
{@link android.app.Activity#registerForContextMenu(View) registerForContextMenu()}
.
For example, here is some code that can be used with the
-Notepad application
+Notepad application
to add a context menu for each note in the list:
public void onCreateContextMenu(ContextMenu menu, View v,
@@ -518,5 +518,5 @@ a <category>
element in the intent filter. For example:
Intents and Intent Filters document.
For a sample application using this technique, see the
-Note Pad
+Note Pad
sample code.
diff --git a/docs/html/guide/topics/ui/ui-events.jd b/docs/html/guide/topics/ui/ui-events.jd
index 5628d46..a4dd614 100644
--- a/docs/html/guide/topics/ui/ui-events.jd
+++ b/docs/html/guide/topics/ui/ui-events.jd
@@ -15,7 +15,7 @@ parent.link=index.html
See also
- - Hello Form Stuff tutorial
+ - Hello Form Stuff tutorial
diff --git a/docs/html/guide/topics/views/custom-views.jd b/docs/html/guide/topics/views/custom-views.jd
index c5f9346..c255293 100644
--- a/docs/html/guide/topics/views/custom-views.jd
+++ b/docs/html/guide/topics/views/custom-views.jd
@@ -40,7 +40,7 @@ parent.link=index.html
-
You could override the way that an EditText component is rendered on the screen
- (the Notepad sample uses this to good effect,
+ (the Notepad sample uses this to good effect,
to create a lined-notepad page).
-
diff --git a/docs/html/intl/ja/guide/basics/what-is-android.jd b/docs/html/intl/ja/guide/basics/what-is-android.jd
index 89558a0..fcf670d 100644
--- a/docs/html/intl/ja/guide/basics/what-is-android.jd
+++ b/docs/html/intl/ja/guide/basics/what-is-android.jd
@@ -39,7 +39,7 @@ page.title=Android とは
アプリケーションの基盤となるのは、次のサービスとシステムのセットです:
- アプリケーションの構築を可能にする、拡張可能で豊富なビューのセット。ビューには、リスト、グリッド、テキスト ボックス、ボタンだけでなく、埋め込み可能なウェブブラウザも含まれます。
+ href="{@docRoot}resources/tutorials/views/index.html">ビューのセット。ビューには、リスト、グリッド、テキスト ボックス、ボタンだけでなく、埋め込み可能なウェブブラウザも含まれます。
- コンテンツ プロバイダを使用すると、アプリケーションのデータ(たとえば、連絡先アプリケーション)に、別のアプリケーションからアクセスしたり、データを共有させることができます。
- リソース マネージャは、ローカライズされた文字列、グラフィックス、レイアウト ファイルなどのコード以外のリソースへのアクセスを提供します。
- {@link android.app.NotificationManager 通知マネージャ}を使用すると、すべてのアプリケーションからステータス バーにカスタマイズした警告を表示することができます。
@@ -47,7 +47,7 @@ page.title=Android とは
アプリケーションの簡単な説明と詳細については、Notepad チュートリアルをご覧ください。
+href="{@docRoot}resources/tutorials/notepad/index.html">Notepad チュートリアルをご覧ください。
ライブラリ
diff --git a/docs/html/intl/ja/guide/index.jd b/docs/html/intl/ja/guide/index.jd
index 73ca18a..5d35e0a 100644
--- a/docs/html/intl/ja/guide/index.jd
+++ b/docs/html/intl/ja/guide/index.jd
@@ -41,12 +41,12 @@ Android 向けプログラム開発の最初のステップは、SDK(ソフト
-SDK のダウンロード後は、まずはじめにデベロッパー ガイドを参照してください。コードを実際に見てみることから始めたい場合は、簡単な Hello World チュートリアルを参照してください。Android プラットフォーム向けに作成された標準的な「Hello, World」アプリケーションについて説明しています。アプリケーションの基礎ドキュメントは、アプリケーション フレームワークを理解したいユーザーに最適な出発点となります。
+SDK のダウンロード後は、まずはじめにデベロッパー ガイドを参照してください。コードを実際に見てみることから始めたい場合は、簡単な Hello World チュートリアルを参照してください。Android プラットフォーム向けに作成された標準的な「Hello, World」アプリケーションについて説明しています。アプリケーションの基礎ドキュメントは、アプリケーション フレームワークを理解したいユーザーに最適な出発点となります。
-不明点などがある場合は、Android ディスカッション グループへの参加をおすすめします。詳しくは上部にある [コミュニティ] タブをご覧ください。
+不明点などがある場合は、Android ディスカッション グループへの参加をおすすめします。詳しくは上部にある [コミュニティ] タブをご覧ください。
デベロッパー ガイドの別のページに移動してから、このページに戻るには、[デベロッパー ガイド] タブをクリックします。
\ No newline at end of file
diff --git a/docs/html/intl/ja/guide/publishing/app-signing.jd b/docs/html/intl/ja/guide/publishing/app-signing.jd
index 23d8cf7..710591d 100644
--- a/docs/html/intl/ja/guide/publishing/app-signing.jd
+++ b/docs/html/intl/ja/guide/publishing/app-signing.jd
@@ -153,7 +153,7 @@ page.title=アプリケーションへの署名
次にビルドを行うと、ビルド ツールは新しいキーストアとデバッグ キーを再度生成します。
-開発コンピュータがグレゴリオ暦以外のロケールを使用している場合、ビルド ツールが誤って期限切れのデバッグ証明書を生成することがあります。このため、アプリケーションをコンパイルしようとするとエラーが発生します。解決策については、トラブルシューティング トピックの ビルド ツールが期限切れのデバッグ証明書を生成するため、アプリケーションがコンパイルできない をご覧ください。
+開発コンピュータがグレゴリオ暦以外のロケールを使用している場合、ビルド ツールが誤って期限切れのデバッグ証明書を生成することがあります。このため、アプリケーションをコンパイルしようとするとエラーが発生します。解決策については、トラブルシューティング トピックの ビルド ツールが期限切れのデバッグ証明書を生成するため、アプリケーションがコンパイルできない をご覧ください。
公開リリースへの署名
diff --git a/docs/html/intl/ja/resources/community-groups.jd b/docs/html/intl/ja/resources/community-groups.jd
new file mode 100644
index 0000000..c99b1f8
--- /dev/null
+++ b/docs/html/intl/ja/resources/community-groups.jd
@@ -0,0 +1,116 @@
+community=true
+page.title=コミュニティ
+@jd:body
+
+
+
コミュニティ
+
Android デベロッパー コミュニティへようこそ。コミュニティでのディスカッションにぜひ参加してください。投稿する前に、コミュニティ ガイドラインが記載されているグループの趣意をお読みください。
+
+
注: Android ソース コード(アプリケーション開発ではなく)に関するディスカッションは、オープンソース プロジェクトのメーリング リスト(英語)を参照してください。
+
+
目次
+
+ - 質問を投稿する前に
+ - アプリケーション デベロッパー メーリング リスト
+ - メーリング リストにメールを使用
+ - IRC の使用
+
+
+
質問を投稿する前に
+
投稿を作成する前に、下記をお試しください:
+
+
+- よくある質問を参照します。Android アプリケーションの開発について非常に一般的な質問が、この一覧に記載されており、頻繁に更新されています。
+- Android のメイン サイトの検索バー(このページの上部にあるのと同じもの)に、調べたいキーワードを入力してください。この検索は、サイト、ドキュメント、ブログに含まれるすべてのコンテンツの他に、すべてのグループで以前行われたすべてのディスカッションを網羅しています。誰か他の人が、以前にも同じ問題に遭遇した可能性は大いにあります。
+- メーリング リストのアーカイブを検索して、同じ質問に関するディスカッションが既に存在しないか調べてください。
+
+
+
+
質問への答えが見つからない場合、コミュニティで質問することをおすすめします。投稿する際は、次の手順に従ってください。
+
+- コミュニティ ガイドラインが記載されているAndroid メーリングリストの趣意をお読みください。
+
+- 質問に最適なメーリング リストを選択してください。後述するように、デベロッパー向けのメーリング リストは何種類かに分かれています。
+-
+ 質問の内容を明確に。明確な質問は、回答者と、将来情報を探そうとする人の双方にとって有益です。
+- 投稿は詳しく書いてください。回答者の人たちが問題を理解するのに役立ちます。コードやログのスニペット、スクリーンショットへのリンクを含めることも有用です。質問をわかりやすく表現するための詳しいガイドラインは、賢い質問のしかた(英語)をご覧ください。
+
+
+
+
+
アプリケーション デベロッパー メーリング リスト
+
+
+- Android SDK Japan - Android SDK に関する質問と答え、提案とフィードバックを交換できる場です。
+
+
+
+- Android 初心者向け - Android アプリケーションの開発初心者向けです。Android SDK と基本的な Android API の利用方法について学習したい場合は、このメーリング リストから始めてください。このメーリング リストには、SDK を利用するデベロッパーの初歩的なディスカッションの場所です。Android プラットフォームで初めてアプリケーションを作成して実行する際は、非常に有益な情報を得ることができるでしょう。開発環境のインストール方法についての質問を投稿したり、Android 開発の初歩(初めて作成するユーザー インターフェース、権限、Android ファイルシステムでのファイル、Android マーケットでのアプリケーションなど)について教えてもらうことができます。新たに質問する前に、必ず最初にアーカイブを確認してください。高度な内容の質問の場合はここでは質問せず、android-developers メーリング リストで質問してください。また使用に関する質問は、android-discuss メーリング リストの方が適しています。
+
+
+
+- Android デベロッパー向け - Android アプリケーション デベロッパーとして経験を積むにつれ、Android アプリケーション開発の基本を把握して、SDK を使いこなせるようになります。今度は、より高度な内容について質問する必要があります。アプリケーションのトラブルシューティング、実装へのアドバイス、アプリケーションのパフォーマンスやユーザー エクスペリエンスを改良するテクニックに関する質問には、次のメーリング リストが役立ちます。使用に関する問題(android-discuss をご利用ください)や、Android SDK を使用する際の初歩的質問(android-beginners をご利用ください)についてのディスカッションの場所ではありません。
+
+
+
+- Android ディスカッション - Android に関する「井戸端会議」です。ここでは、Android プラットフォームへのアイデア、自分のアプリケーションの公表、Android 携帯端末に関するディスカッション、コミュニティ リソースなど、Android に関することなら何でも投稿可能です。ただし他のメーリング リストに該当する内容の場合は、そのメーリング リストに投稿することをおすすめします。質問のテーマが限定されている場所の方が、より多くの回答を得ることができるでしょう。
+
+
+
+- Android セキュリティ ディスカッション - 安全な開発、新たに発生したセキュリティの問題、Android デベロッパー向けの Android デベロッパーによるベスト プラクティスについて自由にディスカッションを行える場所です。メーリング リストで脆弱性を直接公開することは、すべての Android ユーザーを危険にさらすことになるので、避けてください。
+
+
+
+- Android セキュリティに関する発表 - Android セキュリティ チームがセキュリティ関連の発表を行う、小規模なグループです。
+
+
+
+- Android マーケット ヘルプフォーラム - Android マーケットに関する質問や問題の報告をするための、ウェブベースのディスカッション フォーラムです。
+
+
+
+
+
+
+
+
メーリング リストにメールを使用
+
Google グループ のサイトを使用する代わりに、メール クライアントを使用して、メーリング リストに投稿することも可能です。
+
Google グループのサイトを使用せずに、グループに登録するには、上記の「メールで登録」のリンクを使用します。
+
メーリング リストへの投稿をメールで受信するように設定する方法は、次のとおりです:
+
+
- Google グループ サイトから、グループにログインします。たとえば android-framework グループには http://groups.google.com/group/android-framework?hl=ja にアクセスします。
+- 右側の [メンバーステータスを編集] をクリックします。
+- [このグループの閲覧方法] で、メール オプションのいずれかを選択します。
+
+
+
IRC の使用
+
Android コミュニティは irc.freenode.net サーバーの #android チャンネルを使用しています。
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/intl/ja/resources/tutorials/hello-world.jd b/docs/html/intl/ja/resources/tutorials/hello-world.jd
new file mode 100644
index 0000000..c12965c
--- /dev/null
+++ b/docs/html/intl/ja/resources/tutorials/hello-world.jd
@@ -0,0 +1,375 @@
+page.title=Hello, World
+@jd:body
+
+
+
+デベロッパーにとって、開発フレームワークの第一印象は、どれだけ簡単に「Hello, World」を記述できるかで決まります。Android では、非常に簡単に記述できます。総合開発環境として Eclipse を使用している場合には、開発は特に簡単です。プロジェクトの作成と管理に使用できる便利なプラグインが用意されており、開発サイクルを大幅にスピードアップできるためです。
+
+Eclipse を使用していない場合でも問題ありません。Developing in Other IDEsに慣れてから、このチュートリアルに戻り、Eclipse に関する部分以外を参考にしてください。
+
+開始する前に、最新の SDK がインストールされている必要があります。また、Eclipse を使用する場合には、ADT プラグインもインストールされている必要があります。これらのプログラムがインストールされていない場合は、「Installing the Android SDK」を参考にインストールを実行して、完了後にこのチュートリアルに戻ってください。
+
+AVD の作成
+
+
+
+このチュートリアルでは、開発したアプリケーションを Android エミュレータで実行します。エミュレータを起動するには、事前に Android 仮想デバイス(AVD)を作成する必要があります。AVD は、エミュレータが使用するシステム イメージとデバイスの設定を定義するものです。
+
+AVD を作成するには、Android SDK に含まれている「android」ツールを使用します。コマンド プロンプトまたはターミナルを開き、SDK パッケージの中の tools/
ディレクトリに移動して、次のコマンドを実行します。
+
+android create avd --target 2 --name my_avd
+
+
+カスタム ハードウェア プロファイルを作成するかどうかを尋ねられます。ここではひとまず、リターン キーを押してスキップします(デフォルトの回答は「No」となっています)以上で AVD の作成は終了です。この作業により、Android 1.5 プラットフォームを使用する「my_avd」という名前の AVD が構成されました。これで、AVD をエミュレータで使用できる状態になりました。
+
+上記のコマンドで使用した --target
オプションは、エミュレータを実行する配備ターゲットを指定するもので、必須オプションです。--name
オプションは新規 AVD の名前を定義するもので、これも必須オプションです。
+
+
+新規 Android プロジェクトを作成する
+
+AVD を作成したら、次は Eclipse 内で新規 Android プロジェクトを開始します。
+
+
+ - Eclipse で、[[]ファイル(File)] > [[]新規(New)] > [[]プロジェクト(Project)] を選択します。
+
ADT Plugin for Eclipse が正常にインストールされていれば、表示されるダイアログに、「Android」というラベルの付いたフォルダと、その中の「Android プロジェクト(Android Project)」が表示されます(1 つまたは複数の Android プロジェクトを作成した後は、「Android XML File」というエントリも表示されるようになります)。
+
+
+ - 「Android プロジェクト(Android Project)」を選択して、[[]次へ(Next)] をクリックします。
+
+
+ - プロジェクトの詳細項目に以下の値を入力します。
+
+ - プロジェクト名(Project name): HelloAndroid
+ - アプリケーション名(Application name): Hello, Android
+ - パッケージ名(Package name): com.example.helloandroid(または自分のプライベート ネームスペース)
+ - アクティビティを作成(Create Activity): HelloAndroid
+ - SDK の最小バージョン(Min SDK Version): 2
+
+ [[]完了(Finish)] をクリックします。
+
+
+
+ 各フィールドの説明は以下のとおりです。
+
+
+ - プロジェクト名(Project Name)
+ - Eclipse のプロジェクト名。プロジェクト ファイルを格納するディレクトリの名前です。
+ - アプリケーション名(Application Name)
+ - アプリケーション名はユーザーにわかりやすいアプリケーションのタイトルにします。この名前が Android 携帯端末に表示されます。
+ - パッケージ名(Package Name)
+ - 作成したすべてのソース コードを格納するパッケージ ネームスペースです(Java プログラミング言語で作成するパッケージと同じルールに従います)。また、これにより、スタブ Activity が生成されるパッケージの名前も設定されます。
+
パッケージ名は Android システムにインストールされたすべてのパッケージに共通して固有のものでなければなりません。このため、作成するアプリケーションに標準的なドメイン スタイルのパッケージを使用することが非常に重要です。上記の例では、「com.example」というネームスペースを使用しています。これはサンプル ドキュメント用のネームスペースです。実際にアプリケーションを作成する際には、所属する組織または法人に適切なネームスペースを使用します。
+ - アクティビティを作成(Create Activity)
+ - プラグインによって生成されるクラス スタブの名前です。クラス スタブは Android の {@link android.app.Activity} クラスのサブクラスとなります。アクティビティとは単に、実行して何らかの処理を行うことができるクラスを意味します。選択に応じて UI を作成することもできます(ただし必須ではありません)。チェックボックスになっていることからわかるように、これは任意選択の項目です。しかし、実際にはほとんどのアプリケーションでは、アクティビティをアプリケーションの基盤として使用しています。
+ - SDK の最小バージョン(Min SDK Version)
+ - 作成するアプリケーションが必要とする最小 API レベルを指定する値です。ここに入力した API レベルが、選択可能なターゲットのいずれかで提供される API レベルと一致する場合は、ビルド ターゲットが自動的に選択されます(この例では、API レベルに「2」と入力するとターゲット Android 1.1 が選択されます)。Android システム イメージと Android SDK それぞれの新しいバージョンでは、API に追加または変更が加えられている可能性があります。追加または変更が加えられている場合、新しい API レベルがシステム イメージに割り当てられ、どのアプリケーションの実行を許可するかが規制されます。アプリケーションで必要な API レベルがデバイスでサポートされるレベルよりも高い場合、アプリケーションはインストールされません。
+
+
+ その他のフィールド: 「デフォルト ロケーションの使用」チェックボックスでは、プロジェクトのファイルが生成され保存されるディスク上の場所を変更することができます。「ビルド ターゲット」は、作成するアプリケーションがコンパイルされるときにターゲットとするプラットフォームです(この項目は [[]SDK の最小バージョン(Min SDK Version)] の入力値に基づいて自動的に選択されます)。
+
+ ここで、選択した「ビルド ターゲット」で Android 1.1 プラットフォームが使用されることに注目してください。これは、作成するアプリケーションが Android 1.1 プラットフォーム ライブラリをターゲットとしてコンパイルされることを意味します。先ほど作成した AVD は Android 1.5 プラットフォームで実行されます。バージョンの数字が一致しませんが、Android アプリケーションには上方互換性があるため、1.1 プラットフォーム ライブラリをターゲットとして構築されたアプリケーションでも 1.5 プラットフォームで正常に動作します。ただしその逆の場合は正常に動作しません。
+
+
+
+さて、これで Android プロジェクトを使用できる状態になりました。プロジェクトは左側のパッケージ エクスプローラー(Package Explorer)で表示できます。「HelloAndroid」 > 「src」 > 「com.example.helloandroid」 の中にある HelloAndroid.java
ファイルを開きます。ファイルの内容は次のようになっています。
+
+
+package com.example.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
+
+クラスが {@link android.app.Activity} クラスに基づいていることに注目してください。アクティビティ(Activity)とは、処理を実行するために使用される単体のアプリケーション エンティティです。1 つのアプリケーションにはいくつものアクティビティが含まれる場合がありますが、ユーザーが一度に操作するのは 1 つのアクティビティです。アクティビティが開始すると、Android システムによって {@link android.app.Activity#onCreate(Bundle) onCreate()} メソッドが呼び出されます。このタイミングですべての初期化と UI セットアップを実行します。アクティビティにユーザー インターフェースは必須ではありませんが、通常はユーザー インターフェースを装備します。
+
+では、コードを変更してみましょう。
+
+
+UI を構築する
+
+下記の変更済みのコードを参照して、お手元の HelloAndroid クラスに同じ変更を加えてみてください。太字の部分が追加された行です。
+
+
+package com.android.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView tv = new TextView(this);
+ tv.setText("Hello, Android");
+ setContentView(tv);
+ }
+}
+
+ヒント: プロジェクトにインポート パッケージを簡単に追加できる方法として、Ctrl+Shift+O(Mac では コマンド+Shift+O)を押す方法があります。これは、コードの記述に基づいて足りないパッケージを特定して追加する Eclipse のショートカット キーです。
+
+Android のユーザー インターフェースは、「ビュー(Views)」と呼ばれるオブジェクトの階層で構成されています。{@link android.view.View} は、UI レイアウト内でボタン、画像、または(このサンプルのように)テキスト ラベルといった要素として使用される、描画可能なオブジェクトです。これらのオブジェクトのそれぞれが View クラスのサブクラスであり、テキストを処理するサブクラスは {@link android.widget.TextView} です。
+
+この変更では、クラス コンストラクタを使用して TextView を作成します。このクラス コンストラクタは、パラメータとして Android {@link android.content.Context} インスタンスを受け入れます。Context とは、システムへのハンドルであり、リソースの解決、データベースや設定へのアクセスの取得などのサービスを提供します。Activity クラスは Context を継承します。作成する HelloAndroid クラスは、Activity のサブクラスであるため、Context でもあります。したがって、this
を Context 参照として TextView に引き渡すことができます。
+
+次に、{@link android.widget.TextView setText(CharSequence) setText()} を使用してテキスト コンテンツを定義します。
+
+最後に、そのコンテンツが Activity UI のコンテンツとして表示されるように、TextView を {@link android.app.Activity#setContentView(View) setContentView()} に引き渡します。Activity によってこのメソッドが呼び出されなければ、UI は表示されず、空白の画面が表示されます。
+
+これで、Android で「Hello, World」が表示されるようになりました。次の手順はもちろん、アプリケーションの実行です。
+
+
+アプリケーションを実行する
+
+Eclipse プラグインでは、非常に簡単にアプリケーションを実行できます。
+
+
+ - [[]実行] > [[]実行] を選択します。
+ - 「Android Application」を選択します。
+
+
+
+
+Eclipse ADT によって自動的にプロジェクトの新規起動構成が作成され、Android エミュレータが自動的に起動します。エミュレータが起動した後、少し経つとアプリケーションが表示されます。次のような画面が表示されます。
+
+
+
+グレーのバーに表示されている「Hello, Android」は、アプリケーションのタイトルです。このタイトルは Eclipse プラグインによって自動的に作成されます(文字列は res/values/strings.xml
ファイル内で定義され、AndroidManifest.xml
によって参照されます)。タイトルの下のテキストは、先ほど TextView オブジェクトで作成した実際のテキストです。
+
+これで「Hello World」についての基本的なチュートリアルは終了ですが、この続きもぜひ読んでください。Android アプリケーションの開発に関するさらに有益な情報を紹介しています。
+
+
+UI を XML レイアウトにアップグレードする
+
+先ほど作成した「Hello, World」のサンプルは、「プログラマティック」と呼ばれる UI レイアウトを使用しています。「プログラマティック」とは、アプリケーションの UI を直接ソース コードで作成および構築することを意味します。UI プログラミングの経験が豊富な方であればおそらく、このようなアプローチが時にいかに脆弱になり得るかをよくご存じでしょう。レイアウトの軽微な変更のたびに、ソース コード全体に関わる大きな問題が発生する可能性があるからです。また、複数のビューを適切に結びつけることも忘れられがちであるため、これによりレイアウトにエラーが発生し、コードのデバッグで時間が無駄になる場合があります。
+
+その理由から、Android では、XML ベースのレイアウト ファイルを使用する別の UI 構築モデルを用意しています。この概念を簡単に説明するには、サンプルを紹介するのが一番です。ここに示すのは、上記の「プログラマティック」に構築したサンプルと同じように動作する XML レイアウト ファイルです。
+
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/hello"/>
+
+Android XML レイアウト ファイルの全般的な構造はシンプルです。XML 要素がツリー構造になっており、含まれた各ノードが View クラスの名前を表しています(このサンプルでは View 要素が 1 つのみですが)。XML レイアウト内の要素として、{@link android.view.View} を拡張する任意のクラスの名前を使用できます。これには作成するコードの中で定義するカスタム View クラスも含まれます。この構造により、プログラマティックなレイアウトよりもシンプルな構造と構文を使用して、迅速な UI 構築を非常に簡単に行うことができます。このモデルは、アプリケーションの表示(つまり UI)を、データの取得と入力に使用されるアプリケーション ロジックから切り離すことができる Web 開発モデルからヒントを得て考案されました。
+
+上記の XML サンプルには、TextView
という View 要素 1 つのみが含まれています。この要素は 4 つの XML 属性を持っています。下表に、これらの 4 つの属性の説明をまとめました。
+
+
+
+
+
+ 属性
+ |
+
+ 説明
+ |
+
+
+
+ xmlns:android
+ |
+
+ Android ネームスペースで定義された共通の属性を参照することを Android ツールに伝える XML ネームスペース宣言です。すべての Android レイアウト ファイル内の最初と最後のタグはこの属性を持つ必要があります。
+ |
+
+
+
+ android:layout_width
+ |
+
+ 該当の View が画面の利用可能な幅のうちどれくらいを占めるかを定義します。このサンプルでは、この View しかないため、「fill_parent」という値を使用して画面全体を占めることにします。
+ |
+
+
+
+ android:layout_height
+ |
+
+ android:layout_width とよく似た属性で、幅ではなく高さを表します。
+ |
+
+
+
+ android:text
+ |
+
+ TextView が表示するテキストを設定します。このサンプルでは、ハードコード記述された文字列値ではなく文字列リソースを使用します。文字列「hello」は res/values/strings.xml ファイル内で定義されます。アプリケーションに文字列を挿入する場合にはこの方法が推奨されます。レイアウト ファイルのハードコードを直接変更する必要がないため、アプリケーションの他の言語へのローカライズがスムーズに進むからです。詳しくは、「リソースと国際化」を参照してください。
+ |
+
+
+
+
+
+これらの XML レイアウト ファイルは、作成するプロジェクトの res/layout/
ディレクトリ内に置かれます。「res」は「resources」の略で、アプリケーションに必要なコード以外のすべてのアセットがこのディレクトリに格納されます。リソースには、レイアウト ファイルの他に、画像、音声、ローカライズされた文字列などのアセットがあります。
+
+
+
横表示レイアウト
+
横表示の場合に異なるデザインで表示するには、レイアウト XML ファイルを /res/layout-land 内に入れます。Android 端末のレイアウトが横表示に変わると自動的にこのディレクトリが参照されます。このように横表示向けに定義されたレイアウトが存在しない場合、自動的にデフォルトのレイアウトが拡大して使用されます。
+
+
+Eclipse プラグインでは、このようなレイアウト ファイルの 1 つである「main.xml」が自動的に作成されます。先ほど「Hello World」アプリケーションを作成した際には、このファイルは無視してプログラマティックにレイアウトを作成しました。この作成方法は Android フレームワークについてより深く理解していただくことを意図したもので、実際にはほとんどの場合レイアウトはコードではなく XML ファイルで定義します。以下の手順では、既存のアプリケーションを変更して XML レイアウトが使用されるようにする方法を説明します。
+
+
+ - Eclipse のパッケージ エクスプローラー(Package Explorer)で、
/res/layout/
フォルダを展開し、main.xml
を開きます(開いた後、場合によっては XML ソースを見るのにウィンドウ下部にある「main.xml」タブをクリックする必要があります)。ファイルの内容を以下の XML に置き換えます。
+
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/hello"/>
+ファイルを保存します。
+
+
+res/values/
フォルダ内の strings.xml
を開きます。このファイルは、作成するユーザー インターフェースのためのすべてのデフォルトのテキスト文字列を保存するものです。Eclipse を使用している場合、ADT によってあらかじめ hello と app_name という 2 つの文字列が用意された状態になります。hello を何か別の文字列に書き換えてみましょう。たとえば「Hello, Android! I am a string resource!」としてみましょう。変更後のファイルの全体は次のようになります。
+
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello, Android! I am a string resource!</string>
+ <string name="app_name">Hello, Android</string>
+</resources>
+
+
+
+- 次に、
HelloAndroid
クラスを開いて、XML レイアウトを使用して変更します。ファイルを編集して次のような内容にします。
+
+package com.example.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
+
+この変更を行う際に、コードを手入力してコード補完機能を試してみましょう。「R.layout.main」と入力しようとすると、プラグインによって入力候補が表示されます。この機能の便利さは、開発中に何回も実感すると思います。
+
+View オブジェクトに setContentView()
を引き渡す代わりに、レイアウト リソースへの参照を付与します。リソースは R.layout.main
として識別されます。これは、/res/layout/main.xml
で定義されたレイアウトを、コンパイルされたオブジェクトで表したものです。Eclipse プラグインでは、この参照がプロジェクトの R.java クラス内に自動的に作成されます。Eclipse を使用していない場合、Ant を実行してアプリケーションのビルドを行う際に R.java クラスが生成されます(R クラスについて詳しくは後ほど説明します)。
+
+
+
+ここで、アプリケーションを再実行します。起動構成は作成済みであるため、ここでは緑色の矢印アイコンをクリックして実行するか、または [[]実行(Run)] > [[]ヒストリーの実行(Run History)] > [[]Android Activity] を選択するだけです。TextView 文字列に加えた変更を除けば、アプリケーションは同じに見えます。ここでポイントとなるのは、2 つの異なるレイアウト編集方法を使用して同じ結果が得られるということです。
+
+ヒント: ショートカット キーCtrl+F11(Mac では コマンド+Shift+F11)を使用して、現在表示されているアプリケーションを実行することができます。
+
+ここからは、デバッグの基礎知識と、他の総合開発環境に関する補足情報について説明します。さらに詳しく学習したい場合は、「アプリケーションの基礎」を参照してください。Android アプリケーションが動作するためのすべての要素について説明しています。また、「デベロッパー ガイド」の導入ページを参照して、デベロッパー ガイド ドキュメントの概要を確認してください。
+
+
+
+
R クラス
+
Eclipse で、R.java
という名前のファイル(gen/
(「生成された Java ファイル(Generated Java Files)」フォルダ内)を開きます。ファイルの内容は次のようになっています。
+
+
+package com.example.helloandroid;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int icon=0x7f020000;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f040001;
+ public static final int hello=0x7f040000;
+ }
+}
+
+
+
プロジェクトの R.java
ファイルは、ファイル内で定義されたすべてのリソースへのインデックスです。ソース コード内では、プロジェクトに含めたすべてのリソースを参照するための簡略形式としてこのクラスを使用します。これは、Eclipse などの総合開発環境のコード補完機能とともに使用すると特に便利です。探している特定の参照をすばやくインタラクティブに見つけることができるからです。
+
+
お手元のファイルはこれとは若干異なる可能性があります(おそらく 16 進値が異なるためです)。ここでは、「layout」という名前の内部クラスと、そのメンバーであるフィールド「main」に注目します。Eclipse プラグインにより main.xml という名前の XML レイアウト ファイルが認識され、ここにそのためのクラスが生成されたものです。プロジェクトに他のリソース(res/values/string.xml
ファイル内の文字列や res/drawable/
ディレクトリ内の描画可能オブジェクトなど)を追加すると、R.java
に最新の変更が反映されます。
+
Eclipse を使用していない場合は、(Ant ツールを使用した)ビルド時にこのクラス ファイルが生成されます。
+
くれぐれもこのファイルを手動で編集しないようにしてください。
+
+
+プロジェクトをデバッグする
+
+Android Plugin for Eclipse は、Eclipse のデバッガと優れた連動性を発揮します。このメリットを確認するため、作成したコードにバグを埋め込んでみましょう。作成した HelloAndroid ソース コードを次のように変更します。
+
+
+package com.android.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Object o = null;
+ o.toString();
+ setContentView(R.layout.main);
+ }
+}
+
+この変更は、単にコードに NullPointerException を発生させるものです。アプリケーションを再度実行すると、最終的に次のような画面が表示されます。
+
+
+
+「強制終了」を押してアプリケーションを終了し、エミュレータ ウィンドウを閉じます。
+
+エラーの詳細を確認するには、ソース コード内の Object o = null;
行にブレークポイントを設定します(該当するソース コード行の横にあるマーカー バーをダブルクリックします)。次に、メニューから [[]実行(Run)] > [[]デバッグ ヒストリー(Debug History)] > [[]Hello, Android] を選択して、デバッグ モードに入ります。エミュレータでアプリケーションが再起動されますが、今度は、先ほど設定したブレークポイントに到達した時点で中断されます。その後 Eclipse のデバッグ パースペクティブ(Debug Perspective)で、他のアプリケーションで通常行うように、コードの内容を確認できます。
+
+
+
+
+Eclipse を使用せずにプロジェクトを作成する
+
+ Eclipse を使用していない場合(普段から使用している総合開発環境がある場合や、シンプルにテキスト エディタやコマンド ライン ツールを使用している場合など)は、Eclipse プラグインを利用することはできません。しかし心配は無用です。Eclipse を使用していないからといって何らかの機能が失われることはありません。
+
+ Android Plugin for Eclipse は、単に Android SDK に含まれるツール セットをまとめたものに過ぎません(エミュレータ、aapt、adb、ddms などの個別のツールについては、こちらで別途説明しています)。このため、これらのツールを別のツール、たとえば「Ant」のビルド ファイルなどでまとめることも可能です。
+
+ Android SDK には、「android」という名前のツールが含まれています。このツールを使用すると、作成するプロジェクトのソース コードとディレクトリ スタブすべて、および Ant と互換性のある build.xml
ファイルを作成することができます。これにより、プロジェクトをコマンド ラインで作成したり、普段使用している総合開発環境と統合したりすることができます。
+
+ たとえば、Eclipse で作成されるものと同様の HelloAndroid プロジェクトを作成するには、次のコマンドを使用します。
+
+
+android create project \
+ --package com.android.helloandroid \
+ --activity HelloAndroid \
+ --target 2 \
+ --path <path-to-your-project>/HelloAndroid
+
+
+ これにより、path で定義された場所に、プロジェクトに必要なフォルダとファイルが作成されます。
+
+ SDK ツールを使用してプロジェクトを作成および構築する方法について詳しくは、「Developing in Other IDEs」を参照してください。
diff --git a/docs/html/intl/ja/sdk/1.5_r2/installing.jd b/docs/html/intl/ja/sdk/1.5_r2/installing.jd
index a587b1a..789fc26 100644
--- a/docs/html/intl/ja/sdk/1.5_r2/installing.jd
+++ b/docs/html/intl/ja/sdk/1.5_r2/installing.jd
@@ -130,7 +130,7 @@ page.title=Android SDK のインストール
その他のインストール エラー
-オプションの Eclipse コンポーネント(WST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui" をご覧ください。
+オプションの Eclipse コンポーネント(WST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui" をご覧ください。
Linux ユーザーの場合
Eclipse 用 ADT プラグインのインストール時に、次のエラーが発生する場合があります。
@@ -166,15 +166,15 @@ JKS
サンプル コードの参照
Android デベロッパー グループへのアクセス
- [コミュニティ] タブで、Android デベロッパー グループの一覧を参照します。特に Android Developers グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。
+ href="{@docRoot}resources/community-groups.html">コミュニティ] タブで、Android デベロッパー グループの一覧を参照します。特に Android Developers グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。
diff --git a/docs/html/intl/ja/sdk/1.5_r3/installing.jd b/docs/html/intl/ja/sdk/1.5_r3/installing.jd
index a587b1a..789fc26 100644
--- a/docs/html/intl/ja/sdk/1.5_r3/installing.jd
+++ b/docs/html/intl/ja/sdk/1.5_r3/installing.jd
@@ -130,7 +130,7 @@ page.title=Android SDK のインストール
その他のインストール エラー
-オプションの Eclipse コンポーネント(WST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui" をご覧ください。
+オプションの Eclipse コンポーネント(WST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui" をご覧ください。
Linux ユーザーの場合
Eclipse 用 ADT プラグインのインストール時に、次のエラーが発生する場合があります。
@@ -166,15 +166,15 @@ JKS
サンプル コードの参照
Android デベロッパー グループへのアクセス
- [コミュニティ] タブで、Android デベロッパー グループの一覧を参照します。特に Android Developers グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。
+ href="{@docRoot}resources/community-groups.html">コミュニティ] タブで、Android デベロッパー グループの一覧を参照します。特に Android Developers グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。
diff --git a/docs/html/resources/articles/avoiding-memory-leaks.jd b/docs/html/resources/articles/avoiding-memory-leaks.jd
new file mode 100644
index 0000000..3361bc1
--- /dev/null
+++ b/docs/html/resources/articles/avoiding-memory-leaks.jd
@@ -0,0 +1,109 @@
+page.title=Avoiding Memory Leaks
+@jd:body
+
+
+Android applications are, at least on the T-Mobile G1, limited
+to 16 MB of heap. It's both a lot of memory for a phone and yet very
+little for what some developers want to achieve. Even if you do not
+plan on using all of this memory, you should use as little as possible
+to let other applications run without getting them killed. The more
+applications Android can keep in memory, the faster it will be for the
+user to switch between his apps. As part of my job, I ran into memory
+leaks issues in Android applications and they are most of the time due
+to the same mistake: keeping a long-lived reference to a
+{@link android.content.Context Context}.
+
+On Android, a Context
is used for many operations
+ but mostly to load and access resources. This is why all the widgets
+receive a Context
parameter in their constructor. In a
+regular Android application, you usually have two kinds of
+Context
, {@link android.app.Activity} and
+{@link android.app.Application}. It's usually the first one that
+the developer passes to classes and methods that need a Context
:
+
+@Override
+protected void onCreate(Bundle state) {
+ super.onCreate(state);
+
+ TextView label = new TextView(this);
+ label.setText("Leaks are bad");
+
+ setContentView(label);
+}
+
+
+This means that views have a reference to the entire activity and
+therefore to anything your activity is holding onto; usually the entire
+View hierarchy and all its resources. Therefore, if you leak the Context
+("leak" meaning you keep a reference to it thus preventing the GC from
+collecting it), you leak a lot of memory. Leaking an entire activity
+can be really easy if you're not careful.
+
+When the screen orientation changes the system will, by default,
+destroy the current activity and create a new one while preserving its
+state. In doing so, Android will reload the application's UI from the
+resources. Now imagine you wrote an application with a large bitmap
+that you don't want to load on every rotation. The easiest way to keep
+it around and not having to reload it on every rotation is to keep in a
+static field:
+
+private static Drawable sBackground;
+
+@Override
+protected void onCreate(Bundle state) {
+ super.onCreate(state);
+
+ TextView label = new TextView(this);
+ label.setText("Leaks are bad");
+
+ if (sBackground == null) {
+ sBackground = getDrawable(R.drawable.large_bitmap);
+ }
+ label.setBackgroundDrawable(sBackground);
+
+ setContentView(label);
+}
+
+
+This code is very fast and also very wrong; it leaks the first activity
+created upon the first screen orientation change. When a
+{@link android.graphics.drawable.Drawable Drawable} is attached to a view, the view is set as a
+{@link android.graphics.drawable.Drawable#setCallback(android.graphics.drawable.Drawable.Callback) callback}
+on the drawable. In the code snippet above, this means the drawable has a
+reference to the TextView
which itself has a reference to the
+activity (the Context
) which in turns has references to
+pretty much anything (depending on your code.)
+
+This example is one of the simplest cases of leaking the
+Context
and you can see how we worked around it in the
+Home screen's source code
+(look for the unbindDrawables()
method) by setting the stored
+drawables' callbacks to null when the activity is destroyed. Interestingly
+enough, there are cases where you can create a chain of leaked contexts,
+and they are bad. They make you run out of memory rather quickly.
+
+There are two easy ways to avoid context-related memory leaks. The most
+obvious one is to avoid escaping the context outside of its own scope. The
+example above showed the case of a static reference but inner classes and
+their implicit reference to the outer class can be equally dangerous. The
+second solution is to use the Application
context. This
+context will live as long as your application is alive and does not depend
+on the activities life cycle. If you plan on keeping long-lived objects
+that need a context, remember the application object. You can obtain it
+easily by calling
+{@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
+or {@link android.app.Activity#getApplication() Activity.getApplication()}.
+
+In summary, to avoid context-related memory leaks, remember the following:
+
+- Do not keep long-lived references to a context-activity (a reference
+to an activity should have the same life cycle as the activity itself)
+- Try using the context-application instead of a context-activity
+- Avoid non-static inner classes in an activity if you don't control
+their life cycle, use a static inner class and make a weak reference to
+the activity inside. The solution to this issue is to use a static inner
+class with a {@link java.lang.ref.WeakReference WeakReference} to the
+outer class, as done in ViewRoot
+and its W inner class for instance
+- A garbage collector is not an insurance against memory leaks
+
diff --git a/docs/html/resources/articles/backward-compatibility.jd b/docs/html/resources/articles/backward-compatibility.jd
new file mode 100644
index 0000000..9f0ddf5
--- /dev/null
+++ b/docs/html/resources/articles/backward-compatibility.jd
@@ -0,0 +1,238 @@
+page.title=Backward Compatibility for Applications
+@jd:body
+
+A variety of Android-powered devices are now available to consumers from carriers
+in geographies around the world. Across those devices, a range of Android
+platform versions are in use, some running the latest version of the platform,
+others running older versions. As a developer, you need to consider the approach
+to backward compatibility that you will take in your application — do you
+want to allow your application to run on all devices, or just those running the
+latest software? In some cases it will be useful to employ the newer APIs on
+devices that support them, while continuing to support older devices.
+
+Setting the minSdkVersion
+If the use of a new API is integral to the application — perhaps you
+need to record video using an API introduced in Android 1.5 (API Level 3)
+— you should add a <android:minSdkVersion>
+ to the application's manifest, to ensure your app won't
+be installed on older devices. For example, if your application depends on an
+API introduced in API Level 3, you would specify "3" as the value of the minimum
+SDK version:
+
+ <manifest>
+ ...
+ <uses-sdk android:minSdkVersion="3" />
+ ...
+ </manifest>
+
+However, if you want to add a useful but non-essential feature, such as
+popping up an on-screen keyboard even when a hardware keyboard is available, you
+can write your program in a way that allows it to use the newer features without
+failing on older devices.
+
+Using reflection
+
+Suppose there's a simple new call you want to use, like {@link
+android.os.Debug#dumpHprofData(java.lang.String)
+android.os.Debug.dumpHprofData(String filename)}. The {@link android.os.Debug}
+class has existed since Android 1.0, but the method is new in Anroid 1.5 (API
+Level 3). If you try to call it directly, your app will fail to run on devices
+running Android 1.1 or earlier.
+
+The simplest way to call the method is through reflection. This requires
+doing a one-time lookup and caching the result in a Method
object.
+Using the method is a matter of calling Method.invoke
and un-boxing
+the result. Consider the following:
+
+public class Reflect {
+ private static Method mDebug_dumpHprofData;
+
+ static {
+ initCompatibility();
+ };
+
+ private static void initCompatibility() {
+ try {
+ mDebug_dumpHprofData = Debug.class.getMethod(
+ "dumpHprofData", new Class[] { String.class } );
+ /* success, this is a newer device */
+ } catch (NoSuchMethodException nsme) {
+ /* failure, must be older device */
+ }
+ }
+
+ private static void dumpHprofData(String fileName) throws IOException {
+ try {
+ mDebug_dumpHprofData.invoke(null, fileName);
+ } catch (InvocationTargetException ite) {
+ /* unpack original exception when possible */
+ Throwable cause = ite.getCause();
+ if (cause instanceof IOException) {
+ throw (IOException) cause;
+ } else if (cause instanceof RuntimeException) {
+ throw (RuntimeException) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ /* unexpected checked exception; wrap and re-throw */
+ throw new RuntimeException(ite);
+ }
+ } catch (IllegalAccessException ie) {
+ System.err.println("unexpected " + ie);
+ }
+ }
+
+ public void fiddle() {
+ if (mDebug_dumpHprofData != null) {
+ /* feature is supported */
+ try {
+ dumpHprofData("/sdcard/dump.hprof");
+ } catch (IOException ie) {
+ System.err.println("dump failed!");
+ }
+ } else {
+ /* feature not supported, do something else */
+ System.out.println("dump not supported");
+ }
+ }
+}
+
+This uses a static initializer to call initCompatibility
,
+which does the method lookup. If that succeeds, it uses a private
+method with the same semantics as the original (arguments, return
+value, checked exceptions) to do the call. The return value (if it had
+one) and exception are unpacked and returned in a way that mimics the
+original. The fiddle
method demonstrates how the
+application logic would choose to call the new API or do something
+different based on the presence of the new method.
+
+For each additional method you want to call, you would add an additional
+private Method
field, field initializer, and call wrapper to the
+class.
+
+This approach becomes a bit more complex when the method is declared in a
+previously undefined class. It's also much slower to call
+Method.invoke()
than it is to call the method directly. These
+issues can be mitigated by using a wrapper class.
+
+Using a wrapper class
+
+The idea is to create a class that wraps all of the new APIs exposed by a new
+or existing class. Each method in the wrapper class just calls through to the
+corresponding real method and returns the same result.
+
+If the target class and method exist, you get the same behavior you would get
+by calling the class directly, with a small amount of overhead from the
+additional method call. If the target class or method doesn't exist, the
+initialization of the wrapper class fails, and your application knows that it
+should avoid using the newer calls.
+
+Suppose this new class were added:
public class NewClass {
+ private static int mDiv = 1;
+
+ private int mMult;
+
+ public static void setGlobalDiv(int div) {
+ mDiv = div;
+ }
+
+ public NewClass(int mult) {
+ mMult = mult;
+ }
+
+ public int doStuff(int val) {
+ return (val * mMult) / mDiv;
+ }
+}
+
+We would create a wrapper class for it:
+
+class WrapNewClass {
+ private NewClass mInstance;
+
+ /* class initialization fails when this throws an exception */
+ static {
+ try {
+ Class.forName("NewClass");
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ /* calling here forces class initialization */
+ public static void checkAvailable() {}
+
+ public static void setGlobalDiv(int div) {
+ NewClass.setGlobalDiv(div);
+ }
+
+ public WrapNewClass(int mult) {
+ mInstance = new NewClass(mult);
+ }
+
+ public int doStuff(int val) {
+ return mInstance.doStuff(val);
+ }
+}
+
+This has one method for each constructor and method in the original, plus a
+static initializer that tests for the presence of the new class. If the new
+class isn't available, initialization of WrapNewClass
fails,
+ensuring that the wrapper class can't be used inadvertently. The
+checkAvailable
method is used as a simple way to force class
+initialization. We use it like this:
+
+public class MyApp {
+ private static boolean mNewClassAvailable;
+
+ /* establish whether the "new" class is available to us */
+ static {
+ try {
+ WrapNewClass.checkAvailable();
+ mNewClassAvailable = true;
+ } catch (Throwable t) {
+ mNewClassAvailable = false;
+ }
+ }
+
+ public void diddle() {
+ if (mNewClassAvailable) {
+ WrapNewClass.setGlobalDiv(4);
+ WrapNewClass wnc = new WrapNewClass(40);
+ System.out.println("newer API is available - " + wnc.doStuff(10));
+ } else {
+ System.out.println("newer API not available");
+ }
+ }
+}
+
+If the call to checkAvailable
succeeds, we know the new class is
+part of the system. If it fails, we know the class isn't there, and adjust our
+expectations accordingly. It should be noted that the call to
+checkAvailable
will fail before it even starts if the bytecode
+verifier decides that it doesn't want to accept a class that has references to a
+nonexistent class. The way this code is structured, the end result is the same
+whether the exception comes from the verifier or from the call to
+Class.forName
.
+
+When wrapping an existing class that now has new methods, you only need to
+put the new methods in the wrapper class. Invoke the old methods directly. The
+static initializer in WrapNewClass
would be augmented to do a
+one-time check with reflection.
+
+Testing is key
+
+You must test your application on every version of the Android framework that
+is expected to support it. By definition, the behavior of your application will
+be different on each. Remember the mantra: if you haven't tried it, it doesn't
+work.
+
+You can test for backward compatibility by running your application in an
+emulator that uses an older version of the platform. The Android SDK allows you
+to do this easily by creating "Android Virtual Devices" with different API
+levels. Once you create the AVDs, you can test your application with old and new
+versions of the system, perhaps running them side-by-side to see the
+differences. More information about emulator AVDs can be found in the AVD documentation and
+from emulator -help-virtual-device
.
\ No newline at end of file
diff --git a/docs/html/resources/articles/can-i-use-this-intent.jd b/docs/html/resources/articles/can-i-use-this-intent.jd
new file mode 100644
index 0000000..a726189
--- /dev/null
+++ b/docs/html/resources/articles/can-i-use-this-intent.jd
@@ -0,0 +1,69 @@
+page.title=Can I Use this Intent?
+@jd:body
+
+Android offers a very powerful and yet easy-to-use message type called
+an intents.
+You can use intents to turn applications into high-level libraries and
+make code modular and reusable. The Android Home screen and AnyCut
+applications, for instance, use intents extensively to create shortcuts.
+
+While it is nice to be able to make use of a loosely coupled
+API, there is no guarantee that the intent you send will be received by
+another application. This happens in particular with third-party apps, like
+Panoramio
+and its RADAR intent.
+
+This article describes a technique you can use to find out whether the system
+contains any application capable of responding to the intent you want to use.
+The example below shows a helper method that queries the system package manager
+to determine whether there's an app that can respond to a specified intent. Your
+application can pass an intent to the method and then, for example, show or hide
+user options that the user would normally use to trigger the intent.
+
+/**
+ * Indicates whether the specified action can be used as an intent. This
+ * method queries the package manager for installed packages that can
+ * respond to an intent with the specified action. If no suitable package is
+ * found, this method returns false.
+ *
+ * @param context The application's environment.
+ * @param action The Intent action to check for availability.
+ *
+ * @return True if an Intent with the specified action can be sent and
+ * responded to, false otherwise.
+ */
+public static boolean isIntentAvailable(Context context, String action) {
+ final PackageManager packageManager = context.getPackageManager();
+ final Intent intent = new Intent(action);
+ List<ResolveInfo> list =
+ packageManager.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+ return list.size() > 0;
+}
+
+
+Here is how you could use the helper method:
+
+@Override
+public boolean onPrepareOptionsMenu(Menu menu) {
+ final boolean scanAvailable = isIntentAvailable(this,
+ "com.google.zxing.client.android.SCAN");
+
+ MenuItem item;
+ item = menu.findItem(R.id.menu_item_add);
+ item.setEnabled(scanAvailable);
+
+ return super.onPrepareOptionsMenu(menu);
+}
+
+
+In this example, the menu is grayed out if the Barcode Scanner
+application is not installed.
+
+Another, simpler, way to do this is to catch the
+ActivityNotFoundException
when calling startActivity()
+but it only lets you react to the problem, you cannot predict it and update the
+UI accordingly to prevent the user from doing something that won't work. The
+technique described here can also be used at startup time to ask the user
+whether he'd like to install the missing package, you can then simply redirect
+him to the Android Market by using the appropriate URI.
\ No newline at end of file
diff --git a/docs/html/resources/articles/creating-input-method.jd b/docs/html/resources/articles/creating-input-method.jd
new file mode 100644
index 0000000..5a92970
--- /dev/null
+++ b/docs/html/resources/articles/creating-input-method.jd
@@ -0,0 +1,235 @@
+page.title=Creating an Input Method
+@jd:body
+
+
+To create an input method (IME) for entering text into text fields
+and other Views, you need to extend the {@link android.inputmethodservice.InputMethodService}.
+class. This class provides much of the basic implementation for an input
+method, in terms of managing the state and visibility of the input method and
+communicating with the currently visible activity.
+
+A good starting point would be the SoftKeyboard sample code provided as part
+of the SDK. You can modify the sample code to start building your own input
+method.
+
+An input method is packaged like any other application or service. In the
+AndroidManifest.xml
file, you declare the input method as a
+service, with the appropriate intent filter and any associated meta data:
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.fastinput">
+
+ <application android:label="@string/app_label">
+ <!-- Declares the input method service -->
+ <service android:name="FastInputIME"
+ android:label="@string/fast_input_label"
+ android:permission="android.permission.BIND_INPUT_METHOD">
+ <intent-filter>
+ <action android:name="android.view.InputMethod" />
+ </intent-filter>
+ <meta-data android:name="android.view.im" android:resource="@xml/method" />
+ </service>
+
+ <!-- Optional activities. A good idea to have some user settings. -->
+ <activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
+
+If your input method allows the user to tweak some settings, you should
+provide a settings activity that can be launched from the Settings application.
+This is optional and you may choose to provide all user settings directly in
+your IME's UI.
+
+The typical life-cycle of an InputMethodService
looks like
+this:
+
+![](images/ime_003.png)
+
+Visual Elements
+
+There are two main visual elements for an input method—the input view and the
+candidates view. You don't have to follow this style though, if one of them is
+not relevant to your input method experience.
+
+Input View
+
+This is where the user can input text either in the form of keypresses,
+handwriting or other gestures. When the input method is displayed for the first
+time, InputMethodService.onCreateInputView()
will be called. Create
+and return the view hierarchy that you would like to display in the input method
+window.
+
+Candidates View
+
+This is where potential word corrections or completions are presented to the
+user for selection. Again, this may or may not be relevant to your input method
+and you can return null
from calls to
+InputMethodService.onCreateCandidatesView()
, which is the default
+behavior.
+
+Designing for the different Input Types
+
+An application's text fields can have different input types specified on
+them, such as free form text, numeric, URL, email address and search. When you
+implement a new input method, you need to be aware of the different input types.
+Input methods are not automatically switched for different input types and so
+you need to support all types in your IME. However, the IME is not responsible
+for validating the input sent to the application. That's the responsibility of
+the application.
+
+For example, the LatinIME provided with the Android platform provides
+different layouts for text and phone number entry:
+
+![](images/ime_002.png)
![](images/ime.png)
+
+InputMethodService.onStartInputView()
is called with an
+EditorInfo
object that contains details about the input type and other
+attributes of the application's text field.
(EditorInfo.inputType
+& EditorInfo.TYPE_CLASS_MASK
) can be one of many different values,
+including:
+
+
+TYPE_CLASS_NUMBER
+TYPE_CLASS_DATETIME
+TYPE_CLASS_PHONE
+TYPE_CLASS_TEXT
+
+
+See android.text.InputType
for more details.
+
+EditorInfo.inputType
can contain other masked bits that
+indicate the class variation and other flags. For example,
+TYPE_TEXT_VARIATION_PASSWORD
or TYPE_TEXT_VARIATION_URI
+or TYPE_TEXT_FLAG_AUTO_COMPLETE
.
+
+Password fields
+
+Pay
+specific attention when sending text to password fields. Make sure that
+the password is not visible within your UI — neither in the input
+view or the candidates view. Also, do not save the password anywhere without
+explicitly informing the user.
+
+Landscape vs. portrait
+
+The UI needs to be able to scale between landscape and portrait orientations.
+In non-fullscreen IME mode, leave sufficient space for the application to show
+the text field and any associated context. Preferably, no more than half the
+screen should be occupied by the IME. In fullscreen IME mode this is not an
+issue.
+
+Sending text to the application
+
+There are two ways to send text to the application. You can either send
+individual key events or you can edit the text around the cursor in the
+application's text field.
+
+To send a key event, you can simply construct KeyEvent objects and call
+InputConnection.sendKeyEvent()
. Here are some examples:
+
+InputConnection ic = getCurrentInputConnection();
+long eventTime = SystemClock.uptimeMillis();
+ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
+ KeyEvent.ACTION_DOWN, keyEventCode, 0, 0, 0, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
+ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+ KeyEvent.ACTION_UP, keyEventCode, 0, 0, 0, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE));
+
+Or use the convenience method:
+
+InputMethodService.sendDownUpKeyEvents(keyEventCode);
+
+Note:
+It is recommended to use the above method for certain fields such as
+phone number fields because of filters that may be applied to the text
+after each key press. Return key and delete key should also be sent as
+raw key events for certain input types, as applications may be watching
+for specific key events in order to perform an action.
+
+When editing text in a text field, some of the more useful methods on
+android.view.inputmethod.InputConnection
are:
+
+
+getTextBeforeCursor()
+getTextAfterCursor()
+deleteSurroundingText()
+commitText()
+
+
+For example, let's say the text "Fell" is to the left of the cursor
+and you want to replace it with "Hello!":
+
+InputConnection ic = getCurrentInputConnection();
+ic.deleteSurroundingText(4, 0);
+ic.commitText("Hello", 1);
+ic.commitText("!", 1);
+
+Composing text before committing
+
+If your input method does some kind of text prediction or requires multiple
+steps to compose a word or glyph, you can show the progress in the text field
+until the user commits the word and then you can replace the partial composition
+with the completed text. The text that is being composed will be highlighted in
+the text field in some fashion, such as an underline.
+
+InputConnection ic = getCurrentInputConnection();
+ic.setComposingText("Composi", 1);
+...
+ic.setComposingText("Composin", 1);
+...
+ic.commitText("Composing ", 1);
+
+
+
+![](images/ime_004.png)
+
+Intercepting hard key events
+
+Even though the input method window doesn't have explicit focus, it receives
+hard key events first and can choose to consume them or forward them along to
+the application. For instance, you may want to consume the directional keys to
+navigate within your UI for candidate selection during composition. Or you may
+want to trap the back key to dismiss any popups originating from the input
+method window. To intercept hard keys, override
+InputMethodService.onKeyDown()
and
+InputMethodService.onKeyUp().
Remember to call
+super.onKey
* if you don't want to consume a certain key
+yourself.
+
+Other considerations
+
+
+- Provide a way for the user to easily bring up any associated settings
+directly from the input method UI
+- Provide
+a way for the user to switch to a different input method (multiple
+input methods may be installed) directly from the input method UI.
+- Bring
+up the UI quickly - preload or lazy-load any large resources so that
+the user sees the input method quickly on tapping on a text field. And
+cache any resources and views for subsequent invocations of the input
+method.
+- On the flip side, any large memory allocations should
+be released soon after the input method window is hidden so that
+applications can have sufficient memory to run. Consider using a
+delayed message to release resources if the input method is in a hidden
+state for a few seconds.
+- Make sure that most common characters
+can be entered using the input method, as users may use punctuation in
+passwords or user names and they shouldn't be stuck in a situation
+where they can't enter a certain character in order to gain access into
+a password-locked device.
+
+
+Samples
+
+For a real world example, with support for multiple input types and text
+prediction, see the LatinIME source code. The
+Android SDK also includes a SoftKeyboard sample as well.
diff --git a/docs/html/resources/articles/drawable-mutations.jd b/docs/html/resources/articles/drawable-mutations.jd
new file mode 100644
index 0000000..f979829
--- /dev/null
+++ b/docs/html/resources/articles/drawable-mutations.jd
@@ -0,0 +1,91 @@
+page.title=Drawable Mutations
+@jd:body
+
+Android's drawables are extremely useful to easily build applications. A
+{@link android.graphics.drawable.Drawable Drawable} is a pluggable drawing
+container that is usually associated with a View. For instance, a
+{@link android.graphics.drawable.BitmapDrawable BitmapDrawable} is used to display
+images, a {@link android.graphics.drawable.ShapeDrawable ShapeDrawable} to draw
+shapes and gradients, and so on. You can even combine them to create complex
+renderings.
+
+Drawables allow you to easily customize the rendering of the widgets without
+subclassing them. As a matter of fact, they are so convenient that most of the
+default Android apps and widgets are built using drawables; there are about 700
+drawables used in the core Android framework. Because drawables are used so
+extensively throughout the system, Android optimizes them when they are loaded
+from resources. For instance, every time you create a
+{@link android.widget.Button Button}, a new drawable is loaded from the framework
+resources (android.R.drawable.btn_default
). This means all buttons
+across all the apps use a different drawable instance as their background.
+However, all these drawables share a common state, called the "constant state."
+The content of this state varies according to the type of drawable you are
+using, but it usually contains all the properties that can be defined by a
+resource. In the case of a button, the constant state contains a bitmap image.
+This way, all buttons across all applications share the same bitmap, which saves
+a lot of memory.
+
+The following diagram shows what entities are
+created when you assign the same image resource as the background of
+two different views. As you can see, two drawables are created but they
+both share the same constant state, hence the same bitmap:
+
+
+
+This state sharing feature is great to avoid wasting memory but it can cause
+problems when you try to modify the properties of a drawable. Imagine an
+application with a list of books. Each book has a star next to its name, totally
+opaque when the user marks the book as a favorite, and translucent when the book
+is not a favorite. To achieve this effect, you would probably write the
+following code in your list adapter's getView()
method:
+
+Book book = ...;
+TextView listItem = ...;
+
+listItem.setText(book.getTitle());
+
+Drawable star = context.getResources().getDrawable(R.drawable.star);
+if (book.isFavorite()) {
+ star.setAlpha(255); // opaque
+} else {
+ star.setAlpha(70); // translucent
+}
+
+Unfortunately, this piece of code yields a rather strange result:
+all of the drawables have the same opacity:
+
+
+
+This
+result is explained by the constant state. Even though we are getting a
+new drawable instance for each list item, the constant state remains
+the same and, in the case of BitmapDrawable, the opacity is part of the
+constant state. Thus, changing the opacity of one drawable instance
+changes the opacity of all the other instances. Even worse, working
+around this issue was not easy with Android 1.0 and 1.1.
+
+Android 1.5 and higher offers a very easy way to solve this issue
+with the new {@link android.graphics.drawable.Drawable#mutate()} method.
+When you invoke this method on a drawable, the constant state of the
+drawable is duplicated to allow you to change any property without
+affecting other drawables. Note that bitmaps are still shared, even
+after mutating a drawable. The diagram below shows what happens when
+you invoke mutate()
on a drawable:
+
+
+
+Let's update our previous piece of code to make use of mutate()
:
+
+Drawable star = context.getResources().getDrawable(R.drawable.star);
+if (book.isFavorite()) {
+ star.mutate().setAlpha(255); // opaque
+} else {
+ star. mutate().setAlpha(70); // translucent
+}
+
+For convenience, mutate()
+returns the drawable itself, which allows to chain method calls. It
+does not however create a new drawable instance. With this new piece of
+code, our application now behaves correctly:
+
+
diff --git a/docs/html/resources/articles/faster-screen-orientation-change.jd b/docs/html/resources/articles/faster-screen-orientation-change.jd
new file mode 100644
index 0000000..c500035
--- /dev/null
+++ b/docs/html/resources/articles/faster-screen-orientation-change.jd
@@ -0,0 +1,115 @@
+page.title=Faster Screen Orientation Change
+@jd:body
+
+Android is designed to run efficiently on a wide
+array of devices, with very different hardware configurations. Some
+devices, like the T-Mobile G1, can change their hardware configuration
+at runtime. For instance, when you open the keyboard, the screen change
+from the portrait orientation to the landscape orientation.
+
+
+
+
Using the alternate resources framework
+
+
The platform's support for loading orientation-specific
+resources at run time is based on the alternate resources framework.
+
+
Providing orientation-specific resources is an important part of
+developing your app. If you are not familiar with resource directory qualifiers
+or how the platform uses them, please read
+
+Alternate Resources.
+
+
+
+To make
+Android app development easier, the Android system automatically handles
+configuration change events and restarts the current activity with the new
+configuration. This is the default behavior that lets you declare
+resources like layouts and drawables based on the orientation, screen
+size, locale, etc.
+
+While this behavior is really powerful, since your application adapts
+automatically to the device's configuration at runtime, it is sometimes
+confusing for new Android developers, who wonder why their activity is
+destroyed and recreated.
+
+Facing this "issue," some developers choose to handle configuration changes
+themselves which is, in general, a short-term solution that will only complicate
+their lives later. On the other hand, the system's automatic resource handling
+is a very efficient and easy way to adapt an application's user interface to
+various devices and devices configurations. It sometimes comes at a price,
+though.
+
+When your application displays a lot of data, or data that is expensive to fetch,
+the automatic destruction/creation of the activities can be lead to a
+painful user experience. Take the example of Photostream,
+a simple Flickr browsing application. After you launch the application and choose a Flickr account, the
+application downloads a set of 6 photos (on a T-Mobile G1) from the
+Flickr servers and displays them on screen. To improve the user
+experience, the application uses slightly different layouts and drawables in
+portrait and landscape modes and this is what the result looks like:
+
+![](images/photostream_landscape.png)
+
+![](images/photostream_portrait.png)
+
+Photostream lets Android take care of the configuration change when the
+screen is rotated. However, can you imagine how painful it would be for the user
+to see all the images being downloaded again? The obvious solution to this
+problem is to temporarily cache the images. They could be cached on the SD card
+(if there's one), in the Application object, in a static field, etc. None of
+these techniques is adapted to the current situation: why should we bother
+caching the images when the screen is not rotated? Fortunately for us, Android
+offers a great API exactly for that purpose.
+
+The Activity class has a special method called
+{@link android.app.Activity#onRetainNonConfigurationInstance()}. This method
+can be used to pass an arbitrary object your future self and Android
+is smart enough to call this method only when needed. In the case of Photostream,
+the application used this method
+to pass the downloaded images to the future activity on orientation change.
+The implementation can be summarized like so:
+
+@Override
+public Object onRetainNonConfigurationInstance() {
+ final LoadedPhoto[] list = new LoadedPhoto[numberOfPhotos];
+ keepPhotos(list);
+ return list;
+}
+
+
+In the new activity, in onCreate()
, all you have to do to
+get your object back is to call {@link android.app.Activity#getLastNonConfigurationInstance()}.
+In Photostream, this method is invoked
+and if the returned value is not null, the grid is loaded with the list of
+photos from the previous activity:
+
+private void loadPhotos() {
+ final Object data = getLastNonConfigurationInstance();
+
+ // The activity is starting for the first time, load the photos from Flickr
+ if (data == null) {
+ mTask = new GetPhotoListTask().execute(mCurrentPage);
+ } else {
+ // The activity was destroyed/created automatically, populate the grid
+ // of photos with the images loaded by the previous activity
+ final LoadedPhoto[] photos = (LoadedPhoto[]) data;
+ for (LoadedPhoto photo : photos) {
+ addPhoto(photo);
+ }
+ }
+}
+
+
+Be very careful with the object you pass through
+onRetainNonConfigurationChange()
, though. If the object you
+pass is for some reason tied to the Activity/Context, you will leak
+all the views and resources of the activity. This means you should
+never pass a View, a Drawable, an Adapter, etc. Photostream for
+instance extracts the bitmaps from the drawables and pass the bitmaps
+only, not the drawables. Finally, remember that
+onRetainNonConfigurationChange()
should be used only to retain
+data that is expensive to load. Otherwise, keep it simple and let Android
+do everything.
diff --git a/docs/html/resources/articles/future-proofing.jd b/docs/html/resources/articles/future-proofing.jd
new file mode 100644
index 0000000..ee98186
--- /dev/null
+++ b/docs/html/resources/articles/future-proofing.jd
@@ -0,0 +1,89 @@
+page.title=Future-Proofing Your Apps
+@jd:body
+
+It's important to implement your application so that it will not break as new
+versions of the Android platform are loaded onto the users device. The list
+below is based on our observations of five ways that we've seen bad apps fail.
+You can think of these as "anti-patterns" (that is, techniques to avoid) for
+Android development.
+
+If your application uses any of the dubious techniques below, break out
+your IDE and duct tape, spackle, and patch up the app.
+
+Technique to Avoid, #1: Using Internal APIs
+
+Even
+though we've always strongly advised against doing so, some developers
+have chosen to use unsupported or internal APIs. For instance, many
+developers are using the internal brightness control and bluetooth
+toggle APIs that were present in 1.0 and 1.1. A bug -- which was
+fixed in Android 1.5 -- allowed apps to use those APIs without
+requesting permission. As a result, apps that used those APIs broke
+on 1.5. If you've used internal APIs in your apps, you need to update
+your apps to stop doing so.
+
+Technique to Avoid, #2: Directly Manipulating Settings
+
+Strictly speaking this one isn't evil, since this is a change in
+behavior that we made to Android itself. But we made it because some
+developers were doing naughty things: a number of apps were changing
+system settings silently without even notifying the user. For instance,
+some apps turn on GPS without asking the user, and others might turn on
+data roaming.
+
+As a result, applications can no longer directly
+manipulate the values of certain system Settings, even if they
+previously had permission to do so. For instance, apps can no longer
+directly turn on or off GPS. These apps won't crash, but the APIs in
+question now have no effect, and do nothing. Instead, apps will need to
+issue an Intent to launch the appropriate Settings configuration
+screen, so that the user can change these settings manually. For
+details, see the android.provider.Settings.Secure class, which you can
+find in the 1.5_pre SDK documentation (and later). Note that only
+Settings that were moved to the Settings.Secure class are affected.
+Other, less sensitive, settings will continue to have the same behavior
+as in Android 1.1.
+
+Technique to Avoid, #3: Going Overboard with Layouts
+
+Due to changes in the View rendering infrastructure, unreasonably deep
+(more than 10 or so) or broad (more than 30 total) View hierarchies in
+layouts are now likely to cause crashes. This was always a risk for
+excessively complex layouts, but you can think of Android 1.5 as being
+better than 1.1 at exposing this problem. Most developers won't need to
+worry about this, but if your app has very complicated layouts, you'll
+need to put it on a diet. You can simplify your layouts using the more
+advanced layout classes like FrameLayout and TableLayout.
+
+Technique to Avoid, #4: Bad Hardware Assumptions
+
+Android 1.5 includes support for soft keyboards, and there will soon be many
+devices that run Android but do not have physical keyboards. If your
+application assumes the presence of a physical keyboard (such as if you
+have created a custom View that sinks keypress events) you should make
+sure it degrades gracefully on devices that only have soft keyboards.
+For more information on this, keep on eye on this blog as we'll be
+posting more detailed information about handling the new soft keyboards.
+
+Technique to Avoid, #5: Incautious Rotations
+
+Devices running Android 1.5 and later can automatically rotate the screen,
+depending on how the user orients the device. Some 1.5 devices will do
+this by default, and on all others it can be turned on by the user.
+This can sometimes result in unpredictable behavior from applications
+that do their own reorientations (whether using the accelerometer, or
+something else.) This often happens when applications assume that the
+screen can only rotate if the physical keyboard is exposed; if the
+device lacks a physical keyboard, these apps do not expect to be
+reoriented, which is a coding error. Developers should be sure that
+their applications can gracefully handle being reoriented at any time.
+
+Also, apps that use the accelerometer directly to reorient themselves
+sometimes compete with the system doing the same thing, with odd
+results. And finally, some apps that use the accelerometer to detect
+things like shaking motions and that don't lock their orientation to
+portrait or landscape, often end up flipping back and forth between
+orientations. This can be irritating to the user. (You can lock your
+app's orientation to portrait or landscape using the
+android:screenOrientation
attribute in the manifest file.)
+
diff --git a/docs/html/resources/articles/gestures.jd b/docs/html/resources/articles/gestures.jd
new file mode 100644
index 0000000..8711645
--- /dev/null
+++ b/docs/html/resources/articles/gestures.jd
@@ -0,0 +1,211 @@
+page.title=Gestures
+@jd:body
+
+Touch screens are a great way to interact with applications on
+mobile devices. With a touch screen, users can easily tap, drag, fling,
+or slide to quickly perform actions in their favorite applications.
+For app developers. the Android framework makes it's easy to
+recognize simple actions, like a swipe, but it has been more
+difficult to handle complicated gestures, sometimes requiring
+developers to write a lot of code.
+
+That's why we introduced a new gestures API in Android 1.6. This API, located
+in the new package {@link android.gesture}, lets you store, load, draw, and
+recognize gestures. This article will show you how you can use the
+android.gesture
API in your applications. Before going any further,
+you should download the source code
+of the examples.
+
+Creating a gestures library
+
+Android 1.6 and higher SDK platforms include a new application pre-installed
+on the emulator, called Gestures Builder. You can use this application to create
+a set of pre-defined gestures for your own application. It also serves as an
+example of how to let the user define his own gestures in your applications. You
+can find the source code of Gestures Builders in the samples directory of each
+SDK platform. In our example we will use Gestures Builder to generate a set of
+gestures for us (make sure to create an AVD with an SD card image to use
+Gestures Builder.) The screenshot below shows what the application looks like
+after adding a few gestures:
+
+
+
+As you can see, a gesture is always associated with a name. That name is very
+important because it identifies each gesture within your application. The names
+do not have to be unique. Actually it can be very useful to have several
+gestures with the same name to increase the precision of the recognition. Every
+time you add or edit a gesture in the Gestures Builder, a file is generated on
+the emulator's SD card, /sdcard/gestures
. This file contains the
+description of all the gestures, and you will need to package it inside your
+application inside the resources directory, in
+/res/raw
.
+
+Loading the gestures library
+
+Now that you have a set of pre-defined gestures, you must load it inside your
+application. This can be achieved in several ways but the easiest is to use the
+GestureLibraries
class:
+
+mLibrary = GestureLibraries.fromRawResource(this, R.raw.spells);
+if (!mLibrary.load()) {
+ finish();
+}
+
+In this example, the gesture library is loaded from the file
+/res/raw/spells
. You can easily load libraries from other sources,
+like the SD card, which is very important if you want your application to be
+able to save the library; a library loaded from a raw resource is read-only and
+cannot be modified. The following diagram shows the structure of a library:
+
+
+
+Recognizing gestures
+
+To start recognizing gestures in your application, all you have to do
+is add a GestureOverlayView
to your XML layout:
+
+<android.gesture.GestureOverlayView
+ android:id="@+id/gestures"
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1.0" />
+
+Notice that the GestureOverlayView
+is not part of the usual android.widget package. Therefore, you must
+use its fully qualified name. A gesture overlay acts as a simple
+drawing board on which the user can draw his gestures. You can tweak
+several visual properties, like the color and the width of the stroke
+used to draw gestures, and register various listeners to follow what
+the user is doing. The most commonly used listener is
+GestureOverlayView.OnGesturePerformedListener
,
+which fires whenever a user is done drawing a gesture:
+
+GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
+gestures.addOnGesturePerformedListener(this);
+
+When the listener fires, you can ask the GestureLibrary
+to try to recognize the gesture. In return, you will get a list of
+Prediction instances, each with a name - the same name you entered in
+the Gestures Builder - and a score. The list is sorted by descending
+scores; the higher the score, the more likely the associated gesture is
+the one the user intended to draw. The following code snippet
+demonstrates how to retrieve the name of the first prediction:
+
+public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+ ArrayList<prediction> predictions = mLibrary.recognize(gesture);
+
+ // We want at least one prediction
+ if (predictions.size() > 0) {
+ Prediction prediction = predictions.get(0);
+ // We want at least some confidence in the result
+ if (prediction.score > 1.0) {
+ // Show the spell
+ Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
+ }
+ }
+}
+
+In this example, the first prediction is taken into account only if it's
+score is greater than 1.0. The threshold you use is entirely up to you
+but know that scores lower than 1.0 are typically poor matches. And
+this is all the code you need to create a simple application that can
+recognize pre-defined gestures (see the source code of the project
+GesturesDemo):
+
+
+
+Gestures overlay
+
+In the example above, the GestureOverlayView
was used
+as a normal view, embedded inside a LinearLayout
.
+However, as its name suggests, it can also be used as an overlay on top
+of other views. This can be useful to recognize gestures in a game or
+just anywhere in the UI of an application. In the second example,
+called GesturesListDemo, we'll create an overlay on top of a list of
+contacts. We start again in Gestures Builder to create a new set of
+pre-defined gestures:
+
+![](images/gestures_005.png)
+
+And here is what the XML layout looks like:
+
+<android.gesture.GestureOverlayView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/gestures"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:gestureStrokeType="multiple"
+ android:eventsInterceptionEnabled="true"
+ android:orientation="vertical">
+
+ <ListView
+ android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+</android.gesture.GestureOverlayView>
+
+In this application, the gestures view is an overlay on top of a regular
+ListView. The overlay also specifies a few properties that we did not
+need before:
+
+
+gestureStrokeType
: indicates
+whether we want to recognize gestures made of a single stroke or
+multiple strokes. Since one of our gestures is the "+" symbol, we need
+multiple strokes
+eventsInterceptionEnabled
: when
+set to true, this property tells the overlay to steal the events from
+its children as soon as it knows the user is really drawing a gesture.
+This is useful when there's a scrollable view under the overlay, to
+avoid scrolling the underlying child as the user draws his gesture
+orientation
:
+indicates the scroll orientation of the views underneath. In this case
+the list scrolls vertically, which means that any horizontal gestures
+(like action_delete
) can immediately be recognized as a
+gesture. Gestures that start with a vertical stroke must contain at
+least one horizontal component to be recognized. In other words, a
+simple vertical line cannot be recognized as a gesture since it would
+conflict with the list's scrolling.
+
+
+The code used to load and set up the gestures library and overlay is exactly
+the same as before. The only difference is that we now check the name of the
+predictions to know what the user intended to do:
+
+public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+ ArrayList<Prediction> predictions = mLibrary.recognize(gesture);
+ if (predictions.size() > 0 && predictions.get(0).score > 1.0) {
+ String action = predictions.get(0).name;
+ if ("action_add".equals(action)) {
+ Toast.makeText(this, "Adding a contact", Toast.LENGTH_SHORT).show();
+ } else if ("action_delete".equals(action)) {
+ Toast.makeText(this, "Removing a contact", Toast.LENGTH_SHORT).show();
+ } else if ("action_refresh".equals(action)) {
+ Toast.makeText(this, "Reloading contacts", Toast.LENGTH_SHORT).show();
+ }
+ }
+}
+
+The user is now able to draw his gestures on top of the list without
+interfering with the scrolling:
+
+
+
+The overlay even gives visual clues as to whether the gesture is considered
+valid for recognition. In the case of a vertical overlay, for instance,
+a single vertical stroke cannot be recognized as a gesture and is
+therefore drawn with a translucent color:
+
+
+
+It's your turn
+
+Adding support for gestures in your application is easy and can be a valuable
+addition. The gestures API does not even have to be used to recognize complex
+shapes; it will work equally well to recognize simple swipes. We are very
+excited by the possibilities the gestures API offers, and we're eager to see
+what cool applications the community will create with it.
diff --git a/docs/html/resources/articles/glsurfaceview.jd b/docs/html/resources/articles/glsurfaceview.jd
new file mode 100644
index 0000000..57403ea
--- /dev/null
+++ b/docs/html/resources/articles/glsurfaceview.jd
@@ -0,0 +1,268 @@
+page.title=Introducing GLSurfaceView
+@jd:body
+
+
+The {@link android android.opengl.GLSurfaceView} class makes it
+easier for you to use OpenGL ES rendering in your applications by:
+
+
+- Providing the glue code to connect OpenGL ES to the {@link
+android.view.View} system.
+- Providing the glue code to make OpenGL ES work with the {@link
+android.app.Activity} life-cycle.
+- Making it easy to choose an appropriate frame buffer pixel format.
+- Creating and managing a separate rendering thread, to enable smooth
+animation.
+- Providing easy-to-use debugging tools for tracing OpenGL ES API calls and
+checking for errors.
+
+
+GLSurfaceView is a good base for building an application that uses OpenGL ES
+for part or all of its rendering. A 2D or 3D action game would be a good
+candidate, as would a 2D or 3D data visualization application such as Google Maps StreetView.
+
+A simple GLSurfaceView application
+
+Here's the source code to the simplest possible OpenGL ES application:
+
+package com.example.android.apis.graphics;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+
+public class ClearActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mGLView = new GLSurfaceView(this);
+ mGLView.setRenderer(new ClearRenderer());
+ setContentView(mGLView);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGLView.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGLView.onResume();
+ }
+
+ private GLSurfaceView mGLView;
+}
+
+class ClearRenderer implements GLSurfaceView.Renderer {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ // Do nothing special.
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
+ gl.glViewport(0, 0, w, h);
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ }
+}
+
+This program doesn't do much: it clears the screen to black on every frame.
+But it is a complete OpenGL application that correctly implements the
+Android activity life-cycle. It pauses rendering when the activity is
+paused, and resumes it when the activity is resumed. You could use this
+application as the basis for non-interactive demonstration programs.
+Just add more OpenGL calls to the ClearRenderer.onDrawFrame()
method.
+Notice that you don't even need to subclass the GLSurfaceView
view.
+
+The {@link android.opengl.GLSurfaceView.Renderer} interface has three methods:
+
+
+- The
+
onSurfaceCreated()
method is called at the start of rendering, and
+whenever the OpenGL ES drawing context has to be recreated. (The
+drawing context is typically lost and recreated when the activity is
+paused and resumed.) OnSurfaceCreated()
is a good place to create
+long-lived OpenGL resources such as textures.
+- The
onSurfaceChanged()
+method is called when the surface changes size. It's a good place to
+set your OpenGL viewport. You may also want to set your camera here, if
+it's a fixed camera that doesn't move around the scene.
+- The
onDrawFrame()
method is called every frame, and is
+responsible for drawing the scene. You would typically start by calling
+glClear
to clear the framebuffer, followed by other OpenGL ES calls
+to draw the current scene.
+
+
+How about user input?
+
+If you want an interactive application (such as a game), you will typically
+subclass GLSurfaceView
, because that's an easy way of obtaining
+input events. Here's a slightly longer example showing how to do that:
+
+package com.google.android.ClearTest;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.MotionEvent;
+
+public class ClearActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mGLView = new ClearGLSurfaceView(this);
+ setContentView(mGLView);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mGLView.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mGLView.onResume();
+ }
+
+ private GLSurfaceView mGLView;
+}
+
+class ClearGLSurfaceView extends GLSurfaceView {
+ public ClearGLSurfaceView(Context context) {
+ super(context);
+ mRenderer = new ClearRenderer();
+ setRenderer(mRenderer);
+ }
+
+ public boolean onTouchEvent(final MotionEvent event) {
+ queueEvent(new Runnable(){
+ public void run() {
+ mRenderer.setColor(event.getX() / getWidth(),
+ event.getY() / getHeight(), 1.0f);
+ }});
+ return true;
+ }
+
+ ClearRenderer mRenderer;
+}
+
+class ClearRenderer implements GLSurfaceView.Renderer {
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ // Do nothing special.
+ }
+
+ public void onSurfaceChanged(GL10 gl, int w, int h) {
+ gl.glViewport(0, 0, w, h);
+ }
+
+ public void onDrawFrame(GL10 gl) {
+ gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ }
+
+ public void setColor(float r, float g, float b) {
+ mRed = r;
+ mGreen = g;
+ mBlue = b;
+ }
+
+ private float mRed;
+ private float mGreen;
+ private float mBlue;
+}
+
+This application clears the screen for every frame. When you tap on the
+screen, it sets the clear color based on the (x,y) coordinates of your touch
+event. Note the use of queueEvent()
in
+ClearGLSurfaceView.onTouchEvent()
. The queueEvent()
+method is used to safely communicate between the UI thread and the rendering
+thread. If you prefer, you can use some other Java cross-thread communication
+technique, such as synchronized methods on the Renderer
class
+itself. However, queueing events is often the simplest way of dealing with
+cross-thread communication.
+
+Other GLSurfaceView samples
+
+Tired
+of just clearing the screen? You can find more interesting samples in
+the API Demos sample included in the Android SDK. All the OpenGL ES samples have been
+converted to use the GLSurfaceView
view:
+
+
+- GLSurfaceView - a spinning triangle
+- Kube - a cube puzzle demo
+- Translucent GLSurfaceView - shows how to display 3D graphics on a translucent background
+- Textured Triangle - shows how to draw a textured 3D triangle
+- Sprite Text - shows how to draw text into a texture and then composite it into a 3D scene
+- Touch Rotate - shows how to rotate a 3D object in response to user input.
+
+
+Choosing a surface
+
+GLSurfaceView
+helps you choose the type of surface to render to. Different Android
+devices support different types of surfaces, with no common subset.
+This makes it tricky problem to choose the best available surface on
+each device.
+
+By default, GLSurfaceView
tries to find a surface that's as
+close as possible to a 16-bit RGB frame buffer with a 16-bit depth
+buffer. Depending upon your application's needs you may want to change
+this behavior. For example, the Translucent GLSurfaceView sample needs
+an Alpha channel in order to render translucent data. GLSurfaceView
+provides an overloaded setEGLSurfaceChooser()
method to give
+you control over which surface type is chosen:
+
+
+setEGLConfigChooser(boolean needDepth)
+- Choose a config that's closest to R5G6B5 with or without a 16-bit framebuffer
+setEGLConfigChooser(int redSize, int greenSize,int blueSize,
+int alphaSize,int depthSize, int stencilSize)
+- Choose the config with the fewest number of bits per pixel that has at least
+as many bits-per-channel as specified in the constructor.
+setEGLConfigChooser(EGLConfigChooser configChooser)
+- Allow total control over choosing a configuration. You pass in your own
+implementation of
EGLConfigChooser
, which gets to inspect the
+device's capabilities and choose a configuration.
+
+
+Continuous rendering versus render-when-dirty
+
+Most 3D applications, such as games or simulations, are continuously
+animated. But some 3D applications are more reactive: they wait passively until
+the user does something, and then react to it. For those types of applications,
+the default GLSurfaceView
behavior of continuously redrawing the
+screen is a waste of time. If you are developing a reactive application, you can
+call GLSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY)
, which
+turns off the continuous animation. Then you call
+GLSurfaceView.requestRender()
whenever you want to re-render.
+
+Help With debugging
+
+GLSurfaceView
has a handy built-in feature for debugging OpenGL ES
+applications: the GLSurfaceView.setDebugFlags()
method can be used
+to enable logging and/or error checking your OpenGL ES calls. Call this method
+in your GLSurfaceView
's constructor, before calling
+setRenderer()
:
+
+public ClearGLSurfaceView(Context context) {
+ super(context);
+ // Turn on error-checking and logging
+ setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
+ mRenderer = new ClearRenderer();
+ setRenderer(mRenderer);
+}
\ No newline at end of file
diff --git a/docs/html/resources/articles/images/File.png b/docs/html/resources/articles/images/File.png
new file mode 100644
index 0000000..bc5a2b8
Binary files /dev/null and b/docs/html/resources/articles/images/File.png differ
diff --git a/docs/html/resources/articles/images/File_002.png b/docs/html/resources/articles/images/File_002.png
new file mode 100644
index 0000000..39254b30
Binary files /dev/null and b/docs/html/resources/articles/images/File_002.png differ
diff --git a/docs/html/resources/articles/images/JFlubber.png b/docs/html/resources/articles/images/JFlubber.png
new file mode 100644
index 0000000..d95e32b
Binary files /dev/null and b/docs/html/resources/articles/images/JFlubber.png differ
diff --git a/docs/html/resources/articles/images/WikiNotes.png b/docs/html/resources/articles/images/WikiNotes.png
new file mode 100644
index 0000000..d52c4fc
Binary files /dev/null and b/docs/html/resources/articles/images/WikiNotes.png differ
diff --git a/docs/html/resources/articles/images/all_drawables_changed.png b/docs/html/resources/articles/images/all_drawables_changed.png
new file mode 100644
index 0000000..04ec4a2
Binary files /dev/null and b/docs/html/resources/articles/images/all_drawables_changed.png differ
diff --git a/docs/html/resources/articles/images/android.png b/docs/html/resources/articles/images/android.png
new file mode 100644
index 0000000..6dc88cc
Binary files /dev/null and b/docs/html/resources/articles/images/android.png differ
diff --git a/docs/html/resources/articles/images/buttons.png b/docs/html/resources/articles/images/buttons.png
new file mode 100644
index 0000000..8c220b9
Binary files /dev/null and b/docs/html/resources/articles/images/buttons.png differ
diff --git a/docs/html/resources/articles/images/contacts.png b/docs/html/resources/articles/images/contacts.png
new file mode 100644
index 0000000..d8b067d
Binary files /dev/null and b/docs/html/resources/articles/images/contacts.png differ
diff --git a/docs/html/resources/articles/images/correct_drawables.png b/docs/html/resources/articles/images/correct_drawables.png
new file mode 100644
index 0000000..516309b
Binary files /dev/null and b/docs/html/resources/articles/images/correct_drawables.png differ
diff --git a/docs/html/resources/articles/images/ddms_allocation_tracker.png b/docs/html/resources/articles/images/ddms_allocation_tracker.png
new file mode 100644
index 0000000..b9fa0a1
Binary files /dev/null and b/docs/html/resources/articles/images/ddms_allocation_tracker.png differ
diff --git a/docs/html/resources/articles/images/ddms_allocation_trackerl.png b/docs/html/resources/articles/images/ddms_allocation_trackerl.png
new file mode 100644
index 0000000..5ac8d2a
Binary files /dev/null and b/docs/html/resources/articles/images/ddms_allocation_trackerl.png differ
diff --git a/docs/html/resources/articles/images/device.png b/docs/html/resources/articles/images/device.png
new file mode 100644
index 0000000..186b960
Binary files /dev/null and b/docs/html/resources/articles/images/device.png differ
diff --git a/docs/html/resources/articles/images/device_002.png b/docs/html/resources/articles/images/device_002.png
new file mode 100644
index 0000000..4bc3b0c
Binary files /dev/null and b/docs/html/resources/articles/images/device_002.png differ
diff --git a/docs/html/resources/articles/images/gestures.png b/docs/html/resources/articles/images/gestures.png
new file mode 100644
index 0000000..fe8f7cd
Binary files /dev/null and b/docs/html/resources/articles/images/gestures.png differ
diff --git a/docs/html/resources/articles/images/gestures_002.png b/docs/html/resources/articles/images/gestures_002.png
new file mode 100644
index 0000000..b20da98
Binary files /dev/null and b/docs/html/resources/articles/images/gestures_002.png differ
diff --git a/docs/html/resources/articles/images/gestures_003.png b/docs/html/resources/articles/images/gestures_003.png
new file mode 100644
index 0000000..a295939
Binary files /dev/null and b/docs/html/resources/articles/images/gestures_003.png differ
diff --git a/docs/html/resources/articles/images/gestures_004.png b/docs/html/resources/articles/images/gestures_004.png
new file mode 100644
index 0000000..3fe5fb1
Binary files /dev/null and b/docs/html/resources/articles/images/gestures_004.png differ
diff --git a/docs/html/resources/articles/images/gestures_005.png b/docs/html/resources/articles/images/gestures_005.png
new file mode 100644
index 0000000..3efc519
Binary files /dev/null and b/docs/html/resources/articles/images/gestures_005.png differ
diff --git a/docs/html/resources/articles/images/gestures_006.png b/docs/html/resources/articles/images/gestures_006.png
new file mode 100644
index 0000000..399c31d
Binary files /dev/null and b/docs/html/resources/articles/images/gestures_006.png differ
diff --git a/docs/html/resources/articles/images/grid.png b/docs/html/resources/articles/images/grid.png
new file mode 100644
index 0000000..4713de5
Binary files /dev/null and b/docs/html/resources/articles/images/grid.png differ
diff --git a/docs/html/resources/articles/images/ime.png b/docs/html/resources/articles/images/ime.png
new file mode 100644
index 0000000..57f6df1
Binary files /dev/null and b/docs/html/resources/articles/images/ime.png differ
diff --git a/docs/html/resources/articles/images/ime_002.png b/docs/html/resources/articles/images/ime_002.png
new file mode 100644
index 0000000..3ec00b2
Binary files /dev/null and b/docs/html/resources/articles/images/ime_002.png differ
diff --git a/docs/html/resources/articles/images/ime_003.png b/docs/html/resources/articles/images/ime_003.png
new file mode 100644
index 0000000..a3f57bb
Binary files /dev/null and b/docs/html/resources/articles/images/ime_003.png differ
diff --git a/docs/html/resources/articles/images/ime_004.png b/docs/html/resources/articles/images/ime_004.png
new file mode 100644
index 0000000..efeddf0
Binary files /dev/null and b/docs/html/resources/articles/images/ime_004.png differ
diff --git a/docs/html/resources/articles/images/ime_005.png b/docs/html/resources/articles/images/ime_005.png
new file mode 100644
index 0000000..a7394e0
Binary files /dev/null and b/docs/html/resources/articles/images/ime_005.png differ
diff --git a/docs/html/resources/articles/images/ime_006.png b/docs/html/resources/articles/images/ime_006.png
new file mode 100644
index 0000000..0b55c79
Binary files /dev/null and b/docs/html/resources/articles/images/ime_006.png differ
diff --git a/docs/html/resources/articles/images/layouts_comparison_small.png b/docs/html/resources/articles/images/layouts_comparison_small.png
new file mode 100644
index 0000000..0ba4cb8
Binary files /dev/null and b/docs/html/resources/articles/images/layouts_comparison_small.png differ
diff --git a/docs/html/resources/articles/images/list01.png b/docs/html/resources/articles/images/list01.png
new file mode 100644
index 0000000..e1b7fa8
Binary files /dev/null and b/docs/html/resources/articles/images/list01.png differ
diff --git a/docs/html/resources/articles/images/list02.png b/docs/html/resources/articles/images/list02.png
new file mode 100644
index 0000000..7f72a3f
Binary files /dev/null and b/docs/html/resources/articles/images/list02.png differ
diff --git a/docs/html/resources/articles/images/list_fade_1.png b/docs/html/resources/articles/images/list_fade_1.png
new file mode 100644
index 0000000..43013d6
Binary files /dev/null and b/docs/html/resources/articles/images/list_fade_1.png differ
diff --git a/docs/html/resources/articles/images/list_fade_2.png b/docs/html/resources/articles/images/list_fade_2.png
new file mode 100644
index 0000000..160d3ff
Binary files /dev/null and b/docs/html/resources/articles/images/list_fade_2.png differ
diff --git a/docs/html/resources/articles/images/list_fade_3.png b/docs/html/resources/articles/images/list_fade_3.png
new file mode 100644
index 0000000..70dca64
Binary files /dev/null and b/docs/html/resources/articles/images/list_fade_3.png differ
diff --git a/docs/html/resources/articles/images/list_fade_4.png b/docs/html/resources/articles/images/list_fade_4.png
new file mode 100644
index 0000000..7619fca
Binary files /dev/null and b/docs/html/resources/articles/images/list_fade_4.png differ
diff --git a/docs/html/resources/articles/images/merge1.jpg b/docs/html/resources/articles/images/merge1.jpg
new file mode 100644
index 0000000..114eed6
Binary files /dev/null and b/docs/html/resources/articles/images/merge1.jpg differ
diff --git a/docs/html/resources/articles/images/merge2.png b/docs/html/resources/articles/images/merge2.png
new file mode 100644
index 0000000..b4a8d4c
Binary files /dev/null and b/docs/html/resources/articles/images/merge2.png differ
diff --git a/docs/html/resources/articles/images/merge3.png b/docs/html/resources/articles/images/merge3.png
new file mode 100644
index 0000000..61ed983
Binary files /dev/null and b/docs/html/resources/articles/images/merge3.png differ
diff --git a/docs/html/resources/articles/images/merge4.jpg b/docs/html/resources/articles/images/merge4.jpg
new file mode 100644
index 0000000..17b6c20
Binary files /dev/null and b/docs/html/resources/articles/images/merge4.jpg differ
diff --git a/docs/html/resources/articles/images/merge5.png b/docs/html/resources/articles/images/merge5.png
new file mode 100644
index 0000000..289f47e
Binary files /dev/null and b/docs/html/resources/articles/images/merge5.png differ
diff --git a/docs/html/resources/articles/images/mutated_states.png b/docs/html/resources/articles/images/mutated_states.png
new file mode 100644
index 0000000..50518b6
Binary files /dev/null and b/docs/html/resources/articles/images/mutated_states.png differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs.png b/docs/html/resources/articles/images/on-screen-inputs.png
new file mode 100644
index 0000000..b8b3cf7
Binary files /dev/null and b/docs/html/resources/articles/images/on-screen-inputs.png differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_002.png b/docs/html/resources/articles/images/on-screen-inputs_002.png
new file mode 100644
index 0000000..a5d21c7
Binary files /dev/null and b/docs/html/resources/articles/images/on-screen-inputs_002.png differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_003.png b/docs/html/resources/articles/images/on-screen-inputs_003.png
new file mode 100644
index 0000000..81ee257
Binary files /dev/null and b/docs/html/resources/articles/images/on-screen-inputs_003.png differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_004.png b/docs/html/resources/articles/images/on-screen-inputs_004.png
new file mode 100644
index 0000000..651b72a
Binary files /dev/null and b/docs/html/resources/articles/images/on-screen-inputs_004.png differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_005.png b/docs/html/resources/articles/images/on-screen-inputs_005.png
new file mode 100644
index 0000000..75185ff
Binary files /dev/null and b/docs/html/resources/articles/images/on-screen-inputs_005.png differ
diff --git a/docs/html/resources/articles/images/on-screen-inputs_006.png b/docs/html/resources/articles/images/on-screen-inputs_006.png
new file mode 100644
index 0000000..b653d75
Binary files /dev/null and b/docs/html/resources/articles/images/on-screen-inputs_006.png differ
diff --git a/docs/html/resources/articles/images/photostream_landscape.png b/docs/html/resources/articles/images/photostream_landscape.png
new file mode 100644
index 0000000..ad4a0c5
Binary files /dev/null and b/docs/html/resources/articles/images/photostream_landscape.png differ
diff --git a/docs/html/resources/articles/images/photostream_portrait.png b/docs/html/resources/articles/images/photostream_portrait.png
new file mode 100644
index 0000000..3794f63
Binary files /dev/null and b/docs/html/resources/articles/images/photostream_portrait.png differ
diff --git a/docs/html/resources/articles/images/qsb.png b/docs/html/resources/articles/images/qsb.png
new file mode 100644
index 0000000..4e40af1
Binary files /dev/null and b/docs/html/resources/articles/images/qsb.png differ
diff --git a/docs/html/resources/articles/images/qsb_002.png b/docs/html/resources/articles/images/qsb_002.png
new file mode 100644
index 0000000..8c2f772
Binary files /dev/null and b/docs/html/resources/articles/images/qsb_002.png differ
diff --git a/docs/html/resources/articles/images/qsb_003.png b/docs/html/resources/articles/images/qsb_003.png
new file mode 100644
index 0000000..069b6cd
Binary files /dev/null and b/docs/html/resources/articles/images/qsb_003.png differ
diff --git a/docs/html/resources/articles/images/relativelayout_1.png b/docs/html/resources/articles/images/relativelayout_1.png
new file mode 100644
index 0000000..3360ad8
Binary files /dev/null and b/docs/html/resources/articles/images/relativelayout_1.png differ
diff --git a/docs/html/resources/articles/images/relativelayout_2.png b/docs/html/resources/articles/images/relativelayout_2.png
new file mode 100644
index 0000000..8e71bb2
Binary files /dev/null and b/docs/html/resources/articles/images/relativelayout_2.png differ
diff --git a/docs/html/resources/articles/images/relativelayout_3.png b/docs/html/resources/articles/images/relativelayout_3.png
new file mode 100644
index 0000000..16a9767
Binary files /dev/null and b/docs/html/resources/articles/images/relativelayout_3.png differ
diff --git a/docs/html/resources/articles/images/relativelayout_wire_1.png b/docs/html/resources/articles/images/relativelayout_wire_1.png
new file mode 100644
index 0000000..9cb241d
Binary files /dev/null and b/docs/html/resources/articles/images/relativelayout_wire_1.png differ
diff --git a/docs/html/resources/articles/images/relativelayout_wire_2.png b/docs/html/resources/articles/images/relativelayout_wire_2.png
new file mode 100644
index 0000000..4243812
Binary files /dev/null and b/docs/html/resources/articles/images/relativelayout_wire_2.png differ
diff --git a/docs/html/resources/articles/images/relativelayout_wire_3.png b/docs/html/resources/articles/images/relativelayout_wire_3.png
new file mode 100644
index 0000000..04ce1ce
Binary files /dev/null and b/docs/html/resources/articles/images/relativelayout_wire_3.png differ
diff --git a/docs/html/resources/articles/images/search01.png b/docs/html/resources/articles/images/search01.png
new file mode 100644
index 0000000..4160a76
Binary files /dev/null and b/docs/html/resources/articles/images/search01.png differ
diff --git a/docs/html/resources/articles/images/search02.png b/docs/html/resources/articles/images/search02.png
new file mode 100644
index 0000000..6300018
Binary files /dev/null and b/docs/html/resources/articles/images/search02.png differ
diff --git a/docs/html/resources/articles/images/shared_states.png b/docs/html/resources/articles/images/shared_states.png
new file mode 100644
index 0000000..81bec09
Binary files /dev/null and b/docs/html/resources/articles/images/shared_states.png differ
diff --git a/docs/html/resources/articles/images/shelves2.png b/docs/html/resources/articles/images/shelves2.png
new file mode 100644
index 0000000..2de239f
Binary files /dev/null and b/docs/html/resources/articles/images/shelves2.png differ
diff --git a/docs/html/resources/articles/images/text_field.png b/docs/html/resources/articles/images/text_field.png
new file mode 100644
index 0000000..b9dedec
Binary files /dev/null and b/docs/html/resources/articles/images/text_field.png differ
diff --git a/docs/html/resources/articles/images/ui-1.6.png b/docs/html/resources/articles/images/ui-1.6.png
new file mode 100644
index 0000000..bc5a2b8
Binary files /dev/null and b/docs/html/resources/articles/images/ui-1.6.png differ
diff --git a/docs/html/resources/articles/images/ui-1.6_002.png b/docs/html/resources/articles/images/ui-1.6_002.png
new file mode 100644
index 0000000..39254b30
Binary files /dev/null and b/docs/html/resources/articles/images/ui-1.6_002.png differ
diff --git a/docs/html/resources/articles/images/viewstub1.png b/docs/html/resources/articles/images/viewstub1.png
new file mode 100644
index 0000000..2de239f
Binary files /dev/null and b/docs/html/resources/articles/images/viewstub1.png differ
diff --git a/docs/html/resources/articles/images/viewstub2.png b/docs/html/resources/articles/images/viewstub2.png
new file mode 100644
index 0000000..6e6feb9
Binary files /dev/null and b/docs/html/resources/articles/images/viewstub2.png differ
diff --git a/docs/html/resources/articles/images/viewstub3.png b/docs/html/resources/articles/images/viewstub3.png
new file mode 100644
index 0000000..5e793e6
Binary files /dev/null and b/docs/html/resources/articles/images/viewstub3.png differ
diff --git a/docs/html/resources/articles/images/viewstub4.png b/docs/html/resources/articles/images/viewstub4.png
new file mode 100644
index 0000000..cffb9c6
Binary files /dev/null and b/docs/html/resources/articles/images/viewstub4.png differ
diff --git a/docs/html/resources/articles/images/webview.png b/docs/html/resources/articles/images/webview.png
new file mode 100644
index 0000000..92472af
Binary files /dev/null and b/docs/html/resources/articles/images/webview.png differ
diff --git a/docs/html/resources/articles/images/window_background.png b/docs/html/resources/articles/images/window_background.png
new file mode 100644
index 0000000..58f4f7e
Binary files /dev/null and b/docs/html/resources/articles/images/window_background.png differ
diff --git a/docs/html/resources/articles/images/window_background_null.png b/docs/html/resources/articles/images/window_background_null.png
new file mode 100644
index 0000000..83f7b45
Binary files /dev/null and b/docs/html/resources/articles/images/window_background_null.png differ
diff --git a/docs/html/resources/articles/images/window_background_root.png b/docs/html/resources/articles/images/window_background_root.png
new file mode 100644
index 0000000..95a47c0
Binary files /dev/null and b/docs/html/resources/articles/images/window_background_root.png differ
diff --git a/docs/html/resources/articles/index.jd b/docs/html/resources/articles/index.jd
new file mode 100644
index 0000000..3080453
--- /dev/null
+++ b/docs/html/resources/articles/index.jd
@@ -0,0 +1,9 @@
+page.title=Technical Articles
+@jd:body
+
+
+
+ - Using Text-to-Speech
+ - The text-to-speech API lets your application "speak" to users, in any of several languages. This article provides an overview of the TTS API and how you use to add speech capabilities to your application.
+
+
diff --git a/docs/html/resources/articles/layout-tricks-efficiency.jd b/docs/html/resources/articles/layout-tricks-efficiency.jd
new file mode 100644
index 0000000..b7b5761
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-efficiency.jd
@@ -0,0 +1,177 @@
+page.title=Layout Tricks: Creating Efficient Layouts
+@jd:body
+
+The Android UI toolkit offers several layout managers that are
+rather easy to use and, most of the time, you only need the basic
+features of these layout managers to implement a user interface.
+
+Sticking to the basic features is unfortunately not the most efficient
+way to create user interfaces. A common example is the abuse of
+{@link android.widget.LinearLayout}, which leads to a proliferation of
+views in the view hierarchy. Every view — or worse, every layout
+manager — that you add to your application comes at a cost:
+initialization, layout and drawing become slower. The layout pass can be
+especially expensive when you nest several LinearLayout
+that use the {@link android.R.attr#layout_weight weight}
+parameter, which requires the child to be measured twice.
+
+Let's consider a very simple and common example of a layout: a list item
+with an icon on the left, a title at the top and an optional description
+underneath the title. Here is what such an item looks like:
+
+
+
+To clearly understand how the views, one {@link android.widget.ImageView} and
+two {@link android.widget.TextView}, are positioned with respect to each other,
+here is the wireframe of the layout as captured by HierarchyViewer:
+
+
+
+Implementing this layout is straightforward with LinearLayout
.
+The item itself is a horizontal LinearLayout
with an
+ImageView
and a vertical LinearLayout
, which contains
+the two TextView
. Here's the source code of this layout:
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+
+ android:padding="6dip">
+
+ <ImageView
+ android:id="@+id/icon"
+
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:layout_marginRight="6dip"
+
+ android:src="@drawable/icon" />
+
+ <LinearLayout
+ android:orientation="vertical"
+
+ android:layout_width="0dip"
+ android:layout_weight="1"
+ android:layout_height="fill_parent">
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+
+ android:gravity="center_vertical"
+ android:text="My Application" />
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1"
+
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:text="Simple application that shows how to use RelativeLayout" />
+
+ </LinearLayout>
+
+</LinearLayout>
+
+This layout works but can be wasteful if you instantiate it for every list
+item of a {@link android.widget.ListView}. The same layout can be rewritten
+using a single {@link android.widget.RelativeLayout}, thus saving one view, and
+even better one level in view hierarchy, per list item. The implementation of
+the layout with a RelativeLayout
remains simple:
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+
+ android:padding="6dip">
+
+ <ImageView
+ android:id="@+id/icon"
+
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+
+ android:layout_alignParentTop="true"
+ android:layout_alignParentBottom="true"
+ android:layout_marginRight="6dip"
+
+ android:src="@drawable/icon" />
+
+ <TextView
+ android:id="@+id/secondLine"
+
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:layout_toRightOf="@id/icon"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentRight="true"
+
+ android:singleLine="true"
+ android:ellipsize="marquee"
+ android:text="Simple application that shows how to use RelativeLayout" />
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+
+ android:layout_toRightOf="@id/icon"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentTop="true"
+ android:layout_above="@id/secondLine"
+ android:layout_alignWithParentIfMissing="true"
+
+ android:gravity="center_vertical"
+ android:text="My Application" />
+
+</RelativeLayout>
+
+This new implementation behaves exactly the same way as the previous
+implementation, except in one case. The list item we want to display has two
+lines of text: the title and an optional description. When a
+description is not available for a given list item, the application would simply
+set the visibility of the second TextView
to
+{@link android.view.View#GONE}. This works perfectly with the LinearLayout
+implementation but not with the RelativeLayout
version:
+
+![RelativeLayout and description GONE](images/relativelayout_2.png)
+![RelativeLayout and description GONE](images/relativelayout_wire_2.png)
+
+In a RelativeLayout
, views are aligned with their parent, with the
+RelativeLayout
itself, or with other views. For instance, we declared that
+the description is aligned with the bottom of the RelativeLayout
and
+that the title is positioned above the description and anchored to the
+parent's top. With the description GONE, RelativeLayout doesn't know
+where to position the title's bottom edge. To solve this problem, you
+can use a very special layout parameter called
+{@link android.R.attr#layout_alignWithParentIfMissing}.
+
+
+This boolean parameter simply tells RelativeLayout to use its own edges as
+anchors when a constraint target is missing. For instance, if you position a
+view to the right of a GONE view and set alignWithParentIfMissing
+to true
, RelativeLayout
will instead anchor the view
+to its left edge. In our case, using alignWithParentIfMissing
will
+cause RelativeLayout
to align the title's bottom with its own
+bottom. The result is the following:
+
+
+
+
+The
+behavior of our layout is now perfect, even when the description is
+GONE. Even better, the hierarchy is simpler and because we are not
+using LinearLayout's weights it's also more efficient. The difference
+between the two implementations becomes obvious when comparing the view
+hierarchies in HierarchyViewer:
+
+
+
+Again, the difference will be much more important when you use such a layout
+for every item in a ListView for instance. Hopefully this simple
+example showed you that getting to know your layouts is the best way to
+learn how to optimize your UI.
diff --git a/docs/html/resources/articles/layout-tricks-merge.jd b/docs/html/resources/articles/layout-tricks-merge.jd
new file mode 100644
index 0000000..3e165d2
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-merge.jd
@@ -0,0 +1,198 @@
+page.title=Layout Tricks: Merging Layouts
+@jd:body
+
+The articles showed you how to use the <include />
tag in XML layouts, to reuse and share your layout code. This article explains the <merge />
tag and how it complements the <include />
tag.
+
+The <merge />
tag was created for the purpose of
+optimizing Android layouts by reducing the number of levels in view trees. It's
+easier to understand the problem this tag solves by looking at an example. The
+following XML layout declares a layout that shows an image with its title on top
+of it. The structure is fairly simple; a {@link android.widget.FrameLayout} is
+used to stack a {@link android.widget.TextView} on top of an
+{@link android.widget.ImageView}:
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:scaleType="center"
+ android:src="@drawable/golden_gate" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="20dip"
+ android:layout_gravity="center_horizontal|bottom"
+
+ android:padding="12dip"
+
+ android:background="#AA000000"
+ android:textColor="#ffffffff"
+
+ android:text="Golden Gate" />
+
+</FrameLayout>
+
+This layout renders nicely and nothing seems wrong with it:
+
+
+
+Things get more interesting when you inspect the result with HierarchyViewer.
+If you look closely at the resulting tree, you will notice that the
+FrameLayout
defined in our XML file (highlighted in blue below) is
+the sole child of another FrameLayout
:
+
+
+
+Since our FrameLayout
has the same dimension as its parent, by
+the virtue of using the fill_parent
constraints, and does not
+define any background, extra padding or a gravity, it is totally
+useless. We only made the UI more complex for no good reason. But how could
+we get rid of this FrameLayout
? After all, XML documents require a
+root tag and tags in XML layouts always represent view instances.
+
+That's where the <merge />
tag comes in handy. When the
+{@link android.view.LayoutInflater} encounters this tag, it skips it and adds
+the <merge />
children to the <merge />
+parent. Confused? Let's rewrite our previous XML layout by replacing the
+FrameLayout
with <merge />
:
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:scaleType="center"
+ android:src="@drawable/golden_gate" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="20dip"
+ android:layout_gravity="center_horizontal|bottom"
+
+ android:padding="12dip"
+
+ android:background="#AA000000"
+ android:textColor="#ffffffff"
+
+ android:text="Golden Gate" />
+
+</merge>
+
+With this new version, both the TextView
and the
+ImageView
will be added directly to the top-level
+FrameLayout
. The result will be visually the same but the view
+hierarchy is simpler:
+
+
+
+Obviously, using <merge />
works in this case because the
+parent of an activity's content view is always a FrameLayout
. You
+could not apply this trick if your layout was using a LinearLayout
+as its root tag for instance. The <merge />
can be useful in
+other situations though. For instance, it works perfectly when combined with the
+<include />
tag. You can also use <merge
+/>
when you create a custom composite view. Let's see how we can use
+this tag to create a new view called OkCancelBar
which simply shows
+two buttons with customizable labels. You can also download the complete
+source code of this example. Here is the XML used to display this custom
+view on top of an image:
+
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:okCancelBar="http://schemas.android.com/apk/res/com.example.android.merge">
+
+ <ImageView
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ android:scaleType="center"
+ android:src="@drawable/golden_gate" />
+
+ <com.example.android.merge.OkCancelBar
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+
+ android:paddingTop="8dip"
+ android:gravity="center_horizontal"
+
+ android:background="#AA000000"
+
+ okCancelBar:okLabel="Save"
+ okCancelBar:cancelLabel="Don't save" />
+
+</merge>
+
+This new layout produces the following result on a device:
+
+
+
+The source code of OkCancelBar
is very simple because the two
+buttons are defined in an external XML file, loaded using a
+LayoutInflate
. As you can see in the following snippet, the XML
+layout R.layout.okcancelbar
is inflated with the
+OkCancelBar
as the parent:
+
+public class OkCancelBar extends LinearLayout {
+ public OkCancelBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setOrientation(HORIZONTAL);
+ setGravity(Gravity.CENTER);
+ setWeightSum(1.0f);
+
+ LayoutInflater.from(context).inflate(R.layout.okcancelbar, this, true);
+
+ TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.OkCancelBar, 0, 0);
+
+ String text = array.getString(R.styleable.OkCancelBar_okLabel);
+ if (text == null) text = "Ok";
+ ((Button) findViewById(R.id.okcancelbar_ok)).setText(text);
+
+ text = array.getString(R.styleable.OkCancelBar_cancelLabel);
+ if (text == null) text = "Cancel";
+ ((Button) findViewById(R.id.okcancelbar_cancel)).setText(text);
+
+ array.recycle();
+ }
+}
+
+The two buttons are defined in the following XML layout. As you can see, we
+use the <merge />
tag to add the two buttons directly to the
+OkCancelBar
. Each button is included from the same external XML
+layout file to make them easier to maintain; we simply override their id:
+
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+ <include
+ layout="@layout/okcancelbar_button"
+ android:id="@+id/okcancelbar_ok" />
+
+ <include
+ layout="@layout/okcancelbar_button"
+ android:id="@+id/okcancelbar_cancel" />
+</merge>
+
+We have created a flexible and easy to maintain custom view that generates
+an efficient view hierarchy:
+
+
+
+The <merge />
tag is extremely useful and can do wonders
+in your code. However, it suffers from a couple of limitations:
+
+
+<merge />
can only be used as the root tag of an XML layout
+- When inflating a layout starting with a
<merge />
, you must
+specify a parent ViewGroup
and you must set attachToRoot
to
+true
(see the documentation for
+{@link android.view.LayoutInflater#inflate(int, android.view.ViewGroup, boolean)} method)
+
+
diff --git a/docs/html/resources/articles/layout-tricks-reuse.jd b/docs/html/resources/articles/layout-tricks-reuse.jd
new file mode 100644
index 0000000..072ba89
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-reuse.jd
@@ -0,0 +1,67 @@
+page.title=Layout Tricks: Creating Reusable UI Components
+@jd:body
+
+The Android platform offers a wide variety of UI widgets, small
+visual construction blocks that you can glue together to present users with
+complex and useful interfaces. However applications often need higher-level
+visual components. To meet that need, and to do so efficiently, you can
+combine multiple standard widgets into a single, reusable component.
+
+For example, you could create a reusable component that contains a progress
+bar and a cancel button, a panel containing two buttons (positive and negative
+actions), a panel with an icon, a title and a description, and so on. You can
+create UI components easily by writing a custom View
, but you can
+do it even more easily using only XML.
+
+In Android XML layout files, each tag is mapped to an actual class instance
+(the class is always a subclass of {@link android.view.View} The UI toolkit lets
+you also use three special tags that are not mapped to a View
+instance: <requestFocus />
, <merge />
and
+<include />
. This article shows how to use <include
+/>
to create pure XML visual components. For information about how to
+use <merge />
, which can be particularly powerful when
+combined with <include />
see the Merging Layouts
+article.
+
+The <include />
element does exactly what its name
+suggests; it includes another XML layout. Using this tag is straightforward as
+shown in the following example, taken straight from the source code of the Home application
+that ships with Android:
+
+<com.android.launcher.Workspace
+ android:id="@+id/workspace"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+
+ launcher:defaultScreen="1">
+
+ <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
+ <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
+
+</com.android.launcher.Workspace>
+
+In the <include />
only the layout
attribute
+is required. This attribute, without the android
namespace prefix,
+is a reference to the layout file you wish to include. In this example, the same
+layout is included three times in a row. This tag also lets you override a few
+attributes of the included layout. The above example shows that you can use
+android:id
to specify the id of the root view of the included
+layout; it will also override the id of the included layout if one is defined.
+Similarly, you can override all the layout parameters. This means that any
+android:layout_*
attribute can be used with the <include
+/>
tag. Here is an example:
+
+<include android:layout_width="fill_parent" layout="@layout/image_holder" />
+<include android:layout_width="256dip" layout="@layout/image_holder" />
+
+
+This tag is particularly useful when you need to customize only part of your
+UI depending on the device's configuration. For instance, the main layout of
+your activity can be placed in the layout/
directory and can
+include another layout which exists in two flavors, in layout-land/
+and layout-port/
. This allows you to share most of the UI in
+portrait and landscape.
\ No newline at end of file
diff --git a/docs/html/resources/articles/layout-tricks-stubs.jd b/docs/html/resources/articles/layout-tricks-stubs.jd
new file mode 100644
index 0000000..e494a54
--- /dev/null
+++ b/docs/html/resources/articles/layout-tricks-stubs.jd
@@ -0,0 +1,84 @@
+page.title=Layout Tricks: Using ViewStubs
+@jd:body
+
+Sharing and reusing UI components is very easy with Android, thanks to the <include /> tag. Sometimes it's so
+easy to create complex UI constructs that your UI ends up with a large number of
+views, some of which are rarely used. Thankfully, Android offers a very special
+widget called {@link android.view.ViewStub}, which brings you all the benefits
+of the <include />
without polluting your user interface with
+rarely used views.
+
+A ViewStub
is a dumb and lightweight view. It has no dimension,
+it does not draw anything and does not participate in the layout in any way.
+This means that a ViewStub
is very cheap to inflate and very cheap
+to keep in a view hierarchy. A ViewStub
can be best described as a
+lazy include. The layout referenced by a ViewStub
is
+inflated and added to the user interface only when you decide so.
+
+The following screenshot comes from the Shelves application. The main purpose of
+the activity shown in the screenshot is to present the user with a browsable
+list of books:
+
+
+
+The same activity is also used when the user adds or imports new books.
+During such an operation, Shelves shows extra bits of user interface.
+The screenshot below shows the progress bar and cancel button that
+appear at the bottom of the screen during an import:
+
+
+
+Because importing books is not a common operation, at least when compared to
+browsing the list of books, the import panel is originally represented
+by a ViewStub
:
+
+
+
+When the user initiates the import process, the ViewStub
is
+inflated and replaced by the content of the layout file it references:
+
+
+
+To use a ViewStub
, all you need is to specify an
+android:id
attribute, to later inflate the stub, and an
+android:layout
attribute, to reference what layout file
+to include and inflate. A stub lets you use a third attribute,
+android:inflatedId
, which can be used to override the
+id
of the root of the included file. Finally, the layout
+parameters specified on the stub will be applied to the roof of the
+included layout. Here is an example:
+
+<ViewStub
+ android:id="@+id/stub_import"
+ android:inflatedId="@+id/panel_import"
+
+ android:layout="@layout/progress_overlay"
+
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom" />
+
+When you are ready to inflate the stub, simply invoke the
+{@link android.view.ViewStub#inflate()} method. You can also simply change the
+visibility of the stub to {@link android.view.View#VISIBLE} or
+{@link android.view.View#INVISIBLE} and the stub will inflate. Note however that the
+inflate()
method has the benefit of returning the root
+View
of the inflate layout:
+
+((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
+// or
+View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();
+
+It is very important to remember that after the stub is inflated, the stub is
+removed from the view hierarchy. As such, it is unnecessary to keep a
+long-lived reference, for instance in an class instance field, to a
+ViewStub
.
+
+A ViewStub
is a great compromise between ease of programming and
+efficiency. Instead of inflating views manually and adding them at runtime to
+your view hierarchy, simply use a ViewStub
. It's cheap and easy.
+The only drawback of ViewStub
is that it currently does
+not support the <merge />
+tag.
diff --git a/docs/html/resources/articles/listview-backgrounds.jd b/docs/html/resources/articles/listview-backgrounds.jd
new file mode 100644
index 0000000..f4c6998
--- /dev/null
+++ b/docs/html/resources/articles/listview-backgrounds.jd
@@ -0,0 +1,86 @@
+page.title=ListView Backgrounds: An Optimization
+@jd:body
+
+{@link android.widget.ListView} is one of Android's most widely used widgets.
+It is rather easy to use, very flexible, and incredibly powerful.
+ListView
can also be difficult to understand at times.
+
+One of the most common issues with ListView
happens when you try
+to use a custom background. By default, like many Android widgets,
+ListView
has a transparent background which means that you can see
+through the default window's background, a very dark gray
+(#FF191919
with the current dark
theme.) Additionally,
+ListView
enables the fading edges by default, as you can
+see at the top of the following screenshot — the first text item gradually
+fades to black. This technique is used throughout the system to indicate that
+the container can be scrolled.
+
+
+
+The fade effect is implemented using a combination of
+{@link android.graphics.Canvas#saveLayerAlpha(float, float, float, float, int, int) Canvas.saveLayerAlpha()}
+and the {@link android.graphics.PorterDuff.Mode#DST_OUT Porter-Duff Destination Out blending mode}.
+
+Unfortunately, things start to get ugly when you try to use a custom
+background on the ListView
or when you change the window's
+background. The following two screenshots show what happens in an application
+when you change the window's background. The left image shows what the list
+looks like by default and the right image shows what the list looks like during
+a scroll initiated with a touch gesture:
+
+
+
![Dark fade](images/list_fade_2.png)
+
![Dark list](images/list_fade_3.png)
+
+This rendering issue is caused by an optimization of the Android framework
+enabled by default on all instances of ListView
. I mentioned
+earlier that the fade effect is implemented using a Porter-Duff blending mode.
+This implementation works really well but is unfortunately very costly and can
+bring down drawing performance by quite a bit as it requires to capture a
+portion of the rendering in an offscreen bitmap and then requires extra blending
+(which implies readbacks from memory.)
+
+Since ListView
is most of the time displayed on a solid
+background, there is no reason to go down that expensive route. That's why we
+introduced an optimization called the "cache color hint." The cache color hint
+is an RGB color set by default to the window's background color, that is #191919
+in Android's dark theme. When this hint is set, ListView
(actually,
+its base class View
) knows it will draw on a solid background and
+therefore replaces th expensive saveLayerAlpha()/Porter-Duff
+rendering with a simple gradient. This gradient goes from fully transparent to
+the cache color hint value and this is exactly what you see on the image above,
+with the dark gradient at the bottom of the list. However, this still does not
+explain why the entire list turns black during a scroll.
+
+As mentioned before, ListView
has a transparent/translucent
+background by default, and so all default widgets in the Android UI toolkit.
+This implies that when ListView
redraws its children, it has to
+blend the children with the window's background. Once again, this requires
+costly readbacks from memory that are particularly painful during a scroll or a
+fling when drawing happens dozen of times per second.
+
+To improve drawing performance during scrolling operations, the Android
+framework reuses the cache color hint. When this hint is set, the framework
+copies each child of the list in a Bitmap
filled with the hint
+value (assuming that another optimization, called scrolling cache, is
+not turned off). ListView
then blits these bitmaps directly on
+screen and because these bitmaps are known to be opaque, no blending is
+required. Also, since the default cache color hint is #191919
, you
+get a dark background behind each item during a scroll.
+
+To fix this issue, all you have to do is either disable the cache color hint
+optimization, if you use a non-solid color background, or set the hint to the
+appropriate solid color value. You can do this from code (see
+{@link android.widget.AbsListView#setCacheColorHint(int)}) or preferably from
+XML, by using the android:cacheColorHint
attribute. To disable the
+optimization, simply use the transparent color #00000000
. The
+following screenshot shows a list with
+android:cacheColorHint="#00000000"
set in the XML layout file:
+
+
+
+As you can see, the fade works perfectly against the custom wooden
+background. The cache color hint feature is interesting because it
+shows how optimizations can make your life more difficult in
+some situations. In this particular case, however, the benefit of the
+default behavior outweighs the added complexity..
diff --git a/docs/html/resources/articles/live-folders.jd b/docs/html/resources/articles/live-folders.jd
new file mode 100644
index 0000000..be974f4
--- /dev/null
+++ b/docs/html/resources/articles/live-folders.jd
@@ -0,0 +1,168 @@
+page.title=Live Folders
+@jd:body
+
+Live folders, introduced in Android 1.5 (API Level 3), let you display any source of data
+on the Home screen without forcing the user to launch an application. A live
+folder is simply a real-time view of a {@link android.content.ContentProvider}.
+As such, a live folder can be used to display all of the user's contacts or
+bookmarks, email, playlists, an RSS feed, and so on. The possibilities are
+endless!
+
+The platform includes several standard folders for displaying contacts. For
+instance, the screenshot below shows the content of the live folders that
+displays all contacts with a phone number:
+
+
+
+If a contacts sync happens in the background while the user is browsing this live
+folder, the user will see the change happen in real-time. Live folders are not
+only useful, but they are also easy to add to to your application and data.
+
+This articles shows how to add a live folder to an example application called
+Shelves. To better understand how live folders work, you can download the source code of the
+application and modify it by following the instructions below.
+
+To give the user the option to create a new live folder for an application,
+you first need to create a new activity with an intent filter whose action is
+android.intent.action.CREATE_LIVE_FOLDER
. To do so, simply open
+AndroidManifest.xml
and add something similar to this:
+
+<activity
+ android:name=".activity.BookShelfLiveFolder"
+ android:label="BookShelf">
+ <intent-filter>
+ <action android:name="android.intent.action.CREATE_LIVE_FOLDER" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+</activity>
+
+The label and icon of this activity are what the user will see on the Home
+screen when choosing a live folder to create:
+
+
+
+Since you just need an intent filter, it is possible, and sometimes advised,
+to reuse an existing activity. In the case of Shelves, we will create a new
+activity, org.curiouscreature.android.shelves.activity.BookShelfLiveFolder
.
+The role of this activity is to send an Intent
result to Home
+containing the description of the live folder: its name, icon, display mode and
+content URI. The content URI is very important as it describes what
+ContentProvider
will be used to populate the live folder. The code
+of the activity is very simple as you can see here:
+
+public class BookShelfLiveFolder extends Activity {
+ public static final Uri CONTENT_URI = Uri.parse("content://shelves/live_folders/books");
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ final Intent intent = getIntent();
+ final String action = intent.getAction();
+
+ if (LiveFolders.ACTION_CREATE_LIVE_FOLDER.equals(action)) {
+ setResult(RESULT_OK, createLiveFolder(this, CONTENT_URI,
+ "Books", R.drawable.ic_live_folder));
+ } else {
+ setResult(RESULT_CANCELED);
+ }
+
+ finish();
+ }
+
+ private static Intent createLiveFolder(Context context, Uri uri, String name, int icon) {
+ final Intent intent = new Intent();
+
+ intent.setData(uri);
+ intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_NAME, name);
+ intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_ICON,
+ Intent.ShortcutIconResource.fromContext(context, icon));
+ intent.putExtra(LiveFolders.EXTRA_LIVE_FOLDER_DISPLAY_MODE, LiveFolders.DISPLAY_MODE_LIST);
+
+ return intent;
+ }
+}
+
+This activity, when invoked with theACTION_CREATE_LIVE_FOLDER
+intent, returns an intent with a URI,
+content://shelves/live_folders/books
, and three extras to describe
+the live folder. There are other extras and constants you can use and you should
+refer to the documentation of android.provider.LiveFolders
for more
+details. When Home receives this intent, a new live folder is created on the
+user's desktop, with the name and icon you provided. Then, when the user clicks
+on the live folder to open it, Home queries the content provider referenced by
+the provided URI.
+
+Live folders' content providers must obey specific naming rules. The
+Cursor
returned by the query()
method must have at
+least two columns named LiveFolders._ID
and
+LiveFolders.NAME
. The first one is the unique identifier of each
+item in the live folder and the second one is the name of the item. There are
+other column names you can use to specify an icon, a description, the intent to
+associate with the item (fired when the user clicks that item), etc. Again,
+refer to the documentation of android.provider.LiveFolders
for more
+details.
In our example, all we need to do is modify the existing provider
+in Shelves called
+org.curiouscreature.android.shelves.provider.BooksProvider
. First,
+we need to modify the URI_MATCHER
to recognize our
+content://shelves/live_folders/books
content URI:
+
+private static final int LIVE_FOLDER_BOOKS = 4;
+// ...
+URI_MATCHER.addURI(AUTHORITY, "live_folders/books", LIVE_FOLDER_BOOKS);
+
+Then we need to create a new projection map for the cursor. A projection map
+can be used to "rename" columns. In our case, we will replace
+BooksStore.Book._ID
, BooksStore.Book.TITLE
and
+BooksStore.Book.AUTHORS
with LiveFolders._ID
,
+LiveFolders.TITLE
and LiveFolders.DESCRIPTION
:
+
+private static final HashMap<string, string=""> LIVE_FOLDER_PROJECTION_MAP;
+static {
+ LIVE_FOLDER_PROJECTION_MAP = new HashMap<string, string="">();
+ LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders._ID, BooksStore.Book._ID +
+ " AS " + LiveFolders._ID);
+ LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.NAME, BooksStore.Book.TITLE +
+ " AS " + LiveFolders.NAME);
+ LIVE_FOLDER_PROJECTION_MAP.put(LiveFolders.DESCRIPTION, BooksStore.Book.AUTHORS +
+ " AS " + LiveFolders.DESCRIPTION);
+}
+
+Because we are providing a title and a description for each row, Home will
+automatically display each item of the live folder with two lines of text.
+Finally, we implement the query()
method by supplying our
+projection map to the SQL query builder:
+
+public Cursor query(Uri uri, String[] projection, String selection,
+ String[] selectionArgs, String sortOrder) {
+
+ SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
+
+ switch (URI_MATCHER.match(uri)) {
+ // ...
+ case LIVE_FOLDER_BOOKS:
+ qb.setTables("books");
+ qb.setProjectionMap(LIVE_FOLDER_PROJECTION_MAP);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown URI " + uri);
+ }
+
+ SQLiteDatabase db = mOpenHelper.getReadableDatabase();
+ Cursor c = qb.query(db, projection, selection, selectionArgs, null, null, BooksStore.Book.DEFAULT_SORT_ORDER);
+ c.setNotificationUri(getContext().getContentResolver(), uri);
+
+ return c;
+}
+
+You can now compile and deploy the application, go to the Home screen and
+try to add a live folder. You can add a books live folder to your Home screen
+and when you open it, see the list of all of your books, with their
+titles and authors, and all it took was a few lines of code:
+
+
+
+The live folders API is extremely simple and relies only on intents and
+content URI. If you want to see more examples of live folders
+implementation, you can read the source code of the Contacts application and of the Contacts provider.
You can also download the result of our exercise, the modified version of Shelves with live folders support.
\ No newline at end of file
diff --git a/docs/html/resources/articles/on-screen-inputs.jd b/docs/html/resources/articles/on-screen-inputs.jd
new file mode 100644
index 0000000..057325a
--- /dev/null
+++ b/docs/html/resources/articles/on-screen-inputs.jd
@@ -0,0 +1,249 @@
+page.title=Onscreen Input Methods
+@jd:body
+
+
+Starting from Android 1.5, the Android platform offers an Input Method
+Framework (IMF) that lets you create on-screen input methods such as software
+keyboards. This article provide an overview of what Android input method editors
+(IMEs) are and what an application needs to do to work well with them. The IMF
+is designed to support new classes of Android devices, such as those without
+hardware keyboards, so it is important that your application works well with the
+IMF and offers a great experience for users.
+
+What is an input method?
+
+The Android IMF is designed to support a variety of IMEs, including soft
+keyboard, hand-writing recognizers, and hard keyboard translators. Our focus,
+however, will be on soft keyboards, since this is the kind of input method that
+is currently part of the platform.
+
+A user will usually access the current IME by tapping on a text view to
+edit, as shown here in the home screen:
+
+
+
+
+The soft keyboard is positioned at the bottom of the screen over the
+application's window. To organize the available space between the application
+and IME, we use a few approaches; the one shown here is called pan and
+scan, and simply involves scrolling the application window around so that
+the currently focused view is visible. This is the default mode, since it is the
+safest for existing applications.
+
+Most often the preferred screen layout is a resize, where the
+application's window is resized to be entirely visible. An example is shown
+here, when composing an e-mail message:
+
+
+
+
+The size of the application window is changed so that none of it is hidden by
+the IME, allowing full access to both the application and IME. This of course
+only works for applications that have a resizeable area that can be reduced to
+make enough space, but the vertical space in this mode is actually no less than
+what is available in landscape orientation, so very often an application can
+already accommodate it.
+
+The final major mode is fullscreen or extract
+mode. This is used when the IME is too large to reasonably share space
+with the underlying application. With the standard IMEs, you will only
+encounter this situation when the screen is in a landscape orientation,
+although other IMEs are free to use it whenever they desire. In this
+case the application window is left as-is, and the IME simply displays
+fullscreen on top of it, as shown here:
+
+
+
+
+Because the IME is covering the application, it has its own editing area,
+which shows the text actually contained in the application. There are also some
+limited opportunities the application has to customize parts of the IME (the
+"done" button at the top and enter key label at the bottom) to improve the user
+experience.
+
+Basic XML attributes for controlling IMEs
+
+There are a number of things the system does to try to help existing
+applications work with IMEs as well as possible, such as:
+
+
+- Use pan and scan mode by default, unless it can reasonably guess that
+resize mode will work by the existence of lists, scroll views, etc.
+- Analyze the various existing TextView attributes to guess at the kind of
+content (numbers, plain text, etc) to help the soft keyboard display an
+appropriate key layout.
+- Assign a few default actions to the fullscreen IME, such as "next field"
+and "done".
+
+
+There are also some simple things you can do in your application that will
+often greatly improve its user experience. Except where explicitly mentioned,
+these will work in any Android platform version, even those previous to Android
+1.5 (since they will simply ignore these new options).
+
+Specifying each EditText control's input type
+
+The most important thing for an application to do is to use the new
+android:inputType
+attribute on each EditText
. The attribute provides much richer
+information
+about the text content. This attribute actually replaces many existing
+attributes (android:
password
,
+android:
singleLine
,
+android:
numeric
,
+android:
phoneNumber
,
+android:
capitalize
,
+android:
autoText
, and
+android:
editable
). If you specify the older attributes
+and the new android:inputType
attribute, the system uses
+android:inputType
and ignores the others.
+
+The android:inputType
attribute has three pieces:
+
+
+- The class is the overall interpretation of characters. The
+currently supported classes are
text
(plain text),
+number
(decimal number), phone
(phone number), and
+datetime
(a date or time).
+- The variation is a further refinement on the class. In the
+attribute you will normally specify the class and variant together, with the
+class as a prefix. For example,
textEmailAddress
is a text field
+where the user will enter something that is an e-mail address (foo@bar.com) so
+the key layout will have an '@' character in easy access, and
+numberSigned
is a numeric field with a sign. If only the class is
+specified, then you get the default/generic variant.
+- Additional flags can be specified that supply further refinement.
+These flags are specific to a class. For example, some flags for the
+
text
class are textCapSentences
,
+textAutoCorrect
, and textMultiline
.
+
+
+As an example, here is the new EditText for the IM application's message text view:
+
+ <EditText android:id="@+id/edtInput"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:inputType="textShortMessage|textAutoCorrect|textCapSentences|textMultiLine"
+ android:imeOptions="actionSend|flagNoEnterAction"
+ android:maxLines="4"
+ android:maxLength="2000"
+ android:hint="@string/compose_hint"/>
+
+A full description of all of the input types can be found in the
+documentation. It is important to make use of the correct input types that are
+available, so that the soft keyboard can use the optimal keyboard layout for the
+text the user will be entering.
+
+Enabling resize mode and other window features
+
+The second most important thing for your app to do is to specify the overall
+behavior of your window in relation to the input method. The most visible aspect
+of this is controlling resize vs. pan and scan mode, but there are other things
+you can do as well to improve your user experience.
+
+You will usually control this behavior through the
+android:windowSoftInputMode
attribute on each
+<activity>
definition in your
+AndroidManifest.xml
. Like the input type, there are a couple
+different pieces of data that can be specified here by combining them
+together:
+
+
+- The window adjustment mode is specified with either
+
adjustResize
or adjustPan
. It is highly recommended
+that you always specify one or the other.
+- You can further control whether the IME will be shown automatically when
+your activity is displayed and other situations where the user moves to it. The
+system won't automatically show an IME by default, but in some cases it can be
+convenient for the user if an application enables this behavior. You can request
+this with
stateVisible
. There are also a number of other state
+options for finer-grained control that you can find in the documentation.
+
+
+A typical example of this field can be see in the edit contact activity,
+which ensures it is resized and automatically displays the IME for the user:
+
+ <activity name="EditContactActivity"
+ android:windowSoftInputMode="stateVisible|adjustResize">
+ ...
+ </activity>
+
+Note:Starting from Android 1.5 (API Level 3),
+the platform offers a new method,
+{@link android.view.Window#setSoftInputMode(int mode)},
+that non-Activity windows can use to control their behavior. Calling this method
+in your will make your application incompatible with previous versions of the
+Android platform.
+
+Controlling the action buttons
+
+The final customization we will look at is the "action" buttons in the IME.
+There are currently two types of actions:
+
+
+- The enter key on a soft keyboard is typically bound to an action when not
+operating on a mult-line edit text. For example, on the G1 pressing the hard
+enter key will typically move to the next field or the application will
+intercept it to execute an action; with a soft keyboard, this overloading of the
+enter key remains, since the enter button just sends an enter key event.
+- When in fullscreen mode, an IME may also put an additional action button to
+the right of the text being edited, giving the user quick access to a common
+application operation.
+
+
+These options are controlled with the android:imeOptions
+attribute on TextView
. The value you supply here can be any
+combination of:
+
+
+- One of the pre-defined action constants (
actionGo
,
+actionSearch
, actionSend
, actionNext
,
+actionDone
). If none of these are specified, the system will infer
+either actionNext
or actionDone
depending on whether
+there is a focusable field after this one; you can explicitly force no action
+with actionNone
.
+- The
flagNoEnterAction
option tells the IME that the action
+should not be available on the enter key, even if the text itself is
+not multi-line. This avoids having unrecoverable actions like (send) that can be
+accidentally touched by the user while typing.
+- The
flagNoAccessoryAction
removes the action button from the
+text area, leaving more room for text. - The
flagNoExtractUi
+completely removes the text area, allowing the application to be seen behind
+it.
+
+
+The previous IM application message view also provides an example of an
+interesting use of imeOptions
, to specify the send action but not
+let it be shown on the enter key:
+
+android:imeOptions="actionSend|flagNoEnterAction"
+
+APIs for controlling IMEs
+
+For more advanced control over the IME, there are a variety of new APIs you
+can use. Unless special care is taken (such as by using reflection), using these
+APIs will cause your application to be incompatible with previous versions of
+Android, and you should make sure you specify
+android:minSdkVersion="3"
in your manifest. For more information,
+see the documentation for the <uses-sdk> manifest element.
+
+The primary API is the new android.view.inputmethod.InputMethodManager
class, which you can retrieve with Context.getSystemService()
.
+It allows you to interact with the global input method state, such as
+explicitly hiding or showing the current IME's input area.
+
+There are also new window flags controlling input method interaction, which you can control through the existing Window.addFlags()
method and new Window.setSoftInputMode()
method. The PopupWindow
+class has grown corresponding methods to control these options on its
+window. One thing in particular to be aware of is the new WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
constant, which is used to control whether a window is on top of or behind the current IME.
+
+Most of the interaction between an active IME and application is done through the android.view.inputmethod.InputConnection
+class. This is the API an application implement, which an IME calls to
+perform the appropriate edit operations on the application. You won't
+normally need to worry about this, since TextView
provides its own implementation for itself.
+
+There are also a handful of new View
APIs, the most important of these being onCreateInputConnection()
which creates a new InputConnection
for an IME (and fills in an android.view.inputmethod.EditorInfo
+structure with your input type, IME options, and other data); again,
+most developers won't need to worry about this, since TextView takes
+care of it for you.
\ No newline at end of file
diff --git a/docs/html/resources/articles/painless-threading.jd b/docs/html/resources/articles/painless-threading.jd
new file mode 100644
index 0000000..921f4df
--- /dev/null
+++ b/docs/html/resources/articles/painless-threading.jd
@@ -0,0 +1,147 @@
+page.title=Painless Threading
+@jd:body
+
+This article discusses the threading model used by Android applications and how applications can ensure best UI performance by spawning worker threads to handle long-running operations, rather than handling them in the main thread. The article also explains the API that your application can use to interact with Android UI toolkit components running on the main thread and spawn managed worker threads.
+
+The UI thread
+
+When an application is launched, the system creates a thread called
+"main" for the application. The main thread, also called the UI
+thread, is very important because it is in charge of dispatching the
+events to the appropriate widgets, including drawing events.
+It is also the thread where your application interacts with running
+components of the Android UI toolkit.
+
+For instance, if you touch the a button on screen, the UI thread dispatches
+the touch event to the widget, which in turn sets its pressed state and
+posts an invalidate request to the event queue. The UI thread dequeues
+the request and notifies the widget to redraw itself.
+
+This single-thread model can yield poor performance unless your application
+is implemented properly. Specifically, if everything is happening in a single
+thread, performing long operations such as network access or database
+queries on the UI thread will block the whole user interface. No event
+can be dispatched, including drawing events, while the long operation
+is underway. From the user's perspective, the application appears hung.
+Even worse, if the UI thread is blocked for more than a few seconds
+(about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog.
+
+If you want to see how bad this can look, write a simple application
+with a button that invokes Thread.sleep(2000)
in its
+OnClickListener.
+The button will remain in its pressed state for about 2 seconds before
+going back to its normal state. When this happens, it is very easy for
+the user to perceive the application as slow.
+
+To summarize, it's vital to the responsiveness of your application's UI to
+keep the UI thread unblocked. If you have long operations to perform, you should
+make sure to do them in extra threads (background or worker
+threads).
+
+Here's an example of a click listener downloading an image over the
+network and displaying it in an ImageView:
+
+public void onClick(View v) {
+ new Thread(new Runnable() {
+ public void run() {
+ Bitmap b = loadImageFromNetwork();
+ mImageView.setImageBitmap(b);
+ }
+ }).start();
+}
+
+At first, this code seems to be a good solution to your problem, as it does
+not block the UI thread. Unfortunately, it violates the single-threaded model
+for the UI: the Android UI toolkit is not thread-safe and must always
+be manipulated on the UI thread. In this piece of code above, the
+ImageView
is manipulated on a worker thread, which can cause really
+weird problems. Tracking down and fixing such bugs can be difficult and
+time-consuming.
+
+Android offers several ways to access the UI
+thread from other threads. You may already be familiar with some of
+them but here is a comprehensive list:
+
+
+- {@link android.app.Activity#runOnUiThread(java.lang.Runnable) Activity.runOnUiThread(Runnable)}
+- {@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}
+- {@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable, long)}
+- {@link android.os.Handler}
+
+
+You can use any of these classes and methods to correct the previous code example:
+
+public void onClick(View v) {
+ new Thread(new Runnable() {
+ public void run() {
+ final Bitmap b = loadImageFromNetwork();
+ mImageView.post(new Runnable() {
+ public void run() {
+ mImageView.setImageBitmap(b);
+ }
+ });
+ }
+ }).start();
+}
+
+Unfortunately,
+these classes and methods could also tend to make your code more complicated
+and more difficult to read. It becomes even worse when your implement
+complex operations that require frequent UI updates.
+
+To remedy this problem, Android 1.5 and later platforms offer a utility class
+called {@link android.os.AsyncTask}, that simplifies the creation of
+long-running tasks that need to communicate with the user interface.
+
+An AsyncTask
equivalent is also available for applications that
+will run on Android 1.0 and 1.1. The name of the class is UserTask. It offers the
+exact same API and all you have to do is copy its source code in your
+application.
+
+The goal of AsyncTask
is to take care of thread management for
+you. Our previous example can easily be rewritten with
+AsyncTask
:
+
+public void onClick(View v) {
+ new DownloadImageTask().execute("http://example.com/image.png");
+}
+
+private class DownloadImageTask extends AsyncTask<string, void,="" bitmap=""> {
+ protected Bitmap doInBackground(String... urls) {
+ return loadImageFromNetwork(urls[0]);
+ }
+
+ protected void onPostExecute(Bitmap result) {
+ mImageView.setImageBitmap(result);
+ }
+ }
+
+As you can see, AsyncTask
must be used by subclassing
+it. It is also very important to remember that an AsyncTask
+instance has to be created on the UI thread and can be executed only once. You
+can read the
+AsyncTask documentation for a full understanding on how to use this class,
+but here is a quick overview of how it works:
+
+
+
+In addition to the official documentation, you can read several complex examples in the source code of Shelves (ShelvesActivity.java and AddBookActivity.java) and Photostream (LoginActivity.java, PhotostreamActivity.java and ViewPhotoActivity.java). We highly recommend reading the source code of Shelves to see how to persist tasks across configuration changes and how to cancel them properly when the activity is destroyed.
+
+Regardless of whether or not you use AsyncTask,
+always remember these two rules about the single thread model:
+
+
+- Do not block the UI thread, and
+
- Make sure that you access the Android UI toolkit only on the UI thread.
+
+
+AsyncTask
just makes it easier to do both of these things.
diff --git a/docs/html/resources/articles/qsb.jd b/docs/html/resources/articles/qsb.jd
new file mode 100644
index 0000000..1249f21
--- /dev/null
+++ b/docs/html/resources/articles/qsb.jd
@@ -0,0 +1,151 @@
+page.title=Quick Search Box
+@jd:body
+
+
+
+Starting with Android 1.6, the platform includes support for Quick Search
+Box (QSB), a powerful, system-wide search framework. Quick Search Box makes it
+possible for users to quickly and easily find what they're looking for, both on
+their devices and on the web. It suggests content on your device as you type,
+like apps, contacts, browser history, and music. It also offers results from the
+web search suggestions, local business listings, and other info from
+Google, such as stock quotes, weather, and flight status. All of this is
+available right from the home screen, by tapping on Quick Search Box.
+
+What
+we're most excited about with this new feature is the ability for you,
+the developers, to leverage the QSB framework to provide quicker and
+easier access to the content inside your apps. Your apps can provide
+search suggestions that will surface to users in QSB alongside other
+search results and suggestions. This makes it possible for users to
+access your application's content from outside your application—for
+example, from the home screen.
+
+Note: The code fragments in this document are
+related to a sample app called Searchable Dictionary. The app is
+available for Android 1.6 and later platforms.
+
+The story before now: searching within your app
+
+Platform releases versions previous to Android 1.6 already provided a mechanism
+that let you expose search and search suggestions in your app, as described in
+the docs for {@link android.app.SearchManager}. That mechanism has not changed
+and requires the following two things in your
+AndroidManifest.xml
:
+
+1) In your <activity>
, an intent filter, and a reference
+to a searchable.xml
file (described below):
+
+<intent-filter>
+ <action android:name="android.intent.action.SEARCH" />
+ <category android:name="android.intent.category.DEFAULT" />
+</intent-filter>
+
+<meta-data android:name="android.app.searchable"
+ android:resource="@xml/searchable" />
+
+2) A content provider that can provide search suggestions according to the
+URIs and column formats specified by the
+Search Suggestions
+section of the SearchManager docs:
+
+<!-- Provides search suggestions for words and their definitions. -->
+<provider android:name="DictionaryProvider"
+ android:authorities="dictionary"
+ android:syncable="false" />
+
+In the searchable.xml
file, you specify a few things about how
+you want the search system to present search for your app, including the
+authority of the content provider that provides suggestions for the user as they
+type. Here's an example of the searchable.xml
of an Android app
+that provides search suggestions within its own activities:
+
+<searchable xmlns:android="http://schemas.android.com/apk/res/android"
+ android:label="@string/search_label"
+ android:searchSuggestAuthority="dictionary"
+ android:searchSuggestIntentAction="android.intent.action.VIEW">
+</searchable>
+
+Note that the android:searchSuggestAuthority
attribute refers to
+the authority of the content provider we declared in
+AndroidManifest.xml
.
+
+For more details on this, see the
+Searchability Metadata
+section of the of the SearchManager docs.
+
+Including your app in Quick Search Box
+
+
+
+
Searchable Dictionary Sample App
+
Quick Search Box provides a really cool way to make it easier and faster for
+users to access your app's content. To help you get your app started with it,
+we've created a sample app that simply provides access to a small dictionary of
+words in QSB. The app is called Searchable Dictionary, and we encourage you to
+check it
+out.
+
+
+
+In Android 1.6, we added a new attribute to the metadata for searchables:
+android:includeInGlobalSearch
. By specifying this as
+"true"
in your searchable.xml
, you allow QSB to pick
+up your search suggestion content provider and include its suggestions along
+with the rest (if the user enables your suggestions from the system search
+settings).
+
+You should also specify a string value for
+android:searchSettingsDescription
, which describes to users what
+sorts of suggestions your app provides in the system settings for search.
+
+<searchable xmlns:android="http://schemas.android.com/apk/res/android"
+ android:label="@string/search_label"
+ android:searchSettingsDescription="@string/settings_description"
+ android:includeInGlobalSearch="true"
+ android:searchSuggestAuthority="dictionary"
+ android:searchSuggestIntentAction="android.intent.action.VIEW">
+</searchable>
+
+These new attributes are supported only in Android 1.6 and later.
+
+What to expect
+
+The
+first and most important thing to note is that when a user installs an
+app with a suggestion provider that participates in QSB, this new app
+will not be enabled for QSB by default. The user can choose
+to enable particular suggestion sources from the system settings for
+search (by going to "Search" > "Searchable items" in settings).
+
+You
+should consider how to handle this in your app. Perhaps show a notice
+that instructs the user to visit system settings and enable your app's
+suggestions.
+
+Once the user enables your searchable item, the
+app's suggestions will have a chance to show up in QSB, most likely
+under the "more results" section to begin with. As your app's
+suggestions are chosen more frequently, they can move up in the list.
+
+
+
+
+Shortcuts
+
+One
+of our objectives with QSB is to make it faster for users to access the
+things they access most often. One way we've done this is by
+'shortcutting' some of the previously chosen search suggestions, so
+they will be shown immediately as the user starts typing, instead of
+waiting to query the content providers. Suggestions from your app may
+be chosen as shortcuts when the user clicks on them.
+
+For dynamic suggestions that may wish to change their content (or become invalid)
+in the future, you can provide a 'shortcut id'. This tells QSB to query
+your suggestion provider for up-to-date content for a suggestion after
+it has been displayed. For more details on how to manage shortcuts, see
+the Shortcuts section
+within the SearchManager docs.
diff --git a/docs/html/resources/articles/timed-ui-updates.jd b/docs/html/resources/articles/timed-ui-updates.jd
new file mode 100644
index 0000000..863387c
--- /dev/null
+++ b/docs/html/resources/articles/timed-ui-updates.jd
@@ -0,0 +1,149 @@
+page.title=Updating the UI from a Timer
+@jd:body
+
+
+
+Background: While developing my first useful
+(though small) application for Android, which was a port of an existing
+utility I use when podcasting, I needed a way of updating a clock
+displayed on the UI at regular intervals, but in a lightweight and CPU
+efficient way.
+
+Problem: In the original application I used
+java.util.Timer to update the clock, but that class is not such a good
+choice on Android. Using a Timer introduces a new thread into the
+application for a relatively minor reason. Thinking in terms of mobile
+applications often means re-considering choices that you might make
+differently for a desktop application with relatively richer resources
+at its disposal. We would like to find a more efficient way of updating
+that clock.
+
+The Application: The original application is a
+Java Swing and SE application. It is like a stopwatch with a lap timer
+that we use when recording podcasts; when you start the recording, you
+start the stopwatch. Then for every mistake that someone makes, you hit
+the flub button. At the end you can save out the bookmarked mistakes
+which can be loaded into the wonderful
+Audacity
+audio editor as a labels track. You can then see where all of the mistakes
+are in the recording and edit them out.
+
+The article describing it is: http://www.developer.com/java/ent/print.php/3589961
+
+In the original version, the timer code looked like this:
+
+class UpdateTimeTask extends TimerTask {
+ public void run() {
+ long millis = System.currentTimeMillis() - startTime;
+ int seconds = (int) (millis / 1000);
+ int minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ timeLabel.setText(String.format("%d:%02d", minutes, seconds));
+ }
+}
And in the event listener to start this update, the following Timer() instance is used:
+
if(startTime == 0L) {
+ startTime = evt.getWhen();
+ timer = new Timer();
+ timer.schedule(new UpdateTimeTask(), 100, 200);
+}
+
+In particular, note the 100, 200 parameters. The first parameter
+means wait 100 ms before running the clock update task the first time.
+The second means repeat every 200ms after that, until stopped. 200 ms
+should not be too noticeable if the second resolution happens to fall
+close to or on the update. If the resolution was a second, you could
+find the clock sometimes not updating for close to 2 seconds, or
+possibly skipping a second in the counting, it would look odd).
+
+When I ported the application to use the Android SDKs, this code
+actually compiled in Eclipse, but failed with a runtime error because
+the Timer() class was not available at runtime (fortunately, this was
+easy to figure out from the error messages). On a related note, the
+String.format method was also not available, so the eventual solution
+uses a quick hack to format the seconds nicely as you will see.
+
+Fortunately, the role of Timer can be replaced by the
+android.os.Handler class, with a few tweaks. To set it up from an event
+listener:
+
+private Handler mHandler = new Handler();
+
+...
+
+OnClickListener mStartListener = new OnClickListener() {
+ public void onClick(View v) {
+ if (mStartTime == 0L) {
+ mStartTime = System.currentTimeMillis();
+ mHandler.removeCallbacks(mUpdateTimeTask);
+ mHandler.postDelayed(mUpdateTimeTask, 100);
+ }
+ }
+};
+
+A couple of things to take note of here. First, the event doesn't
+have a .getWhen() method on it, which we handily used to set the start
+time for the timer. Instead, we grab the System.currentTimeMillis().
+Also, the Handler.postDelayed() method only takes one time parameter,
+it doesn't have a "repeating" field. In this case we are saying to the
+Handler "call mUpdateTimeTask() after 100ms", a sort of fire and forget
+one time shot. We also remove any existing callbacks to the handler
+before adding the new handler, to make absolutely sure we don't get
+more callback events than we want.
+
+But we want it to repeat, until we tell it to stop. To do this, just
+put another postDelayed at the tail of the mUpdateTimeTask run()
+method. Note also that Handler requires an implementation of Runnable,
+so we change mUpdateTimeTask to implement that rather than extending
+TimerTask. The new clock updater, with all these changes, looks like
+this:
+
+private Runnable mUpdateTimeTask = new Runnable() {
+ public void run() {
+ final long start = mStartTime;
+ long millis = SystemClock.uptimeMillis() - start;
+ int seconds = (int) (millis / 1000);
+ int minutes = seconds / 60;
+ seconds = seconds % 60;
+
+ if (seconds < 10) {
+ mTimeLabel.setText("" + minutes + ":0" + seconds);
+ } else {
+ mTimeLabel.setText("" + minutes + ":" + seconds);
+ }
+
+ mHandler.postAtTime(this,
+ start + (((minutes * 60) + seconds + 1) * 1000));
+ }
+};
+
+and can be defined as a class member field.
+
+The if statement is just a way to make sure the label is set to
+10:06 instead of 10:6 when the seconds modulo 60 are less than 10
+(hopefully String.format() will eventually be available). At the end of
+the clock update, the task sets up another call to itself from the
+Handler, but instead of a hand-wavy 200ms before the update, we can
+schedule it to happen at a particular wall-clock time — the line: start
++ (((minutes * 60) + seconds + 1) * 1000) does this.
+
+All we need now is a way to stop the timer when the stop button
+is pressed. Another button listener defined like this:
+
+OnClickListener mStopListener = new OnClickListener() {
+ public void onClick(View v) {
+ mHandler.removeCallbacks(mUpdateTimeTask);
+ }
+};
+
+will make sure that the next callback is removed when the stop button
+is pressed, thus interrupting the tail iteration.
+
+Handler is actually a better choice than Timer for another reason
+too. The Handler runs the update code as a part of your main thread,
+avoiding the overhead of a second thread and also making for easy
+access to the View hierarchy used for the user interface. Just remember
+to keep such tasks small and light to avoid slowing down the user
+experience.
+
+
diff --git a/docs/html/resources/articles/touch-mode.jd b/docs/html/resources/articles/touch-mode.jd
new file mode 100644
index 0000000..e340062
--- /dev/null
+++ b/docs/html/resources/articles/touch-mode.jd
@@ -0,0 +1,138 @@
+page.title=Touch Mode
+@jd:body
+
+This article explains the touch mode, one of the most
+important principles of Android's UI toolkit.
+
+The touch mode is a state of the view hierarchy that depends solely on the
+user interaction with the phone. By itself, the touch mode is something very
+easy to understand as it simply indicates whether the last user interaction was
+performed with the touch screen. For example, if you are using an
+Android-powered device, selecting a widget with the trackball will take you out
+of touch mode; however, if you touch a button on the screen with your finger,
+you will enter touch mode. When the user is not in touch mode, we talk about the
+trackball mode, navigation mode or keyboard navigation, so do not be surprised
+if you encounter these terms.
+
+There is only one API directly related to touch mode,
+{@link android.view.View#isInTouchMode() View.isInTouchMode()}.
+
+Sounds easy enough, right? Oddly enough, touch mode is deceivingly simple and
+the consequences of entering touch mode are far greater than you might
+think. Let's look at some of the reasons why.
+
+Touch Mode, Selection, and Focus
+
+Designing a UI toolkit for mobile devices is difficult because of the various
+interaction mechanisms they provide. Some devices offer only 12 keys, some have
+a touch screen, some require a stylus, some have both a touch screen and a
+keyboard. Based on the hardware capabilities of the he user can interact with
+your application using different mechanisms, so we had to think very hard about
+all the possible issues that could arise. One issue led us to create the touch
+mode.
+
+Imagine a simple application, ApiDemos
+for example, that shows a list of text items. The user can freely
+navigate through the list using the trackball but also, alternatively, scroll
+and fling the list using the touch screen. The issue in this scenario is
+how to handle the selection properly when the user manipulates the list
+through the touch screen.
+
+In this case, if the user selects an item at the top of the list and then
+flings the list towards the bottom, what should happen to the selection? Should
+it remain on the item and scroll off the screen? What should happen if the user
+then decided to move the selection with the trackball? Or worse, what should
+happen if the user presses the trackball to act upon the currently selected
+item, which is not shown on screen anymore?
+
+After careful consideration, we decided to remove the selection altogether,
+when the user manipulates the UI through the touch screen.
+
+In touch mode, there is no focus and no selection. Any selected item in a
+list of in a grid becomes unselected as soon as the user enters touch
+mode. Similarly, any focused widgets become unfocused when the user
+enters touch mode. The image below illustrates what happens when the
+user touches a list after selecting an item with the trackball.
+
+
+
+
+To
+make things more natural for the user, the framework knows how to
+resurrect the selection/focus whenever the user leaves touch mode. For
+instance, in the example above, if the user were to use the trackball
+again, the selection would reappear on the previously-selected item.
+This is why some developers are confused when they create a custom view
+and start receiving key events only after moving the trackball once:
+their application is in touch mode, and they need to use the trackball
+to exit touch mode and resurrect the focus.
+
+The relationship between touch mode, selection, and focus means you must not
+rely on selection and/or focus to exist in your application. A very common
+problem with new Android developers is to rely on
+{@link android.widget.AdapterView#getSelectedItemPosition() ListView.getSelectedItemPosition()}.
+In touch mode, this method will return
+{@link android.widget.AdapterView#INVALID_POSITION INVALID_POSITION}.
+ You should instead use click listeners (see
+{@link android.widget.AdapterView#setOnItemClickListener(android.widget.AdapterView.OnItemClickListener)})
+or the choice mode (see
+{@link android.widget.ListView#setChoiceMode(int)}).
+
+Focusable in Touch Mode
+
+In general, focus doesn't exist in touch mode. However, focus can exist in
+touch mode in a very special way called focusable. This special mode
+was created for widgets that receive text input, such as
+{@link android.widget.EditText} or, when filtering is enabled,
+{@link android.widget.ListView}. The focusable mode is what lets the user enter text
+inside a text field on the screen, without first selecting it with the trackball
+or their finger.
+
+When a user
+touches the screen, the application will enter touch mode if it wasn't
+in touch mode already. What happens during the transition to
+touch mode depends on what the user touched, and what currently has
+focus. If the user touches a widget that is focusable in touch
+mode, that widget will receive focus. Otherwise, any currently
+focused widget will not retain focus unless it is focusable in touch
+mode. For instance, in the picture below, when the user touches
+the screen, the input text field receives the focus.
+
+
+
+Fousable in touch mode (see
+{@link android.view.View#setFocusableInTouchMode(boolean) View.setFocusableInTouchMode})
+ is a property that you can set yourself, either from code or from XML.
+However, you should use it sparingly and only in very specific situations,
+because it breaks consistency with the normal behavior of the Android UI. A game
+is a good example of an application that could make good use of the focusable in
+touch mode property. MapView, if used in fullscreen as in Google Maps, is
+another good example of where you can use focusable in touch mode correctly.
+
+Below is another example of a focusable in touch mode widget. When the user
+taps an AutoCompleteTextView
suggestion with his finger, the focus
+remains on the input text field:
+
+
+
+
+Developers new to Android often think that focusable in touch mode is the
+solution they need to "fix" the problem of "disappearing" selection/focus. We
+really encourage you to think very hard before using it. If used incorrectly, it
+can make your application behave differently from the rest of the system and
+simply throw off the user's habits. The Android framework contains all the tools
+you need to handle user interactions without using focusable in touch mode. For
+example, instead of trying to make ListView
always keep its
+selection, simply use the appropriate choice mode, as shown in
+{@link android.widget.ListView#setChoiceMode(int)}.
+
+
Touch Mode Cheat Sheet
+
+Do:
+
+- Remain consistent with the core applications
- Use the appropriate feature if you need persistent selection (radio button, check box, the
ListView
choice mode, etc.)
+- Use focusable in touch mode if you write a game
+
+
+Don't:
+- Do not try to keep the focus or selection in touch mode
diff --git a/docs/html/resources/articles/track-mem.jd b/docs/html/resources/articles/track-mem.jd
new file mode 100644
index 0000000..d580e82
--- /dev/null
+++ b/docs/html/resources/articles/track-mem.jd
@@ -0,0 +1,62 @@
+page.title=Tracking Memory Allocations
+@jd:body
+
+Writing efficient mobile applications is not always straightforward. In
+particular, Android applications rely on automatic memory management handled by
+Dalvik's garbage collector, which can sometimes cause performance issues if you
+are not careful with memory allocations.
+
+In a performance-sensitive code path, such as the layout or drawing method of
+a view or the logic code of a game, any allocation comes at a price. After too
+many allocations, the garbage collector will kick in and stop your application
+to let it free some memory. Most of the time, garbage collections happen fast
+enough for you not to notice. However, if a collection happens while you are
+scrolling through a list of items or while you are trying to defeat a foe in a
+game, you may suddenly see a drop in performance/responsiveness of the
+application. It's not unusual for a garbage collection to take 100 to 200 ms.
+For comparison, a smooth animation needs to draw each frame in 16 to 33 ms. If
+the animation is suddenly interrupted for 10 frames, you can be certain that
+your users will notice.
+
+Most of the time, garbage collection occurs because of tons of small,
+short-lived objects and some garbage collectors, like generational garbage
+collectors, can optimize the collection of these objects so that the application
+does not get interrupted too often. The Android garbage collector is
+unfortunately not able to perform such optimizations and the creation of
+short-lived objects in performance critical code paths is thus very costly for
+your application.
+
+To help you avoid frequent garbage collections, the Android SDK ships with a
+very useful tool called allocation tracker. This tool is part of DDMS,
+which you must have already used for debugging purposes. To start using the
+allocation tracker, you must first launch the standalone version of DDMS, which
+can be found in the tools/
directory of the SDK. The version of
+DDMS included in the Eclipse plugin does not offer you ability to use the
+allocation tracker yet.
+
+Once DDMS is running, simply select your application process and then click
+the Allocation Tracker tab. In the new view, click Start
+Tracking and then use your application to make it execute the code paths
+you want to analyze. When you are ready, click Get Allocations. A list
+of allocated objects will be shown in the first table. By clicking on a line you
+can see, in the second table, the stack trace that led to the allocation. Not
+only you will know what type of object was allocated, but also in which thread,
+in which class, in which file and at which line. The following screenshot shows
+the allocations performed by Shelves while scrolling a
+ListView.
+
+
+
+
+
+
+Even though it is not necessary — and sometimes not possible — to
+remove all allocations for your performance critical code paths. the allocation
+tracker will help you identify important issues in your code. For instance, a
+common mistake I have seen in many applications is to create a new
+Paint
object on every draw. Moving the paint into an instance field
+is a simple fix that helps performance a lot. I highly encourage you to peruse
+the Android source code to see how we
+reduce allocations in performance-critical code paths. You will also thus
+discover the APIs Android provide to help you reuse objects.
diff --git a/docs/html/resources/articles/tts.jd b/docs/html/resources/articles/tts.jd
new file mode 100644
index 0000000..e3fad91
--- /dev/null
+++ b/docs/html/resources/articles/tts.jd
@@ -0,0 +1,241 @@
+page.title=Using Text-to-Speech
+@jd:body
+
+Starting with Android 1.6 (API Level 4), the Android platform includes a new
+Text-to-Speech (TTS) capability. Also known as "speech synthesis", TTS enables
+your Android device to "speak" text of different languages.
+
+Before we explain how to use the TTS API itself, let's first review a few
+aspects of the engine that will be important to your TTS-enabled application. We
+will then show how to make your Android application talk and how to configure
+the way it speaks.
+
+Languages and resources
+
+The TTS engine that ships with the Android platform supports a number of
+languages: English, French, German, Italian and Spanish. Also, depending on
+which side of the Atlantic you are on, American and British accents for English
+are both supported.
+
+The TTS engine needs to know which language to speak, as a word like "Paris",
+for example, is pronounced differently in French and English. So the voice and
+dictionary are language-specific resources that need to be loaded before the
+engine can start to speak.
+
+Although all Android-powered devices that support the TTS functionality ship
+with the engine, some devices have limited storage and may lack the
+language-specific resource files. If a user wants to install those resources,
+the TTS API enables an application to query the platform for the availability of
+language files and can initiate their download and installation. So upon
+creating your activity, a good first step is to check for the presence of the
+TTS resources with the corresponding intent:
+
+Intent checkIntent = new Intent();
+checkIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
+startActivityForResult(checkIntent, MY_DATA_CHECK_CODE);
+
+A successful check will be marked by a CHECK_VOICE_DATA_PASS
+result code, indicating this device is ready to speak, after the creation of
+our
+{@link android.speech.tts.TextToSpeech} object. If not, we need to let the user
+know to install the data that's required for the device to become a
+multi-lingual talking machine! Downloading and installing the data is
+accomplished by firing off the ACTION_INSTALL_TTS_DATA intent, which will take
+the user to Android Market, and will let her/him initiate the download.
+Installation of the data will happen automatically once the download completes.
+Here is an example of what your implementation of
+onActivityResult()
would look like:
+
+private TextToSpeech mTts;
+protected void onActivityResult(
+ int requestCode, int resultCode, Intent data) {
+ if (requestCode == MY_DATA_CHECK_CODE) {
+ if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
+ // success, create the TTS instance
+ mTts = new TextToSpeech(this, this);
+ } else {
+ // missing data, install it
+ Intent installIntent = new Intent();
+ installIntent.setAction(
+ TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
+ startActivity(installIntent);
+ }
+ }
+}
+
+In the constructor of the TextToSpeech
instance we pass a
+reference to the Context
to be used (here the current Activity),
+and to an OnInitListener
(here our Activity as well). This listener
+enables our application to be notified when the Text-To-Speech engine is fully
+loaded, so we can start configuring it and using it.
+
+Languages and Locale
+
+At Google I/O 2009, we showed an example of TTS where it was used to speak the result of a
+translation from and to one of the 5 languages the Android TTS engine currently
+supports. Loading a language is as simple as calling for instance:
+
+mTts.setLanguage(Locale.US);
to load and set the language to
+English, as spoken in the country "US". A locale is the preferred way to specify
+a language because it accounts for the fact that the same language can vary from
+one country to another. To query whether a specific Locale is supported, you can
+use isLanguageAvailable()
, which returns the level of support for
+the given Locale. For instance the calls:
+
+mTts.isLanguageAvailable(Locale.UK))
+mTts.isLanguageAvailable(Locale.FRANCE))
+mTts.isLanguageAvailable(new Locale("spa", "ESP")))
+
+will return TextToSpeech.LANG_COUNTRY_AVAILABLE to indicate that the language
+AND country as described by the Locale parameter are supported (and the data is
+correctly installed). But the calls:
+
+mTts.isLanguageAvailable(Locale.CANADA_FRENCH))
+mTts.isLanguageAvailable(new Locale("spa"))
+
+will return TextToSpeech.LANG_AVAILABLE
. In the first example,
+French is supported, but not the given country. And in the second, only the
+language was specified for the Locale, so that's what the match was made on.
+
+Also note that besides the ACTION_CHECK_TTS_DATA
intent to check
+the availability of the TTS data, you can also use
+isLanguageAvailable()
once you have created your
+TextToSpeech
instance, which will return
+TextToSpeech.LANG_MISSING_DATA
if the required resources are not
+installed for the queried language.
+
+Making the engine speak an Italian string while the engine is set to the
+French language will produce some pretty interesting results, but it will
+not exactly be something your user would understand So try to match the
+language of your application's content and the language that you loaded in your
+TextToSpeech
instance. Also if you are using
+Locale.getDefault()
to query the current Locale, make sure that at
+least the default language is supported.
+
+Making your application speak
+
+Now that our TextToSpeech
instance is properly initialized and
+configured, we can start to make your application speak. The simplest way to do
+so is to use the speak()
method. Let's iterate on the following
+example to make a talking alarm clock:
+
+String myText1 = "Did you sleep well?";
+String myText2 = "I hope so, because it's time to wake up.";
+mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, null);
+mTts.speak(myText2, TextToSpeech.QUEUE_ADD, null);
+
+The TTS engine manages a global queue of all the entries to synthesize, which
+are also known as "utterances". Each TextToSpeech
instance can
+manage its own queue in order to control which utterance will interrupt the
+current one and which one is simply queued. Here the first speak()
+request would interrupt whatever was currently being synthesized: the queue is
+flushed and the new utterance is queued, which places it at the head of the
+queue. The second utterance is queued and will be played after
+myText1
has completed.
+
+Using optional parameters to change the playback stream type
+
+On Android, each audio stream that is played is associated with one stream
+type, as defined in
+{@link android.media.AudioManager android.media.AudioManager}. For a talking
+alarm clock, we would like our text to be played on the
+AudioManager.STREAM_ALARM
stream type so that it respects the alarm
+settings the user has chosen on the device. The last parameter of the speak()
+method allows you to pass to the TTS engine optional parameters, specified as
+key/value pairs in a HashMap. Let's use that mechanism to change the stream type
+of our utterances:
+
+HashMap<String, String> myHashAlarm = new HashMap();
+myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
+ String.valueOf(AudioManager.STREAM_ALARM));
+mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
+mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);
+
+Using optional parameters for playback completion callbacks
+
+Note that speak()
calls are asynchronous, so they will return
+well before the text is done being synthesized and played by Android, regardless
+of the use of QUEUE_FLUSH
or QUEUE_ADD
. But you might
+need to know when a particular utterance is done playing. For instance you might
+want to start playing an annoying music after myText2
has finished
+synthesizing (remember, we're trying to wake up the user). We will again use an
+optional parameter, this time to tag our utterance as one we want to identify.
+We also need to make sure our activity implements the
+TextToSpeech.OnUtteranceCompletedListener
interface:
+
+mTts.setOnUtteranceCompletedListener(this);
+myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_STREAM,
+ String.valueOf(AudioManager.STREAM_ALARM));
+mTts.speak(myText1, TextToSpeech.QUEUE_FLUSH, myHashAlarm);
+myHashAlarm.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
+ "end of wakeup message ID");
+// myHashAlarm now contains two optional parameters
+mTts.speak(myText2, TextToSpeech.QUEUE_ADD, myHashAlarm);
+
+And the Activity gets notified of the completion in the implementation
+of the listener:
+
+public void onUtteranceCompleted(String uttId) {
+ if (uttId == "end of wakeup message ID") {
+ playAnnoyingMusic();
+ }
+}
+
+File rendering and playback
+
+While the speak()
method is used to make Android speak the text
+right away, there are cases where you would want the result of the synthesis to
+be recorded in an audio file instead. This would be the case if, for instance,
+there is text your application will speak often; you could avoid the synthesis
+CPU-overhead by rendering only once to a file, and then playing back that audio
+file whenever needed. Just like for speak()
, you can use an
+optional utterance identifier to be notified on the completion of the synthesis
+to the file:
+
+HashMap<String, String> myHashRender = new HashMap();
+String wakeUpText = "Are you up yet?";
+String destFileName = "/sdcard/myAppCache/wakeUp.wav";
+myHashRender.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, wakeUpText);
+mTts.synthesizeToFile(wakuUpText, myHashRender, destFileName);
+
+Once you are notified of the synthesis completion, you can play the output
+file just like any other audio resource with
+{@link android.media.MediaPlayer android.media.MediaPlayer}.
+
+But the TextToSpeech
class offers other ways of associating
+audio resources with speech. So at this point we have a WAV file that contains
+the result of the synthesis of "Wake up" in the previously selected language. We
+can tell our TTS instance to associate the contents of the string "Wake up" with
+an audio resource, which can be accessed through its path, or through the
+package it's in, and its resource ID, using one of the two
+addSpeech()
methods:
+
+mTts.addSpeech(wakeUpText, destFileName);
+
+This way any call to speak() for the same string content as
+wakeUpText
will result in the playback of
+destFileName
. If the file is missing, then speak will behave as if
+the audio file wasn't there, and will synthesize and play the given string. But
+you can also take advantage of that feature to provide an option to the user to
+customize how "Wake up" sounds, by recording their own version if they choose
+to. Regardless of where that audio file comes from, you can still use the same
+line in your Activity code to ask repeatedly "Are you up yet?":
+
+mTts.speak(wakeUpText, TextToSpeech.QUEUE_ADD, myHashAlarm);
+
+When not in use...
The text-to-speech functionality relies on a
+dedicated service shared across all applications that use that feature. When you
+are done using TTS, be a good citizen and tell it "you won't be needing its
+services anymore" by calling mTts.shutdown()
, in your Activity
+onDestroy()
method for instance.
+
+Conclusion
+
+Android now talks, and so can your apps. Remember that in order for
+synthesized speech to be intelligible, you need to match the language you select
+to that of the text to synthesize. Text-to-speech can help you push your app in
+new directions. Whether you use TTS to help users with disabilities, to enable
+the use of your application while looking away from the screen, or simply to
+make it cool, we hope you'll enjoy this new feature.
\ No newline at end of file
diff --git a/docs/html/resources/articles/ui-1.5.jd b/docs/html/resources/articles/ui-1.5.jd
new file mode 100644
index 0000000..c10cf52
--- /dev/null
+++ b/docs/html/resources/articles/ui-1.5.jd
@@ -0,0 +1,48 @@
+page.title=UI Framework Changes in Android 1.5
+@jd:body
+
+
+Android 1.5 offers a different default look for
+the Android UI framework, in relation to Android 1.0 and 1.1. The
+screenshots below show the same activity (creating a new contact) on
+Android 1.1 and Android 1.5:
+
+
+
+You
+can see in this example that the buttons and checkboxes have a new
+appearance. Even though these changes do not affect binary nor source
+compatibility, they might still break the UI of your apps. As part of
+the UI refresh, the minimum size of some of the widgets has changed.
+For instance, Android 1.1 buttons have a minimum size of 44x48 pixels
+whereas Android 1.5 buttons now have a minimum size of 24x48 pixels.
+The image below compares the sizes of Android 1.1 buttons with Android
+1.5 buttons:
+
+
+
+If you rely on the button's minimum size, then the layout of your application
+may not be the same in Android 1.5 as it was in Android 1.1 because of this
+change. This would happen for instance if you created a grid of buttons using
+LinearLayout
and relying on the minimum size yielded by
+wrap_content
to align the buttons properly:
+
+
+
+This layout could easily be fixed by using the
+android:layout_weight
attribute or by replacing the
+LinearLayout
containers with a TableLayout
.
+
+This example is probably the worst-case UI issue you may encounter when
+running your application on Android 1.5. Other changes introduced in Android
+1.5, especially bug fixes in the layout views, may also impact your
+application—especially if it is relying on faulty/buggy behavior of the UI
+framework.
+
+If you encounter issues when running your application on Android 1.5, please
+join us on the Android
+developer groups or IRC so that we and the
+Android community can help you fix your application.
+
+Happy coding!
diff --git a/docs/html/resources/articles/ui-1.6.jd b/docs/html/resources/articles/ui-1.6.jd
new file mode 100644
index 0000000..10cb524
--- /dev/null
+++ b/docs/html/resources/articles/ui-1.6.jd
@@ -0,0 +1,130 @@
+page.title=UI Framework Changes in Android 1.6
+@jd:body
+
+Android 1.6 introduces numerous enhancements and bug fixes in the UI
+framework. This article highlights two improvements in particular: more flexible
+and robust RelativeLayout and easier click listeners.
+
+More flexible, more robust RelativeLayout
+
+RelativeLayout is the most versatile layout offered by the Android UI toolkit
+and can be successfully used to reduce the number of views created by your
+applications. This layout used to suffer from various bugs and limitations,
+sometimes making it difficult to use without having some knowledge of its
+implementation. To make your life easier, Android 1.6 comes with a revamped
+RelativeLayout.
+
+This new implementation not only fixes all known bugs in
+RelativeLayout but also addresses its major limitation: the
+fact that views had to be declared in a particular order. Consider the following
+XML layout:
+
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="64dip"
+ android:padding="6dip">
+
+ <TextView
+ android:id="@+id/band"
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:layout_below="@+id/track"
+ android:layout_alignLeft="@id/track"
+ android:layout_alignParentBottom="true"
+
+ android:gravity="top"
+ android:text="The Airborne Toxic Event" />
+
+ <TextView
+ android:id="@id/track"
+ android:layout_marginLeft="6dip"
+ android:layout_width="fill_parent"
+ android:layout_height="26dip"
+
+ android:layout_toRightOf="@+id/artwork"
+
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="bottom"
+ android:text="Sometime Around Midnight" />
+
+ <ImageView
+ android:id="@id/artwork"
+ android:layout_width="56dip"
+ android:layout_height="56dip"
+ android:layout_gravity="center_vertical"
+
+ android:src="@drawable/artwork" />
+
+</RelativeLayout>
+
+This code builds a very simple layout—an image on the left with two lines of
+text stacked vertically. This XML layout is perfectly fine and contains no
+errors. Unfortunately, Android 1.5's RelativeLayout is incapable of rendering it
+correctly, as shown in the screenshot below.
+
+
+
+The problem is that this layout uses forward references. For instance, the
+"band" TextView is positioned below the "track" TextView but "track" is declared
+after "band" and, in Android 1.5, RelativeLayout does not know how to handle
+this case. Now look at the exact same layout running on Android 1.6:
+
+
+
+As you can see Android 1.6 is now better able to handle forward reference.
+The result on screen is exactly what you would expect when writing the
+layout.
+
+Easier click listeners
+
+Setting up a click listener on a button is very common task, but
+it requires quite a bit of boilerplate code:
+
+findViewById(R.id.myButton).setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ // Do stuff
+ }
+});
+
+One way to reduce the amount of boilerplate is to share a single click
+listener between several buttons. While this technique reduces the
+number of classes, it still requires a fair amount of code and it still
+requires giving each button an id in your XML layout file:
+
+View.OnClickListener handler = View.OnClickListener() {
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.myButton: // doStuff
+ break;
+ case R.id.myOtherButton: // doStuff
+ break;
+ }
+ }
+}
+
+findViewById(R.id.myButton).setOnClickListener(handler);
+findViewById(R.id.myOtherButton).setOnClickListener(handler);
+
+With Android 1.6, none of this is necessary. All you have to do is
+declare a public method in your Activity to handle the click
+(the method must have one View argument):
+
+class MyActivity extends Activity {
+ public void myClickHandler(View target) {
+ // Do stuff
+ }
+}
+
+And then reference this method from your XML layout:
+
+<Button android:onClick="myClickHandler" />
+
+This new feature reduces both the amount of Java and XML you have to write,
+leaving you more time to concentrate on your application.
+
+The Android team is committed to helping you write applications in the
+easiest and most efficient way possible. We hope you find these improvements
+useful and we're excited to see your applications on Android Market.
diff --git a/docs/html/resources/articles/using-webviews.jd b/docs/html/resources/articles/using-webviews.jd
new file mode 100644
index 0000000..3a1f34c
--- /dev/null
+++ b/docs/html/resources/articles/using-webviews.jd
@@ -0,0 +1,61 @@
+page.title=Using WebViews
+@jd:body
+
+A small application called WebViewDemo shows how you can add web content to your
+application. You can find it in the apps-for-android project.
+This application demonstrates how you can embed a {@link android.webkit.WebView}
+into an activity and also how you can have two way communication between your
+application and the web content.
+
+A
+WebView uses the same rendering and JavaScript engine as the browser,
+but it runs under the control of your application. The WebView can be
+full screen or you can mix it with other Views. The content for your
+WebView can come from anywhere. The WebView can download content from
+the web, or it can come from local files stored in your assets
+directory. The content can even be dynamically generated by your
+application code. For this example, the HTML comes from a local file
+called demo.html.
+
+This application does not do very much: when you click on the
+android, he raises his arm.
+
+
+
+This
+could, of course, easily be accomplished with a little bit of
+JavaScript. Instead, though, WebViewDemo takes a slightly more
+complicated path to illustrate two very powerful features of WebView.
+
+First,
+JavaScript running inside the WebView can call out to code in your
+Activity. You can use this to have your JavaScript trigger actions like
+starting a new activity, or it can be used to fetch data from a
+database or {@link android.content.ContentProvider}. The API for this
+is very simple: just call the
+{@link android.webkit.WebView#addJavascriptInterface(java.lang.Object, java.lang.String) addJavascriptInterface()}
+method on your WebView. You pass an object whose methods you want to
+expose to JavaScript and the name to use when making calls. You can see
+the exact syntax in WebViewDemo.
+java. Here we are making our DemoJavascriptInterface object available to
+JavaScript where it will be called "window.demo".
+
+Second, your Activity can invoke JavaScript methods. All you have to do
+is call the {@link android.webkit.WebView#loadUrl(java.lang.String) loadUrl}
+method with the appropriate JavaScript call:
+
+mWebView.loadUrl("javascript:wave()");
+
+Our WebViewDemo uses both techniques: when you click on the
+android, it calls out to the activity, which then turns around and calls back
+into the JavaScript. WebViews are very powerful, and they may be a valuable tool
+to help you build your application – especially if you already have a lot of
+HTML content. As it happens, we've used exactly this approach in some of the
+applications we've written.
diff --git a/docs/html/resources/articles/wikinotes-intents.jd b/docs/html/resources/articles/wikinotes-intents.jd
new file mode 100644
index 0000000..bc64544
--- /dev/null
+++ b/docs/html/resources/articles/wikinotes-intents.jd
@@ -0,0 +1,255 @@
+page.title=WikiNotes: Routing Intents
+@jd:body
+
+
+In the Linkify! article, we talked about
+using Linkify to turn wiki words (those that match a regular expression that we
+have defined) into a content:
URI and defining a path to data that
+matched a note belonging to that wiki word. As an example, a matching word like
+ToDoList
would be turned into a URI such as
+content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList
+
and then acted upon using the VIEW action from the Linkify class.
+
+This article examines how the Android system takes this combination of
+VIEW
action and content:
URI and finds the correct
+activity to fire in order to do something with the data. It will also explain
+how the other default links created by Linkify, such as web URLs and telephone
+numbers, also result in the correct activity to handle that data type being
+fired. Finally, this article will start to examine the custom
+ContentProvider
that has been created to handle WikiNotes data. The
+full description of the ContentProvider and what it does will span a couple more
+articles as well, because there is a lot to cover.
+
+The Linkify-calls-intent Workflow
+
+At a high level, the steps for Linkify to invoke an intent, and for the
+resulting activity (if any) to handle it, look like this:
+
+
+ - Linkify is invoked on a TextView to turn matching text patterns into Intent links.
+ - Linkify takes over monitoring for those Intent links being selected by the user.
+ - When the user selects a link, Linkify calls the VIEW action using the content: URI associated with the link.
+ - Android takes the content: URI that represents the data, and looks for a
+ContentProvider registered in the system that matches the URI.
+ - If a match is found, Android queries the ContentProvider using the URI,
+and asks what MIME type the data that will be returned from the URI is.
+ - Android then looks for an activity registered in the system with an
+intent-filter that matches both the VIEW action, and the MIME type for
+the data represented by the content: URI.
+ - Assuming a match is found, Linkify then invokes the intent for
+the URI, at which point the activity takes over, and is handed
+the content: URI.
+ - The activity can then use the URI to retrieve the data and act on
+it.
+
+
+This is actually a simpler process than it
+sounds, and it is quite lightweight as well. Perhaps a more
+understandable statement about how it works might be:
+
+Linkify is used to turn matching text into hot-links. When the user
+selects a hot-link, Android takes the data locator represented by the
+hot-link and looks for a data handler for that data locator. If it
+finds one, it asks for what type of data is returned for that locator.
+It then looks for something registered with the system that handles
+that type of data for the VIEW action, and starts it, including the
+data locator in the request.
+
+The real key here is the MIME type. MIME stands for Multipurpose Internet Mail
+Extensions — a standard for sending attachments over email. The MIME
+type (which is the part Android uses) is a way of describing certain kinds of
+data. That type is then used to look for an Activity that can do something with
+that data type. In this way, ContentProviders and Activities (or other
+IntentReceivers) are decoupled, meaning that a given Content URI might have a
+different ContentProvider to handle it, but could still use the same MIME type
+meaning that the same activity could be called upon to handle the resulting
+data.
+
+Linkify on a wiki word
+
+Using the above workflow, let's take a look at exactly how the process
+works in WikiNotes for Android:
+
+First, Linkify is used to turn text matching the wiki word regular expression
+into a link that provides a Content URI for that wiki word, for example
+content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList
.
+
+When the user clicks on the wiki word link, Linkify invokes the VIEW
+action on the Content URI. At this point, the Android system takes over
+getting the Intent request to the correct activity.
+
+Next, Android looks for a ContentProvider that has been registered
+with the system to handle URIs matching our Content URI format.
+
+In our case, we have a definition inside
+our application's AndroidManifest.xml
+file that reads:
+
+<provider name="com.google.android.wikinotes.db.WikiNotesProvider"
+ android:authorities="com.google.android.wikinotes.db.wikinotes" />
+
+This establishes that we have a ContentProvider defined in our application
+that provides the "root authority":
+com.google.android.wikinotes.db.wikinotes
. This is the first part
+of the Content URI that we create for a wiki word link. Root Authority is just
+another way of thinking about a descriptor that is registered with Android to
+allow requests for certain URLs to be routed to the correct class.
+
+So, the whole definition is that a class called
+com.google.android.wikinotes.db.WikiNotesProvider
is registered
+with the system as able to handle the
+com.google.android.wikinotes.db.wikinotes
root authority (i.e. URIs
+starting with that identifier).
+
+From here, Android takes the rest of the URI and presents it to that
+ContentProvider. If you look at the
+WikiNotesProvider
+class and scroll to the very bottom, in the static block there, you can see
+the pattern definitions to match the rest of the URL.
+
+In particular, take a look at the two lines:
+
+URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes", NOTES);
+URI_MATCHER.addURI(WikiNote.WIKINOTES_AUTHORITY, "wikinotes/*", NOTE_NAME);
+
+These are the definitions of URIs that our ContentProvider recognizes and can
+handle. The first recognizes a full URI of
+content://com.google.android.wikinotes.db.wikinotes/wikinotes
and
+associates that with a constant called NOTES. This is used elsewhere in the
+ContentProvider to provide a list of all of the wiki notes in the database when
+the URI is requested.
+
+The second line uses a wildcard — '*' — to match a request of the
+form that Linkify will create, e.g.
+content://com.google.android.wikinotes.db.wikinotes/wikinotes/ToDoList
+
. In this example, the * matches the ToDoList part of the URI and is
+available to the handler of the request, so that it can fish out the matching
+note for ToDoList and return it as the data. This also associates that match
+with a constant called NOTE_NAME, which again is used as an identifier elsewhere
+in the ContentProvider.
+
+The other matches in this static block are related to forms of
+searching that have been implemented in the WikiNotes for Android
+application, and will be covered in later articles. Likewise, how the
+data is obtained from this matching pattern will be the subject of the
+next article.
+
+For right now we are concerned with the MIME type for the URI. This is
+defined in the getType()
method also in the
+WikiNotesProvider
+class (about halfway through the file). Take a quick look at this. The key
+parts for now are:
+
+case NOTES:
+ return "vnd.android.cursor.dir/vnd.google.wikinote";
+
+and
+
+case NOTE_NAME:
+ return "vnd.android.cursor.item/vnd.google.wikinote";
+
+These are the same constant names we defined in our pattern
+matchers. In the first case, that of the all notes URI, the MIME type
+returned is vnd.android.cursor.dir/vnd.google.wikinote
+which is like saying an Android list (dir) of Google wiki notes (the
+vnd bit is MIME-speak for "vendor specific definition"). Likewise, in
+the case of a NOTE_NAME match, the MIME type returned is
+vnd.android.cursor.item/vnd.google.wikinote
which is
+like saying an Android item of Google wiki notes.
+
+Note that if you define your own MIME data types like this, the
+vnd.android.cursor.dir
and vnd.android.cursor.item
+categories should be retained, since they have meaning to the Android
+system, but the actual item types should be changed to reflect your
+particular data type.
+
+So far Android has been able to find a ContentProvider that handles
+the Content URI supplied by the Linkify Intent call, and has queried
+the ContentProvider to find out the MIME types for that URI. The final
+step is to find an activity that can handle the VIEW action for that
+MIME type. Take a look in the the
+AndroidManifest.xml file
+again. Inside the WikiNotes activity definition, you will see:
+
+<intent-filter>
+ <action name="android.intent.action.VIEW"/>
+ <category name="android.intent.category.DEFAULT"/>
+ <category name="android.intent.category.BROWSABLE"/>
+ <data mimetype="vnd.android.cursor.item/vnd.google.wikinote"/>
+</intent-filter>
+
+This is the correct combination of matches for the VIEW action on a
+WikiNote type that is requested from the LINKIFY class. The DEFAULT
+category indicates that the WikiNotes activity should be treated as a
+default handler (a primary choice) for this kind of data, and the
+BROWSABLE category means it can be invoked from a "browser", in this
+case the marked-up Linkified text.
+
+Using this information, Android can match up the VIEW action request
+for the WikiNotes data type with the WikiNotes activity, and can then
+use the WikiNotes activity to handle the request.
+
+Why do it like this?
+
+It's quite a trip through the system, and there is a lot to absorb
+here, but this is one of the main reasons I wanted to write WikiNotes
+in the first place. If you follow and understand the steps here, you'll
+have a good grasp of the whole Intents mechanism in Android, and how it
+helps loosely coupled activities cooperate to get things done.
+
+In this case, we could have found another way to detect wiki words
+based on a regular expression, and maybe written our own handler to
+intercept clicks within the TextView and dig out the right data and
+display it. This would seem to accomplish the same functionality just
+as easily as using intents, so what is the advantage to using the full
+Intents mechanism?
+
+In fact there are several advantages:
+
+The most obvious is that because we are using the standard Intent
+based approach, we are not limited to just linking and navigating to
+other wiki notes. We get similar behavior to a number of other data
+types as well. For example, a telephone number or web URL in a wiki
+note will be marked up by Linkify, and using this same mechanism (VIEW
+action on the linked data type) the browser or dialer activities will
+be automatically fired.
+
+It also means that each operation on a wiki note can be treated as a
+separate life cycle by our activity. We are not dealing with swapping
+data in and out of an existing activity - each activity works on a
+particular wiki note and that's all you have to worry about.
+
+Another advantage is that we now have a public activity to handle
+VIEW actions in WikiNotes no matter where the request comes from.
+Another application could request to view a wiki note (perhaps without
+even knowing what kind of data it is) and our activity could start up
+and handle it.
+
+The backstack is automatically maintained for you too. As you
+forward navigate through WikiNotes, Android maintains the history of
+notes visited, and so when you hit the back button you go back to the
+last note you were on. All this is free because we rely on the Android
+intents mechanism.
+
+Finally, if you run WikiNotes for Android and then start DDMS to
+take a look at the Activity threads in the WikiNotes application while
+it is running, you can see that despite what you might think, letting
+Android manage the navigation is very efficient. Create a few linked
+notes, as many links deep as you like, and then follow them. If you
+follow links hundreds of notes deep, you will still only see a handful
+of WikiNotes activities. Android is managing the activities, closing
+the older ones as necessary and using the life cycle to swap data in
+and out.
+
+Next Time
+
+This was a long article, but necessarily so. It demonstrates the
+importance of the Intents mechanism and to reinforce the notion that it
+should be used whenever possible for forward navigation, even within a
+single application. Illustrating this is one of the primary reasons I
+wrote WikiNotes for Android in the first place.
+
+In the next article we will look deeper into the ContentProvider and
+examine how it turns a Content URI into a row (or several rows) of data
+that can be used by an activity.
diff --git a/docs/html/resources/articles/wikinotes-linkify.jd b/docs/html/resources/articles/wikinotes-linkify.jd
new file mode 100644
index 0000000..21b1f13
--- /dev/null
+++ b/docs/html/resources/articles/wikinotes-linkify.jd
@@ -0,0 +1,113 @@
+page.title=WikiNotes: Linkify your Text!
+@jd:body
+
+
+
+This article introduces WikiNotes for Android, part of the Apps for Android
+project. It covers the use of Linkify to turn ordinary text views
+into richer, link-oriented content that causes Android intents to fire
+when a link is selected.
+
+Linkify: The {@link android.text.util.Linkify} class in the
+framework is perfect for creating a wiki note pad. It lets you specify a regular expression
+»
+to match, and a scheme to prepend. The scheme is a string that, when
+the matched text is added, forms a Content URI to allow the correct
+data to be looked up.
+
+For example, in our case we want to look for a regular expression match for a
+WikiWord (that is, a word with camel case » and no
+spaces). Linkify can then turn this into a Content URI — something like
+content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord
,
+which can then be used to locate the correct wiki page from a
+{@link android.content.ContentProvider}.
+
+As a bonus, the Linkify class also defines several default matches,
+in particular it is able to turn web URLs, email addresses and
+telephone numbers into active links which fire Android intents
+automatically.
+
+Linkify can be passed any TextView in your application, and will
+take care of creating the links and enabling their "clickability" for
+you.
+
+Default Linkify: Using the set of default active
+link options is very straightforward. Simply pass it a handle to a
+TextView with content in it, and the Linkify.ALL
flag:
+
+TextView noteView = (TextView) findViewById(R.id.noteview);
+noteView.setText(someContent);
+Linkify.addLinks(noteView, Linkify.ALL);
+
+and that's it. The Linkify.ALL
flag applies all of the predefined
+link actions, and the TextView will be immediately updated with a set
+of active links which, if you select them, fire default intents for the
+actions (e.g. a web URL will start the browser with that URL, a
+telephone number will bring up the phone dialer with that number ready
+to call, etc.).
+
+Custom Linkify: So what about our WikiWord? There is no
+pre-defined action for that, so it needs to be defined and associated with a
+scheme.
+
+The first task is to define a regular expression that matches the kind of
+WikiWords we want to find. The regex in this case is:
+
+\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\b
+
+Obvious, no? Well actually this is equivalent to the following
+description: "Starting with a word boundary (the \b) find at least one
+upper case letter, followed by at least one lower case letter or a
+numeric digit, followed by another upper case letter, and then any mix
+of upper case, lower case or numeric until the next word boundary (the
+final \b)". Regular expressions are not very pretty, but they are an
+extremely concise and accurate way of specifying a search pattern.
+
+We also need to tell Linkify what to do with a match to the
+WikiWord. Linkify will automatically append whatever is matched to a
+scheme that is supplied to it, so for the sake of argument let's assume
+we have a {@link android.content.ContentProvider} that matches the
+following content URI:
+
+content://com.google.android.wikinotes.db.wikinotes/wikinotes/WikiWord
+
+The WikiWord part will be appended by Linkify when it finds a match, so we
+just need the part before that as our scheme.
+
+Now that we have these two things, we use Linkify to connect them up:
+
+Pattern wikiWordMatcher = Pattern.compile("\\b[A-Z]+[a-z0-9]+[A-Z][A-Za-z0-9]+\\b");
+String wikiViewURL = "content://com.google.android.wikinotes.db.wikinotes/wikinotes/";
+Linkify.addLinks(noteView, wikiWordMatcher, wikiViewURL);
+
+Note that the \b's had to be escaped with double backslashes for the Java
+Pattern.compile line.
+
+Linkify can be used multiple times on the same view to add more
+links, so using this after the Default Linkify call means that the
+existing active links will be maintained and the new WikiWords will be
+added. You could define more Linkify actions and keep applying them to
+the same TextView if you wanted to.
+
+Now, if we have a WikiWord in the TextView, let's say
+MyToDoList
, Linkify will turn it into an active link with the
+content URI:
+
+content://com.google.android.wikinotes.db.wikinotes/wikinotes/MyToDoList
+
+and if you click on it, Android will fire the default intent for that content
+URI.
+
+For this to all work, you will need a ContentProvider that
+understands that Content URI, and you will need a default activity
+capable of doing something with the resulting data. I plan to cover
+these in future blog entries (and soon). In fact, the whole Wiki Note
+Pad application is currently undergoing some clean up and review, and
+will then hopefully be released as a sample application.
diff --git a/docs/html/resources/articles/window-bg-speed.jd b/docs/html/resources/articles/window-bg-speed.jd
new file mode 100644
index 0000000..bd7a303
--- /dev/null
+++ b/docs/html/resources/articles/window-bg-speed.jd
@@ -0,0 +1,125 @@
+page.title=Window Backgrounds & UI Speed
+@jd:body
+
+Some Android applications require to squeeze every bit of performance out of
+the UI toolkit and there are many ways to do so. In this article, you will
+discover how to speed up the drawing and the perceived startup time of
+your activities. Both these techniques rely on a single feature, the window's
+background drawable.
+
+The term window background is a bit misleading, however. When you
+setup your user interface by calling setContentView()
on an
+{@link android.app.Activity}, Android adds your views to the Activity
's
+window. The window however does not contain only your views, but a few others
+created for you. The most important one is, in the current implementation used
+on the T-Mobile G1, the DecorView
, highlighted in the view
+hierarchy below:
+
+
+
+The DecorView
is the view that actually holds the
+window's background drawable. Calling
+{@link android.view.Window#setBackgroundDrawable(android.graphics.drawable.Drawable) getWindow().setBackgroundDrawable()}
+from your Activity
changes the background of the window by changing
+the DecorView
's background drawable. As mentioned before, this
+setup is very specific to the current implementation of Android and can change
+in a future version or even on another device.
+
+If you are using the standard Android themes, a default background drawable
+is set on your activities. The standard theme currently used on the T-Mobile G1
+uses for instance a {@link android.graphics.drawable.ColorDrawable}. For most
+applications, this background drawable works just fine and can be left alone. It
+can however impacts your application's drawing performance. Let's take the
+example of an application that always draws a full screen opaque picture:
+
+![An opaque user interface doesn't need a window background](images/window_background.png)
+
+You can see on this screenshot that the window's background is invisible,
+entirely covered by an ImageView
. This application is setup to
+redraw as fast as it can and draws at about 44 frames per second, or 22
+milliseconds per frame (note: the number of frames per second
+used in this article were obtained on a T-Mobile G1 with my finger on the screen
+so as to reduce the drawing speed which would otherwise be capped at 60 fps.) An
+easy way to make such an application draw faster is to remove the
+background drawable. Since the user interface is entirely opaque, drawing the
+background is simply wasteful. Removing the background improves the performance
+quite nicely:
+
+![Remove the background for faster drawing](images/window_background_null.png)
+
+In this new version of the application, the drawing speed went up to 51
+frames per second, or 19 milliseconds per frame. The difference of 3
+milliseconds per is easily explained by the speed of the memory bus on the
+T-Mobile G1: it is exactly the time it takes to move the equivalent of a
+screenful of pixels on the bus. The difference could be even greater if the
+default background was using a more expensive drawable.
+
+Removing the window's background can be achieved very easily by using
+a custom theme. To do so, first create a file called
+res/values/theme.xml
containing the following:
+
+<resources>
+ <style name="Theme.NoBackground" parent="android:Theme">
+ <item name="android:windowBackground">@null</item>
+ </style>
+</resources>
+
+You then need to apply the theme to your activity by adding the attribute
+android:theme="@style/Theme.NoBackground"
to your
+<activity />
or <application />
tag. This
+trick comes in very handy for any app that uses a MapView
, a
+WebView
or any other full screen opaque view.
+
+Opaque views and Android: this optimization is currently
+necessary because the Android UI toolkit is not smart enough to prevent the
+drawing of views hidden by opaque children. The main reason why this
+optimization was not implemented is simply because there are usually very few
+opaque views in Android applications. This is however something that I
+definitely plan on implementing as soon as possible and I can only apologize for
+not having been able to do this earlier.
Using a theme to change the
+window's background is also a fantastic way to improve the perceived
+startup performance of some of your activities. This particular trick can only
+be applied to activities that use a custom background, like a texture or a logo.
+The Shelves application is a good
+example:
+
+![Textured backgrounds are good candidates for window's background](images/shelves2.png)
+
+If this application simply set the wooden background in the XML layout or in
+onCreate()
the user would see the application startup with the
+default theme and its dark background. The wooden texture would only appear
+after the inflation of the content view and the first layout/drawing pass. This
+causes a jarring effect and gives the user the impression that the application
+takes time to load (which can actually be the case.) Instead, the application
+defines the wooden background in a theme, picked up by the system as soon as the
+application starts. The user never sees the default theme and gets the
+impression that the application is up and running right away. To limit the
+memory and disk usage, the background is a tiled texture defined in
+res/drawable/background_shelf.xml
:
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/shelf_panel"
+ android:tileMode="repeat" />
This drawable is simply referenced by the theme:
+
+<resources>
+ <style name="Theme.Shelves" parent="android:Theme">
+ <item name="android:windowBackground">@drawable/background_shelf</item>
+ <item name="android:windowNoTitle">true</item>
+ </style>
+</resources>
+
+The same exact trick is used in the Google Maps application that ships
+with the T-Mobile G1. When the application is launched, the user immediately
+sees the loading tiles of MapView
. This is only a trick, the theme
+is simply using a tiled background that looks exactly like the loading tiles of
+MapView
.
+
+Sometimes the best tricks are also the simplest, so the next time you create
+an activity with an opaque UI or a custom background, remember to change the
+window's background.
+
+Download the source code of the first example.
+
+Download the source code of Shelves.
+
+
diff --git a/docs/html/resources/articles/zipalign.jd b/docs/html/resources/articles/zipalign.jd
new file mode 100644
index 0000000..013d0fe
--- /dev/null
+++ b/docs/html/resources/articles/zipalign.jd
@@ -0,0 +1,98 @@
+page.title=Zipalign: an Easy Optimization
+@jd:body
+
+The Android SDK includes a tool called zipalign
+that optimizes the way an application is packaged. Running zipalign against your
+application enables Android to interact it more efficiently at run time and thus
+has the potential to make it and the overall system run faster. We strongly
+encourage you to use zipalign
on both new and already published
+applications and to make the optimized version available — even if your
+application targets a previous version of Android. This article describes how
+zipalign
helps performance and how to use it to optimize your
+app.
+
+In Android, data files stored in each application's apk are accessed by
+multiple processes: the installer reads the manifest to handle the
+permissions associated with that application; the Home application
+reads resources to get the application's name and icon; the system
+server reads resources for a variety of reasons (e.g. to display that
+application's notifications); and last but not least, the resource
+files are obviously used by the application itself.
+
+The resource-handling code in Android can efficiently access resources when
+they're aligned on 4-byte boundaries by memory-mapping them. But for resources
+that are not aligned (that is, when zipalign
hasn't been run on an
+apk), it has to fall back to explicitly reading them — which is slower and
+consumes additional memory.
+
+For an application developer, this fallback mechanism is very
+convenient. It provides a lot of flexibility by allowing for several
+different development methods, including those that don't include
+aligning resources as part of their normal flow.
+
+Unfortunately, for users the situation is reversed — reading resources
+from unaligned apks is slow and takes a lot of memory. In the best case, the
+only visible result is that both the Home application and the unaligned
+application launch slower than they otherwise should. In the worst case,
+installing several applications with unaligned resources increases memory
+pressure, thus causing the system to thrash around by having to constantly start
+and kill processes. The user ends up with a slow device with a poor battery
+life.
+
+Luckily, it's very easy for you to align the resources in your application:
+
+
+- Using ADT:
+-
+
+- The ADT plugin for Eclipse (starting from version 0.9.3) will automatically
+align release application packages if the export wizard is used to create them.
+To use the wizard, right click the project and choose "Android Tools" >
+"Export Signed Application Package..." It can also be accessed from the first
+page of the
AndroidManifest.xml
editor.
+
+
+- Using Ant:
-
+
+
+- The Ant build script (starting from Android 1.6) can align
+application packages. Targets for older versions of the Android platform are not
+aligned by the Ant build script and need to be manually aligned.
+- Starting from the Android 1.6 SDK, Ant aligns and signs packages automatically,
+when building in debug mode.
+- In release mode, Ant aligns packages only if it has enough
+information to sign the packages, since aligning has to happen after signing. In
+order to be able to sign packages, and therefore to align them, Ant
+needs to know the location of the keystore and the name of the key in
+
build.properties
. The name of the properties are
+key.store
and key.alias
respectively. If those
+properties are present, the signing tool will prompt to enter the store/key
+passwords during the build, and the script will sign and then align the apk
+file. If the properties are missing, the release package will not be signed, and
+therefore will not get aligned either.
+
+
+- Manually:
+-
+
+- In order to manually align a package,
zipalign
+is in the tools/
folder of Android 1.6 and later SDKs. You can use
+it to align application packages targeting any version of Android. You should run
+it only after signing the apk file, using the following command:
+
zipalign -v 4 source.apk destination.apk
+
+
+- Verifying alignment:
+-
+
+- The following command verifies that a package is aligned:
zipalign -c -v 4 application.apk
+
+
+
+
+
+We encourage you manually run zipalign
+on your currently published applications and to make the newly aligned
+versions available to users. Also, don't forget to align any new
+applications going forward!
diff --git a/docs/html/resources/community-groups.jd b/docs/html/resources/community-groups.jd
new file mode 100644
index 0000000..61fbcc8
--- /dev/null
+++ b/docs/html/resources/community-groups.jd
@@ -0,0 +1,121 @@
+community=true
+page.title=Android Developer Groups
+@jd:body
+
+Welcome to the Android developers community! We're glad you're here and invite you to participate in these discussions. Before posting, please read the Groups Charter that covers the community guidelines.
+
+Note: If you are seeking discussion about Android source code (not application development),
+then please refer to the Open Source Project Mailing lists.
+
+Contents
+
+ - Before you post
+ - Application developer mailing lists
+ - Using email with the mailing lists
+
+
+Before you post
+Before writing a post, please try the following:
+
+
+- Read the FAQs The most common questions about developing Android applications are addressed in this frequently updated list.
+- Type in keywords of your questions in the main Android site's search bar (such as the one above). This search encompasses all previous discussions, across all groups, as well as the full contents of the site, documentation, and blogs. Chances are good that somebody has run into the same issue before.
+- Search the mailing list archives to see whether your questions have already been discussed.
+
+
+
+If you can't find your answer, then we encourage you to address the community.
+As you write your post, please do the following:
+
+- Read
+the mailing list charter that covers the community guidelines.
+
+- Select the most appropriate mailing list for your question. There are several different lists for
+developers, described below.
+-
+ Be very clear about your question
+in the subject -- it helps everyone, both those trying to answer your
+question as well as those who may be looking for information in the
+future.
+- Give plenty of details in your post to
+help others understand your problem. Code or log snippets, as well as
+pointers to screenshots, may also be helpful. For a great guide to
+phrasing your questions, read How To Ask Questions The Smart Way.
+
+
+
+
+Application developer mailing lists
+
+- Android beginners - You're new to Android application development. You want to figure out how to get started with the Android SDK and the basic Android APIs? Start here. This list is open to any discussion around beginner-type questions for developers using the SDK; this is a great way to get up and running with your new application on the Android platform. Ask about getting your development environment set up, get help with the first steps of Android development (your first User Interface, your first permission, your first file on the Android filesystem, your first app on the Android Market...). Be sure to check the archives first before asking new questions. Please avoid advanced subjects, which belong on android-developers, and user questions, which will get a better reception on android-discuss.
+
+
+
+- Android developers - You're now an experienced Android application developer. You've grasped the basics of Android app development, you're comfortable using the SDK, now you want to move to advanced topics. Get help here with troubleshooting applications, advice on implementation, and strategies for improving your application's performance and user experience. This is the not the right place to discuss user issues (use android-discuss for that) or beginner questions with the Android SDK (use android-beginners for that).
+
+
+
+- Android discuss - The "water cooler" of Android discussion. You can discuss just about anything Android-related here, ideas for the Android platform, announcements about your applications, discussions about Android devices, community resources... As long as your discussion is related to Android, it's on-topic here. However, if you have a discussion here that could belong on another list, you are probably not reaching all of your target audience here and may want to consider shifting to a more targeted list.
+
+
+
+- Android ndk - A place for discussing the Android NDK and topics related to using native code in Android applications.
+
+
+
+- Android security discuss - A place for open discussion on secure development, emerging security concerns, and best practices for and by android developers. Please don't disclose vulnerabilities directly on this list, you'd be putting all Android users at risk.
+
+
+
+- Android security announce - A low-volume group for security-related announcements by the Android Security Team.
+
+
+
+- Android Market Help Forum - A web-based discussion forum where you can ask questions or report issues relating to Android Market.
+
+
+
+
+
+
+
+Using email with the mailing lists
+Instead of using the Google Groups site, you can use your email client of choice to participate in the mailing lists.
+To subscribe to a group without using the Google Groups site, use the link under "subscribe via email" in the lists above.
+To set up how you receive mailing list postings by email:
+
+- Sign into the group via the Google Groups site. For example, for the android-framework group you would visit http://groups.google.com/group/android-framework.
+- Click "Edit
+my membership" on the right side.
+- Under "How do
+you want to read this group?" select one of the email options.
+
+
+
+
+
+
+
+
+
+
diff --git a/docs/html/resources/community-more.jd b/docs/html/resources/community-more.jd
new file mode 100644
index 0000000..2be015a
--- /dev/null
+++ b/docs/html/resources/community-more.jd
@@ -0,0 +1,48 @@
+community=true
+page.title=IRC and Twitter
+@jd:body
+
+In addition to the Android developer groups, you can also participate in the Android developer community through IRC, and you can also follow us on Twitter.
+
+IRC
+
+Several IRC channels are available for discussions about developing Android applications.
+
+
+
+ Channel | Host | Description |
+
+
+ #android |
+ irc.freenode.net |
+ General discussion about Android (and Android development). |
+
+
+ #android-dev |
+ irc.freenode.net |
+ Discussion focused on developing Android apps. |
+
+
+
+If you haven't used IRC before, check http://en.wikipedia.org/wiki/List_of_IRC_clients » for a helpful list of IRC clients. Alternatively, you could also use this web interface », which does not require any installation, to join discussions on the Android IRC channels.
+
+Here are some tips for using IRC:
+
+
+- Set your nickname before you join the channel.
+- Registering your nickname prevents others from using your nickname or impersonating you later:
+
/nick <yournickname>
+/msg nickserv register <password> <email>
+Afterwards, when you connect, you'll need to supply a password:
+/connect irc.freenode.net
+/nick <yournickname>
+/msg nickserv identify <password>
+/join #android-dev
+
+
+
+
+You can follow us on Twitter at this account:
+
+http://twitter.com/androiddev
+
diff --git a/docs/html/resources/faq/commontasks.jd b/docs/html/resources/faq/commontasks.jd
new file mode 100644
index 0000000..fa487f7
--- /dev/null
+++ b/docs/html/resources/faq/commontasks.jd
@@ -0,0 +1,821 @@
+page.title=Common Tasks and How to Do Them in Android
+parent.title=FAQs, Tips, and How-to
+parent.link=index.html
+@jd:body
+
+
+The ApiDemos sample application includes many, many examples of common
+tasks and UI features. See the code inside
+<sdk>samples/ApiDemos
and the other sample applications
+under the samples/
folder in the SDK.
+
+
+Creating an Android Application using the Eclipse Plugin
+
+Using the Android Eclipse plugin is the fastest and easiest way
+to start creating a new Android application. The plugin automatically generates
+the correct project structure for your application, and keeps the resources
+compiled for you automatically.
+
+It is still a good idea to know what is going on though. Take a look at Application Fundamentals
+to understand the basics of how an Android application works.
+
+You should also take a look at the ApiDemos application and the other sample
+applications included in the SDK, in the <sdk>/samples/
+folder in the SDK.
+
+Finally, a great way to started with Android development in Eclipse is to
+follow both the Hello,
+World and Notepad code
+tutorials. In particular, the start of the Hello Android tutorial is an
+excellent introduction to creating a new Android application in Eclipse.
+
+Creating an Android Application without the Eclipse Plugin
+
+This topic describes the manual steps in creating an Android application.
+Before reading this, you should read Application Fundamentals
+to understand the basics of how an Android application works. You might also
+want to look at the sample code included with the Android SDK, in the
+<sdk>/samples/
directory.
+
+Here is a list of the basic steps in building an application.
+
+ - Create your required resource files This includes
+ the AndroidManifest.xml global description file, string files that your application
+ needs, and layout files describing your user interface. A full list of optional
+ and required files and syntax details for each is given in File
+ List for an Android Application.
+ - Design your user interface See User Interface for
+ details on elements of the Android screen.
+ - Implement your Activity (this page) You
+ will create one class/file for each screen in your application. Screens will
+ inherit from an {@link android.app android.app} class, typically {@link android.app.Activity
+ android.app.Activity} for basic screens, {@link android.app.ListActivity
+ android.app.ListActivity} for list screens, or {@link android.app.Dialog
+ android.app.Dialog} for dialog boxes. You will implement the required callbacks
+ that let you draw your screen, query data, and commit changes, and also perform
+ any required tasks such as opening additional screens or reading data from
+ the device. Common tasks, such as opening a new screen or reading data from
+ the device, are described below.
+ The list of files you'll need for your application are described in List
+ of Files for an Android Application.
+ - Build and install your
+ package. The Android SDK has some nice tools for generating
+ projects and debugging code.
+
+
+Adding an External Library (.jar) using Eclipse
+
+You can use a third party JAR in your application by adding it to your Eclipse project as follows:
+
+
+-
+In the Package Explorer panel, right-click on your project and select Properties.
+
-
+Select Java Build Path, then the tab Libraries.
+
-
+Press the Add External JARs... button and select the JAR file.
+
+
+Alternatively, if you want to include third party JARs with your package, create a new directory for them within your project and select Add Library... instead.
+
+It is not necessary to put external JARs in the assets folder.
+
+
+
+Implementing Activity Callbacks
+Android calls a number of callbacks to let you draw your screen, store data before
+ pausing, and refresh data after closing. You must implement at least some of
+ these methods. See Lifecycles
+ discussion in Application Fundamentals to learn when and in what order these methods
+ are called. Here are some of the standard types of screen classes that Android provides:
+
+ - {@link android.app.Activity android.app.Activity} - This is a standard screen,
+ with no specialization.
+ - {@link android.app.ListActivity android.app.ListActivity} - This is a screen
+ that is used to display a list of something. It hosts a ListView object,
+ and exposes methods to let you identify the selected item, receive callbacks
+ when the selected item changes, and perform other list-related actions.
+ - {@link android.app.Dialog android.app.Dialog} - This is a small, popup dialog-style
+ window that isn't intended to remain in the history stack. (It is not resizeable
+ or moveable by the user.)
+
+
+Opening a New Screen
+Your Activity will often need to open another Activity screen as it progresses.
+ This new screen can be part of the same application or part of another application,
+ the new screen can be floating or full screen, it can return a result, and you
+ can decide whether to close this screen and remove it from the history stack
+ when you are done with it, or to keep the screen open in history. These next
+ sections describe all these options.
+Floating or full?
+When you open a new screen you can decide whether to make it transparent or floating,
+ or full-screen. The choice of new screen affects the event sequence of events
+ in the old screen (if the new screen obscures the old screen, a different
+ series of events is called in the old screen). See Lifecycles discussion
+ in Application Fundamentals for details.
+Transparent or floating windows are implemented in three
+ standard ways:
+
+ - Create an {@link android.app.Dialog app.Dialog} class
+ - Create an {@link android.app.AlertDialog app.AlertDialog} class
+ - Set the {@link android.R.style#Theme_Dialog} theme attribute to
@android:style/Theme.Dialog
+ in your AndroidManifest.xml file. For example:
+
+
+ <activity class="AddRssItem" android:label="Add an item" android:theme="@android:style/Theme.Dialog"/>
+
+
+Calling startActivity() or startActivityForResult() will open a new screen in whatever
+ way it defines itself (if it uses a floating theme it will be floating,
+ otherwise it will be full screen).
+Opening a Screen
+When you want to open a new screen, you can either explicitly specify the activity
+ class to open, or you can let the operating system decide which screen to open,
+ based upon the data and various parameters you pass in. A screen is opened by
+ calling {@link android.app.Activity#startActivity(android.content.Intent) startActivity}
+ and passing in an {@link android.content.Intent Intent} object, which specifies
+ the criteria for the handling screen. To specify a specific screen, call Intent.setClass
+ or setClassName with the exact activity class to open. Otherwise, set a variety
+ of values and data, and let Android decide which screen is appropriate to open.
+ Android will find one or zero Activities that match the specified requirements;
+ it will never open multiple activities for a single request. More information
+ on Intents and how Android resolves them to a specific class is given in the
+ {@link android.content.Intent Intent} topic.
+Some Intent examples
+The following snippet loads the com.android.samples.Animation1 class, and
+ passes it some arbitrary data.:
+Intent myIntent = new Intent();
+myIntent.setClassName("com.android.samples", "com.android.samples.Animation1");
+myIntent.putExtra("com.android.samples.SpecialValue", "Hello, Joe!"); // key/value pair, where key needs current package prefix.
+startActivity(myIntent);
+The next snippet requests that a Web page be opened by specifying the VIEW action,
+ and a URI data string starting with "http://" schema:
+Intent myIntent = new Intent(Intent.VIEW_ACTION, Uri.parse("http://www.google.com"));
+Here is the intent filter from the AndroidManifest.xml file for com.android.browser:
+<intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <scheme android:name="http" />
+ <scheme android:name="https" />
+ <scheme android:name="file" />
+</intent-filter>
+Android defines a number of standard values, for instance the action constants
+ defined by {@link android.content.Intent}. You can define custom values, but
+ both the caller and handler must use them. See the <intent-filter>
+ tag description in The AndroidManifest.xml
+ File for more information on the manifest syntax for the handling
+ application.
+Returning a Result from a Screen
+A window can return a result after it closes. This result will be passed back
+ into the calling Activity's {@link android.app.Activity#onActivityResult(int,int,android.content.Intent)
+ onActivityResult()} method, which can supply an Intent containing arbitrary data, along with
+ the request code passed to startActivityForResult(). Note that you must call the {@link
+ android.app.Activity#startActivityForResult(android.content.Intent,int) startActivityForResult()}
+ method that accepts a request code parameter to get this callback. The following
+ code demonstrates opening a new screen and retrieving a result.
+// Open the new screen.
+public void onClick(View v){
+ // Start the activity whose result we want to retrieve. The
+ // result will come back with request code GET_CODE.
+ Intent intent = new Intent(this, com.example.app.ChooseYourBoxer.class);
+ startActivityForResult(intent, CHOOSE_FIGHTER);
+}
+
+// Listen for results.
+protected void onActivityResult(int requestCode, int resultCode, Intent data){
+ // See which child activity is calling us back.
+ switch (resultCode) {
+ case CHOOSE_FIGHTER:
+ // This is the standard resultCode that is sent back if the
+ // activity crashed or didn't doesn't supply an explicit result.
+ if (resultCode == RESULT_CANCELED){
+ myMessageboxFunction("Fight cancelled");
+ }
+ else {
+ myFightFunction(data);
+ }
+ default:
+ break;
+ }
+}
+
+// Class SentResult
+// Temporary screen to let the user choose something.
+ private OnClickListener mLincolnListener = new OnClickListener(){
+ public void onClick(View v) {
+ Bundle stats = new Bundle();
+ stats.putString("height","6\'4\"");
+ stats.putString("weight", "190 lbs");
+ stats.putString("reach", "74\"");
+ setResult(RESULT_OK, "Lincoln", stats);
+ finish();
+ }
+ };
+
+ private OnClickListener mWashingtonListener = new OnClickListener() {
+ public void onClick(View v){
+ Bundle stats = new Bundle();
+ stats.putString("height","6\'2\"");
+ stats.putString("weight", "190 lbs");
+ stats.putString("reach", "73\"");
+ setResult(RESULT_OK, "Washington", Bundle);
+ finish();
+ }
+ };
+
+Lifetime of the new screen
+An activity can remove itself from the history stack by calling {@link android.app.Activity#finish()
+ Activity.finish()} on itself, or the activity that opened the screen can call
+ {@link android.app.Activity#finishActivity(int) Activity.finishActivity()}
+ on any screens that it opens to close them.
+Listening for Button Clicks
+Button click and other UI event capturing are covered in Handling UI Events on the UI Design page.
+Configuring General Window Properties
+You can set a number of general window properties, such as whether to display
+ a title, whether the window is floating, and whether it displays an icon, by
+ calling methods on the {@link android.view.Window Window} member
+ of the underlying View object for the window. Examples include calling {@link
+ android.app.Activity#getWindow() getWindow().requestFeature()} (or the convenience
+ method {@link android.app.Activity#requestWindowFeature(int) requestWindowFeature(some_feature)})
+ to hide the title. Here is an example of hiding the title bar:
+//Hide the title bar
+requestWindowFeature(Window.FEATURE_NO_TITLE);
+
+A better way to achieve the same end is to specify a theme in your Android
+Manifest file:
+<application android:icon="@drawable/icon" android:theme="@android:style/Theme.NoTitleBar">
+
+This is preferable because it tells the system not to show a title bar while
+your application is starting up. With the explicit method call, your application
+will have a title bar visible to the user until onCreate
runs.
+(Note that this can be applied to either the <application>
+tag or to individual <activity>
tags.)
+Referring to localhost from the emulated environment
+
+If you need to refer to your host computer's localhost, such as when you
+want the emulator client to contact a server running on the same host, use the alias
+10.0.2.2
to refer to the host computer's loopback interface.
+From the emulator's perspective, localhost (127.0.0.1
) refers to its own
+loopback interface.
+
+Storing and Retrieving State
+If your application is dumped from memory because of space concerns, it will lose
+ all user interface state information such as checkbox state and text box values
+ as well as class member values. Android calls {@link android.app.Activity#onSaveInstanceState(android.os.Bundle)
+ Activity.onSaveInstanceState} before it pauses the application. This method hands in a {@link
+ android.os.Bundle Bundle} that can be used to store name/value pairs that will
+ persist and be handed back to the application even if it is dropped from memory.
+ Android will pass this Bundle back to you when it calls {@link android.app.Activity#onCreate(android.os.Bundle)
+ onCreate()}. This Bundle only exists while the application is still in the history
+ stack (whether or not it has been removed from memory) and will be lost when
+ the application is finalized. See the topics for {@link android.app.Activity#onSaveInstanceState} and
+ {@link android.app.Activity#onCreate} for
+ examples of storing and retrieving state.
+Read more about the lifecycle of an application in Application Fundamentals.
+Storing and Retrieving Larger or More Complex Persistent Data
+Your application can store files or complex collection objects, and reserve them
+ for private use by itself or other activities in the application, or it can expose
+ its data to all other applications on the device. See Storing,
+ Retrieving, and Exposing Data to learn how to store and retrieve private data,
+ how to store and retrieve common data from the device, and how to expose your
+ private data to other applications.
+Playing Media Files
+Please see the document Audio and Video for more details.
+Listening For and Broadcasting Global Messages, and Setting Alarms
+You can create a listening class that can be notified or even instantiated whenever
+ a specific type of system message is sent.
+
+The listening classes, called broadcast receivers, extend {@link android.content.BroadcastReceiver
+ BroadcastReceiver}. If you want Android to instantiate the object whenever an appropriate
+ intent notification is sent, define the receiver with a <receiver>
element
+ in the AndroidManifext.xml file. If the caller is expected to instantiate the
+ object in preparation to receive a message, this is not required. The receiver
+ will get a call to their {@link android.content.BroadcastReceiver#onReceive(android.content.Context,android.content.Intent)
+ BroadcastReceiver.onReceive()} method. A receiver can define an <intent-filter>
tag
+ that describes the types of messages it will receive. Just as Android's IntentResolver
+ will look for appropriate Activity matches for a startActivity() call, it will
+ look for any matching Receivers (but it will send the message to all matching
+ receivers, not to the "best" match).
+To send a notification, the caller creates an {@link android.content.Intent Intent}
+ object and calls {@link android.app.Activity#sendBroadcast(android.content.Intent)
+ Context.sendBroadcast()} with that Intent. Multiple recipients can receive
+ the same message. You can broadcast an Intent message to an intent receiver in
+ any application, not only your own. If the receiving class is not registered
+ using <receiver>
in its manifest, you can dynamically instantiate
+ and register a receiver by calling {@link android.content.Context#registerReceiver(android.content.BroadcastReceiver,android.content.IntentFilter)
+ Context.registerReceiver()}.
+Receivers can include intent filters to specify what kinds of intents they are
+ listening for. Alternatively, if you expect a single known caller to contact
+ a single known receiver, the receiver does not specify an intent filter, and
+ the caller specifies the receiver's class name in the Intent by calling {@link
+ android.content.Intent#setClassName(java.lang.String, java.lang.String) Intent.setClassName()}
+ with the recipient's class name. The recipient receives a {@link android.content.Context
+ Context} object that refers to its own package, not to the package of the sender.
+Note: If a receiver or broadcaster
+ enforces permissions, your application might need to request permission
+ to send or receive messages from that object. You can request permission by using
+ the <uses-permission> tag in the manifest.
+Here is a code snippet of a sender and receiver. This example does not demonstrate
+ registering receivers dynamically. For a full code example, see the AlarmService
+ class in the ApiDemos project.
+Sending the message
+// We are sending this to a specific recipient, so we will
+// only specify the recipient class name.
+Intent intent = new Intent(this, AlarmReceiver.class);
+intent.putExtra("message","Wake up.");
+sendBroadcast(intent);
+
+Receiving the message
+Receiver AndroidManifest.xml (because there is no intent filter
+ child, this class will only receive a broadcast when the receiver class is specified
+ by name, as is done in this example):
+
+<receiver class=".AlarmReceiver" />
+Receiver Java code:
+
+public class AlarmReceiver extends BroadcastReceiver{
+ // Display an alert that we've received a message.
+ @Override
+ public void onReceive(Context context, Intent intent){
+ // Send a text notification to the screen.
+ NotificationManager nm = (NotificationManager)
+ context.getSystemService(Context.NOTIFICATION_SERVICE);
+ nm.notifyWithText(R.id.alarm,
+ "Alarm!!!",
+ NotificationManager.LENGTH_SHORT,
+ null);
+ }
+}
+Other system messages
+You can listen for other system messages sent by Android as well, such as USB
+ connection/removal messages, SMS arrival messages, and timezone changes. See
+ {@link android.content.Intent} for a list of broadcast messages to listen for.
+ Messages are marked "Broadcast Action" in the documentation.
+Listening for phone events
+The {@link android.telephony android.telephony} package overview page describes how to
+ register to listen for phone events.
+Setting Alarms
+Android provides an {@link android.app.AlarmManager AlarmManager} service that
+ will let you specify an Intent to send at a designated time. This intent is typically
+ used to start an application at a preset time. (Note: If you want to send
+ a notification to a sleeping or running application, use {@link android.os.Handler
+ Handler} instead.)
+Displaying Alerts
+There are two major kinds of alerts that you may display to the user:
+(1) Normal alerts are displayed in response to a user action, such as
+trying to perform an action that is not allowed. (2) Out-of-band alerts,
+called notifications, are
+displayed as a result of something happening in the background, such as the
+user receiving new e-mail.
+
+Normal Alerts
+
+Android provides a number of ways for you to show popup notifications to your
+ user as they interact with your application.
+
+
+ Class |
+ Description |
+
+
+ {@link android.app.Dialog app.Dialog} |
+ A generic floating dialog box with a layout that you design. |
+
+
+ {@link android.app.AlertDialog app.AlertDialog} |
+ A popup alert dialog with two buttons (typically OK and Cancel) that
+ take callback handlers. See the section after this table for more details. |
+
+
+ {@link android.app.ProgressDialog ProgressDialog} |
+ A dialog box used to indicate progress of an operation with a known progress
+ value or an indeterminate length (setProgress(bool)). See Views > Progress Bar in
+ ApiDemos for examples. |
+
+
+ Activity |
+ By setting the theme of an activity to
+ {@link android.R.style#Theme_Dialog
+ android:theme="@android:style/Theme.Dialog"},
+ your activity will take on
+ the appearance of a normal dialog, floating on top of whatever was
+ underneath it. You usually set the theme through the
+ {@link android.R.attr#theme android:theme} attribute in your AndroidManifest.xml.
+ The advantage of this
+ over Dialog and AlertDialog is that Application has a much better managed
+ life cycle than dialogs: if a dialog goes to the background and is killed,
+ you cannot recapture state, whereas Application exposes a {@link android.os.Bundle
+ Bundle} of saved values in onCreate() to help you maintain state. |
+
+
+AlertDialog
+This is a basic warning dialog box that lets you configure a message, button text,
+ and callback. You can create one by calling using the {@link
+ android.app.AlertDialog.Builder} class, as shown here.
+private Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case ACCEPT_CALL:
+ answer(msg.obj);
+ break;
+
+ case BOUNCE_TO_VOICEMAIL:
+ voicemail(msg.obj);
+ break;
+
+ }
+ }
+};
+
+
+private void IncomingMotherInlawCall(Connection c) {
+ String Text;
+
+ // "Answer" callback.
+ Message acceptMsg = Message.obtain();
+ acceptMsg.target = mHandler;
+ acceptMsg.what = ACCEPT_CALL;
+ acceptMsg.obj = c.getCall();
+
+ // "Cancel" callback.
+ final Message rejectMsg = Message.obtain();
+ rejectMsg.target = mHandler;
+ rejectMsg.what = BOUNCE_TO_VOICEMAIL;
+ rejectMsg.obj = c.getCall();
+
+ new AlertDialog.Builder(this)
+ .setMessage("Phyllis is calling")
+ .setPositiveButton("Answer", acceptMsg)
+ .setOnCanceListener(new OnCancelListener() {
+ public void onCancel(DialogInterface dialog) {
+ rejectMsg.sendToTarget();
+ }});
+ .show();
+}
+
+Notifications
+
+Out-of-band alerts should always be displayed using the
+{@link android.app.NotificationManager}, which allows you to tell the user
+about something they may be interested in without disrupting what they are
+currently doing. A notification can be anything from a brief pop-up box
+informing the user of the new information, through displaying a persistent
+icon in the status bar, to vibrating, playing sounds, or flashing lights to
+get the user's attention. In all cases, the user must explicitly shift their
+focus to the notification before they can interact with it.
+
+The following code demonstrates using NotificationManager to display a basic text
+ popup when a new SMS message arrives in a listening service, and provides the
+ current message count. You can see several more examples in the ApiDemos application,
+ under app/ (named notification*.java).
+static void setNewMessageIndicator(Context context, int messageCount){
+ // Get the static global NotificationManager object.
+ NotificationManager nm = NotificationManager.getDefault();
+
+ // If we're being called because a new message has been received,
+ // then display an icon and a count. Otherwise, delete the persistent
+ // message.
+ if (messageCount > 0) {
+ nm.notifyWithText(myApp.NOTIFICATION_GUID, // ID for this notification.
+ messageCount + " new message" + messageCount > 1 ? "s":"", // Text to display.
+ NotificationManager.LENGTH_SHORT); // Show it for a short time only.
+ }
+}
+To display a notification in the status bar and have it launch an intent when
+ the user selects it (such as the new text message notification does), call {@link
+ android.app.NotificationManager#notify(int, android.app.Notification) NotificationManager.notify()},
+ and pass in vibration patterns, status bar icons, or Intents to associate with
+ the notification.
+Displaying a Progress Bar
+An activity can display a progress bar to notify the user that something is happening.
+ To display a progress bar in a screen, call {@link android.app.Activity#requestWindowFeature(int)
+ Activity.requestWindowFeature(Window.FEATURE_PROGRESS)}. To set the value
+ of the progress bar, call {@link android.view.Window#setFeatureInt(int,int)
+ Activity.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, level)}.
+ Progress bar values are from 0 to 9,999, or set the value to 10,000 to make the
+ progress bar invisible.
+You can also use the {@link android.app.ProgressDialog ProgressDialog} class,
+ which enables a dialog box with an embedded progress bar to send a "I'm working
+ on it" notification to the user.
+Adding Items to the Screen Menu
+See Creating Menus.
+
+Display a Web Page
+Use the {@link android.webkit.WebView webkit.WebView} object.
+Binding to Data
+You can bind a ListView to a set of underlying data by using a shim class called
+ {@link android.widget.ListAdapter ListAdapter} (or a subclass). ListAdapter subclasses
+ bind to a variety of data sources, and expose a common set of methods such as
+ getItem() and getView(), and uses them to pick View items to display in its list.
+ You can extend ListAdapter and override getView() to create your own custom list
+ items. There are essentially only two steps you need to perform to bind to data:
+
+ - Create a ListAdapter object and specify its data source
+ - Give the ListAdapter to your ListView object.
+
+That's it!
+Here's an example of binding a ListActivity screen to the results from a cursor
+ query. (Note that the setListAdapter() method shown is a convenience method that
+ gets the page's ListView object and calls setAdapter() on it.)
+// Run a query and get a Cursor pointing to the results.
+Cursor c = People.query(this.getContentResolver(), null);
+startManagingCursor(c);
+
+// Create the ListAdapter. A SimpleCursorAdapter lets you specify two interesting things:
+// an XML template for your list item, and
+// The column to map to a specific item, by ID, in your template.
+ListAdapter adapter = new SimpleCursorAdapter(this,
+ android.R.layout.simple_list_item_1, // Use a template that displays a text view
+ c, // Give the cursor to the list adapter
+ new String[] {People.NAME} , // Map the NAME column in the people database to...
+ new String[] {"text1"}); // The "text1" view defined in the XML template
+setListAdapter(adapter);
+See view/List4 in the ApiDemos project for an example of extending ListAdapter
+ for a new data type.
+
+
+
+Getting a Handle to a Screen Element
+You can get a handle to a screen element by calling {@link
+android.app.Activity#findViewById(int) Activity.findViewById}. You can then use
+the handle to set or retrieve any values exposed by the object.
+Capture Images from the Phone Camera
+You can hook into the device's camera onto your own Canvas object by using the
+ {@link android.hardware.Camera Camera} class. See that class's documentation,
+ and the ApiDemos project's Camera Preview application (Graphics/Camera Preview)
+ for example code.
+
+
+Handling Expensive Operations in the UI Thread
+Avoid performing long-running operations (such as network I/O) directly in the UI thread —
+the main thread of an application where the UI is run — or your application may be blocked
+and become unresponsive. Here is a brief summary of the recommended approach for handling expensive operations:
+
+- Create a Handler object in your UI thread
+- Spawn off worker threads to perform any required expensive operations
+- Post results from a worker thread back to the UI thread's handler either through a Runnable or a {@link android.os.Message}
+- Update the views on the UI thread as needed
+
+
+The following outline illustrates a typical implementation:
+
+
+public class MyActivity extends Activity {
+
+ [ . . . ]
+ // Need handler for callbacks to the UI thread
+ final Handler mHandler = new Handler();
+
+ // Create runnable for posting
+ final Runnable mUpdateResults = new Runnable() {
+ public void run() {
+ updateResultsInUi();
+ }
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ [ . . . ]
+ }
+
+ protected void startLongRunningOperation() {
+
+ // Fire off a thread to do some work that we shouldn't do directly in the UI thread
+ Thread t = new Thread() {
+ public void run() {
+ mResults = doSomethingExpensive();
+ mHandler.post(mUpdateResults);
+ }
+ };
+ t.start();
+ }
+
+ private void updateResultsInUi() {
+
+ // Back in the UI thread -- update our UI elements based on the data in mResults
+ [ . . . ]
+ }
+}
+
+
+For further discussions on this topic, see
+Designing for Responsiveness
+and the {@link android.os.Handler} documentation.
+
+Selecting, Highlighting, or Styling Portions of Text
+You can highlight or style the formatting of strings or substrings of text in
+ a TextView object. There are two ways to do this:
+
+ - If you use a string resource,
+ you can add some simple styling, such as bold or italic using HTML notation.
+ The currently supported tags are:
B
(bold),
+ I
(italic), U
(underline),
+ TT
(monospace), BIG
, SMALL
,
+ SUP
(superscript), SUB
(subscript),
+ and STRIKE
(strikethrough).
+ So, for example, in res/values/strings.xml you could declare this:
+ <resource>
+ <string>id="@+id/styled_welcome_message">We
+ are <b><i>so</i></b> glad to see you.</string>
+ </resources>
+ - To style text on the fly, or to add highlighting or more complex styling,
+ you must use the Spannable object as described next.
+
+To style text on the fly, you must make sure the TextView is using {@link android.text.Spannable}
+ storage for the text (this will always be true if the TextView is an EditText),
+ retrieve its text with {@link android.widget.TextView#getText}, and call {@link
+ android.text.Spannable#setSpan}, passing in a new style class from the {@link
+ android.text.style} package and the selection range.
+The following code snippet demonstrates creating a string with a highlighted section,
+ italic section, and bold section, and adding it to an EditText object.
+// Get our EditText object.
+EditText vw = (EditText)findViewById(R.id.text);
+
+// Set the EditText's text.
+vw.setText("Italic, highlighted, bold.");
+
+// If this were just a TextView, we could do:
+// vw.setText("Italic, highlighted, bold.", TextView.BufferType.SPANNABLE);
+// to force it to use Spannable storage so styles can be attached.
+// Or we could specify that in the XML.
+
+// Get the EditText's internal text storage
+Spannable str = vw.getText();
+
+// Create our span sections, and assign a format to each.
+str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+str.setSpan(new BackgroundColorSpan(0xFFFFFF00), 8, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 21, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+
+Utilizing attributes in a Map query
+
+When using a search intent to ask the Maps activity to search for something, the Maps activity responds to the following attributes in the optional context bundle:
+
+
+ float "centerLatitude" default 0.0f
+ float "centerLongitude" default 0.0f
+ float "latitudeSpan" default 0.0f
+ float "longitudeSpan" default 0.0f
+ int "zoomLevel" default 10
+
+
+This context information is used to center the search result in a particular area, and is equivalent to adjusting the Map activity to the described location and zoom level before issuing the query.
+
+
+If the latitudeSpan, longitudeSpan, and zoomLevel attributes are not consistent, then it is undefined which one takes precedence.
+
+
+List of Files for an Android Application
+The following list describes the structure and files of an Android application.
+ Many of these files can be built for you (or stubbed out) by the android tool
+ shipped in the tools/ menu of the SDK.
+
+
+ MyApp/
|
+ |
+
+
+ AndroidManifest.xml |
+ (required) Advertises the screens that this application provides,
+ where they can be launched (from the main program menu or elsewhere),
+ any content providers it implements and what kind of data they handle,
+ where the implementation classes are, and other application-wide
+ information. Syntax details for this file are described in The AndroidManifest.xml File. |
+
+
+ src/
+ /myPackagePath/.../MyClass.java |
+ (required) This folder holds all the source code files for your
+ application, inside the appropriate package subfolders. |
+
+
+ res/ |
+ (required) This folder holds all the resources for
+ your application. Resources are external data files or description files
+ that are compiled into your code at build time. Files in different folders
+ are compiled differently, so you must put the proper resource into the
+ proper folder. (See Resources for details.) |
+
+
+ anim/
+ animation1.xml
+ ... |
+ (optional) Holds any animation XML description files that the
+ application uses. The format of these files is described in Resources. |
+
+
+ drawable/
+ some_picture.png
+ some_stretchable.9.png
+ some_background.xml
+ ... |
+ (optional) Zero or more files that will be compiled to {@link
+ android.graphics.drawable android.graphics.drawable} resources. Files
+ can be image files (png, gif, or other) or XML files describing other
+ graphics such as bitmaps, stretchable bitmaps, or gradients. Supported
+ bitmap file formats are PNG (preferred), JPG, and GIF (discouraged),
+ as well as the custom 9-patch stretchable bitmap format. These formats
+ are described in Resources. |
+
+
+ layout/
+ screen_1_layout.xml
+ ...
|
+ (optional) Holds all the XML files describing screens or parts
+ of screens. Although you could create a screen in Java, defining them
+ in XML files is typically easier. A layout file is similar in concept
+ to an HTML file that describes the screen layout and components. See User Interface for more information about designing screens, and Available Resource Types for the syntax of these files. |
+
+
+ values/
+ arrays
+ classes.xml
+ colors.xml
+ dimens.xml
+ strings.xml
+ styles.xml
+ values.xml
|
+ (optional) XML files describing additional resources
+ such as strings, colors, and styles. The naming, quantity, and number
+ of these files are not enforced--any XML file is compiled, but these
+ are the standard names given to these files. However, the syntax
+ of these files is prescribed by Android, and described in Resources.
+ |
+
+
+ xml/ |
+ (optional) XML files that can be read at run time on the device. |
+
+
+ raw/ |
+ (optional) Any files to be copied directly to the device. |
+
+
+
+
+
+Print Messages to a Log File
+
+To write log messages from your application:
+- Import
android.util.Log
.
+ - Use
Log.v()
, Log.d()
, Log.i()
,
+ Log.w()
, or Log.e()
to log messages.
+ (See the {@link android.util.Log} class.)
E.g.,
+ Log.e(this.toString(), "error: " + err.toString())
+ - Launch DDMS from a terminal
+ by executing
ddms
in your Android SDK /tools
path.
+ - Run your application in the Android emulator.
+ - From the DDMS application, select the emulator
+ (e.g., "emulator-5554") and click Device > Run logcat...
+ to view all the log data.
+
+Note: If you are running Eclipse and
+encounter a warning about the VM debug port when opening DDMS, you can ignore it
+if you're only interested in logs. However, if you want to further inspect and
+control your processes from DDMS, then you should close Eclipse before launching DDMS so that
+it may use the VM debugging port.
+
+
diff --git a/docs/html/resources/faq/framework.jd b/docs/html/resources/faq/framework.jd
new file mode 100644
index 0000000..f4b8db0
--- /dev/null
+++ b/docs/html/resources/faq/framework.jd
@@ -0,0 +1,197 @@
+page.title=Android Application Framework FAQ
+parent.title=FAQs, Tips, and How-to
+parent.link=index.html
+@jd:body
+
+
+
+
+
+
+Do all the Activities and Services of an application run in a
+single process?
+
+All Activities and Services in an application run in a single process by
+default. If needed, you can declare an android:process
attribute
+in your manifest file, to explicitly place a component (Activity/Service) in
+another process.
+
+
+
+
+
+Do all Activities run in the main thread of an application
+process?
+
+By default, all of the application code in a single process runs
+in the main UI thread. This is the same thread
+that also handles UI events. The only exception is the code that handles
+IPC calls coming in from other processes. The system maintains a
+separate pool of transaction threads in each process to dispatch all
+incoming IPC calls. The developer should create separate threads for any
+long-running code, to avoid blocking the main UI thread.
+
+
+
+
+
+How do I pass data between Activities/Services within a single
+application?
+
+It depends on the type of data that you want to share:
+
+Primitive Data Types
+
+To share primitive data between Activities/Services in an
+application, use Intent.putExtras(). For passing primitive data that
+needs to persist use the
+
+Preferences storage mechanism.
+
+Non-Persistent Objects
+
+For sharing complex non-persistent user-defined objects for short
+duration, the following approaches are recommended:
+
+ The android.app.Application class
+ The android.app.Application is a base class for those who need to
+maintain global application state. It can be accessed via
+getApplication() from any Activity or Service. It has a couple of
+life-cycle methods and will be instantiated by Android automatically if
+your register it in AndroidManifest.xml.
+
+ A public static field/method
+ An alternate way to make data accessible across Activities/Services is to use public static
+fields and/or methods. You can access these static fields from any other
+class in your application. To share an object, the activity which creates your object sets a
+static field to point to this object and any other activity that wants to use
+this object just accesses this static field.
+
+ A HashMap of WeakReferences to Objects
+ You can also use a HashMap of WeakReferences to Objects with Long
+keys. When an activity wants to pass an object to another activity, it
+simply puts the object in the map and sends the key (which is a unique
+Long based on a counter or time stamp) to the recipient activity via
+intent extras. The recipient activity retrieves the object using this
+key.
+
+ A Singleton class
+ There are advantages to using a static Singleton, such as you can
+refer to them without casting getApplication() to an
+application-specific class, or going to the trouble of hanging an
+interface on all your Application subclasses so that your various
+modules can refer to that interface instead.
+But, the life cycle of a static is not well under your control; so
+to abide by the life-cycle model, the application class should initiate and
+tear down these static objects in the onCreate() and onTerminate() methods
+of the Application Class
+
+
+Persistent Objects
+
+Even while an application appears to continue running, the system
+may choose to kill its process and restart it later. If you have data
+that you need to persist from one activity invocation to the next, you
+need to represent that data as state that gets saved by an activity when
+it is informed that it might go away.
+
+For sharing complex persistent user-defined objects, the
+following approaches are recommended:
+
+ - Application Preferences
+ - Files
+ - contentProviders
+ - SQLite DB
+
+
+
+If the shared data needs to be retained across points where the application
+process can be killed, then place that data in persistent storage like
+Application Preferences, SQLite DB, Files or ContentProviders. Please refer to
+the Data Storage
+for further details on how to use these components.
+
+
+
+
+
+
+How can I check if an Activity is already running before starting
+it?
+
+The general mechanism to start a new activity if its not running—
+or to bring the activity stack to the front if is already running in the
+background— is the to use the NEW_TASK_LAUNCH flag in the startActivity()
+call.
+
+
+
+
+
+If an Activity starts a remote service, is there any way for the
+Service to pass a message back to the Activity?
+
+The remote service can define a callback interface and register it with the
+clients to callback into the clients. The
+{@link android.os.RemoteCallbackList RemoteCallbackList} class provides methods to
+register and unregister clients with the service, and send and receive
+messages.
+
+The sample code for remote service callbacks is given in ApiDemos/RemoteService
+
+
+
+
+
+How to avoid getting the Application not responding dialog?
+
+Please read the Designing for Responsiveness
+document.
+
+
+
+
+
+
+How does an application know if a package is added or removed?
+
+
+Whenever a package is added, an intent with PACKAGE_ADDED action
+is broadcast by the system. Similarly when a package is removed, an
+intent with PACKAGE_REMOVED action is broadcast. To receive these
+intents, you should write something like this:
+
+ <receiver android:name ="com.android.samples.app.PackageReceiver">
+ <intent-filter>
+ <action android:name="android.intent.action.PACKAGE_ADDED"/>
+ <action android:name="android.intent.action.PACKAGE_REMOVED"/>
+
+ <data android:scheme="package" />
+ </intent-filter>
+ </receiver>
+
+
+Here PackageReceiver is a BroadcastReceiver class.Its onReceive()
+method is invoked, every time an application package is installed or
+removed.
+
+
+
+
+
diff --git a/docs/html/resources/faq/index.jd b/docs/html/resources/faq/index.jd
new file mode 100644
index 0000000..9a2614b
--- /dev/null
+++ b/docs/html/resources/faq/index.jd
@@ -0,0 +1,11 @@
+page.title=Android FAQs
+@jd:body
+
+
+ - Application Framework FAQ
+ - Common questions about the Android Application Framework.
+ - Open Source Licensing FAQ
+ - Common topics around licensing and Android Open Source
+ - Android Security FAQ
+ - Answers to common questions about Android security.
+
diff --git a/docs/html/resources/faq/licensingandoss.jd b/docs/html/resources/faq/licensingandoss.jd
new file mode 100644
index 0000000..c267fe8
--- /dev/null
+++ b/docs/html/resources/faq/licensingandoss.jd
@@ -0,0 +1,19 @@
+page.title=Android Open Source Licensing FAQ
+parent.title=FAQs, Tips, and How-to
+parent.link=index.html
+@jd:body
+
+
+
+Where can I find the open source components of Android?
+The source code for the full Android stack is available from the Android Open Source Project site.
+
+
Other mirrored GPL and LGPL'd components are available at http://code.google.com/p/android/downloads/list
.
+Notices for other licenses can be found within the SDK.
+
+Why are you releasing the code under the Apache License instead of GPLv2?
+One of the best explanations for the reasoning behind releasing code under Apache2 can be found in a ArsTechnica article by Ryan Paul.
diff --git a/docs/html/resources/faq/security.jd b/docs/html/resources/faq/security.jd
new file mode 100644
index 0000000..b0d832b
--- /dev/null
+++ b/docs/html/resources/faq/security.jd
@@ -0,0 +1,156 @@
+page.title=Android Security FAQ
+parent.title=FAQs, Tips, and How-to
+parent.link=index.html
+@jd:body
+
+
+
+
+Is Android secure?
+
+The security and privacy of our users' data is of primary importance to the
+Android Open Source Project. We are dedicated to building and maintaining one
+of the most secure mobile platforms available while still fulfilling our goal
+of opening the mobile device space to innovation and competition.
+
+The Android Platform provides a rich security model
+that allows developers to request the capabilities, or access, needed by their
+application and to define new capabilities that other applications can request.
+The Android user can choose to grant or deny an application's request for
+certain capabilities on the handset.
+
+We have made great efforts to secure the Android platform, but it is
+inevitable that security bugs will be found in any system of this complexity.
+Therefore, the Android team works hard to find new bugs internally and responds
+quickly and professionally to vulnerability reports from external researchers.
+
+
+
+I think I found a security flaw. How do I
+report it?
+
+You can reach the Android security team at security@android.com. If you like, you
+can protect your message using our PGP
+key.
+
+We appreciate researchers practicing responsible disclosure by emailing us
+with a detailed summary of the issue and keeping the issue confidential while
+users are at risk. In return, we will make sure to keep the researcher informed
+of our progress in issuing a fix and will properly credit the reporter(s) when
+we announce the patch. We will always move swiftly to mitigate or fix an
+externally-reported flaw and will publicly announce the fix once patches are
+available to users.
+
+
+How can I stay informed of Android
+security announcements?
+
+An important part of sustainably securing a platform, such as, Android is
+keeping the user and security community informed of bugs and fixes. We will
+publicly announce security bugs when the fixes are available via postings to
+the android-security-announce
+group on Google Groups. You can subscribe to this group as you would a mailing
+list and view the archives here.
+
+For more general discussion of Android platform security, or how to use
+security features in your Android application, please subscribe to android-security-discuss.
+
+
+
+How do I securely use my Android phone?
+
+As an open platform, Android allows users to load software from any
+developer onto a device. As with a home PC, the user must be
+aware of who is providing the software they are downloading and must decide
+whether they want to grant the application the capabilities it requests.
+This decision can be informed by the user's judgment of the software
+developer's trustworthiness, and where the software came from.
+
+Despite the security protections in Android, it is important
+for users to only download and install software from developers they trust.
+More details on how Android users can make smart security decisions will be
+released when consumer devices become available.
+
+
+I think I found malicious software being
+distributed for Android. How can I help?
+
+Like any other open platform, it will be possible for unethical developers
+to create malicious software, known as malware, for Android. If you
+think somebody is trying to spread malware, please let us know at security@android.com. Please include as
+much detail about the application as possible, with the location it is
+being distributed from and why you suspect it of being malicious software.
+
+The term malicious software is subjective, and we cannot make an
+exhaustive definition. Some examples of what the Android Security Team believes
+to be malicious software is any application that:
+
+ - drains the device's battery very quickly;
+ - shows the user unsolicited messages (especially messages urging the
+ user to buy something);
+ - resists (or attempts to resist) the user's effort to uninstall it;
+ - attempts to automatically spread itself to other devices;
+ - hides its files and/or processes;
+ - discloses the user's private information to a third party, without the
+ user's knowledge and consent;
+ - destroys the user's data (or the device itself) without the user's
+ knowledge and consent;
+ - impersonates the user (such as by sending email or buying things from a
+ web store) without the user's knowledge and consent; or
+ - otherwise degrades the user's experience with the device.
+
+
+
+
+How will Android-powered devices receive security
+fixes?
+
+The manufacturer of each device is responsible for distributing software
+upgrades for it, including security fixes. Many devices will update themselves
+automatically with software downloaded "over the air", while some devices
+require the user to upgrade them manually.
+
+When Android-powered devices are publicly available, this FAQ will provide links how
+Open Handset Alliance members release updates.
+
+Can I get a fix directly from the
+Android Platform Project?
+
+Android is a mobile platform that will be released as open source and
+available for free use by anybody. This means that there will be many
+Android-based products available to consumers, and most of them will be created
+without the knowledge or participation of the Android Open Source Project. Like
+the maintainers of other open source projects, we cannot build and release
+patches for the entire ecosystem of products using Android. Instead, we will
+work diligently to find and fix flaws as quickly as possible and to distribute
+those fixes to the manufacturers of the products.
+
+In addition, We will add security fixes to the open source distribution of
+Android and publicly announce the changes on android-security-announce.
+
+
+If you are making an Android-powered device and would like to know how you can
+properly support your customers by keeping abreast of software updates, please
+contact us at info@openhandsetalliance.com.
diff --git a/docs/html/resources/faq/troubleshooting.jd b/docs/html/resources/faq/troubleshooting.jd
new file mode 100644
index 0000000..0cf1ab0
--- /dev/null
+++ b/docs/html/resources/faq/troubleshooting.jd
@@ -0,0 +1,261 @@
+page.title=Troubleshooting
+parent.title=FAQs, Tips, and How-to
+parent.link=index.html
+@jd:body
+
+
+Here are some tips and tricks for common Android errors. Don't forget to use the
+ ddms logcat capability to get a deeper view when errors occur. See Debugging for more debugging tips.
+
+
+ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui".
+
+The "Android Editors" feature of the ADT Plugin requires specific Eclipse components, such as WST. If you
+encounter this error message during ADT installation, you need to install the
+required Eclipse components and then try the ADT installation again. Follow the steps below to install the required components for the
+Android Editors feature, based on the version of Eclipse that you are using.
+
+
+Eclipse 3.3 (Europa) | Eclipse 3.4 (Ganymede) |
+
+
+
+- From the dialog where you select the Update sites to visit, select the checkboxes for both the
+ADT site, and the Callisto/Europa/Ganymede Discovery Site (you may want to
+check Automatically select mirrors at the bottom).
+- Click Finish.
+- In the Next dialog, select the Android Plugins.
+- Now, expand the tree item of the discovery site. It seems that if you
+don't do it, it doesn't load the content of the discovery site.
+- On the right, click Select required. This will select all the components
+that are required to install the Android plugin (wst, emf, etc...).
+- Click Next, accept the agreement, click Install All, and restart Eclipse.
+
+ |
+
+
+ - Select Help > Software Updates...
+ - Select the Installed Software tab.
+ - Click Update...
+ - If an update for ADT is available, select it and click Finish.
+
+ |
+
+
+
+
+
+ADB reports "no device" when an emulator is running
+ Try restarting adb by stopping it (adb
+ kill-server
) then any other adb command to restart it.
+
+My new application/activity isn't showing up in the
+ applications list
+
+ - You often must restart your device or emulator before a new activity shows
+ up in the applications list. This is particularly true when it is a completely
+ new application with a new AndroidManifest.xml file.
+ - If this is for a new activity in an existing AndroidManifest.xml file, did
+ you include an
<activity>
tag for your app (or a <service>
tag
+ for a service, or a <receiver>
tag for a receiver, etc.)?
+ - Make sure that your AndroidManifest.xml file is valid. Errors in attribute
+ values, such as the value attribute in
<action value="<something>">
+ will often not be caught by compilers, but will prevent your application
+ from being displayed because the intent filter will not be matched. Extra
+ spaces or other characters can often sneak into these strings.
+ - Did you send your .apk file to the device (adb install)?
+ - Run logcat on your device (
adb logcat
)
+ and then install your .apk file. Check the logcat output to see whether the
+ application is being installed and recognized properly. Here's sample output
+ from a successful installation:
+I/FileObserver( 414): *** onEvent wfd: 3 mask: 8 path: MyRSSReader.apk
+D/PackageManager( 414): Scanning package: /data/app/MyRSSReader.apk
+D/PackageManager( 414): Adding package com.example.codelab.rssexample
+D/PackageManager( 414): Registered content provider: my_rss_item, className = com.example.codelab.rssexample.RssContentProvider, isSyncable = false
+D/PackageManager( 414): Providers: com.example.codelab.rssexample.RssContentProvider
+D/PackageManager( 414): Activities: com.example.codelab.rssexample.MyRssReader com.example.codelab.rssexample.MyRssReader2
+
+ - If logcat shows that the package manager is having problems loading the manifest
+ file, force your manifest to be recompiled by adding a space in the file and
+ compiling it.
+
+I updated my app, but the updates don't seem to be showing up on the device
+ Did you remember to send your .apk file to the device (adb
+ install)?
+
+I'm getting a "Binary XML file line #2: You must supply a layout_wilih
+ attribute" error
+ when I start an application (but I declare a layout_wilih attribute right
+ there!!!)
+
+ - Make sure that the SDK you are building with is the same version as the Android
+ OS that you are running on.
+ - Make sure that you're calling setContentView() early in your onCreate() method.
+ Calling other methods, such as setListAdapter() before calling setContentView()
+ can sometimes create odd errors when Android tries to access screen elements
+ that haven't been set before.
+
+My request to (make a call, catch an incoming SMS,
+receive a notification, send an intent to an Android application) is being
+ignored
+ You might not have permission (or might not have requested permission) to
+ call this activity or receive this intent. Many standard Android activities,
+ such as making a call, have a permission assigned to it to prevent arbitrary
+ applications from sending or receiving requests. See Security and
+ Permissions for more information on permissions, and
+ {@link android.Manifest.permission Manifest.permission} for a list of
+ standard permissions supported by the Android platform.
+
+Help! My project won't build in Eclipse
+If your project doesn't build, you may notice symptoms such as new
+resources added in the res/
sub-folders not showing up in the R class,
+the emulator not being started, not being able to run the application, or even seeming to run an old version of the application.
+To troubleshoot these types of problems, first try:
+
+ - Switch to the DDMS view in Eclipse (if you don't already have it open):
+
+ - From the menu select
Window > Open Perspective > Other
+ - Select DDMS from the list and hit OK
+
+
+ - In the Devices panel (top right panel by default), click on the down triangle
+ to bring up the panel menu
+ - Select
Reset ADB
from the menu, and then try running the
+ application again
+
+If the above still doesn't work, you can try these steps:
+
+ -
+ Check the console and problems tabs at the bottom of the Eclipse UI
+
+ -
+ If there are problems listed in either place, they should give you a clue
+ what is wrong
+
+ -
+ If you aren't sure if the problems are fresh or stale, clear the console
+ with a right click > Clear, then clean the project
+
+ -
+ To clean the project (a good idea with any kind of build error), select
+ Project > Clean from the eclipse main menu, then select the project you
+ are working on (or clean all)
+
+
+Eclipse isn't talking to the emulator
+When communication doesn't seem to be happening between Eclipse and the emulator, symptoms can include: nothing happening when you press run, the emulator hanging waiting
+for a debugger to connect, or errors that Eclipse reports about not being able
+to find the emulator or shell. By far the most common symptom is that when you press run, the emulator starts (or
+is already running), but the application doesn't start.
+
+You may find any of these steps will fix the problem and with practice you
+probably can figure out which one you need to do for your particular issue, but
+to start with, the safest option is to run through all of them in order:
+
+ -
+ Quit the emulator if it is running
+
+ -
+ Check that any emulator processes are killed (sometimes they can hang, use ps on unix or mac, or task manager in the process view on
+ windows).
+
+ -
+ Quit Eclipse
+
+ -
+ From the command line, type:
+
adb kill-server
+
+ -
+ Start Eclipse and try again
+
+
+
+When I go to preferences in Eclipse and select "Android", I get the following error message: Unsupported major.minor version 49.0.
+This error is displayed if you are using an older version of the JDK. Please make sure you are using JDK version 5 or 6.
+
+I can't install ApiDemos apps in my IDE because of a signing error
+
+The Android system requires that all applications be signed, as described in
+ Signing Your Applications. The ApiDemos
+applications included with the SDK are preinstalled on the emulator and for that reason have been
+compiled and signed with a private key.
+
+If you want to modify or run one of the ApiDemos apps from Eclipse/ADT or other IDE, you can do so
+so only after you uninstall the preinstalled version of the app from the emulator. If
+you try to run an ApiDemos apps from your IDE without removing the preinstalled version first,
+you will get errors similar to:
+
+[2008-08-13 15:14:15 - ApiDemos] Re-installation failed due to different application signatures.
+[2008-08-13 15:14:15 - ApiDemos] You must perform a full uninstall of the application. WARNING: ...This will remove the application data!
+[2008-08-13 15:14:15 - ApiDemos] Please execute 'adb uninstall com.android.samples' in a shell.
+
+The error occurs because, in this case, you are attempting to install another copy of ApiDemos
+onto the emulator, a copy that is signed with a different certificate (the Android IDE tools will
+have signed the app with a debug certificate, where the existing version was already signed with
+a private certificate). The system does not allow this type of reinstallation.
+
+To resolve the issue, you need to fully uninstall the preinstalled and then reinstall it using
+the adb tool. Here's how to do that:
+
+
+ - In a terminal, change to the tools directory of the SDK.
+ - If no emulator instance is running, start an emulator using using the command
emulator &
.
+ - Uninstall the preinstalled app using the command
adb uninstall com.android.samples
.
+ - Reinstall the app using the command
adb install <path to the ApiDemos.apk>
. If you are
+ working in Eclipse/ADT, you can just compile and run the app in the normal way.
+
+
+Note that if multiple emulator instances are running, you need to direct your uninstall/install
+commands to the emulator instance that you are targeting. To do that you can add the
+-s <serialNumber>
to the command, for example:
+
+adb -s emulator-5556 install
+
+For more information about adb, see the Android Debug Bridge
+documentation.
+
+
+I can't compile my app because the build tools generated an expired debug certificate
+
+If your development machine uses a locale that has a non-Gregorian calendar, you may encounter problems when first trying to compile and run your application. Specifically, you may find that the Android build tools won't compile your application because the debug key is expired.
+
+The problem occurs because the Keytool utility — included in the JDK and used by the Android build tools — fails to properly handle non-Gregorian locales and may create validity dates that are in the past. That is, it may generate a debug key that is already expired, which results in the compile error.
+
+If you encounter this problem, follow these steps to work around it:
+
+
+- First, delete the debug keystore/key already generated by the Android build tools. Specifically, delete the
debug.keystore
file. On Linux/Mac OSX, the file is stored in ~/.android
. On Windows XP, the file is stored in
+C:\Documents and Settings\<user>\.android
. On Windows Vista, the file is stored in
+C:\Users\<user>\.android
+- Next, you can either
+
+- Temporarily change your development machine's locale (date and time) to one that uses a Gregorian calendar, for example, United States. Once the locale is changed, use the Android build tools to compile and install your app. The build tools will regenerate a new keystore and debug key with valid dates. Once the new debug key is generated, you can reset your development machine to the original locale.
+- Alternatively, if you do not want to change your machine's locale settings, you can generate the keystore/key on any machine using the Gregorian calendar, then copy the
debug.keystore
file from that computer to the proper location on your development machine.
+
+
+
+
+This problem has been verified on Windows and may apply to other platforms.
+
+For general information about signing Android applications, see
+Signing Your Applications.
+
diff --git a/docs/html/resources/index.jd b/docs/html/resources/index.jd
new file mode 100644
index 0000000..5174dee
--- /dev/null
+++ b/docs/html/resources/index.jd
@@ -0,0 +1,38 @@
+page.title=Developer Resources
+@jd:body
+
+
+This section provides technical articles, tutorials, sample code, and other
+information to help you quickly implement the features you want in your
+application.
+
+
+
+- Technical Articles
+- Focused discussions about Android development subjects, including
+optimizations, tips, interesting implementations,
+and so on. Most of the articles provide "how-to" instructions for adding
+features or functionality to your app. The articles are drawn from posts to the
+Android Developers Blog.
+
+
+- Tutorials
+- Step-by-step instructions demonstrating how to build an Android application
+that has the specific features you want.
+
+- Sample Code
+- Fully-functioning sample applications that you can look at or build and run,
+to learn about how Android works. Feel free to reuse any of the code or
+techniques that you find in the samples!
+
+- Community
+- Links to the Android discussion groups and information about other ways to
+collaborate with other developers.
+
+- More
+- Quick development tips, troubleshooting information, and frequently asked
+questions (FAQs).
+
+
+To return to this page later, just click the "Resources" tab while any
+Resources page is loaded.
\ No newline at end of file
diff --git a/docs/html/resources/resources_toc.cs b/docs/html/resources/resources_toc.cs
new file mode 100644
index 0000000..60d044a
--- /dev/null
+++ b/docs/html/resources/resources_toc.cs
@@ -0,0 +1,242 @@
+
+ -
+
Community
+
+ Comunidad
+ Communauté
+
+ コミュニティ
+ 社区
+ 社群
+
+
+
+
+ -
+
Technical Articles
+
+
+
+
+ -
+
Tutorials
+ Lernprogramme
+ Tutoriales
+ Didacticiels
+ Esercitazioni
+ チュートリアル
+
+
+
+
+
+
+
+ -
+
Sample Code
+ Beispielcode
+ Código de ejemplo
+ Exemple de code
+ Codice di esempio
+ サンプル コード
+
+
+
+
+
+
+
+
+ -
+
More
+
+
+
+
+
+
+
+
diff --git a/docs/html/resources/samples/images/BluetoothChat1.png b/docs/html/resources/samples/images/BluetoothChat1.png
new file mode 100644
index 0000000..f87da6a
Binary files /dev/null and b/docs/html/resources/samples/images/BluetoothChat1.png differ
diff --git a/docs/html/resources/samples/images/BluetoothChat2.png b/docs/html/resources/samples/images/BluetoothChat2.png
new file mode 100644
index 0000000..6218eff
Binary files /dev/null and b/docs/html/resources/samples/images/BluetoothChat2.png differ
diff --git a/docs/html/resources/samples/images/ContactManager1.png b/docs/html/resources/samples/images/ContactManager1.png
new file mode 100644
index 0000000..5bfd27b
Binary files /dev/null and b/docs/html/resources/samples/images/ContactManager1.png differ
diff --git a/docs/html/resources/samples/images/ContactManager2.png b/docs/html/resources/samples/images/ContactManager2.png
new file mode 100644
index 0000000..0a11ec3
Binary files /dev/null and b/docs/html/resources/samples/images/ContactManager2.png differ
diff --git a/docs/html/resources/samples/images/HomeSample.png b/docs/html/resources/samples/images/HomeSample.png
new file mode 100644
index 0000000..990bebb
Binary files /dev/null and b/docs/html/resources/samples/images/HomeSample.png differ
diff --git a/docs/html/resources/samples/images/JetBoy.png b/docs/html/resources/samples/images/JetBoy.png
new file mode 100644
index 0000000..3da0448
Binary files /dev/null and b/docs/html/resources/samples/images/JetBoy.png differ
diff --git a/docs/html/resources/samples/images/MultiResolution.png b/docs/html/resources/samples/images/MultiResolution.png
new file mode 100644
index 0000000..8b245d9
Binary files /dev/null and b/docs/html/resources/samples/images/MultiResolution.png differ
diff --git a/docs/html/resources/samples/images/SearchableDictionary1.png b/docs/html/resources/samples/images/SearchableDictionary1.png
new file mode 100644
index 0000000..ebb4604
Binary files /dev/null and b/docs/html/resources/samples/images/SearchableDictionary1.png differ
diff --git a/docs/html/resources/samples/images/SearchableDictionary2.png b/docs/html/resources/samples/images/SearchableDictionary2.png
new file mode 100644
index 0000000..34746cd
Binary files /dev/null and b/docs/html/resources/samples/images/SearchableDictionary2.png differ
diff --git a/docs/html/resources/samples/images/Snake.png b/docs/html/resources/samples/images/Snake.png
new file mode 100644
index 0000000..c5211d8
Binary files /dev/null and b/docs/html/resources/samples/images/Snake.png differ
diff --git a/docs/html/resources/samples/images/SoftKeyboard.png b/docs/html/resources/samples/images/SoftKeyboard.png
new file mode 100644
index 0000000..8a4ec63
Binary files /dev/null and b/docs/html/resources/samples/images/SoftKeyboard.png differ
diff --git a/docs/html/resources/samples/images/Wiktionary.png b/docs/html/resources/samples/images/Wiktionary.png
new file mode 100644
index 0000000..eae5da5
Binary files /dev/null and b/docs/html/resources/samples/images/Wiktionary.png differ
diff --git a/docs/html/resources/samples/images/WiktionarySimple.png b/docs/html/resources/samples/images/WiktionarySimple.png
new file mode 100644
index 0000000..a23226b
Binary files /dev/null and b/docs/html/resources/samples/images/WiktionarySimple.png differ
diff --git a/docs/html/resources/samples/images/sample_lunarlander.png b/docs/html/resources/samples/images/sample_lunarlander.png
new file mode 100644
index 0000000..a2ff75a
Binary files /dev/null and b/docs/html/resources/samples/images/sample_lunarlander.png differ
diff --git a/docs/html/resources/samples/images/sample_note.png b/docs/html/resources/samples/images/sample_note.png
new file mode 100644
index 0000000..8fc9dcc
Binary files /dev/null and b/docs/html/resources/samples/images/sample_note.png differ
diff --git a/docs/html/resources/samples/images/sample_notepad.png b/docs/html/resources/samples/images/sample_notepad.png
new file mode 100644
index 0000000..46f2211
Binary files /dev/null and b/docs/html/resources/samples/images/sample_notepad.png differ
diff --git a/docs/html/resources/samples/index.jd b/docs/html/resources/samples/index.jd
new file mode 100644
index 0000000..7fbbea1
--- /dev/null
+++ b/docs/html/resources/samples/index.jd
@@ -0,0 +1,72 @@
+guide=true
+page.title=Sample Code
+@jd:body
+
+
+Sometimes, the best way to learn how things are done is to look at some code.
+Here, you can browse the source of some sample Android applications that are included
+in the Android SDK.
+
+Each version of the Android platform available for the SDK includes a full set of sample
+applications (which may vary between different versions of the platform).
+You can find the samples in your SDK at:
+
+
+<sdk>/platforms/android-<version>/samples/
+
+
+You can easily create new Android projects with these samples, modify them
+if you'd like, then run them on an emulator or device. For example, to create
+a project for the API Demos app from Eclipse,
+start a new Android Project, select "Create project from existing source", then select
+{@code ApiDemos} in the {@code samples/} directory. To create the API Demos project
+using the {@code android} tool, execute:
+
+android update project -s -n API Demos -t <target_ID> -p <path-to-platform>/samples/ApiDemos/
+
+
+The pages below provide an overview of each sample application (available with most
+platforms) and allow you to view the source files in your browser.
+
+
+
+ - API Demos
+ - A variety of small applications that demonstrate an extensive collection of
+ framework topics.
+
+ - Home
+ - An application for saving notes. Similar (but not identical) to the
+ Notepad tutorial.
+
+ - JetBoy
+ - JetBoy is a game that demonstrates the SONiVOX JET interactive music technology,
+ with {@link android.media.JetPlayer}.
+
+ - Lunar Lander
+ - A classic Lunar Lander game.
+
+ - Note Pad
+ - An application for saving notes. Similar (but not identical) to the
+ Notepad tutorial.
+
+ - Searchable Dictionary
+ - A sample application that demonstrates Android's search framework,
+ including how to provide search suggestions for Quick Search Box.
+
+ - Snake
+ - An implementation of the classic game "Snake."
+
+ - Soft Keyboard
+ - An example of writing an input method for a software keyboard.
+
+
+
+
+
+
For more sample applications, check out
+apps-for-android, a
+collection of open source applications that demonstrate various Android APIs.
+
+
+
+
diff --git a/docs/html/resources/tutorials/hello-world.jd b/docs/html/resources/tutorials/hello-world.jd
new file mode 100644
index 0000000..58d1a16
--- /dev/null
+++ b/docs/html/resources/tutorials/hello-world.jd
@@ -0,0 +1,564 @@
+page.title=Hello, World
+@jd:body
+
+
+
+As a developer, you know that the first impression
+of a development framework is how easy it is to write "Hello,
+World." Well, on Android, it's pretty easy.
+It's particularly easy if you're using Eclipse as your IDE, because we've provided a
+great plugin that handles your project creation and management to greatly speed-up your
+development cycles.
+
+If you're not using Eclipse, that's okay. Familiarize yourself with
+Developing in Other IDEs.
+You can then return to this tutorial and ignore anything about Eclipse.
+
+Before you start, you should already have the very latest SDK installed, and if you're using
+Eclipse, you should have installed the ADT plugin as well. If you have not installed these, see
+Installing the Android SDK and return
+here when you've completed the installation.
+
+Create an AVD
+
+
+
+
To learn more about how to use AVDs and the options
+ available to you, refer to the
+ Android
+ Virtual Devices document.
+
+
+
+In this tutorial, you will run your application in the Android Emulator.
+Before you can launch the emulator, you must create an
+Android Virtual Device (AVD). An AVD defines the system image and
+device settings used by the emulator.
+
+To create an AVD, use the "android" tool provided in the Android SDK.
+Open a command prompt or terminal, navigate to the
+tools/
directory in the SDK package and execute:
+
+android create avd --target 2 --name my_avd
+
+
+The tool now asks if you would like to create a custom hardware profile.
+For the time being, press Return to skip it ("no" is the default response).
+That's it. This configures an AVD named "my_avd" that uses the Android 1.5
+platform. The AVD is now ready for use in the emulator.
+
+In the above command, the --target
option is required
+and specifies the deployment target to run on the emulator.
+The --name
option is also required and defines the
+name for the new AVD.
+
+
+Create a New Android Project
+
+After you've created an AVD, the next step is to start a new
+Android project in Eclipse.
+
+
+ - From Eclipse, select File > New > Project.
+
If the ADT
+ Plugin for Eclipse has been successfully installed, the resulting dialog
+ should have a folder labeled "Android" which should contain
+ "Android Project". (After you create one or more Android projects, an entry for
+ "Android XML File" will also be available.)
+
+
+ - Select "Android Project" and click Next.
+
+
+
+ - Fill in the project details with the following values:
+
+ - Project name: HelloAndroid
+ - Application name: Hello, Android
+ - Package name: com.example.helloandroid (or your own private namespace)
+ - Create Activity: HelloAndroid
+ - Min SDK Version: 2
+
+ Click Finish.
+
+
+
+ Here is a description of each field:
+
+
+ - Project Name
+ - This is the Eclipse Project name — the name of the directory
+ that will contain the project files.
+ - Application Name
+ - This is the human-readable title for your application — the name that
+ will appear on the Android device.
+ - Package Name
+ - This is the package namespace (following the same rules as for
+ packages in the Java programming language) that you want all your source code to
+ reside under. This also sets the package name under which the stub
+ Activity will be generated.
+
Your package name must be unique across
+ all packages installed on the Android system; for this reason, it's very
+ important to use a standard domain-style package for your
+ applications. The example above uses the "com.example" namespace, which is
+ a namespace reserved for example documentation —
+ when you develop your own applications, you should use a namespace that's
+ appropriate to your organization or entity.
+ - Create Activity
+ - This is the name for the class stub that will be generated by the plugin.
+ This will be a subclass of Android's {@link android.app.Activity} class. An
+ Activity is simply a class that can run and do work. It can create a UI if it
+ chooses, but it doesn't need to. As the checkbox suggests, this is optional, but an
+ Activity is almost always used as the basis for an application.
+ - Min SDK Version
+ - This value specifies the minimum API Level required by your application. If the API Level
+ entered here matches the API Level provided by one of the available targets,
+ then that Build Target will be automatically selected (in this case, entering
+ "2" as the API Level will select the Android 1.1 target). With each new
+ version of the Android system image and Android SDK, there have likely been
+ additions or changes made to the APIs. When this occurs, a new API Level is assigned
+ to the system image to regulate which applications are allowed to be run. If an
+ application requires an API Level that is higher than the level supported
+ by the device, then the application will not be installed.
+
+
+ Other fields: The checkbox for "Use default location" allows you to change
+ the location on disk where the project's files will be generated and stored. "Build Target"
+ is the platform target that your application will be compiled against
+ (this should be selected automatically, based on your Min SDK Version).
+
+ Notice that the "Build Target" you've selected uses the Android 1.1
+ platform. This means that your application will be compiled against the Android 1.1
+ platform library. If you recall, the AVD created above runs on the Android 1.5 platform.
+ These don't have to match; Android applications are forward-compatible, so an application
+ built against the 1.1 platform library will run normally on the 1.5 platform. The reverse
+ is not true.
+
+
+
+Your Android project is now ready. It should be visible in the Package
+Explorer on the left.
+Open the HelloAndroid.java
file, located inside HelloAndroid > src >
+com.example.helloandroid). It should look like this:
+
+
+package com.example.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
+
+Notice that the class is based on the {@link android.app.Activity} class. An Activity is a
+single application entity that is used to perform actions. An application may have many separate
+activities, but the user interacts with them one at a time. The
+{@link android.app.Activity#onCreate(Bundle) onCreate()} method
+will be called by the Android system when your Activity starts —
+it is where you should perform all initialization and UI setup. An activity is not required to
+have a user interface, but usually will.
+
+Now let's modify some code!
+
+
+Construct the UI
+
+Take a look at the revised code below and then make the same changes to your HelloAndroid class.
+The bold items are lines that have been added.
+
+
+package com.android.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView tv = new TextView(this);
+ tv.setText("Hello, Android");
+ setContentView(tv);
+ }
+}
+
+Tip: An easy way to add import packages to your project is
+to press Ctrl-Shift-O (Cmd-Shift-O, on Mac). This is an Eclipse
+shortcut that identifies missing packages based on your code and adds them for you.
+
+An Android user interface is composed of hierarchies of objects called
+Views. A {@link android.view.View} is a drawable object used as an element in your UI layout,
+such as a button, image, or (in this case) a text label. Each of these objects is a subclass
+of the View class and the subclass that handles text is {@link android.widget.TextView}.
+
+In this change, you create a TextView with the class constructor, which accepts
+an Android {@link android.content.Context} instance as its parameter. A
+Context is a handle to the system; it provides services like
+resolving resources, obtaining access to databases and preferences, and so
+on. The Activity class inherits from Context, and because your
+HelloAndroid class is a subclass of Activity, it is also a Context. So, you can
+pass this
as your Context reference to the TextView.
+
+Next, you define the text content with
+{@link android.widget.TextView setText(CharSequence) setText()}.
+
+Finally, you pass the TextView to
+{@link android.app.Activity#setContentView(View) setContentView()} in order to
+display it as the content for the Activity UI. If your Activity doesn't
+call this method, then no UI is present and the system will display a blank
+screen.
+
+There it is — "Hello, World" in Android! The next step, of course, is
+to see it running.
+
+
+Run the Application
+
+The Eclipse plugin makes it very easy to run your applications:
+
+
+ - Select Run > Run.
+ - Select "Android Application".
+
+
+
+
+The Eclipse ADT will automatically create a new run configuration for your project
+and the Android Emulator will automatically launch. Once the emulator is booted up,
+your application will appear after a moment. You should now see something like this:
+
+
+
+The "Hello, Android" you see in the grey bar is actually the application title. The Eclipse plugin
+creates this automatically (the string is defined in the res/values/strings.xml
file and referenced
+by your AndroidManifest.xml
file). The text below the title is the actual text that you have
+created in the TextView object.
+
+That concludes the basic "Hello World" tutorial, but you should continue reading for some more
+valuable information about developing Android applications.
+
+
+Upgrade the UI to an XML Layout
+
+The "Hello, World" example you just completed uses what is called a "programmatic"
+UI layout. This means that you constructed and built your application's UI
+directly in source code. If you've done much UI programming, you're
+probably familiar with how brittle that approach can sometimes be: small
+changes in layout can result in big source-code headaches. It's also very
+easy to forget to properly connect Views together, which can result in errors in
+your layout and wasted time debugging your code.
+
+That's why Android provides an alternate UI construction model: XML-based
+layout files. The easiest way to explain this concept is to show an
+example. Here's an XML layout file that is identical in behavior to the
+programmatically-constructed example:
+
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/hello"/>
+
+The general structure of an Android XML layout file is simple: it's a tree
+of XML elements, wherein each node is the name of a View class
+(this example, however, is just one View element). You can use the
+name of any class that extends {@link android.view.View} as an element in your XML layouts,
+including custom View classes you define in your own code. This
+structure makes it very easy to quickly build up UIs, using a more simple
+structure and syntax than you would use in a programmatic layout. This model is inspired
+by the web development model, wherein you can separate the presentation of your
+application (its UI) from the application logic used to fetch and fill in data.
+
+In the above XML example, there's just one View element: the TextView
,
+which has four XML attributes. Here's a summary of what they mean:
+
+
+
+
+
+ Attribute
+ |
+
+ Meaning
+ |
+
+
+
+ xmlns:android
+ |
+
+ This is an XML namespace declaration that tells the Android tools that you are going to refer to common attributes defined in the Android namespace. The outermost tag in every Android layout file must have this attribute.
+ |
+
+
+
+ android:layout_width
+ |
+
+ This attribute defines how much of the available width on the screen this View should consume.
+In this case, it's the only View so you want it to take up the entire screen, which is what a value of "fill_parent" means.
+ |
+
+
+
+ android:layout_height
+ |
+
+ This is just like android:layout_width, except that it refers to available screen height.
+ |
+
+
+
+ android:text
+ |
+
+ This sets the text that the TextView should display. In this example, you use a string
+ resource instead of a hard-coded string value.
+ The hello string is defined in the res/values/strings.xml file. This is the
+ recommended practice for inserting strings to your application, because it makes the localization
+ of your application to other languages graceful, without need to hard-code changes to the layout file.
+ For more information, see Resources
+ and Internationalization.
+ |
+
+
+
+
+
+These XML layout files belong in the res/layout/
directory of your project. The "res" is
+short for "resources" and the directory contains all the non-code assets that
+your application requires. In addition to layout files, resources also include assets
+such as images, sounds, and localized strings.
+
+
+
Landscape layout
+
When you want a different design for landscape, put your layout XML file
+ inside /res/layout-land. Android will automatically look here when the layout changes.
+ Without this special landscape layout defined, Android will stretch the default layout.
+
+
+The Eclipse plugin automatically creates one of these layout files for you: main.xml.
+In the "Hello World" application you just completed, this file was ignored and you created a
+layout programmatically. This was meant to teach you more
+about the Android framework, but you should almost always define your layout
+in an XML file instead of in your code.
+The following procedures will instruct you how to change your
+existing application to use an XML layout.
+
+
+ - In the Eclipse Package Explorer, expand the
+
/res/layout/
folder and open main.xml
(once opened, you might need to click
+the "main.xml" tab at the bottom of the window to see the XML source). Replace the contents with
+the following XML:
+
+<?xml version="1.0" encoding="utf-8"?>
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:text="@string/hello"/>
+Save the file.
+
+
+- Inside the
res/values/
folder, open strings.xml
.
+This is where you should save all default text strings for your user interface. If you're using Eclipse, then
+ADT will have started you with two strings, hello and app_name.
+Revise hello to something else. Perhaps "Hello, Android! I am a string resource!"
+The entire file should now look like this:
+
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="hello">Hello, Android! I am a string resource!</string>
+ <string name="app_name">Hello, Android</string>
+</resources>
+
+
+
+- Now open and modify your
HelloAndroid
class use the
+XML layout. Edit the file to look like this:
+
+package com.example.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ }
+}
+
+When you make this change, type it by hand to try the
+code-completion feature. As you begin typing "R.layout.main" the plugin will offer you
+suggestions. You'll find that it helps in a lot of situations.
+
+Instead of passing setContentView()
a View object, you give it a reference
+to the layout resource.
+The resource is identified as R.layout.main
, which is actually a compiled object representation of
+the layout defined in /res/layout/main.xml
. The Eclipse plugin automatically creates this reference for
+you inside the project's R.java class. If you're not using Eclipse, then the R.java class will be generated for you
+when you run Ant to build the application. (More about the R class in a moment.)
+
+
+
+Now re-run your application — because you've created a launch configuration, all
+you need to do is click the green arrow icon to run, or select
+Run > Run History > Android Activity. Other than the change to the TextView
+string, the application looks the same. After all, the point was to show that the two different
+layout approaches produce identical results.
+
+Tip: Use the shortcut Ctrl-F11
+(Cmd-Shift-F11, on Mac) to run your currently visible application.
+
+Continue reading for an introduction
+to debugging and a little more information on using other IDEs. When you're ready to learn more,
+read Application
+Fundamentals for an introduction to all the elements that make Android applications work.
+Also refer to the Developer's Guide
+introduction page for an overview of the Dev Guide documentation.
+
+
+
+
R class
+
In Eclipse, open the file named R.java
(in the gen/
[Generated Java Files] folder).
+It should look something like this:
+
+
+package com.example.helloandroid;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int icon=0x7f020000;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f040001;
+ public static final int hello=0x7f040000;
+ }
+}
+
+
+
A project's R.java
file is an index into all the resources defined in the
+file. You use this class in your source code as a sort of short-hand
+way to refer to resources you've included in your project. This is
+particularly powerful with the code-completion features of IDEs like Eclipse
+because it lets you quickly and interactively locate the specific reference
+you're looking for.
+
+
It's possible yours looks slighly different than this (perhaps the hexadecimal values are different).
+For now, notice the inner class named "layout", and its
+member field "main". The Eclipse plugin noticed the XML
+layout file named main.xml and generated a class for it here. As you add other
+resources to your project (such as strings in the res/values/string.xml
file or drawables inside
+the res/drawable/
direcory) you'll see R.java
change to keep up.
+
When not using Eclipse, this class file will be generated for you at build time (with the Ant tool).
+
You should never edit this file by hand.
+
+
+Debug Your Project
+
+The Android Plugin for Eclipse also has excellent integration with the Eclipse
+debugger. To demonstrate this, introduce a bug into
+your code. Change your HelloAndroid source code to look like this:
+
+
+package com.android.helloandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class HelloAndroid extends Activity {
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Object o = null;
+ o.toString();
+ setContentView(R.layout.main);
+ }
+}
+
+This change simply introduces a NullPointerException into your code. If
+you run your application again, you'll eventually see this:
+
+
+
+Press "Force Quit" to terminate the application and close the emulator window.
+
+To find out more about the error, set a breakpoint in your source code
+on the line Object o = null;
(double-click on the marker bar next to the source code line). Then select Run > Debug History > Hello,
+Android from the menu to enter debug mode. Your app will restart in the
+emulator, but this time it will suspend when it reaches the breakpoint you
+set. You can then step through the code in Eclipse's Debug Perspective,
+just as you would for any other application.
+
+
+
+
+Creating the Project without Eclipse
+
+ If you don't use Eclipse (such as if you prefer another IDE, or simply use text
+ editors and command line tools) then the Eclipse plugin can't help you.
+ Don't worry though — you don't lose any functionality just because you don't
+ use Eclipse.
+
+ The Android Plugin for Eclipse is really just a wrapper around a set of tools
+ included with the Android SDK. (These tools, like the emulator, aapt, adb,
+ ddms, and others are documented elsewhere.)
+ Thus, it's possible to
+ wrap those tools with another tool, such as an 'ant' build file.
+
+ The Android SDK includes a tool named "android" that can be
+ used to create all the source code and directory stubs for your project, as well
+ as an ant-compatible build.xml
file. This allows you to build your project
+ from the command line, or integrate it with the IDE of your choice.
+
+ For example, to create a HelloAndroid project similar to the one created
+ in Eclipse, use this command:
+
+
+android create project \
+ --package com.android.helloandroid \
+ --activity HelloAndroid \
+ --target 2 \
+ --path <path-to-your-project>/HelloAndroid
+
+
+ This creates the required folders and files for the project at the location
+ defined by the path.
+
+ For more information on how to use the SDK tools to create and build projects, please read
+Developing in Other IDEs.
diff --git a/docs/html/resources/tutorials/images/hello_world_0.png b/docs/html/resources/tutorials/images/hello_world_0.png
new file mode 100644
index 0000000..330a07c
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_0.png differ
diff --git a/docs/html/resources/tutorials/images/hello_world_1.png b/docs/html/resources/tutorials/images/hello_world_1.png
new file mode 100644
index 0000000..1e5f7b0
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_1.png differ
diff --git a/docs/html/resources/tutorials/images/hello_world_2.png b/docs/html/resources/tutorials/images/hello_world_2.png
new file mode 100644
index 0000000..3e9c58b
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_2.png differ
diff --git a/docs/html/resources/tutorials/images/hello_world_3.png b/docs/html/resources/tutorials/images/hello_world_3.png
new file mode 100644
index 0000000..22901a9
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_3.png differ
diff --git a/docs/html/resources/tutorials/images/hello_world_4.png b/docs/html/resources/tutorials/images/hello_world_4.png
new file mode 100644
index 0000000..5c41e80
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_4.png differ
diff --git a/docs/html/resources/tutorials/images/hello_world_5.png b/docs/html/resources/tutorials/images/hello_world_5.png
new file mode 100644
index 0000000..96b830a
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_5.png differ
diff --git a/docs/html/resources/tutorials/images/hello_world_8.png b/docs/html/resources/tutorials/images/hello_world_8.png
new file mode 100644
index 0000000..07db360
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_8.png differ
diff --git a/docs/html/resources/tutorials/images/hello_world_9.png b/docs/html/resources/tutorials/images/hello_world_9.png
new file mode 100644
index 0000000..a66526a
Binary files /dev/null and b/docs/html/resources/tutorials/images/hello_world_9.png differ
diff --git a/docs/html/resources/tutorials/index.html b/docs/html/resources/tutorials/index.html
new file mode 100644
index 0000000..4881acf
--- /dev/null
+++ b/docs/html/resources/tutorials/index.html
@@ -0,0 +1,8 @@
+
+
+
+
+
+click here if you are not redirected.
+
+
\ No newline at end of file
diff --git a/docs/html/resources/tutorials/localization/index.jd b/docs/html/resources/tutorials/localization/index.jd
new file mode 100755
index 0000000..8a60814
--- /dev/null
+++ b/docs/html/resources/tutorials/localization/index.jd
@@ -0,0 +1,593 @@
+page.title=Hello, L10N
+@jd:body
+
+
+
+In this tutorial, we will create a Hello, L10N application that uses the
+Android framework to selectively load resources. Then we will localize the
+application by adding resources to the res/
directory.
+
+This tutorial uses the practices described in the Localization
+document.
+
+
+Create an Unlocalized Application
+
+The first version of the Hello, L10N application will use only the default
+resource directories (res/drawable
, res/layout
, and
+res/values
). These resources are not localized — they are the
+graphics, layout, and strings that we expect the application to use most often.
+When a user runs the application in the default locale, or in a locale that the
+application does not specifically support, the application will load resources
+from these default directories.
+
+The application consists of a simple user interface that displays two
+{@link android.widget.TextView} objects and a {@link android.widget.Button} image with a
+ background image of a national flag. When clicked, the button displays an
+{@link android.app.AlertDialog} object that shows additional text.
+
+Create the Project and Layout
+
+For this application, the default language will be British English and the
+default location the United Kingdom.
+
+
+ - Start a new project and Activity called "HelloL10N." If you are
+using Eclipse, fill out these values in the New Android Project wizard:
+
+ - Project name: HelloL10N
+ - Application name: Hello, L10N
+ - Package name: com.example.hellol10n (or your own private
+namespace)
+ - Create Activity: HelloL10N
+ - Min SDK Version: 3
+
+ The basic project contains a res/
directory with
+subdirectories for the three most common types of resources: graphics
+(res/drawable/
), layouts (res/layout/
) and strings
+(res/values/
). Most of the localization work you do later in this
+tutorial will involve adding more subdirectories to the res/
+directory.
+
+
+ - Open the
res/layout/main.xml
file and replace it with the
+following code:
+ <?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ >
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:text="@string/text_a"
+ />
+<TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:text="@string/text_b"
+ />
+<Button
+ android:id="@+id/flag_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ />
+</LinearLayout>
+
+
+ The LinearLayout has two {@link android.widget.TextView} objects that will
+display localized text and one {@link android.widget.Button} that shows a flag.
+
+
+
+
+Create Default Resources
+
+The layout refers to resources that need to be defined.
+
+
+ - Create default text strings. To do this, open the
res/values/strings.xml
file and replace it with the following code:
+ <?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Hello, L10N</string>
+ <string name="text_a">Shall I compare thee to a summer"'"s day?</string>
+ <string name="text_b">Thou art more lovely and more temperate.</string>
+ <string name="dialog_title">No Localisation</string>
+ <string name="dialog_text">This dialog box"'"s strings are not localised. For every locale, the text here will come from values/strings.xml.</string>
+</resources>
+
+ This code provides British English text for each string that the application
+will use. When we localize this application, we will provide alternate text in
+German, French, and Japanese for some of the strings.
+
+ - Add a default flag graphic to the
res/drawable
folder by
+saving flag.png as
+res/drawable/flag.png
. When the application is not localized, it
+will show a British flag.
+
+
+ - Open HelloL10N.java (in the
src/
directory) and add the
+following code inside the onCreate()
method (after
+setContentView
).
+
+ // assign flag.png to the button, loading correct flag image for current locale
+Button b;
+(b = (Button)findViewById(R.id.flag_button)).setBackgroundDrawable(this.getResources().getDrawable(R.drawable.flag));
+
+// build dialog box to display when user clicks the flag
+AlertDialog.Builder builder = new AlertDialog.Builder(this);
+builder.setMessage(R.string.dialog_text)
+ .setCancelable(false)
+ .setTitle(R.string.dialog_title)
+ .setPositiveButton("Done", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.dismiss();
+ }
+ });
+final AlertDialog alert = builder.create();
+
+// set click listener on the flag to show the dialog box
+b.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ alert.show();
+ }
+ });
+
+ Tip: In Eclipse, use
+Ctrl-Shift-O (Cmd-Shift-O, on Mac) to find and
+add missing import packages to your project, then save the HelloL10N.java
+file.
+
+ The code that you added does the following:
+
+
+ - It assigns the correct flag icon to the button.
+ For now, no resources are defined other than the default, so this code
+will always assign the contents of
res/drawable/flag.png
(the
+British flag) as the flag icon, no matter what the locale. Once we add more
+flags for different locales, this code will sometimes assign a different flag.
+
+ - It creates an {@link android.app.AlertDialog} object and sets a click listener so that when the
+user clicks the button, the AlertDialog will display.
+ We will not localize the dialog text;
+the AlertDialog will always display the
dialog_text
that is located
+within res/values/strings.xml
.
+
+
+
+
+
+The project structure now looks like this:
+
+
+
+Tip: If you will want to run the application on
+a device and not just on an emulator, open AndroidManifest.xml
and
+add android:debuggable="true"
inside the
+<application>
element. For information about setting up the
+device itself so it can run applications from your system, see Developing on a Device.
+
+
+Run the Unlocalized Application
+
+Save the project and run the application to see how it works. No matter what
+locale your device or emulator is set to, the application runs the same way. It
+should look something like this:
+
+
+
+ The unlocalized application, running in any locale: |
+ After clicking the flag, in any locale: |
+
+
+ ![]({@docRoot}images/hello_l10n/nonlocalized_screenshot1.png) |
+ ![nonlocalized2]({@docRoot}images/hello_l10n/nonlocalized_screenshot2.png) |
+
+
+Plan the Localization
+The first step in localizing an application is to plan how the application
+will render differently in different locales. In this application, the default
+locale will be the United Kingdom. We will add some locale-specific information
+for Germany, France, Canada, Japan, and the United States. Table 1 shows the
+plan for how the application will appear in different locales.
+
+Table 1
+
+
+
+ Region /
+ Language |
+ United Kingdom |
+ Germany |
+ France |
+ Canada |
+ Japan |
+ United States |
+ Other Location |
+
+
+
+ English |
+ British English text; British flag (default) |
+ - |
+ - |
+ British English text; Canadian flag |
+ - |
+ British English text; U.S. flag |
+ British English text; British flag (default) |
+
+
+ German |
+ - |
+ German text for app_name , text_a and
+text_b ; German flag |
+ - |
+ - |
+ - |
+ - |
+ German text for app_name , text_a and
+text_b ; British flag |
+
+
+ French |
+ - |
+ - |
+ French text for app_name , text_a and
+text_b ; French flag |
+ French text for app_name , text_a and
+text_b ; Canadian flag |
+ - |
+ - |
+ French text for app_name , text_a and
+text_b ; British flag |
+
+
+ Japanese |
+ - |
+ - |
+ - |
+ - |
+ Japanese text for text_a and text_b ; Japanese
+flag |
+ - |
+ Japanese text for text_a and text_b ; British
+flag |
+
+
+ Other Language |
+ - |
+ - |
+ - |
+ - |
+ - |
+ - |
+ British English text; British flag (default) |
+
+
+
+ Note that other behaviors are possible; for example, the
+application could support Canadian English or U.S. English text. But given the
+small amount of text involved, adding more versions of English would not make
+this application more useful.
+
+As shown in the table above, the plan calls for five flag icons in addition
+to the British flag that is already in the res/drawable/
folder. It
+also calls for three sets of text strings other than the text that is in
+res/values/strings.xml
.
+
+Table 2 shows where the needed text strings and flag icons will go, and
+specifies which ones will be loaded for which locales. (For more about the
+locale codes, see
+Alternate Resources.)
+Table 2
+
+
+
+ Locale Code |
+ Language / Country |
+ Location of strings.xml |
+ Location of flag.png |
+
+
+ Default |
+ English / United Kingdom |
+ res/values/ |
+ res/drawable/ |
+
+
+ de-rDE |
+ German / Germany |
+ res/values-de/ |
+ res/drawable-de-rDE/ |
+
+
+ fr-rFR |
+ French / France |
+ res/values-fr/ |
+ res/drawable-fr-rFR/ |
+
+
+ fr-rCA |
+ French / Canada |
+ res/values-fr/ |
+ res/drawable-fr-rCA/ |
+
+
+ en-rCA |
+ English / Canada |
+ (res/values/) |
+ res/drawable-en-rCA/ |
+
+
+ ja-rJP |
+ Japanese / Japan |
+ res/values-ja/ |
+ res/drawable-ja-rJP/ |
+
+
+ en-rUS |
+ English / United States |
+ (res/values/) |
+ res/drawable-en-rUS/ |
+
+
+
+Tip: A folder qualifer cannot specify a region
+without a language. Having a folder named res/drawable-rCA/
,
+for example, will prevent the application from compiling.
+
+At run time, the application will select a set of resources to load based on the locale
+that is set in the user's device. In cases where no locale-specific resources
+are available, the application will fall back on the defaults.
+
+For example, assume that the device's language is set to German and its
+location to Switzerland. Because this application does not have a
+res/drawable-de-rCH/
directory with a flag.png
file in it, the system
+will fall back on the default, which is the UK flag located in
+res/drawable/flag.png
. The language used will be German. Showing a
+British flag to German speakers in Switzerland is not ideal, but for now we will
+just leave the behavior as it is. There are several ways you could improve this
+application's behavior if you wanted to:
+
+
+ - Use a generic default icon. In this application, it might be something
+that represents Shakespeare.
+ - Create a
res/drawable-de/
folder that includes an icon that
+the application will use whenever the language is set to German but the location
+is not Germany.
+
+
+
+Localize the Application
+
+Localize the Strings
+
+The application requires three more strings.xml
files, one
+each for German, French, and Japanese. To create these resource files within
+Eclipse:
+
+
+- Select File > New > Android
+XML File to open the New Android XML File wizard. You can also open
+the wizard by clicking its icon in the toolbar:
+![]({@docRoot}images/hello_l10n/xml_file_wizard_shortcut.png)
+ - Select L10N for the Project field, and type
strings.xml
into
+the File field. In the left-hand list, select Language, then click the right arrow.
+![res_file_copy]({@docRoot}images/hello_l10n/xml_wizard1.png)
+ - Type
de
in the Language box and click Finish.
+
+A new file, res/values-de/strings.xml
, now appears among the project
+files.
+- Repeat the steps twice more, for the language codes
fr
and
+ ja
.
+Now the project includes these new skeleton files:
+ res/values-de/strings.xml
+ res/values-fr/strings.xml
+ res/values-ja/strings.xml
+
+ - Add localized text to the new files. To do
+this, open the
res/values-<qualifier>/strings.xml
files and
+replace the code as follows:
+
+
+
+
+ File |
+ Replace the contents with the following code: |
+
+
+ res/values-de/strings.xml |
+ <?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Hallo, Lokalisierung</string>
+ <string name="text_a">Soll ich dich einem Sommertag vergleichen,</string>
+ <string name="text_b">Der du viel lieblicher und sanfter bist?</string>
+</resources> |
+
+
+ res/values-fr/strings.xml |
+ <?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app_name">Bonjour, Localisation</string>
+ <string name="text_a">Irai-je te comparer au jour d'été?</string>
+ <string name="text_b">Tu es plus tendre et bien plus tempéré.</string>
+</resources> |
+
+
+ res/values-ja/strings.xml |
+
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="text_a">あなたをなにかにたとえるとしたら夏の一日でしょうか?</string>
+ <string name="text_b">だがあなたはもっと美しく、もっとおだやかです。</string>
+</resources> |
+
+
+
+Tip: In the
+values-<qualifier>/strings.xml
files, you only need to
+include text for strings that are different from the default strings. For
+example, when the application runs on a device that is configured for Japanese,
+the plan is for text_a
and text_b
to be in Japanese
+while all the other text is in English, so
+res/values-ja/strings.xml
only needs to include text_a
+and text_b
.
+
+Localize the Images
+
+As shown in Table 2, the application needs six more
+drawable folders, each containing a flag.png
icon. Add the needed
+icons and folders to your project:
+
+
+ - Save this German flag icon
+as
res/drawable-de-rDE/flag.png
in the application's project
+workspace.
+ For example:
+
+ - Click the link to open the flag image.
+ - Save the image in
+
your-workspace/HelloL10N/res/drawable-de-rDE/
.
+
+
+ - Save this French flag icon
+as
res/drawable-fr-rFR/flag.png
in the application's project
+workspace.
+ - Save this Canadian flag icon
+as
res/drawable-fr-rCA/flag.png
in the project workspace.
+ - Save the Canadian flag icon
+again, this time as
res/drawable-en-rCA/flag.png
in the project
+workspace. (Why not have just one folder that contains the Canadian
+flag? Because a folder qualifer cannot specify a region without a language.
+You cannot have a folder named drawable-rCA/
; instead you must
+create two separate folders, one for each of the Canadian languages represented
+in the application.)
+ - Save this Japanese flag icon
+as
res/drawable-ja-rJP/flag.png
in the project workspace.
+ - Save this United States flag
+icon as
res/drawable-en-rUS/flag.png
in the project workspace.
+
+
+
+If you are using Eclipse, refresh the project (F5). The new
+res/drawable-<qualifier>/
folders should appear in the
+project view.
+
+
+Run and Test the Localized Application
+
+Once you've added the localized string and image resources, you are ready to
+ run the application and test its handling of them. To change the locale
+ on a device or in the emulator, use the Settings
+application (Home > Menu > Settings > Locale & text > Select
+locale). Depending on how a device was configured, it might not offer any
+alternate locales via the Settings application, or might offer only a few. The
+emulator, on the other hand, will offer a selection of all the locales that are
+available in the Android system image.
+
+To set the emulator to a locale that is not available in the system image,
+use the Custom Locale application, which is available in the Application
+tab:
+
+![custom locale app]({@docRoot}images/hello_l10n/custom_locale_app.png)
+
+To switch to a new locale, long-press a locale name:
+
+![using custom locale]({@docRoot}images/hello_l10n/using_custom_locale.png)
+
+For a list of locales available on different versions of the Android platform,
+refer to the platform notes documents, listed under "Downloadable SDK Components"
+in the "SDK" tab. For example, Android 2.0 locales.
+
+Run the application for each of the expected locales, plus one unexpected
+locale. Here are some of the results you should see:
+
+
+
+ Locale |
+ Opening screen of application |
+
+
+ German / Germany
+ Specifically supported by the Hello, L10N application. |
+ ![custom locale app]({@docRoot}images/hello_l10n/german_screenshot.png) |
+
+
+ French / Canada
+ Specifically supported by the Hello, L10N application. |
+ ![custom locale app]({@docRoot}images/hello_l10n/frenchCA_screenshot.png) |
+
+
+ German / Switzerland
+ Only the language is specifically supported by
+the Hello, L10N application. |
+ ` |
+
+
+ Japanese
+ Specifically supported by the Hello, L10N application.
+ |
+ ` |
+
+
+ Romansh / Switzerland (custom locale rm_CH )
+ Not specifically supported by the Hello, L10N
+application, so the application uses the default resources. |
+ ![custom locale app]({@docRoot}images/hello_l10n/romanshCH_screenshot.png) |
+
+
diff --git a/docs/html/resources/tutorials/notepad/codelab/NotepadCodeLab.zip b/docs/html/resources/tutorials/notepad/codelab/NotepadCodeLab.zip
new file mode 100644
index 0000000..24fefc1
Binary files /dev/null and b/docs/html/resources/tutorials/notepad/codelab/NotepadCodeLab.zip differ
diff --git a/docs/html/resources/tutorials/notepad/index.jd b/docs/html/resources/tutorials/notepad/index.jd
new file mode 100644
index 0000000..f569314
--- /dev/null
+++ b/docs/html/resources/tutorials/notepad/index.jd
@@ -0,0 +1,142 @@
+page.title=Notepad Tutorial
+@jd:body
+
+
+This tutorial on writing a notepad application gives you a "hands-on" introduction
+to the Android framework and the tools you use to build applications on it.
+Starting from a preconfigured project file, it guides you through the process of
+developing a simple notepad application and provides concrete examples of how to
+set up the project, develop the application logic and user interface, and then
+compile and run the application.
+
+The tutorial presents the application development as a set of
+exercises (see below), each consisting of several steps. You should follow
+the steps in each exercise to gradually build and refine your
+application. The exercises explain each step in detail and provide all the
+sample code you need to complete the application.
+
+When you are finished with the tutorial, you will have created a functioning
+Android application and will have learned many of the most important
+concepts in Android development. If you want to add more complex features to
+your application, you can examine the code in an alternative implementation
+of a Note Pad application, in the
+Sample Code section.
+
+
+
+Who Should Use this Tutorial
+
+This tutorial is designed for experienced developers, especially those with
+knowledge of the Java programming language. If you haven't written Java
+applications before, you can still use the tutorial, but you might need to work
+at a slower pace.
+
+Also note that this tutorial uses
+the Eclipse development environment, with the Android plugin installed. If you
+are not using Eclipse, you can follow the exercises and build the application,
+but you will need to determine how to accomplish the Eclipse-specific
+steps in your environment.
+
+
+Preparing for the Exercises
+
+The tutorial assumes that you have some familiarity with basic Android
+application concepts and terminology. If you are not, you
+should read Application
+Fundamentals before continuing.
+
+This tutorial also builds on the introductory information provided in the
+Hello World
+tutorial, which explains how to set up your Eclipse environment
+for building Android applications. We recommend you complete the Hello World
+tutorial before starting this one.
+
+To prepare for this lesson:
+
+
+ - Download the project
+ exercises archive (.zip).
+ - Unpack the archive file to a suitable location on your machine.
+ - Open the
NotepadCodeLab
folder.
+
+
+Inside the NotepadCodeLab
folder, you should see six project
+files: Notepadv1
,
+ Notepadv2
, Notepadv3
,
+ Notepadv1Solution
, Notepadv2Solution
+ and Notepadv3Solution
. The Notepadv#
projects are
+the starting points for each of the exercises, while the
+Notepadv#Solution
projects are the exercise
+ solutions. If you are having trouble with a particular exercise, you
+ can compare your current work against the exercise solution.
+
+
+ Exercises
+
+ The table below lists the tutorial exercises and describes the development
+areas that each covers. Each exercise assumes that you have completed any
+previous exercises.
+
+
+
+ Exercise
+1 |
+ Start here. Construct a simple notes list that lets the user add new notes but not
+edit them. Demonstrates the basics of ListActivity and creating
+and handling
+ menu options. Uses a SQLite database to store the notes. |
+
+
+ Exercise 2 |
+ Add a second Activity to the
+application. Demonstrates constructing a
+new Activity, adding it to the Android manifest, passing data between the
+activities, and using more advanced screen layout. Also shows how to
+invoke another Activity to return a result, using
+startActivityForResult() . |
+
+
+ Exercise 3 |
+ Add handling of life-cycle events to
+the application, to let it
+maintain application state across the life cycle. |
+
+
+ Extra
+Credit |
+ Demonstrates how to use the Eclipse
+debugger and how you can use it to
+view life-cycle events as they are generated. This section is optional but
+highly recommended. |
+
+
+
+
+
+Other Resources and Further Learning
+
+- For a lighter but broader introduction to concepts not covered in the
+tutorial,
+take a look at Common Android Tasks.
+- The Android SDK includes a variety of fully functioning sample applications
+that make excellent opportunities for further learning. You can find the sample
+applications in the
samples/
directory of your downloaded SDK, or browser them
+here, in the Sample Code section.
+- This tutorial draws from the full Notepad application included in the
+
samples/
directory of the SDK, though it does not match it exactly.
+When you are done with the tutorial,
+it is highly recommended that you take a closer look at this version of the Notepad
+application,
+as it demonstrates a variety of interesting additions for your application,
+such as:
+
+ - Setting up a custom striped list for the list of notes.
+ - Creating a custom text edit view that overrides the
draw()
+ method to make it look like a lined notepad.
+ - Implementing a full
ContentProvider
for notes.
+ - Reverting and discarding edits instead of just automatically saving
+ them.
+
+
diff --git a/docs/html/resources/tutorials/notepad/notepad-ex1.jd b/docs/html/resources/tutorials/notepad/notepad-ex1.jd
new file mode 100644
index 0000000..b26440b
--- /dev/null
+++ b/docs/html/resources/tutorials/notepad/notepad-ex1.jd
@@ -0,0 +1,591 @@
+page.title=Notepad Exercise 1
+parent.title=Notepad Tutorial
+parent.link=index.html
+@jd:body
+
+
+In this exercise, you will construct a simple notes list that lets the
+user add new notes but not edit them. The exercise demonstrates:
+
+- The basics of
ListActivities
and creating and handling menu
+options.
+- How to use a SQLite database to store the notes.
+- How to bind data from a database cursor into a ListView using a
+SimpleCursorAdapter.
+- The basics of screen layouts, including how to lay out a list view, how
+you can add items to the activity menu, and how the activity handles those menu
+selections.
+
+
+
+
+
+
+Step 1
+
+ Open up the Notepadv1
project in Eclipse.
+
+ Notepadv1
is a project that is provided as a starting point. It
+ takes care of some of the boilerplate work that you have already seen if you
+ followed the Hello,
+ World tutorial.
+
+
+ -
+ Start a new Android Project by clicking File >
+ New > Android Project.
+ -
+ In the New Android Project dialog, select Create project from existing source.
+ -
+ Click Browse and navigate to where you copied the
NotepadCodeLab
+ (downloaded during setup)
+ and select Notepadv1
.
+ -
+ The Project Name and other properties should be automatically filled for you.
+ You must select the Build Target—we recommend selecting a target with the
+ lowest platform version available. Also add an integer to the Min SDK Version field
+ that matches the API Level of the selected Build Target.
+ -
+ Click Finish. The
Notepadv1
project should open and be
+ visible in your Eclipse package explorer.
+
+
+ If you see an error about AndroidManifest.xml
, or some
+ problems related to an Android zip file, right click on the project and
+ select Android Tools > Fix Project Properties.
+ (The project is looking in the wrong location for the library file,
+ this will fix it for you.)
+
+ Step 2
+
+
+
Accessing and modifying data
+
For this
+ exercise, we are using a SQLite database to store our data. This is useful
+ if only your application will need to access or modify the data. If you wish for
+ other activities to access or modify the data, you have to expose the data using a
+ {@link android.content.ContentProvider ContentProvider}.
+
If you are interested, you can find out more about
+ content providers or the whole
+ subject of Data Storage.
+ The NotePad sample in the samples/
folder of the SDK also has an example of how
+ to create a ContentProvider.
+
+
+ Take a look at the NotesDbAdapter
class — this class is provided to
+ encapsulate data access to a SQLite database that will hold our notes data
+ and allow us to update it.
+ At the top of the class are some constant definitions that will be used in the application
+ to look up data from the proper field names in the database. There is also a database creation
+ string defined, which is used to create a new database schema if one doesn't exist already.
+ Our database will have the name data
, and have a single table called
+ notes
, which in turn has three fields: _id
, title
and
+ body
. The _id
is named with an underscore convention used in a number of
+ places inside the Android SDK and helps keep a track of state. The _id
+ usually has to be specified when querying or updating the database (in the column projections
+ and so on). The other two fields are simple text fields that will store data.
+
+ The constructor for NotesDbAdapter
takes a Context, which allows it to communicate with aspects
+ of the Android operating system. This is quite common for classes that need to touch the
+ Android system in some way. The Activity class implements the Context class, so usually you will just pass
+ this
from your Activity, when needing a Context.
+ The open()
method calls up an instance of DatabaseHelper, which is our local
+ implementation of the SQLiteOpenHelper class. It calls getWritableDatabase()
,
+ which handles creating/opening a database for us.
+ close()
just closes the database, releasing resources related to the
+ connection.
+ createNote()
takes strings for the title and body of a new note,
+ then creates that note in the database. Assuming the new note is created successfully, the
+ method also returns the row _id
value for the newly created note.
+ deleteNote()
takes a rowId for a particular note, and deletes that note from
+ the database.
+
+ fetchAllNotes()
issues a query to return a {@link android.database.Cursor} over all notes in the
+ database. The query()
call is worth examination and understanding. The first field is the
+ name of the database table to query (in this case DATABASE_TABLE
is "notes").
+ The next is the list of columns we want returned, in this case we want the _id
,
+ title
and body
columns so these are specified in the String array.
+ The remaining fields are, in order: selection
,
+ selectionArgs
, groupBy
, having
and orderBy
.
+ Having these all null
means we want all data, need no grouping, and will take the default
+ order. See {@link android.database.sqlite.SQLiteDatabase SQLiteDatabase} for more details.
+ Note: A Cursor is returned rather than a collection of rows. This allows
+ Android to use resources efficiently -- instead of putting lots of data straight into memory
+ the cursor will retrieve and release data as it is needed, which is much more efficient for
+ tables with lots of rows.
+
+ fetchNote()
is similar to fetchAllNotes()
but just gets one note
+ with the rowId we specify. It uses a slightly different version of the
+ {@link android.database.sqlite.SQLiteDatabase} query()
method.
+ The first parameter (set true) indicates that we are interested
+ in one distinct result. The selection parameter (the fourth parameter) has been specified to search
+ only for the row "where _id =" the rowId we passed in. So we are returned a Cursor on
+ the one row.
+ And finally, updateNote()
takes a rowId, title and body, and uses a
+ {@link android.content.ContentValues ContentValues} instance to update the note of the given
+ rowId.
+
+Step 3
+
+
+
Layouts and activities
+
Most Activity classes will have a layout associated with them. The layout
+ will be the "face" of the Activity to the user. In this case our layout will
+ take over the whole screen and provide a list of notes.
+
Full screen layouts are not the only option for an Activity however. You
+ might also want to use a floating
+ layout (for example, a dialog
+ or alert),
+ or perhaps you don't need a layout at all (the Activity will be invisible
+ to the user unless you specify some kind of layout for it to use).
+
+
+ Open the notepad_list.xml
file in res/layout
+and
+ take a look at it. (You may have to
+ hit the xml tab, at the bottom, in order to view the XML markup.)
+
+ This is a mostly-empty layout definition file. Here are some
+ things you should know about a layout file:
+
+
+
+
+ Step 4
+ We need to create the layout to hold our list. Add code inside
+ of the LinearLayout
element so the whole file looks like this:
+
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ <TextView android:id="@android:id/empty"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/no_notes"/>
+
+</LinearLayout>
+
+
+ -
+ The @ symbol in the id strings of the
ListView
and
+ TextView
tags means
+ that the XML parser should parse and expand the rest of
+ the id string and use an ID resource.
+ -
+ The
ListView
and TextView
can be
+ thought as two alternative views, only one of which will be displayed at once.
+ ListView will be used when there are notes to be shown, while the TextView
+ (which has a default value of "No Notes Yet!" defined as a string
+ resource in res/values/strings.xml
) will be displayed if there
+ aren't any notes to display.
+ - The
list
and empty
IDs are
+ provided for us by the Android platform, so, we must
+ prefix the id
with android:
(e.g., @android:id/list
).
+ - The View with the
empty
id is used
+ automatically when the {@link android.widget.ListAdapter} has no data for the ListView. The
+ ListAdapter knows to look for this name by default. Alternatively, you could change the
+ default empty view by using {@link android.widget.AdapterView#setEmptyView(View)}
+ on the ListView.
+
+ More broadly, the android.R
class is a set of predefined
+ resources provided for you by the platform, while your project's
+ R
class is the set of resources your project has defined.
+ Resources found in the android.R
resource class can be
+ used in the XML files by using the android:
name space prefix
+ (as we see here).
+
+
+
+ Step 5
+
+
+
Resources and the R class
+
The folders under res/ in the Eclipse project are for resources.
+ There is a specific structure to the
+ folders and files under res/.
+
Resources defined in these folders and files will have
+ corresponding entries in the R class allowing them to be easily accessed
+ and used from your application. The R class is automatically generated using the contents
+ of the res/ folder by the eclipse plugin (or by aapt if you use the command line tools).
+ Furthermore, they will be bundled and deployed for you as part of the application.
+
+
+ To make the list of notes in the ListView, we also need to define a View for each row:
+
+ -
+ Create a new file under
res/layout
called
+ notes_row.xml
.
+ -
+ Add the following contents (note: again the XML header is used, and the
+ first node defines the Android XML namespace)
+
+<?xml version="1.0" encoding="utf-8"?>
+<TextView android:id="@+id/text1"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ This is the View that will be used for each notes title row — it has only
+ one text field in it.
+ In this case we create a new id called text1
. The
+ + after the @ in the id string indicates that the id should
+ be automatically created as a resource if it does not already exist, so we are defining
+ text1
on the fly and then using it.
+
+ - Save the file.
+
+ Open the R.java
class in the
+ project and look at it, you should see new definitions for
+ notes_row
and text1
(our new definitions)
+ meaning we can now gain access to these from the our code.
+
+ Step 6
+Next, open the Notepadv1
class in the source. In the following steps, we are going to
+ alter this class to become a list adapter and display our notes, and also
+ allow us to add new notes.
+
+Notepadv1
will inherit from a subclass
+ of Activity
called a ListActivity
,
+ which has extra functionality to accommodate the kinds of
+ things you might want to do with a list, for
+ example: displaying an arbitrary number of list items in rows on the screen,
+ moving through the list items, and allowing them to be selected.
+
+Take a look through the existing code in Notepadv1
class.
+ There is a currently an unused private field called mNoteNumber
that
+ we will use to create numbered note titles.
+ There are also three override methods defined:
+ onCreate
, onCreateOptionsMenu
and
+ onOptionsItemSelected
; we need to fill these
+ out:
+
+ onCreate()
is called when the activity is
+ started — it is a little like the "main" method for an Activity. We use
+ this to set up resources and state for the activity when it is
+ running.
+ onCreateOptionsMenu()
is used to populate the
+ menu for the Activity. This is shown when the user hits the menu button,
+and
+ has a list of options they can select (like "Create
+ Note").
+ onOptionsItemSelected()
is the other half of the
+ menu equation, it is used to handle events generated from the menu (e.g.,
+ when the user selects the "Create Note" item).
+
+
+
+ Step 7
+ Change the inheritance of Notepadv1
from
+Activity
+ to ListActivity
:
+ public class Notepadv1 extends ListActivity
+ Note: you will have to import ListActivity
into the
+Notepadv1
+ class using Eclipse, ctrl-shift-O on Windows or Linux, or
+ cmd-shift-O on the Mac (organize imports) will do this for you
+ after you've written the above change.
+
+ Step 8
+ Fill out the body of the onCreate()
method.
+ Here we will set the title for the Activity (shown at the top of the
+ screen), use the notepad_list
layout we created in XML,
+ set up the NotesDbAdapter
instance that will
+ access notes data, and populate the list with the available note
+ titles:
+
+ -
+ In the
onCreate
method, call super.onCreate()
with the
+ savedInstanceState
parameter that's passed in.
+ -
+ Call
setContentView()
and pass R.layout.notepad_list
.
+ -
+ At the top of the class, create a new private class field called
mDbHelper
of class
+ NotesDbAdapter
.
+
+ -
+ Back in the
onCreate
method, construct a new
+NotesDbAdapter
+ instance and assign it to the mDbHelper
field (pass
+ this
into the constructor for DBHelper
)
+
+ -
+ Call the
open()
method on mDbHelper
to open (or create) the
+ database.
+
+ -
+ Finally, call a new method
fillData()
, which will get the data and
+ populate the ListView using the helper — we haven't defined this method yet.
+
+
+ onCreate()
should now look like this:
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.notepad_list);
+ mDbHelper = new NotesDbAdapter(this);
+ mDbHelper.open();
+ fillData();
+ }
+ And be sure you have the mDbHelper
field definition (right
+ under the mNoteNumber definition):
+ private NotesDbAdapter mDbHelper;
+
+ Step 9
+
+
+
+Fill out the body of the onCreateOptionsMenu()
method.
+
+We will now create the "Add Item" button that can be accessed by pressing the menu
+button on the device. We'll specify that it occupy the first position in the menu.
+
+
+ -
+ In
strings.xml
resource (under res/values
), add
+ a new string named "menu_insert" with its value set to Add Item
:
+ <string name="menu_insert">Add Item</string>
+ Then save the file and return to Notepadv1
.
+
+ - Create a menu position constant at the top of the class:
+
public static final int INSERT_ID = Menu.FIRST;
+
+ - In the
onCreateOptionsMenu()
method, change the
+ super
call so we capture the boolean return as result
. We'll return this value at the end.
+ - Then add the menu item with
menu.add()
.
+
+ The whole method should now look like this:
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ boolean result = super.onCreateOptionsMenu(menu);
+ menu.add(0, INSERT_ID, 0, R.string.menu_insert);
+ return result;
+ }
+ The arguments passed to add()
indicate: a group identifier for this menu (none,
+ in this case), a unique ID (defined above), the order of the item (zero indicates no preference),
+ and the resource of the string to use for the item.
+
+Step 10
+ Fill out the body of the onOptionsItemSelected()
method:
+ This is going
+ to handle our new "Add Note" menu item. When this is selected, the
+ onOptionsItemSelected()
method will be called with the
+ item.getId()
set to INSERT_ID
(the constant we
+ used to identify the menu item). We can detect this, and take the
+ appropriate actions:
+
+ -
+ The
super.onOptionsItemSelected(item)
method call goes at the
+ end of this method — we want to catch our events first!
+ -
+ Write a switch statement on
item.getItemId()
.
+ In the case of INSERT_ID, call a new method, createNote()
,
+ and return true, because we have handled this event and do not want to
+ propagate it through the system.
+
+ - Return the result of the superclass'
onOptionsItemSelected()
+ method at the end.
+
+
+ The whole onOptionsItemSelect()
method should now look like
+ this:
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case INSERT_ID:
+ createNote();
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+Step 11
+ Add a new createNote()
method:
+ In this first version of
+ our application, createNote()
is not going to be very useful.
+We will simply
+ create a new note with a title assigned to it based on a counter ("Note 1",
+ "Note 2"...) and with an empty body. At present we have no way of editing
+ the contents of a note, so for now we will have to be content making one
+ with some default values:
+
+ - Construct the name using "Note" and the counter we defined in the class:
+ String noteName = "Note " + mNoteNumber++
+ -
+ Call
mDbHelper.createNote()
using noteName
as the
+ title and ""
for the body
+
+ -
+ Call
fillData()
to populate the list of notes (inefficient but
+ simple) — we'll create this method next.
+
+
+ The whole createNote()
method should look like this:
+
+ private void createNote() {
+ String noteName = "Note " + mNoteNumber++;
+ mDbHelper.createNote(noteName, "");
+ fillData();
+ }
+
+
+Step 12
+
+
List adapters
+
Our example uses a {@link android.widget.SimpleCursorAdapter
+ SimpleCursorAdapter} to bind a database {@link android.database.Cursor Cursor}
+ into a ListView, and this is a common way to use a {@link android.widget.ListAdapter
+ ListAdapter}. Other options exist like {@link android.widget.ArrayAdapter ArrayAdapter} which
+ can be used to take a List or Array of in-memory data and bind it in to
+ a list as well.
+
+
+ Define the fillData()
method:
+ This
+ method uses SimpleCursorAdapter,
which takes a database Cursor
+ and binds it to fields provided in the layout. These fields define the row elements of our list
+ (in this case we use the text1
field in our
+ notes_row.xml
layout), so this allows us to easily populate the list with
+ entries from our database.
+ To do this we have to provide a mapping from the title
field in the returned Cursor, to
+ our text1
TextView, which is done by defining two arrays: the first a string array
+ with the list of columns to map from (just "title" in this case, from the constant
+ NotesDbAdapter.KEY_TITLE
) and, the second, an int array
+ containing references to the views that we'll bind the data into
+ (the R.id.text1
TextView).
+ This is a bigger chunk of code, so let's first take a look at it:
+
+
+ private void fillData() {
+ // Get all of the notes from the database and create the item list
+ Cursor c = mDbHelper.fetchAllNotes();
+ startManagingCursor(c);
+
+ String[] from = new String[] { NotesDbAdapter.KEY_TITLE };
+ int[] to = new int[] { R.id.text1 };
+
+ // Now create an array adapter and set it to display using our row
+ SimpleCursorAdapter notes =
+ new SimpleCursorAdapter(this, R.layout.notes_row, c, from, to);
+ setListAdapter(notes);
+ }
+
+ Here's what we've done:
+
+ -
+ After obtaining the Cursor from
mDbHelper.fetchAllNotes()
, we
+ use an Activity method called
+ startManagingCursor()
that allows Android to take care of the
+ Cursor lifecycle instead of us needing to worry about it. (We will cover the implications
+ of the lifecycle in exercise 3, but for now just know that this allows Android to do some
+ of our resource management work for us.)
+ -
+ Then we create a string array in which we declare the column(s) we want
+ (just the title, in this case), and an int array that defines the View(s)
+ to which we'd like to bind the columns (these should be in order, respective to
+ the string array, but here we only have one for each).
+ -
+ Next is the SimpleCursorAdapter instantiation.
+ Like many classes in Android, the SimpleCursorAdapter needs a Context in order to do its
+ work, so we pass in
this
for the context (since subclasses of Activity
+ implement Context). We pass the notes_row
View we created as the receptacle
+ for the data, the Cursor we just created, and then our arrays.
+
+
+ In the future, remember that the mapping between the from columns and to resources
+ is done using the respective ordering of the two arrays. If we had more columns we wanted
+ to bind, and more Views to bind them in to, we would specify them in order, for example we
+ might use { NotesDbAdapter.KEY_TITLE, NotesDbAdapter.KEY_BODY }
and
+ { R.id.text1, R.id.text2 }
to bind two fields into the row (and we would also need
+ to define text2 in the notes_row.xml, for the body text). This is how you can bind multiple fields
+ into a single row (and get a custom row layout as well).
+
+ If you get compiler errors about classes not being found, ctrl-shift-O or
+ (cmd-shift-O on the mac) to organize imports.
+
+
+Step 13
+ Run it!
+
+ -
+ Right click on the
Notepadv1
project.
+ -
+ From the popup menu, select Run As >
+ Android Application.
+ -
+ If you see a dialog come up, select Android Launcher as the way of running
+ the application (you can also use the link near the top of the dialog to
+ set this as your default for the workspace; this is recommended as it will
+ stop the plugin from asking you this every time).
+ - Add new notes by hitting the menu button and selecting Add
+ Item from the menu.
+
+
+Solution and Next Steps
+ You can see the solution to this class in Notepadv1Solution
+from
+the zip file to compare with your own.
+
+Once you are ready, move on to Tutorial
+Exercise 2 to add the ability to create, edit and delete notes.
+
diff --git a/docs/html/resources/tutorials/notepad/notepad-ex2.jd b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
new file mode 100644
index 0000000..bab9471
--- /dev/null
+++ b/docs/html/resources/tutorials/notepad/notepad-ex2.jd
@@ -0,0 +1,647 @@
+Rpage.title=Notepad Exercise 2
+parent.title=Notepad Tutorial
+parent.link=index.html
+@jd:body
+
+
+In this exercise, you will add a second Activity to your notepad application, to let the user
+create and edit notes. You will also allow the user to delete existing notes through a context menu.
+The new Activity assumes responsibility for creating new notes by
+collecting user input and packing it into a return Bundle provided by the intent. This exercise
+demonstrates:
+
+- Constructing a new Activity and adding it to the Android manifest
+- Invoking another Activity asynchronously using
startActivityForResult()
+- Passing data between Activity in Bundle objects
+- How to use a more advanced screen layout
+- How to create a context menu
+
+
+
+
+Step 1
+
+Create a new Android project using the sources from Notepadv2
under the
+NotepadCodeLab
folder, just like you did for the first exercise. If you see an error about
+AndroidManifest.xml
, or some problems related to an
+android.zip
file, right click on the project and select Android
+Tools > Fix Project Properties.
+
+Open the Notepadv2
project and take a look around:
+
+ -
+ Open and look at the
strings.xml
file under
+ res/values
— there are several new strings which we will use
+ for our new functionality
+
+ -
+ Also, open and take a look at the top of the
Notepadv2
class,
+ you will notice several new constants have been defined along with a new mNotesCursor
+ field used to hold the cursor we are using.
+
+ -
+ Note also that the
fillData()
method has a few more comments and now uses
+ the new field to store the notes Cursor. The onCreate()
method is
+ unchanged from the first exercise. Also notice that the member field used to store the
+ notes Cursor is now called mNotesCursor
. The m
denotes a member
+ field and is part of the Android coding style standards.
+
+ -
+ There are also a couple of new overridden methods
+ (
onCreateContextMenu()
, onContextItemSelected()
,
+ onListItemClick()
and onActivityResult()
)
+ which we will be filling in below.
+
+
+
+
+Step 2
+
+
+
Context menus should always be used when performing actions upon specific elements in the UI.
+When you register a View to a context menu, the context menu is revealed by performing a "long-click"
+on the UI component (press and hold the touchscreen or highlight and hold down the selection key for about two seconds).
+
+
+First, let's create the context menu that will allow users to delete individual notes.
+Open the Notepadv2 class.
+
+
+ - In order for each list item in the ListView to register for the context menu, we call
+
registerForContextMenu()
and pass it our ListView. So, at the very end of
+ the onCreate()
method add this line:
+ registerForContextMenu(getListView());
+ Because our Activity extends the ListActivity class, getListView()
will return us
+ the local ListView object for the Activity. Now, each list item in this ListView will activate the
+ context menu.
+
-
+ Now fill in the
onCreateContextMenu()
method. This callback is similar to the other
+ menu callback used for the options menu. Here, we add just one line, which will add a menu item
+ to delete a note. Call menu.add()
like so:
+
+public boolean onCreateContextMenu(Menu menu, View v
+ ContextMenuInfo menuInfo) {
+ super.onCreateContextMenu(menu, v, menuInfo);
+ menu.add(0, DELETE_ID, 0, R.string.menu_delete);
+}
+ The onCreateContextMenu()
callback some passes other information in addition to the Menu object,
+ such as the View that has been triggered for the menu and
+ an extra object that may contain additional information about the object selected. However, we don't care about
+ these here, because we only have one kind of object in the Activity that uses context menus. In the next
+ step, we'll handle the menu item selection.
+
+
+
+Step 3
+ Now that the we've registered our ListView for a context menu and defined our context menu item, we need
+ to handle the callback when it is selected. For this, we need to identify the list ID of the
+ selected item, then delete it. So fill in the
+ onContextItemSelected()
method like this:
+
+public boolean onContextItemSelected(MenuItem item) {
+ switch(item.getItemId()) {
+ case DELETE_ID:
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
+ mDbHelper.deleteNote(info.id);
+ fillData();
+ return true;
+ }
+ return super.onContextItemSelected(item);
+}
+Here, we retrieve the {@link android.widget.AdapterView.AdapterContextMenuInfo AdapterContextMenuInfo}
+with {@link android.view.MenuItem#getMenuInfo()}. The id field of this object tells us
+the position of the item in the ListView. We then pass this to the deleteNote()
+method of our NotesDbAdapter and the note is deleted. That's it for the context menu — notes
+can now be deleted.
+
+Step 4
+
+
Starting Other Activities
+
In this example our Intent uses a class name specifically.
+ As well as
+ starting intents in
+ classes we already know about, be they in our own application or another
+ application, we can also create Intents without knowing exactly which
+ application will handle it.
+
For example, we might want to open a page in a
+ browser, and for this we still use
+ an Intent. But instead of specifying a class to handle it, we use
+ a predefined Intent constant, and a content URI that describes what we
+ want to do. See {@link android.content.Intent
+ android.content.Intent} for more information.
+
+
+ Fill in the body of the createNote()
method:
+
Create a new Intent
to create a note
+ (ACTIVITY_CREATE
) using the NoteEdit
class.
+ Then fire the Intent using the startActivityForResult()
method
+ call:
+
+Intent i = new Intent(this, NoteEdit.class);
+startActivityForResult(i, ACTIVITY_CREATE);
+ This form of the Intent call targets a specific class in our Activity, in this case
+ NoteEdit
. Since the Intent class will need to communicate with the Android
+ operating system to route requests, we also have to provide a Context (this
).
+ The startActivityForResult()
method fires the Intent in a way that causes a method
+ in our Activity to be called when the new Activity is completed. The method in our Activity
+ that receives the callback is called
+ onActivityResult()
and we will implement it in a later step. The other way
+ to call an Activity is using startActivity()
but this is a "fire-and-forget" way
+ of calling it — in this manner, our Activity is not informed when the Activity is completed, and there is
+ no way to return result information from the called Activity with startActivity()
.
+
Don't worry about the fact that NoteEdit
doesn't exist yet,
+ we will fix that soon.
+
+
+
+Step 5
+
+ Fill in the body of the onListItemClick()
override.
+ onListItemClick()
is a callback method that we'll override. It is called when
+ the user selects an item from the list. It is passed four parameters: the
+ ListView
object it was invoked from, the View
+ inside the ListView
that was clicked on, the
+ position
in the list that was clicked, and the
+ mRowId
of the item that was clicked. In this instance we can
+ ignore the first two parameters (we only have one ListView
it
+ could be), and we ignore the mRowId
as well. All we are
+ interested in is the position
that the user selected. We use
+ this to get the data from the correct row, and bundle it up to send to
+ the NoteEdit
Activity.
+ In our implementation of the callback, the method creates an
+ Intent
to edit the note using
+ the NoteEdit
class. It then adds data into the extras Bundle of
+ the Intent, which will be passed to the called Activity. We use it
+ to pass in the title and body text, and the mRowId
for the note we are
+ editing. Finally, it will fire the Intent using the
+ startActivityForResult()
method call. Here's the code that
+ belongs in onListItemClick()
:
+
+super.onListItemClick(l, v, position, id);
+Cursor c = mNotesCursor;
+c.moveToPosition(position);
+Intent i = new Intent(this, NoteEdit.class);
+i.putExtra(NotesDbAdapter.KEY_ROWID, id);
+i.putExtra(NotesDbAdapter.KEY_TITLE, c.getString(
+ c.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
+i.putExtra(NotesDbAdapter.KEY_BODY, c.getString(
+ c.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
+startActivityForResult(i, ACTIVITY_EDIT);
+
+ -
+
putExtra()
is the method to add items into the extras Bundle
+ to pass in to intent invocations. Here, we are
+ using the Bundle to pass in the title, body and mRowId of the note we want to edit.
+
+ -
+ The details of the note are pulled out from our query Cursor, which we move to the
+ proper position for the element that was selected in the list, with
+ the
moveToPosition()
method.
+ - With the extras added to the Intent, we invoke the Intent on the
+
NoteEdit
class by passing startActivityForResult()
+ the Intent and the request code. (The request code will be
+ returned to onActivityResult
as the requestCode
parameter.)
+
+ Note: We assign the mNotesCursor field to a local variable at the
+ start of the method. This is done as an optimization of the Android code. Accessing a local
+ variable is much more efficient than accessing a field in the Dalvik VM, so by doing this
+ we make only one access to the field, and five accesses to the local variable, making the
+ routine much more efficient. It is recommended that you use this optimization when possible.
+
+
+Step 6
+
+The above createNote()
and onListItemClick()
+ methods use an asynchronous Intent invocation. We need a handler for the callback, so here we fill
+ in the body of the onActivityResult()
.
+onActivityResult()
is the overridden method
+ which will be called when an Activity returns with a result. (Remember, an Activity
+ will only return a result if launched with startActivityForResult
.) The parameters provided
+ to the callback are:
+
+ requestCode
— the original request code
+ specified in the Intent invocation (either ACTIVITY_CREATE
or
+ ACTIVITY_EDIT
for us).
+
+ resultCode
— the result (or error code) of the call, this
+ should be zero if everything was OK, but may have a non-zero code indicating
+ that something failed. There are standard result codes available, and you
+ can also create your own constants to indicate specific problems.
+
+ intent
— this is an Intent created by the Activity returning
+ results. It can be used to return data in the Intent "extras."
+
+
+ The combination of startActivityForResult()
and
+ onActivityResult()
can be thought of as an asynchronous RPC
+ (remote procedure call) and forms the recommended way for an Activity to invoke
+ another and share services.
+ Here's the code that belongs in your onActivityResult()
:
+
+super.onActivityResult(requestCode, resultCode, intent);
+Bundle extras = intent.getExtras();
+
+switch(requestCode) {
+case ACTIVITY_CREATE:
+ String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String body = extras.getString(NotesDbAdapter.KEY_BODY);
+ mDbHelper.createNote(title, body);
+ fillData();
+ break;
+case ACTIVITY_EDIT:
+ Long mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+ if (mRowId != null) {
+ String editTitle = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String editBody = extras.getString(NotesDbAdapter.KEY_BODY);
+ mDbHelper.updateNote(mRowId, editTitle, editBody);
+ }
+ fillData();
+ break;
+}
+
+
+ -
+ We are handling both the
ACTIVITY_CREATE
and
+ ACTIVITY_EDIT
activity results in this method.
+
+ -
+ In the case of a create, we pull the title and body from the extras (retrieved from the
+ returned Intent) and use them to create a new note.
+
+ -
+ In the case of an edit, we pull the mRowId as well, and use that to update
+ the note in the database.
+
+ -
+
fillData()
at the end ensures everything is up to date .
+
+
+
+
+Step 7
+
+
+
The Art of Layout
+
The provided
+ note_edit.xml layout file is the most sophisticated one in the application we will be building,
+ but that doesn't mean it is even close to the kind of sophistication you will be likely to want
+ in real Android applications.
+
Creating a
+ good UI is part art and part science, and the rest is work. Mastery of Declaring Layout is an essential part of creating
+ a good looking Android application.
+
Take a look at the
+ Hello Views
+ for some example layouts and how to use them. The ApiDemos sample project is also a
+ great resource from which to learn how to create different layouts.
+
+
+Open the file note_edit.xml
that has been provided and take a
+ look at it. This is the UI code for the Note Editor.
+ This is the most
+ sophisticated UI we have dealt with yet. The file is given to you to avoid
+ problems that may sneak in when typing the code. (The XML is very strict
+ about case sensitivity and structure, mistakes in these are the usual cause
+ of problems with layout.)
+ There is a new parameter used
+ here that we haven't seen before: android:layout_weight
(in
+ this case set to use the value 1 in each case).
+ layout_weight
is used in LinearLayouts
+ to assign "importance" to Views within the layout. All Views have a default
+ layout_weight
of zero, meaning they take up only as much room
+ on the screen as they need to be displayed. Assigning a value higher than
+ zero will split up the rest of the available space in the parent View, according
+ to the value of each View's layout_weight
and its ratio to the
+ overall layout_weight
specified in the current layout for this
+ and other View elements.
+ To give an example: let's say we have a text label
+ and two text edit elements in a horizontal row. The label has no
+ layout_weight
specified, so it takes up the minimum space
+ required to render. If the layout_weight
of each of the two
+ text edit elements is set to 1, the remaining width in the parent layout will
+ be split equally between them (because we claim they are equally important).
+ If the first one has a layout_weight
of 1
+ and the second has a layout_weight
of 2, then one third of the
+ remaining space will be given to the first, and two thirds to the
+ second (because we claim the second one is more important).
+ This layout also demonstrates how to nest multiple layouts
+ inside each other to achieve a more complex and pleasant layout. In this
+ example, a horizontal linear layout is nested inside the vertical one to
+ allow the title label and text field to be alongside each other,
+ horizontally.
+
+
+Step 8
+
+ Create a NoteEdit
class that extends
+ android.app.Activity
.
+ This is the first time we will have
+ created an Activity without the Android Eclipse plugin doing it for us. When
+ you do so, the onCreate()
method is not automatically
+ overridden for you. It is hard to imagine an Activity that doesn't override
+ the onCreate()
method, so this should be the first thing you do.
+
+ - Right click on the
com.android.demo.notepad2
package
+ in the Package Explorer, and select New > Class from the popup
+ menu.
+ - Fill in
NoteEdit
for the Name:
field in the
+ dialog.
+ - In the
Superclass:
field, enter
+ android.app.Activity
(you can also just type Activity and hit
+ Ctrl-Space on Windows and Linux or Cmd-Space on the Mac, to invoke code
+ assist and find the right package and class).
+ - Click Finish.
+ - In the resulting
NoteEdit
class, right click in the editor
+ window and select Source > Override/Implement Methods...
+ - Scroll down through the checklist in the dialog until you see
+
onCreate(Bundle)
— and check the box next to it.
+ - Click OK.
The method should now appear in your class.
+
+
+Step 9
+
+Fill in the body of the onCreate()
method for NoteEdit
.
+
+This will set the title of our new Activity to say "Edit Note" (one
+ of the strings defined in strings.xml
). It will also set the
+ content view to use our note_edit.xml
layout file. We can then
+ grab handles to the title and body text edit views, and the confirm button,
+ so that our class can use them to set and get the note title and body,
+ and attach an event to the confirm button for when it is pressed by the
+ user.
+ We can then unbundle the values that were passed in to the Activity
+ with the extras Bundle attached to the calling Intent. We'll use them to pre-populate
+ the title and body text edit views so that the user can edit them.
+ Then we will grab and store the mRowId
so we can keep
+ track of what note the user is editing.
+
+
+ -
+ Inside
onCreate()
, set up the layout:
+ setContentView(R.layout.note_edit);
+
+ -
+ Find the edit and button components we need:
+
These are found by the
+ IDs associated to them in the R class, and need to be cast to the right
+ type of View
(EditText
for the two text views,
+ and Button
for the confirm button):
+
+mTitleText = (EditText) findViewById(R.id.title);
+mBodyText = (EditText) findViewById(R.id.body);
+Button confirmButton = (Button) findViewById(R.id.confirm);
+ Note that mTitleText
and mBodyText
are member
+ fields (you need to declare them at the top of the class definition).
+
+ - At the top of the class, declare a
Long mRowId
private field to store
+ the current mRowId
being edited (if any).
+
+ - Continuing inside
onCreate()
,
+ add code to initialize the title
, body
and
+ mRowId
from the extras Bundle in
+ the Intent (if it is present):
+
+mRowId = null;
+Bundle extras = getIntent().getExtras();
+if (extras != null) {
+ String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String body = extras.getString(NotesDbAdapter.KEY_BODY);
+ mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+
+ if (title != null) {
+ mTitleText.setText(title);
+ }
+ if (body != null) {
+ mBodyText.setText(body);
+ }
+}
+
+ -
+ We are pulling the
title
and
+ body
out of the
+ extras
Bundle that was set from the
+ Intent invocation.
+ -
+ We also null-protect the text field setting (i.e., we don't want to set
+ the text fields to null accidentally).
+
+
+ -
+ Create an
onClickListener()
for the button:
+ Listeners can be one of the more confusing aspects of UI
+ implementation, but
+ what we are trying to achieve in this case is simple. We want an
+ onClick()
method to be called when the user presses the
+ confirm button, and use that to do some work and return the values
+ of the edited note to the Intent caller. We do this using something called
+ an anonymous inner class. This is a bit confusing to look at unless you
+ have seen them before, but all you really need to take away from this is
+ that you can refer to this code in the future to see how to create a
+ listener and attach it to a button. (Listeners are a common idiom
+ in Java development, particularly for user interfaces.) Here's the empty listener:
+
+confirmButton.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View view) {
+
+ }
+
+});
+
+
+Step 10
+
+Fill in the body of the onClick()
method of the OnClickListener
created in the last step.
+
+ This is the code that will be run when the user clicks on the
+ confirm button. We want this to grab the title and body text from the edit
+ text fields, and put them into the return Bundle so that they can be passed
+ back to the Activity that invoked this NoteEdit
Activity. If the
+ operation is an edit rather than a create, we also want to put the
+ mRowId
into the Bundle so that the
+ Notepadv2
class can save the changes back to the correct
+ note.
+
+ -
+ Create a
Bundle
and put the title and body text into it using the
+ constants defined in Notepadv2 as keys:
+
+Bundle bundle = new Bundle();
+
+bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
+bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
+if (mRowId != null) {
+ bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
+}
+
+ -
+ Set the result information (the Bundle) in a new Intent and finish the Activity:
+
+Intent mIntent = new Intent();
+mIntent.putExtras(bundle);
+setResult(RESULT_OK, mIntent);
+finish();
+
+ - The Intent is simply our data carrier that carries our Bundle
+ (with the title, body and mRowId).
+ - The
setResult()
method is used to set the result
+ code and return Intent to be passed back to the
+ Intent caller. In this case everything worked, so we return RESULT_OK for the
+ result code.
+ - The
finish()
call is used to signal that the Activity
+ is done (like a return call). Anything set in the Result will then be
+ returned to the caller, along with execution control.
+
+
+
+ The full onCreate()
method (plus supporting class fields) should
+ now look like this:
+
+private EditText mTitleText;
+private EditText mBodyText;
+private Long mRowId;
+
+@Override
+protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.note_edit);
+
+ mTitleText = (EditText) findViewById(R.id.title);
+ mBodyText = (EditText) findViewById(R.id.body);
+
+ Button confirmButton = (Button) findViewById(R.id.confirm);
+
+ mRowId = null;
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ String title = extras.getString(NotesDbAdapter.KEY_TITLE);
+ String body = extras.getString(NotesDbAdapter.KEY_BODY);
+ mRowId = extras.getLong(NotesDbAdapter.KEY_ROWID);
+
+ if (title != null) {
+ mTitleText.setText(title);
+ }
+ if (body != null) {
+ mBodyText.setText(body);
+ }
+ }
+
+ confirmButton.setOnClickListener(new View.OnClickListener() {
+
+ public void onClick(View view) {
+ Bundle bundle = new Bundle();
+
+ bundle.putString(NotesDbAdapter.KEY_TITLE, mTitleText.getText().toString());
+ bundle.putString(NotesDbAdapter.KEY_BODY, mBodyText.getText().toString());
+ if (mRowId != null) {
+ bundle.putLong(NotesDbAdapter.KEY_ROWID, mRowId);
+ }
+
+ Intent mIntent = new Intent();
+ mIntent.putExtras(bundle);
+ setResult(RESULT_OK, mIntent);
+ finish();
+ }
+ });
+}
+
+
+
+Before the new Activity can be seen by Android, it needs its own
+ Activity entry in the AndroidManifest.xml
file. This is to let
+ the system know that it is there and can be called. We could also specify
+ which IntentFilters the activity implements here, but we are going to skip
+ this for now and just let Android know that the Activity is
+ defined.
+ There is a Manifest editor included in the Eclipse plugin that makes it much easier
+ to edit the AndroidManifest file, and we will use this. If you prefer to edit the file directly
+ or are not using the Eclipse plugin, see the box at the end for information on how to do this
+ without using the new Manifest editor.
The Android Manifest editor helps you add more complex entries into the AndroidManifest.xml
+ file, have a look around at some of the other options available (but be careful not to select
+ them otherwise they will be added to your Manifest). This editor should help you understand
+ and alter the AndroidManifest.xml file as you move on to more advanced Android applications.
+
+ You should now be able to add real notes from
+the menu, as well as delete an existing one. Notice that in order to delete, you must
+first use the directional controls on the device to highlight the note.
+Furthermore, selecting a note title from the list should bring up the note
+editor to let you edit it. Press confirm when finished to save the changes
+back to the database.
+
+
Now try editing a note, and then hitting the back button on the emulator
+instead of the confirm button (the back button is below the menu button). You
+will see an error come up. Clearly our application still has some problems.
+Worse still, if you did make some changes and hit the back button, when you go
+back into the notepad to look at the note you changed, you will find that all
+your changes have been lost. In the next exercise we will fix these
+problems.
+
+The current application has some problems — hitting the back button when editing
+causes a crash, and anything else that happens during editing will cause the
+edits to be lost.
+To fix this, we will move most of the functionality for creating and editing
+the note into the NoteEdit class, and introduce a full life cycle for editing
+notes.
+
+ We will take care of storing the updates or new notes in the database
+ ourselves, using the life-cycle methods.
+
+ Because the other class now does the work, all this has to do is refresh
+ the data.
+
+You can also now remove the mNotesCursor field from the class, and set it back to using
+ a local variable in the fillData()
method:
+