Merge change Ib1eb2e9e into eclair

* changes:
  sdk doc change for esr: Add "resources" tab content. Fix links pointing to the old locations. Change Android.mk to output samples files to resources/samples. Misc other fixes.
This commit is contained in:
Android (Google) Code Review
2009-12-14 12:11:08 -08:00
212 changed files with 11969 additions and 166 deletions

View File

@@ -357,33 +357,31 @@ sample_dir := development/samples
web_docs_sample_code_flags := \
-hdf android.hasSamples 1 \
-samplecode $(sample_dir)/ApiDemos \
guide/samples/ApiDemos "API Demos" \
-samplecode $(sample_dir)/BluetoothChat \
guide/samples/BluetoothChat "Bluetooth Chat" \
-samplecode $(sample_dir)/ContactManager \
guide/samples/ContactManager "Contact Manager" \
resources/samples/ApiDemos "API Demos" \
-samplecode $(sample_dir)/BluetoothChat \
resources/samples/BluetoothChat "Bluetooth Chat" \
-samplecode $(sample_dir)/ContactManager \
resources/samples/ContactManager "Contact Manager" \
-samplecode $(sample_dir)/Home \
guide/samples/Home "Home" \
resources/samples/Home "Home" \
-samplecode $(sample_dir)/JetBoy \
guide/samples/JetBoy "JetBoy" \
resources/samples/JetBoy "JetBoy" \
-samplecode $(sample_dir)/LunarLander \
guide/samples/LunarLander "Lunar Lander" \
-samplecode $(sample_dir)/MultiResolution \
guide/samples/MultiResolution "Multiple Resolutions" \
resources/samples/LunarLander "Lunar Lander" \
-samplecode $(sample_dir)/MultiResolution \
resources/samples/MultiResolution "Multiple Resolutions" \
-samplecode $(sample_dir)/NotePad \
guide/samples/NotePad "Note Pad" \
resources/samples/NotePad "Note Pad" \
-samplecode $(sample_dir)/SearchableDictionary \
guide/samples/SearchableDictionary "Searchable Dictionary" \
resources/samples/SearchableDictionary "Searchable Dictionary" \
-samplecode $(sample_dir)/Snake \
guide/samples/Snake "Snake" \
resources/samples/Snake "Snake" \
-samplecode $(sample_dir)/SoftKeyboard \
guide/samples/SoftKeyboard "Soft Keyboard" \
-samplecode $(sample_dir)/Wiktionary \
guide/samples/Wiktionary "Wiktionary" \
-samplecode $(sample_dir)/WiktionarySimple \
guide/samples/WiktionarySimple "Wiktionary (Simplified)"
resources/samples/SoftKeyboard "Soft Keyboard" \
-samplecode $(sample_dir)/Wiktionary \
resources/samples/Wiktionary "Wiktionary" \
-samplecode $(sample_dir)/WiktionarySimple \
resources/samples/WiktionarySimple "Wiktionary (Simplified)"
## SDK version identifiers used in the published docs
# major[.minor] version for current SDK. (full releases only)

View File

@@ -64,7 +64,7 @@ to be replaced by the user.</p>
<p>Underlying all applications is a set of services and systems, including:
<ul>
<li>A rich and extensible set of <a
href="{@docRoot}guide/tutorials/views/index.html">Views</a> that can be used to
href="{@docRoot}resources/tutorials/views/index.html">Views</a> that can be used to
build an application, including lists, grids, text boxes, buttons, and even
an embeddable web browser</li>
<li><a href="{@docRoot}guide/topics/providers/content-providers.html">Content
@@ -80,7 +80,7 @@ to be replaced by the user.</p>
</ul>
<p>For more details and a walkthrough of an application, see the <a
href="{@docRoot}guide/tutorials/notepad/index.html">Notepad Tutorial</a>.</p>
href="{@docRoot}resources/tutorials/notepad/index.html">Notepad Tutorial</a>.</p>
<a name="libraries" id="libraries"></a>
<h2>Libraries</h2>

View File

@@ -60,7 +60,7 @@ D/ActivityManager( 763): Stopping: HistoryRecord{409dbb20 com.android.home.AllAp
that expose useful information such as CPU usage and frame rate. See <a href="#additionaldebugging">Debug
and Test Settings on the Emulator</a> below. </li>
</ul>
<p>Also, see the <a href="{@docRoot}guide/appendix/faq/troubleshooting.html">Troubleshooting</a> section
<p>Also, see the <a href="{@docRoot}resources/faq/troubleshooting.html">Troubleshooting</a> section
of the doc to figure out why your application isn't appearing on the emulator,
or why it's not starting. </p>

View File

@@ -105,7 +105,7 @@ Eclipse components (for example, WST). If you encounter an error when
installing ADT, your Eclipse installion might not include those components.
For information about how to quickly add the necessary components to your
Eclipse installation, see the troubleshooting topic
<a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui"</a>.</p>
<a href="{@docRoot}resources/faq/troubleshooting.html#installeclipsecomponents">ADT Installation Error: "requires plug-in org.eclipse.wst.sse.ui"</a>.</p>
<h4>For Linux users</h4>
<p>If you encounter this error when installing the ADT Plugin for Eclipse:

View File

@@ -1754,7 +1754,7 @@ to the current working directory): </p>
<p>For emulators running on Mac OS X, if you see an error &quot;Warning: No DNS servers found&quot; when starting the emulator, check to see whether you have an <code>/etc/resolv.conf</code> file. If not, please run the following line in a command window:</p>
<pre>ln -s /private/var/run/resolv.conf /etc/resolv.conf</pre>
<p>See <a href="{@docRoot}guide/appendix/faq/index.html">Frequently Asked Questions</a> for more troubleshooting information. </p>
<p>See <a href="{@docRoot}resources/faq/index.html">Frequently Asked Questions</a> for more troubleshooting information. </p>
<a name="limitations"></a>
<h2>Emulator Limitations</h2>

View File

@@ -364,81 +364,6 @@
</a></li>
</ul>
</li>
<li>
<h2><span class="en">Tutorials and Sample Code</span>
<span class="de" style="display:none">Lernprogramme und Beispielcode</span>
<span class="es" style="display:none">Tutoriales y código de ejemplo</span>
<span class="fr" style="display:none">Didacticiels et exemple de code</span>
<span class="it" style="display:none">Esercitazioni e codice di esempio</span>
<span class="ja" style="display:none"> </span>
<span class="zh-CN" style="display:none"></span>
<span class="zh-TW" style="display:none"></span>
</h2>
<ul>
<li><a href="<?cs var:toroot ?>guide/tutorials/hello-world.html">
<span class="en">Hello World</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/tutorials/views/index.html">
<span class="en">Hello Views</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/tutorials/localization/index.html">
<span class="en">Hello Localization</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/tutorials/notepad/index.html">
<span class="en">Notepad Tutorial</span>
</a></li>
</ul>
<ul>
<li class="toggle-list">
<div><a href="<?cs var:toroot ?>guide/samples/index.html">
<span class="en">Sample Code</span>
</a></div>
<ul>
<li><a href="<?cs var:toroot ?>guide/samples/ApiDemos/index.html">
<span class="en">API Demos</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/BluetoothChat/index.html">
<span class="en">Bluetooth Chat</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/ContactManager/index.html">
<span class="en">Contact Manager</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/Home/index.html">
<span class="en">Home</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/JetBoy/index.html">
<span class="en">JetBoy</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/LunarLander/index.html">
<span class="en">Lunar Lander</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/MultiResolution/index.html">
<span class="en">Multiple Resolutions</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/NotePad/index.html">
<span class="en">Note Pad</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/SearchableDictionary/index.html">
<span class="en">Searchable Dictionary</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/Snake/index.html">
<span class="en">Snake</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/SoftKeyboard/index.html">
<span class="en">Soft Keyboard</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/Wiktionary/index.html">
<span class="en">Wiktionary</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/samples/WiktionarySimple/index.html">
<span class="en">Wiktionary (Simplified)</span>
</a></li>
</ul>
</li>
</ul>
</li>
<li>
<h2><span class="en">Appendix</span>
@@ -463,9 +388,6 @@
<li><a href="<?cs var:toroot ?>guide/appendix/glossary.html">
<span class="en">Glossary</span>
</a></li>
<li><a href="<?cs var:toroot ?>guide/appendix/faq/index.html">
<span class="en">FAQ</span>
</a></li>
</ul>
</li>

View File

@@ -77,7 +77,7 @@ understanding of the application framework.
<p>
For additional help, consider joining one or more of the Android
discussion groups. Go to the
<a href="{@docRoot}community/index.html">Community</a> tab above
<a href="{@docRoot}resources/community-groups.html">Community</a> pages
for more information.
</p>

View File

@@ -268,7 +268,7 @@ in <code>C:\Documents and Settings\<user>\.android\</code> on Windows XP, and in
<p>Note that, if your development machine is using a non-Gregorian locale, the build
tools may erroneously generate an already-expired debug certificate, so that you get an
error when trying to compile your application. For workaround information, see the
troubleshooting topic <a href="{@docRoot}guide/appendix/faq/troubleshooting.html#signingcalendar">
troubleshooting topic <a href="{@docRoot}resources/faq/troubleshooting.html#signingcalendar">
I&nbsp;can't&nbsp;compile my app because the build tools generated an expired debug
certificate</a>. </p>

View File

@@ -170,6 +170,6 @@ maximum API Level. </p>
<code>android:minSdkVersion</code> as an attribute. </p>
<p>For more information, see the <a
href="{@docRoot}guide/developing/manifest/uses-sdk-element.html"><code>&lt;uses-
sdk&gt;</code></a> manifest element documentation and the <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;uses-sdk&gt;</code></a>
manifest element documentation and the <a
href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document.</p>

View File

@@ -339,7 +339,7 @@ without worrying about the AppWidgetProvider closing down due to an
sample's AppWidgetProvider</a> for an example of an App Widget running a {@link android.app.Service}.</p>
<p>Also see the <a
href="{@docRoot}guide/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html">
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html">
ExampleAppWidgetProvider.java</a> sample class.</p>
@@ -468,7 +468,7 @@ reaching the end, the App Widget host is notified that the configuration was can
App Widget will not be added.</p>
<p>See the <a
href="{@docRoot}guide/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.html">
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.html">
ExampleAppWidgetConfigure.java</a> sample class in ApiDemos for an example.</p>

View File

@@ -28,7 +28,7 @@ ES API. However, it may not be identical, so watch out for deviations.</p>
<p>For an example of this usage model (based on the classic GL ColorCube), showing how to use
it with threads can be found in
<a href="{@docRoot}guide/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.html">com.android.samples.graphics.GLSurfaceViewActivity.java</a>.
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/GLSurfaceViewActivity.html">com.android.samples.graphics.GLSurfaceViewActivity.java</a>.
</p>
<p>Writing a summary of how to actually write 3D applications using OpenGL is

View File

@@ -702,8 +702,8 @@ declared in its manifest file. (If you're working offline in the SDK, you
can find all the source files for this sample application, including its
manifest file, at {@code &lt;sdk&gt;/samples/NotePad/index.html}.
If you're viewing the documentation online, the source files are in the
<a href="{@docRoot}guide/samples/index.html">Tutorials and Sample Code</a>
section <a href="{@docRoot}guide/samples/NotePad/index.html">here</a>.)
<a href="{@docRoot}resources/samples/index.html">Tutorials and Sample Code</a>
section <a href="{@docRoot}resources/samples/NotePad/index.html">here</a>.)
</p>
<p>

View File

@@ -31,7 +31,7 @@ or scale them up by a factor of 1.5 (high dpi screens).
The screen density is expressed as dots-per-inch (dpi).</p>
<p>For more information, see
<a href="{@docRoot}guide/practices/screens_suppport.html">Multiple Screens Support</a>.</p>
<a href="{@docRoot}guide/practices/screens_support.html">Multiple Screens Support</a>.</p>
<dt>attributes:</dt>

View File

@@ -51,7 +51,7 @@ defaults.</li>
<h2>See also</h2>
<ol>
<li><a
href="{@docRoot}guide/tutorials/localization/index.html">Hello, L10N Tutorial</a></li>
href="{@docRoot}resources/tutorials/localization/index.html">Hello, L10N Tutorial</a></li>
<li><a href="resources-i18n.html">Resources</a></li>
<li><a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a></li>
<li><a href="{@docRoot}reference/android/app/Activity.html#ActivityLifecycle">Activity Lifecycle</a></li>
@@ -90,7 +90,7 @@ programmatically. This document does not cover how to localize your Java code.
</ul>
<p>The <a
href="{@docRoot}guide/tutorials/localization/index.html">Hello, L10N
href="{@docRoot}resources/tutorials/localization/index.html">Hello, L10N
</a> tutorial takes you through the steps of creating a simple localized
application that uses locale-specific resources in the way described in this
document. </p>

View File

@@ -13,9 +13,9 @@ parent.link=index.html
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/tutorials/views/hello-spinner.html">Hello Spinner tutorial</a></li>
<li><a href="{@docRoot}guide/tutorials/views/hello-listview.html">Hello ListView tutorial</a></li>
<li><a href="{@docRoot}guide/tutorials/views/hello-gridview.html">Hello GridView tutorial</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Hello Spinner tutorial</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-listview.html">Hello ListView tutorial</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Hello GridView tutorial</a></li>
</ol>
</div>
</div>
@@ -107,7 +107,7 @@ mHistoryView.setOnItemClickListener(mMessageClickedHandler);
<div class="special">
<p>For more discussion on how to create different AdapterViews, read the following tutorials:
<a href="{@docRoot}guide/tutorials/views/hello-spinner.html">Hello Spinner</a>,
<a href="{@docRoot}guide/tutorials/views/hello-listview.html">Hello ListView</a>, and
<a href="{@docRoot}guide/tutorials/views/hello-gridview.html">Hello GridView</a>.
<a href="{@docRoot}resources/tutorials/views/hello-spinner.html">Hello Spinner</a>,
<a href="{@docRoot}resources/tutorials/views/hello-listview.html">Hello ListView</a>, and
<a href="{@docRoot}resources/tutorials/views/hello-gridview.html">Hello GridView</a>.
</div>

View File

@@ -61,7 +61,7 @@ examples of what you could do with them:</p>
</li>
<li>
You could override the way that an EditText component is rendered on the screen
(the <a href="{@docRoot}guide/samples/NotePad/index.html">Notepad Tutorial</a> uses this to good effect,
(the <a href="{@docRoot}resources/samples/NotePad/index.html">Notepad Tutorial</a> uses this to good effect,
to create a lined-notepad page).
</li>
<li>
@@ -318,9 +318,9 @@ Here's a summary of some of the other standard methods that the framework calls
<h3 id="customexample">A Custom View Example</h3>
<p>The CustomView sample in the
<a href="{@docRoot}guide/samples/ApiDemos/index.html">API Demos</a> provides an example
<a href="{@docRoot}resources/samples/ApiDemos/index.html">API Demos</a> provides an example
of a customized View. The custom View is defined in the
<a href="{@docRoot}guide/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html">LabelView</a>
<a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/view/LabelView.html">LabelView</a>
class.</p>
<p>The LabelView sample demonstrates a number of different aspects of custom components:</p>
<ul>
@@ -339,7 +339,7 @@ class.</p>
provided canvas.</li>
</ul>
<p>You can see some sample usages of the LabelView custom View in
<a href="{@docRoot}guide/samples/ApiDemos/res/layout/custom_view_1.html">custom_view_1.xml</a>
<a href="{@docRoot}resources/samples/ApiDemos/res/layout/custom_view_1.html">custom_view_1.xml</a>
from the samples. In particular, you can see a mix of both <code>android:</code>
namespace parameters and custom <code>app:</code> namespace parameters. These
<code>app:</code> parameters are the custom ones that the LabelView recognizes
@@ -446,7 +446,7 @@ you would do with a fully customized component, but by starting with a more
specialized class in the View heirarchy, you can also get a lot of behavior for
free that probably does exactly what you want.</p>
<p>For example, the SDK includes a <a
href="{@docRoot}guide/samples/NotePad/index.html">NotePad application</a> in the
href="{@docRoot}resources/samples/NotePad/index.html">NotePad application</a> in the
samples. This demonstrates many aspects of using the Android platform, among
them is extending an EditText View to make a lined notepad. This is not a
perfect example, and the APIs for doing this might change from this early
@@ -455,7 +455,7 @@ preview, but it does demonstrate the principles.</p>
NotePad sample into Eclipse (or
just look at the source using the link provided). In particular look at the definition of
<code>MyEditText</code> in the <a
href="{@docRoot}guide/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">NoteEditor.java</a>
href="{@docRoot}resources/samples/NotePad/src/com/example/android/notepad/NoteEditor.html">NoteEditor.java</a>
file.</p>
<p>Some points to note here</p>
<ol>

View File

@@ -65,7 +65,7 @@ example, the EditText element has a <code>text</code> attribute that corresponds
<p class="note"><strong>Tip:</strong> Learn more about different layout types in <a href="{@docRoot}guide/topics/ui/layout-objects.html">Common
Layout Objects</a>. There are also a collection of tutorials on building various layouts in the
<a href="{@docRoot}guide/tutorials/views/index.html">Hello Views</a> tutorial guide.</p>
<a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a> tutorial guide.</p>
<h2 id="write">Write the XML</h2>

View File

@@ -47,10 +47,10 @@ for notifications and short activities that directly relate to the application i
See <a href="#ProgressDialog">Creating a ProgressDialog</a> below.</dd>
<dt>{@link android.app.DatePickerDialog}</dt>
<dd>A dialog that allows the user to select a date. See the
<a href="{@docRoot}guide/tutorials/views/hello-datepicker.html">Hello DatePicker</a> tutorial.</dd>
<a href="{@docRoot}resources/tutorials/views/hello-datepicker.html">Hello DatePicker</a> tutorial.</dd>
<dt>{@link android.app.TimePickerDialog}</dt>
<dd>A dialog that allows the user to select a time. See the
<a href="{@docRoot}guide/tutorials/views/hello-timepicker.html">Hello TimePicker</a> tutorial.</dd>
<a href="{@docRoot}resources/tutorials/views/hello-timepicker.html">Hello TimePicker</a> tutorial.</dd>
</dl>
<p>If you would like to customize your own dialog, you can extend the

View File

@@ -19,7 +19,7 @@ parent.link=index.html
<p>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}.</p>
<p>Also see the <a href="{@docRoot}guide/tutorials/views/index.html">Hello Views</a> tutorials for
<p>Also see the <a href="{@docRoot}resources/tutorials/views/index.html">Hello Views</a> tutorials for
some guidance on using more Android View layouts.</p>
<h2 id="framelayout">FrameLayout</h2>
@@ -83,7 +83,7 @@ neighboring elements. This can be turned off by setting
<code>android:baselineAligned=&quot;false&quot;</code> in the layout XML. </p>
<p>To view other sample code, see the
<a href="{@docRoot}guide/tutorials/views/hello-linearlayout.html">Hello LinearLayout</a> tutorial.</p>
<a href="{@docRoot}resources/tutorials/views/hello-linearlayout.html">Hello LinearLayout</a> tutorial.</p>
<h2 id="tablelayout">TableLayout</h2>
@@ -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. </p>
<p>To view sample code, see the <a href="{@docRoot}guide/tutorials/views/hello-tablelayout.html">Hello
<p>To view sample code, see the <a href="{@docRoot}resources/tutorials/views/hello-tablelayout.html">Hello
TableLayout</a> tutorial.</p>
@@ -208,7 +208,7 @@ refer to the ID using the syntax of a relative resource
For example, assigning the parameter <code>toLeft="my_button"</code> to a TextView would place the TextView to
the left of the View with the ID <var>my_button</var> (which must be written in the XML <em>before</em> the TextView). </p>
<p>To view this sample code, see the <a href="{@docRoot}guide/tutorials/views/hello-relativelayout.html">Hello
<p>To view this sample code, see the <a href="{@docRoot}resources/tutorials/views/hello-relativelayout.html">Hello
RelativeLayout</a> tutorial.</p>

View File

@@ -180,7 +180,7 @@ Then, register a {@link android.view.ContextMenu} for the View, with
<code>{@link android.app.Activity#registerForContextMenu(View) registerForContextMenu()}</code>.</p>
<p>For example, here is some code that can be used with the
<a href="{@docRoot}guide/tutorials/notepad/index.html">Notepad application</a>
<a href="{@docRoot}resources/tutorials/notepad/index.html">Notepad application</a>
to add a context menu for each note in the list:</p>
<pre>
public void onCreateContextMenu(ContextMenu menu, View v,
@@ -518,5 +518,5 @@ a <code>&lt;category></code> element in the intent filter. For example:</p>
<a href="/guide/topics/intents/intents-filters.html">Intents and Intent Filters</a> document.</p>
<p>For a sample application using this technique, see the
<a href="{@docRoot}guide/samples/NotePad/index.html">Note Pad</a>
<a href="{@docRoot}resources/samples/NotePad/index.html">Note Pad</a>
sample code.</p>

View File

@@ -15,7 +15,7 @@ parent.link=index.html
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}guide/tutorials/views/hello-formstuff.html">Hello Form Stuff tutorial</a></li>
<li><a href="{@docRoot}resources/tutorials/views/hello-formstuff.html">Hello Form Stuff tutorial</a></li>
</ol>
</div>
</div>

View File

@@ -40,7 +40,7 @@ parent.link=index.html
</li>
<li>
You could override the way that an EditText component is rendered on the screen
(the <a href="{@docRoot}guide/samples/NotePad/">Notepad sample</a> uses this to good effect,
(the <a href="{@docRoot}resources/samples/NotePad/">Notepad sample</a> uses this to good effect,
to create a lined-notepad page).
</li>
<li>

View File

@@ -39,7 +39,7 @@ page.title=Android とは
<p>アプリケーションの基盤となるのは、次のサービスとシステムのセットです:
<ul>
<li>アプリケーションの構築を可能にする、拡張可能で豊富な<a
href="{@docRoot}guide/tutorials/views/index.html">ビュー</a>のセット。ビューには、リスト、グリッド、テキスト ボックス、ボタンだけでなく、埋め込み可能なウェブブラウザも含まれます。</li>
href="{@docRoot}resources/tutorials/views/index.html">ビュー</a>のセット。ビューには、リスト、グリッド、テキスト ボックス、ボタンだけでなく、埋め込み可能なウェブブラウザも含まれます。</li>
<li><a href="{@docRoot}guide/topics/providers/content-providers.html">コンテンツ プロバイダ</a>を使用すると、アプリケーションのデータ(たとえば、連絡先アプリケーション)に、別のアプリケーションからアクセスしたり、データを共有させることができます。</li> <li><a
href="{@docRoot}guide/topics/resources/resources-i18n.html">リソース マネージャ</a>は、ローカライズされた文字列、グラフィックス、レイアウト ファイルなどのコード以外のリソースへのアクセスを提供します。</li>
<li>{@link android.app.NotificationManager 通知マネージャ}を使用すると、すべてのアプリケーションからステータス バーにカスタマイズした警告を表示することができます。</li>
@@ -47,7 +47,7 @@ page.title=Android とは
</ul>
<p>アプリケーションの簡単な説明と詳細については、<a
href="{@docRoot}guide/tutorials/notepad/index.html">Notepad チュートリアル</a>をご覧ください。</p>
href="{@docRoot}resources/tutorials/notepad/index.html">Notepad チュートリアル</a>をご覧ください。</p>
<a name="libraries" id="libraries"></a>
<h2>ライブラリ</h2>

View File

@@ -41,12 +41,12 @@ Android 向けプログラム開発の最初のステップは、SDKソフト
</p>
<p>
SDK のダウンロード後は、まずはじめにデベロッパー ガイドを参照してください。コードを実際に見てみることから始めたい場合は、簡単な <a href="{@docRoot}guide/tutorials/hello-world.html">Hello World</a> チュートリアルを参照してください。Android プラットフォーム向けに作成された標準的な「Hello, World」アプリケーションについて説明しています。<a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>ドキュメントは、アプリケーション フレームワークを理解したいユーザーに最適な出発点となります。
SDK のダウンロード後は、まずはじめにデベロッパー ガイドを参照してください。コードを実際に見てみることから始めたい場合は、簡単な <a href="{@docRoot}resources/tutorials/hello-world.html">Hello World</a> チュートリアルを参照してください。Android プラットフォーム向けに作成された標準的な「Hello, World」アプリケーションについて説明しています。<a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>ドキュメントは、アプリケーション フレームワークを理解したいユーザーに最適な出発点となります。
</p>
<p>
不明点などがある場合は、Android ディスカッション グループへの参加をおすすめします。詳しくは上部にある [<a href="{@docRoot}community/index.html">コミュニティ</a>] タブをご覧ください。
不明点などがある場合は、Android ディスカッション グループへの参加をおすすめします。詳しくは上部にある [<a href="{@docRoot}resources/community-groups.html">コミュニティ</a>] タブをご覧ください。
</p>
<p>デベロッパー ガイドの別のページに移動してから、このページに戻るには、[デベロッパー ガイド] タブをクリックします。 </p>

View File

@@ -153,7 +153,7 @@ page.title=アプリケーションへの署名
<p>次にビルドを行うと、ビルド ツールは新しいキーストアとデバッグ キーを再度生成します。</p>
<p>開発コンピュータがグレゴリオ暦以外のロケールを使用している場合、ビルド ツールが誤って期限切れのデバッグ証明書を生成することがあります。このため、アプリケーションをコンパイルしようとするとエラーが発生します。解決策については、トラブルシューティング トピックの <a href="{@docRoot}guide/appendix/faq/troubleshooting.html#signingcalendar">ビルド ツールが期限切れのデバッグ証明書を生成するため、アプリケーションがコンパイルできない</a> をご覧ください。 </p>
<p>開発コンピュータがグレゴリオ暦以外のロケールを使用している場合、ビルド ツールが誤って期限切れのデバッグ証明書を生成することがあります。このため、アプリケーションをコンパイルしようとするとエラーが発生します。解決策については、トラブルシューティング トピックの <a href="{@docRoot}resources/faq/troubleshooting.html#signingcalendar">ビルド ツールが期限切れのデバッグ証明書を生成するため、アプリケーションがコンパイルできない</a> をご覧ください。 </p>
<h2 id="releasemode">公開リリースへの署名</h2>

View File

@@ -0,0 +1,116 @@
community=true
page.title=コミュニティ
@jd:body
<div id="mainBodyFluid">
<h1>コミュニティ</h1>
<p>Android デベロッパー コミュニティへようこそ。コミュニティでのディスカッションにぜひ参加してください。投稿する前に、コミュニティ ガイドラインが記載されている<a href="http://source.android.com/discuss/android-discussion-groups-charter">グループの趣意</a>をお読みください。</p>
<p class="note"><strong>注:</strong> Android ソース コード(アプリケーション開発ではなく)に関するディスカッションは、<a href="http://source.android.com/discuss">オープンソース プロジェクトのメーリング リスト</a>(英語)を参照してください。</p>
<p style="margin-bottom:.5em"><strong>目次</strong></p>
<ol class="toc">
<li><a href="#BeforeYouPost">質問を投稿する前に</a></li>
<li><a href="#ApplicationDeveloperLists">アプリケーション デベロッパー メーリング リスト</a></li>
<li><a href="#UsingEmail">メーリング リストにメールを使用</a></li>
<li><a href="#UsingIRC">IRC の使用</a></li>
</ol>
<h2 id="BeforeYouPost">質問を投稿する前に</h2>
<p>投稿を作成する前に、下記をお試しください:</p>
<ol>
<li><a href="{@docRoot}resources/faq/index.html">よくある質問を参照します</a>。Android アプリケーションの開発について非常に一般的な質問が、この一覧に記載されており、頻繁に更新されています。</li>
<li><strong>Android のメイン サイトの検索バー(このページの上部にあるのと同じもの)に、調べたいキーワードを入力してください</strong>。この検索は、サイト、ドキュメント、ブログに含まれるすべてのコンテンツの他に、すべてのグループで以前行われたすべてのディスカッションを網羅しています。誰か他の人が、以前にも同じ問題に遭遇した可能性は大いにあります。</li>
<li><b>メーリング リストのアーカイブを検索</b>して、同じ質問に関するディスカッションが既に存在しないか調べてください。
</li>
</ol>
<p>質問への答えが見つからない場合、コミュニティで質問することをおすすめします。投稿する際は、次の手順に従ってください。
<ol>
<li>コミュニティ ガイドラインが記載されている<b><a href="http://sites.google.com/a/android.com/opensource/discuss/android-discussion-groups-charter">Android メーリングリストの趣意</a></b>をお読みください。
</li>
<li><b>質問に最適なメーリング リストを選択してください</b>。後述するように、デベロッパー向けのメーリング リストは何種類かに分かれています。</li>
<li>
<b>質問の内容を明確に</b>。明確な質問は、回答者と、将来情報を探そうとする人の双方にとって有益です。</li>
<li><b>投稿は詳しく書いてください</b>。回答者の人たちが問題を理解するのに役立ちます。コードやログのスニペット、スクリーンショットへのリンクを含めることも有用です。質問をわかりやすく表現するための詳しいガイドラインは、<a href="http://www.catb.org/%7Eesr/faqs/smart-questions.html">賢い質問のしかた</a>(英語)をご覧ください。
</li>
</ol>
<h3 id="ApplicationDeveloperLists">アプリケーション デベロッパー メーリング リスト</h3>
<ul>
<li><b>Android SDK Japan</b> - Android SDK に関する質問と答え、提案とフィードバックを交換できる場です。
<ul>
<li>Google グループで登録:&nbsp;<a href="http://groups.google.co.jp/group/android-sdk-japan?hl=ja">android-sdk-japan</a></li>
<li>メールで登録:&nbsp;<a href="mailto:android-sdk-japan-subscribe@googlegroups.com">android-sdk-japan-subscribe@googlegroups.com</a></li>
</ul>
</li>
<li><b>Android 初心者向け</b> - Android アプリケーションの開発初心者向けです。Android SDK と基本的な Android API の利用方法について学習したい場合は、このメーリング リストから始めてください。このメーリング リストには、SDK を利用するデベロッパーの初歩的なディスカッションの場所です。Android プラットフォームで初めてアプリケーションを作成して実行する際は、非常に有益な情報を得ることができるでしょう。開発環境のインストール方法についての質問を投稿したり、Android 開発の初歩(初めて作成するユーザー インターフェース、権限、Android ファイルシステムでのファイル、Android マーケットでのアプリケーションなどについて教えてもらうことができます。新たに質問する前に、必ず最初にアーカイブを確認してください。高度な内容の質問の場合はここでは質問せず、android-developers メーリング リストで質問してください。また使用に関する質問は、android-discuss メーリング リストの方が適しています。
<ul>
<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-beginners?hl=ja">android-beginners</a></li>
<li>メールで登録:&nbsp;<a href="mailto:android-beginners-subscribe@googlegroups.com">android-beginners-subscribe@googlegroups.com</a></li>
</ul>
</li>
<li><b>Android デベロッパー向け</b> - Android アプリケーション デベロッパーとして経験を積むにつれ、Android アプリケーション開発の基本を把握して、SDK を使いこなせるようになります。今度は、より高度な内容について質問する必要があります。アプリケーションのトラブルシューティング、実装へのアドバイス、アプリケーションのパフォーマンスやユーザー エクスペリエンスを改良するテクニックに関する質問には、次のメーリング リストが役立ちます。使用に関する問題android-discuss をご利用くださいや、Android SDK を使用する際の初歩的質問android-beginners をご利用ください)についてのディスカッションの場所ではありません。
<ul>
<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-developers?hl=ja">android-developers</a></li>
<li>メールで登録:&nbsp;<a href="mailto:android-developers-subscribe@googlegroups.com">android-developers-subscribe@googlegroups.com</a></li>
</ul>
</li>
<li><b>Android ディスカッション</b> - Android に関する「井戸端会議」です。ここでは、Android プラットフォームへのアイデア、自分のアプリケーションの公表、Android 携帯端末に関するディスカッション、コミュニティ リソースなど、Android に関することなら何でも投稿可能です。ただし他のメーリング リストに該当する内容の場合は、そのメーリング リストに投稿することをおすすめします。質問のテーマが限定されている場所の方が、より多くの回答を得ることができるでしょう。
<ul>
<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-discuss?hl=ja">android-discuss</a></li>
<li>メールで登録:&nbsp;<a href="mailto:android-discuss-subscribe@googlegroups.com">android-discuss-subscribe@googlegroups.com</a></li>
</ul>
</li>
<li><b>Android セキュリティ ディスカッション</b> - 安全な開発、新たに発生したセキュリティの問題、Android デベロッパー向けの Android デベロッパーによるベスト プラクティスについて自由にディスカッションを行える場所です。メーリング リストで脆弱性を直接公開することは、すべての Android ユーザーを危険にさらすことになるので、避けてください。
<ul>
<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-security-discuss?hl=ja">android-security-discuss</a></li>
<li>メールで登録:&nbsp;<a href="mailto:android-security-discuss@googlegroups.com">android-security-discuss@googlegroups.com</a></li>
</ul>
</li>
<li><b>Android セキュリティに関する発表</b> - Android セキュリティ チームがセキュリティ関連の発表を行う、小規模なグループです。
<ul>
<li>Google グループで登録:&nbsp;<a href="http://groups.google.com/group/android-security-announce?hl=ja">android-security-announce</a></li>
<li>メールで登録:&nbsp;<a href="mailto:android-security-announce-subscribe@googlegroups.com">android-security-announce-subscribe@googlegroups.com</a></li>
</ul>
</li>
<li><b>Android マーケット ヘルプフォーラム</b> - Android マーケットに関する質問や問題の報告をするための、ウェブベースのディスカッション フォーラムです。
<ul>
<li>URL:&nbsp;<a href="http://www.google.com/support/forum/p/Android+Market?hl=ja">http://www.google.com/support/forum/p/Android+Market?hl=ja</a></li>
</ul>
</li>
</ul>
<h2 id="UsingEmail">メーリング リストにメールを使用</h2>
<p><a href="http://groups.google.com/">Google グループ</a> のサイトを使用する代わりに、メール クライアントを使用して、メーリング リストに投稿することも可能です。</p>
<p>Google グループのサイトを使用せずに、グループに登録するには、上記の「メールで登録」のリンクを使用します。</p>
<p>メーリング リストへの投稿をメールで受信するように設定する方法は、次のとおりです:</p>
<ol><li>Google グループ サイトから、グループにログインします。たとえば android-framework グループには <a href="http://groups.google.com/group/android-framework?hl=ja">http://groups.google.com/group/android-framework?hl=ja</a> にアクセスします。</li>
<li>右側の [メンバーステータスを編集] をクリックします。</li>
<li>[このグループの閲覧方法] で、メール オプションのいずれかを選択します。 </li>
</ol>
<h2 id="UsingIRC">IRC の使用</h2>
<p>Android コミュニティは irc.freenode.net サーバーの #android チャンネルを使用しています。
</p>
</div>

View File

@@ -0,0 +1,375 @@
page.title=Hello, World
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>このドキュメントの内容</h2>
<ol>
<li><a href="#avd">AVD の作成</a></li>
<li><a href="#create">プロジェクトを作成する</a></li>
<li><a href="#ui">UI を構築する</a></li>
<li><a href="#run">コードを実行する</a></li>
<li><a href="#upgrading">UI を XML レイアウトにアップグレードする</a></li>
<li><a href="#debugging">プロジェクトをデバッグする</a></li>
<li><a href="#noeclipse">Eclipse を使用せずにプロジェクトを作成する</a></li>
</ol>
</div>
</div>
<p>デベロッパーにとって、開発フレームワークの第一印象は、どれだけ簡単に「Hello, World」を記述できるかで決まります。Android では、非常に簡単に記述できます。総合開発環境として Eclipse を使用している場合には、開発は特に簡単です。プロジェクトの作成と管理に使用できる便利なプラグインが用意されており、開発サイクルを大幅にスピードアップできるためです。</p>
<p>Eclipse を使用していない場合でも問題ありません。<a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>に慣れてから、このチュートリアルに戻り、Eclipse に関する部分以外を参考にしてください。</p>
<p>開始する前に、最新の SDK がインストールされている必要があります。また、Eclipse を使用する場合には、ADT プラグインもインストールされている必要があります。これらのプログラムがインストールされていない場合は、「<a href="{@docRoot}sdk/installing.html">Installing the Android SDK</a>」を参考にインストールを実行して、完了後にこのチュートリアルに戻ってください。</p>
<h2 id="avd">AVD の作成</h2>
<div class="sidebox-wrapper">
<div class="sidebox-inner">
<p>AVD の使用方法と使用可能なオプションについて詳しくは、<a href="{@docRoot}guide/developing/tools/avd.html">Android 仮想デバイス</a> のドキュメントを参照してください。</p>
</div>
</div>
<p>このチュートリアルでは、開発したアプリケーションを Android エミュレータで実行します。エミュレータを起動するには、事前に Android 仮想デバイスAVDを作成する必要があります。AVD は、エミュレータが使用するシステム イメージとデバイスの設定を定義するものです。</p>
<p>AVD を作成するには、Android SDK に含まれている「android」ツールを使用します。コマンド プロンプトまたはターミナルを開き、SDK パッケージの中の <code>tools/</code> ディレクトリに移動して、次のコマンドを実行します。
<pre>
android create avd --target 2 --name my_avd
</pre>
<p>カスタム ハードウェア プロファイルを作成するかどうかを尋ねられます。ここではひとまず、リターン キーを押してスキップしますデフォルトの回答は「No」となっています以上で AVD の作成は終了です。この作業により、Android 1.5 プラットフォームを使用する「my_avd」という名前の AVD が構成されました。これで、AVD をエミュレータで使用できる状態になりました。</p>
<p>上記のコマンドで使用した <code>--target</code> オプションは、エミュレータを実行する配備ターゲットを指定するもので、必須オプションです。<code>--name</code> オプションは新規 AVD の名前を定義するもので、これも必須オプションです。</p>
<h2 id="create">新規 Android プロジェクトを作成する</h2>
<p>AVD を作成したら、次は Eclipse 内で新規 Android プロジェクトを開始します。</p>
<ol>
<li>Eclipse で、<strong>[[]ファイルFile] &gt; [[]新規New] &gt; [[]プロジェクトProject]</strong> を選択します。
<p>ADT Plugin for Eclipse が正常にインストールされていれば、表示されるダイアログに、「Android」というラベルの付いたフォルダと、その中の「Android プロジェクトAndroid Project」が表示されます1 つまたは複数の Android プロジェクトを作成した後は、「Android XML File」というエントリも表示されるようになります。</p>
</li>
<li>「Android プロジェクトAndroid Project」を選択して、[[]<strong>次へNext</strong>] をクリックします。<br/><a href="images/hello_world_0.png"><img src="images/hello_world_0.png" style="height:230px" alt="" /></a>
</li>
<li>プロジェクトの詳細項目に以下の値を入力します。
<ul>
<li><em>プロジェクト名Project name:</em> HelloAndroid</li>
<li><em>アプリケーション名Application name:</em> Hello, Android</li>
<li><em>パッケージ名Package name:</em> com.example.helloandroidまたは自分のプライベート ネームスペース)</li>
<li><em>アクティビティを作成Create Activity:</em> HelloAndroid</li>
<li><em>SDK の最小バージョンMin SDK Version:</em> 2</li>
</ul>
<p>[[]<strong>完了Finish</strong>] をクリックします。</p>
<a href="images/hello_world_1.png"><img src="images/hello_world_1.png" style="height:230px" alt="" /></a>
<p>各フィールドの説明は以下のとおりです。</p>
<dl>
<dt><em>プロジェクト名Project Name</em></dt>
<dd>Eclipse のプロジェクト名。プロジェクト ファイルを格納するディレクトリの名前です。</dd>
<dt><em>アプリケーション名Application Name</em></dt>
<dd>アプリケーション名はユーザーにわかりやすいアプリケーションのタイトルにします。この名前が Android 携帯端末に表示されます。</dd>
<dt><em>パッケージ名Package Name</em></dt>
<dd>作成したすべてのソース コードを格納するパッケージ ネームスペースですJava プログラミング言語で作成するパッケージと同じルールに従います)。また、これにより、スタブ Activity が生成されるパッケージの名前も設定されます。
<p>パッケージ名は Android システムにインストールされたすべてのパッケージに共通して固有のものでなければなりません。このため、作成するアプリケーションに標準的なドメイン スタイルのパッケージを使用することが非常に重要です。上記の例では、「com.example」というネームスペースを使用しています。これはサンプル ドキュメント用のネームスペースです。実際にアプリケーションを作成する際には、所属する組織または法人に適切なネームスペースを使用します。</p></dd>
<dt><em>アクティビティを作成Create Activity</em></dt>
<dd>プラグインによって生成されるクラス スタブの名前です。クラス スタブは Android の {@link android.app.Activity} クラスのサブクラスとなります。アクティビティとは単に、実行して何らかの処理を行うことができるクラスを意味します。選択に応じて UI を作成することもできます(ただし必須ではありません)。チェックボックスになっていることからわかるように、これは任意選択の項目です。しかし、実際にはほとんどのアプリケーションでは、アクティビティをアプリケーションの基盤として使用しています。</dd>
<dt><em>SDK の最小バージョンMin SDK Version</em></dt>
<dd>作成するアプリケーションが必要とする最小 API レベルを指定する値です。ここに入力した API レベルが、選択可能なターゲットのいずれかで提供される API レベルと一致する場合は、ビルド ターゲットが自動的に選択されますこの例では、API レベルに「2」と入力するとターゲット Android 1.1 が選択されます。Android システム イメージと Android SDK それぞれの新しいバージョンでは、API に追加または変更が加えられている可能性があります。追加または変更が加えられている場合、新しい API レベルがシステム イメージに割り当てられ、どのアプリケーションの実行を許可するかが規制されます。アプリケーションで必要な API レベルがデバイスでサポートされるレベルよりも<em>高い</em>場合、アプリケーションはインストールされません。</dd>
</dl>
<p><em>その他のフィールド</em>: 「デフォルト ロケーションの使用」チェックボックスでは、プロジェクトのファイルが生成され保存されるディスク上の場所を変更することができます。「ビルド ターゲット」は、作成するアプリケーションがコンパイルされるときにターゲットとするプラットフォームです(この項目は [[]SDK の最小バージョンMin SDK Version] の入力値に基づいて自動的に選択されます)。</p>
<p class="note">ここで、選択した「ビルド ターゲット」で Android 1.1 プラットフォームが使用されることに注目してください。これは、作成するアプリケーションが Android 1.1 プラットフォーム ライブラリをターゲットとしてコンパイルされることを意味します。先ほど作成した AVD は Android 1.5 プラットフォームで実行されます。バージョンの数字が一致しませんが、Android アプリケーションには上方互換性があるため、1.1 プラットフォーム ライブラリをターゲットとして構築されたアプリケーションでも 1.5 プラットフォームで正常に動作します。ただしその逆の場合は正常に動作しません。</p>
</li>
</ol>
<p>さて、これで Android プロジェクトを使用できる状態になりました。プロジェクトは左側のパッケージ エクスプローラーPackage Explorerで表示できます。<em>「HelloAndroid」 &gt; 「src」 &gt; 「com.example.helloandroid」</em> の中にある <code>HelloAndroid.java</code> ファイルを開きます。ファイルの内容は次のようになっています。</p>
<pre>
package com.example.helloandroid;
import android.app.Activity;
import android.os.Bundle;
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}</pre>
<p>クラスが {@link android.app.Activity} クラスに基づいていることに注目してください。アクティビティActivityとは、処理を実行するために使用される単体のアプリケーション エンティティです。1 つのアプリケーションにはいくつものアクティビティが含まれる場合がありますが、ユーザーが一度に操作するのは 1 つのアクティビティです。アクティビティが開始すると、Android システムによって {@link android.app.Activity#onCreate(Bundle) onCreate()} メソッドが呼び出されます。このタイミングですべての初期化と UI セットアップを実行します。アクティビティにユーザー インターフェースは必須ではありませんが、通常はユーザー インターフェースを装備します。</p>
<p>では、コードを変更してみましょう。 </p>
<h2 id="ui">UI を構築する</h2>
<p>下記の変更済みのコードを参照して、お手元の HelloAndroid クラスに同じ変更を加えてみてください。太字の部分が追加された行です。</p>
<pre>
package com.android.helloandroid;
import android.app.Activity;
import android.os.Bundle;
<strong>import android.widget.TextView;</strong>
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
<strong>TextView tv = new TextView(this);
tv.setText(&quot;Hello, Android&quot;);
setContentView(tv);</strong>
}
}</pre>
<p class="note"><strong>ヒント:</strong> プロジェクトにインポート パッケージを簡単に追加できる方法として、<strong>Ctrl+Shift+O</strong>Mac では <strong>コマンド+Shift+O</strong>)を押す方法があります。これは、コードの記述に基づいて足りないパッケージを特定して追加する Eclipse のショートカット キーです。</p>
<p>Android のユーザー インターフェースは、「ビューViews」と呼ばれるオブジェクトの階層で構成されています。{@link android.view.View} は、UI レイアウト内でボタン、画像、または(このサンプルのように)テキスト ラベルといった要素として使用される、描画可能なオブジェクトです。これらのオブジェクトのそれぞれが View クラスのサブクラスであり、テキストを処理するサブクラスは {@link android.widget.TextView} です。</p>
<p>この変更では、クラス コンストラクタを使用して TextView を作成します。このクラス コンストラクタは、パラメータとして Android {@link android.content.Context} インスタンスを受け入れます。Context とは、システムへのハンドルであり、リソースの解決、データベースや設定へのアクセスの取得などのサービスを提供します。Activity クラスは Context を継承します。作成する HelloAndroid クラスは、Activity のサブクラスであるため、Context でもあります。したがって、<code>this</code> を Context 参照として TextView に引き渡すことができます。</p>
<p>次に、{@link android.widget.TextView setText(CharSequence) setText()} を使用してテキスト コンテンツを定義します。</p>
<p>最後に、そのコンテンツが Activity UI のコンテンツとして表示されるように、TextView を {@link android.app.Activity#setContentView(View) setContentView()} に引き渡します。Activity によってこのメソッドが呼び出されなければ、UI は表示されず、空白の画面が表示されます。</p>
<p>これで、Android で「Hello, World」が表示されるようになりました。次の手順はもちろん、アプリケーションの実行です。</p>
<h2 id="run">アプリケーションを実行する</h2>
<p>Eclipse プラグインでは、非常に簡単にアプリケーションを実行できます。</p>
<ol>
<li><strong>[[]実行] &gt; [[]実行]</strong> を選択します。</li>
<li>「Android Application」を選択します。</li>
</ol>
<div class="sidebox-wrapper">
<div class="sidebox-inner">
<p>Eclipse での起動構成の作成と編集について詳しくは、「<a href="{@docRoot}guide/developing/eclipse-adt.html#RunConfig">ADT を使用した Eclipse での開発</a>」を参照してください。</p>
</div>
</div>
<p>Eclipse ADT によって自動的にプロジェクトの新規起動構成が作成され、Android エミュレータが自動的に起動します。エミュレータが起動した後、少し経つとアプリケーションが表示されます。次のような画面が表示されます。</p>
<a href="images/hello_world_5.png"><img src="images/hello_world_5.png" style="height:230px" alt="" /></a>
<p>グレーのバーに表示されている「Hello, Android」は、アプリケーションのタイトルです。このタイトルは Eclipse プラグインによって自動的に作成されます(文字列は <code>res/values/strings.xml</code> ファイル内で定義され、<code>AndroidManifest.xml</code> によって参照されます)。タイトルの下のテキストは、先ほど TextView オブジェクトで作成した実際のテキストです。</p>
<p>これで「Hello World」についての基本的なチュートリアルは終了ですが、この続きもぜひ読んでください。Android アプリケーションの開発に関するさらに有益な情報を紹介しています。</p>
<h2 id="upgrading">UI を XML レイアウトにアップグレードする</h2>
<p>先ほど作成した「Hello, World」のサンプルは、「プログラマティック」と呼ばれる UI レイアウトを使用しています。「プログラマティック」とは、アプリケーションの UI を直接ソース コードで作成および構築することを意味します。UI プログラミングの経験が豊富な方であればおそらく、このようなアプローチが時にいかに脆弱になり得るかをよくご存じでしょう。レイアウトの軽微な変更のたびに、ソース コード全体に関わる大きな問題が発生する可能性があるからです。また、複数のビューを適切に結びつけることも忘れられがちであるため、これによりレイアウトにエラーが発生し、コードのデバッグで時間が無駄になる場合があります。</p>
<p>その理由から、Android では、XML ベースのレイアウト ファイルを使用する別の UI 構築モデルを用意しています。この概念を簡単に説明するには、サンプルを紹介するのが一番です。ここに示すのは、上記の「プログラマティック」に構築したサンプルと同じように動作する XML レイアウト ファイルです。</p>
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:text=&quot;@string/hello&quot;/&gt;</pre>
<p>Android XML レイアウト ファイルの全般的な構造はシンプルです。XML 要素がツリー構造になっており、含まれた各ノードが View クラスの名前を表しています(このサンプルでは View 要素が 1 つのみですが。XML レイアウト内の要素として、{@link android.view.View} を拡張する任意のクラスの名前を使用できます。これには作成するコードの中で定義するカスタム View クラスも含まれます。この構造により、プログラマティックなレイアウトよりもシンプルな構造と構文を使用して、迅速な UI 構築を非常に簡単に行うことができます。このモデルは、アプリケーションの表示(つまり UIを、データの取得と入力に使用されるアプリケーション ロジックから切り離すことができる Web 開発モデルからヒントを得て考案されました。</p>
<p>上記の XML サンプルには、<code>TextView</code> という View 要素 1 つのみが含まれています。この要素は 4 つの XML 属性を持っています。下表に、これらの 4 つの属性の説明をまとめました。</p>
<table>
<tbody>
<tr>
<th>
属性
</th>
<th>
説明
</th>
</tr>
<tr>
<td>
<code>xmlns:android</code>
</td>
<td>
Android ネームスペースで定義された共通の属性を参照することを Android ツールに伝える XML ネームスペース宣言です。すべての Android レイアウト ファイル内の最初と最後のタグはこの属性を持つ必要があります。<br>
</td>
</tr>
<tr>
<td>
<code>android:layout_width</code>
</td>
<td>
該当の View が画面の利用可能な幅のうちどれくらいを占めるかを定義します。このサンプルでは、この View しかないため、「fill_parent」という値を使用して画面全体を占めることにします。<br>
</td>
</tr>
<tr>
<td>
<code>android:layout_height</code>
</td>
<td>
android:layout_width とよく似た属性で、幅ではなく高さを表します。
</td>
</tr>
<tr>
<td>
<code>android:text</code>
</td>
<td>
TextView が表示するテキストを設定します。このサンプルでは、ハードコード記述された文字列値ではなく文字列リソースを使用します。文字列「<em>hello</em>」は <em>res/values/strings.xml</em> ファイル内で定義されます。アプリケーションに文字列を挿入する場合にはこの方法が推奨されます。レイアウト ファイルのハードコードを直接変更する必要がないため、アプリケーションの他の言語へのローカライズがスムーズに進むからです。詳しくは、「<a href="{@docRoot}guide/topics/resources/resources-i18n.html">リソースと国際化</a>」を参照してください。
</td>
</tr>
</tbody>
</table>
<p>これらの XML レイアウト ファイルは、作成するプロジェクトの <code>res/layout/</code> ディレクトリ内に置かれます。「res」は「resources」の略で、アプリケーションに必要なコード以外のすべてのアセットがこのディレクトリに格納されます。リソースには、レイアウト ファイルの他に、画像、音声、ローカライズされた文字列などのアセットがあります。</p>
<div class="sidebox">
<h2>横表示レイアウト</h2>
<p>横表示の場合に異なるデザインで表示するには、レイアウト XML ファイルを /res/layout-land 内に入れます。Android 端末のレイアウトが横表示に変わると自動的にこのディレクトリが参照されます。このように横表示向けに定義されたレイアウトが存在しない場合、自動的にデフォルトのレイアウトが拡大して使用されます。</p>
</div>
<p>Eclipse プラグインでは、このようなレイアウト ファイルの 1 つである「main.xml」が自動的に作成されます。先ほど「Hello World」アプリケーションを作成した際には、このファイルは無視してプログラマティックにレイアウトを作成しました。この作成方法は Android フレームワークについてより深く理解していただくことを意図したもので、実際にはほとんどの場合レイアウトはコードではなく XML ファイルで定義します。以下の手順では、既存のアプリケーションを変更して XML レイアウトが使用されるようにする方法を説明します。</p>
<ol>
<li>Eclipse のパッケージ エクスプローラーPackage Explorerで、<code>/res/layout/</code> フォルダを展開し、<code>main.xml</code> を開きます(開いた後、場合によっては XML ソースを見るのにウィンドウ下部にある「main.xml」タブをクリックする必要があります。ファイルの内容を以下の XML に置き換えます。
<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
android:layout_width=&quot;fill_parent&quot;
android:layout_height=&quot;fill_parent&quot;
android:text=&quot;@string/hello&quot;/&gt;</pre>
<p>ファイルを保存します。</p>
</li>
<li><code>res/values/</code> フォルダ内の <code>strings.xml</code> を開きます。このファイルは、作成するユーザー インターフェースのためのすべてのデフォルトのテキスト文字列を保存するものです。Eclipse を使用している場合、ADT によってあらかじめ <em>hello</em> と <em>app_name</em> という 2 つの文字列が用意された状態になります。<em>hello</em> を何か別の文字列に書き換えてみましょう。たとえば「Hello, Android! I am a string resource!」としてみましょう。変更後のファイルの全体は次のようになります。
<pre>
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;resources>
&lt;string name="hello">Hello, Android! I am a string resource!&lt;/string>
&lt;string name="app_name">Hello, Android&lt;/string>
&lt;/resources>
</pre>
</li>
<li>次に、<code>HelloAndroid</code> クラスを開いて、XML レイアウトを使用して変更します。ファイルを編集して次のような内容にします。
<pre>
package com.example.helloandroid;
import android.app.Activity;
import android.os.Bundle;
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}</pre>
<p>この変更を行う際に、コードを手入力してコード補完機能を試してみましょう。「R.layout.main」と入力しようとすると、プラグインによって入力候補が表示されます。この機能の便利さは、開発中に何回も実感すると思います。</p>
<p>View オブジェクトに <code>setContentView()</code> を引き渡す代わりに、レイアウト リソースへの参照を付与します。リソースは <code>R.layout.main</code> として識別されます。これは、<code>/res/layout/main.xml</code> で定義されたレイアウトを、コンパイルされたオブジェクトで表したものです。Eclipse プラグインでは、この参照がプロジェクトの R.java クラス内に自動的に作成されます。Eclipse を使用していない場合、Ant を実行してアプリケーションのビルドを行う際に R.java クラスが生成されますR クラスについて詳しくは後ほど説明します)。</p>
</li>
</ol>
<p>ここで、アプリケーションを再実行します。起動構成は作成済みであるため、ここでは緑色の矢印アイコンをクリックして実行するか、または <strong>[[]実行Run] &gt; [[]ヒストリーの実行Run History] &gt; [[]Android Activity]</strong> を選択するだけです。TextView 文字列に加えた変更を除けば、アプリケーションは同じに見えます。ここでポイントとなるのは、2 つの異なるレイアウト編集方法を使用して同じ結果が得られるということです。</p>
<p class="note"><strong>ヒント:</strong> ショートカット キー<strong>Ctrl+F11</strong>Mac では <strong>コマンド+Shift+F11</strong>)を使用して、現在表示されているアプリケーションを実行することができます。</p>
<p>ここからは、デバッグの基礎知識と、他の総合開発環境に関する補足情報について説明します。さらに詳しく学習したい場合は、「<a href="{@docRoot}guide/topics/fundamentals.html">アプリケーションの基礎</a>」を参照してください。Android アプリケーションが動作するためのすべての要素について説明しています。また、「<a href="{@docRoot}guide/index.html">デベロッパー ガイド</a>」の導入ページを参照して、<em>デベロッパー ガイド</em> ドキュメントの概要を確認してください。</p>
<div class="special">
<h3>R クラス</h3>
<p>Eclipse で、<code>R.java</code> という名前のファイル(<code>gen/</code>(「生成された Java ファイルGenerated Java Files」フォルダ内を開きます。ファイルの内容は次のようになっています。</p>
<pre>
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;
}
}
</pre>
<p>プロジェクトの <code>R.java</code> ファイルは、ファイル内で定義されたすべてのリソースへのインデックスです。ソース コード内では、プロジェクトに含めたすべてのリソースを参照するための簡略形式としてこのクラスを使用します。これは、Eclipse などの総合開発環境のコード補完機能とともに使用すると特に便利です。探している特定の参照をすばやくインタラクティブに見つけることができるからです。</p>
<p>お手元のファイルはこれとは若干異なる可能性があります(おそらく 16 進値が異なるためです。ここでは、「layout」という名前の内部クラスと、そのメンバーであるフィールド「main」に注目します。Eclipse プラグインにより main.xml という名前の XML レイアウト ファイルが認識され、ここにそのためのクラスが生成されたものです。プロジェクトに他のリソース(<code>res/values/string.xml</code> ファイル内の文字列や <code>res/drawable/</code> ディレクトリ内の描画可能オブジェクトなど)を追加すると、<code>R.java</code> に最新の変更が反映されます。</p>
<p>Eclipse を使用していない場合は、Ant ツールを使用した)ビルド時にこのクラス ファイルが生成されます。</p>
<p><em>くれぐれもこのファイルを手動で編集しないようにしてください。</em></p>
</div>
<h2 id="debugging">プロジェクトをデバッグする</h2>
<p>Android Plugin for Eclipse は、Eclipse のデバッガと優れた連動性を発揮します。このメリットを確認するため、作成したコードにバグを埋め込んでみましょう。作成した HelloAndroid ソース コードを次のように変更します。</p>
<pre>
package com.android.helloandroid;
import android.app.Activity;
import android.os.Bundle;
public class HelloAndroid extends Activity {
/** Called when the activity is first created. */
&#64;Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Object o = null;
o.toString();
setContentView(R.layout.main);
}
}</pre>
<p>この変更は、単にコードに NullPointerException を発生させるものです。アプリケーションを再度実行すると、最終的に次のような画面が表示されます。</p>
<a href="images/hello_world_8.png"><img src="images/hello_world_8.png" style="height:230px" alt="" /></a>
<p>「強制終了」を押してアプリケーションを終了し、エミュレータ ウィンドウを閉じます。</p>
<p>エラーの詳細を確認するには、ソース コード内の <code>Object o = null;</code> 行にブレークポイントを設定します(該当するソース コード行の横にあるマーカー バーをダブルクリックします)。次に、メニューから <strong>[[]実行Run] &gt; [[]デバッグ ヒストリーDebug History] &gt; [[]Hello, Android]</strong> を選択して、デバッグ モードに入ります。エミュレータでアプリケーションが再起動されますが、今度は、先ほど設定したブレークポイントに到達した時点で中断されます。その後 Eclipse のデバッグ パースペクティブDebug Perspectiveで、他のアプリケーションで通常行うように、コードの内容を確認できます。</p>
<a href="images/hello_world_9.png"><img src="images/hello_world_9.png" style="height:230px" alt="" /></a>
<h2 id="noeclipse">Eclipse を使用せずにプロジェクトを作成する</h2>
<p>Eclipse を使用していない場合(普段から使用している総合開発環境がある場合や、シンプルにテキスト エディタやコマンド ライン ツールを使用している場合などは、Eclipse プラグインを利用することはできません。しかし心配は無用です。Eclipse を使用していないからといって何らかの機能が失われることはありません。</p>
<p>Android Plugin for Eclipse は、単に Android SDK に含まれるツール セットをまとめたものに過ぎませんエミュレータ、aapt、adb、ddms などの個別のツールについては、<a href="{@docRoot}guide/developing/tools/index.html">こちらで別途説明</a>しています。このため、これらのツールを別のツール、たとえば「Ant」のビルド ファイルなどでまとめることも可能です。</p>
<p>Android SDK には、「android」という名前のツールが含まれています。このツールを使用すると、作成するプロジェクトのソース コードとディレクトリ スタブすべて、および Ant と互換性のある <code>build.xml</code> ファイルを作成することができます。これにより、プロジェクトをコマンド ラインで作成したり、普段使用している総合開発環境と統合したりすることができます。</p>
<p>たとえば、Eclipse で作成されるものと同様の HelloAndroid プロジェクトを作成するには、次のコマンドを使用します。</p>
<pre>
android create project \
--package com.android.helloandroid \
--activity HelloAndroid \
--target 2 \
--path <em>&lt;path-to-your-project></em>/HelloAndroid
</pre>
<p>これにより、<em>path</em> で定義された場所に、プロジェクトに必要なフォルダとファイルが作成されます。</p>
<p>SDK ツールを使用してプロジェクトを作成および構築する方法について詳しくは、「<a href="{@docRoot}guide/developing/other-ide.html">Developing in Other IDEs</a>」を参照してください。</p>

View File

@@ -130,7 +130,7 @@ page.title=Android SDK のインストール
<h4>その他のインストール エラー</h4>
<p>オプションの Eclipse コンポーネントWST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック <a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui"</a> をご覧ください。</p>
<p>オプションの Eclipse コンポーネントWST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック <a href="{@docRoot}resources/faq/troubleshooting.html#installeclipsecomponents">ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui"</a> をご覧ください。</p>
<h4>Linux ユーザーの場合</h4>
<p>Eclipse 用 ADT プラグインのインストール時に、次のエラーが発生する場合があります。
@@ -166,15 +166,15 @@ JKS</pre>
<p><strong>サンプル コードの参照</strong></p>
<ul>
<li><a href="{@docRoot}guide/tutorials/hello-world.html">Hello World アプリケーション</a>を構築します(特に Eclipse ユーザーにおすすめです)。</li>
<li><a href="{@docRoot}guide/tutorials/notepad/index.html">Notepad チュートリアル</a>に沿って Android アプリケーションを完全に構築します。 </li>
<li><a href="{@docRoot}resources/tutorials/hello-world.html">Hello World アプリケーション</a>を構築します(特に Eclipse ユーザーにおすすめです)。</li>
<li><a href="{@docRoot}resources/tutorials/notepad/index.html">Notepad チュートリアル</a>に沿って Android アプリケーションを完全に構築します。 </li>
<li><code><em>&lt;sdk&gt;</em>/platforms/<em>&lt;platfrom&gt;</em>/samples</code> に収められている他のサンプル アプリケーションのいずれかを新しいプロジェクトとして作成し、自分の開発環境でコンパイルし、実行します。</li>
</ul>
<p><strong>Android デベロッパー グループへのアクセス</strong></p>
<ul>
<li>[<a
href="{@docRoot}community/index.html">コミュニティ</a>] タブで、Android デベロッパー グループの一覧を参照します。特に <a href="http://groups.google.com/group/android-developers">Android Developers</a> グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。</li>
href="{@docRoot}resources/community-groups.html">コミュニティ</a>] タブで、Android デベロッパー グループの一覧を参照します。特に <a href="http://groups.google.com/group/android-developers">Android Developers</a> グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。</li>
</ul>

View File

@@ -130,7 +130,7 @@ page.title=Android SDK のインストール
<h4>その他のインストール エラー</h4>
<p>オプションの Eclipse コンポーネントWST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック <a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui"</a> をご覧ください。</p>
<p>オプションの Eclipse コンポーネントWST など)を必要とする ADT の機能があります。ADT のインストール時にエラーが発生した場合、お使いの Eclipse インストール環境にこうしたコンポーネントが含まれていない可能性があります。必要なコンポーネントを Eclipse インストール環境に簡単に追加する方法について詳しくは、トラブルシューティング トピック <a href="{@docRoot}resources/faq/troubleshooting.html#installeclipsecomponents">ADT インストールエラー: "requires plug-in org.eclipse.wst.sse.ui"</a> をご覧ください。</p>
<h4>Linux ユーザーの場合</h4>
<p>Eclipse 用 ADT プラグインのインストール時に、次のエラーが発生する場合があります。
@@ -166,15 +166,15 @@ JKS</pre>
<p><strong>サンプル コードの参照</strong></p>
<ul>
<li><a href="{@docRoot}guide/tutorials/hello-world.html">Hello World アプリケーション</a>を構築します(特に Eclipse ユーザーにおすすめです)。</li>
<li><a href="{@docRoot}guide/tutorials/notepad/index.html">Notepad チュートリアル</a>に沿って Android アプリケーションを完全に構築します。 </li>
<li><a href="{@docRoot}resources/tutorials/hello-world.html">Hello World アプリケーション</a>を構築します(特に Eclipse ユーザーにおすすめです)。</li>
<li><a href="{@docRoot}resources/tutorials/notepad/index.html">Notepad チュートリアル</a>に沿って Android アプリケーションを完全に構築します。 </li>
<li><code><em>&lt;sdk&gt;</em>/platforms/<em>&lt;platfrom&gt;</em>/samples</code> に収められている他のサンプル アプリケーションのいずれかを新しいプロジェクトとして作成し、自分の開発環境でコンパイルし、実行します。</li>
</ul>
<p><strong>Android デベロッパー グループへのアクセス</strong></p>
<ul>
<li>[<a
href="{@docRoot}community/index.html">コミュニティ</a>] タブで、Android デベロッパー グループの一覧を参照します。特に <a href="http://groups.google.com/group/android-developers">Android Developers</a> グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。</li>
href="{@docRoot}resources/community-groups.html">コミュニティ</a>] タブで、Android デベロッパー グループの一覧を参照します。特に <a href="http://groups.google.com/group/android-developers">Android Developers</a> グループは、Android デベロッパー コミュニティがどういうものかを知るのに参考になります。</li>
</ul>

View File

@@ -0,0 +1,109 @@
page.title=Avoiding Memory Leaks
@jd:body
<p>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}.</p>
<p>On Android, a <code>Context</code> is used for many operations
but mostly to load and access resources. This is why all the widgets
receive a <code>Context</code> parameter in their constructor. In a
regular Android application, you usually have two kinds of
<code>Context</code>, {@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 <code>Context</code>:</p>
<pre class="prettyprint">&#64;Override
protected void onCreate(Bundle state) {
super.onCreate(state);
TextView label = new TextView(this);
label.setText("Leaks are bad");
setContentView(label);
}
</pre>
<p>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 <code>Context</code>
("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.</p>
<p>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:</p>
<pre class="prettyprint">private static Drawable sBackground;
&#64;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);
}
</pre>
<p>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 <code>TextView</code> which itself has a reference to the
activity (the <code>Context</code>) which in turns has references to
pretty much anything (depending on your code.)</p>
<p>This example is one of the simplest cases of leaking the
<code>Context</code> and you can see how we worked around it in the
<a href="http://android.git.kernel.org/?p=platform/packages/apps/Launcher.git;a=blob;f=src/com/android/launcher/LauncherModel.java;h=0ef2a806b767142b28b2ff3b37f21f4ca16c355d;hb=cupcake">Home screen's source code</a>
(look for the <code>unbindDrawables()</code> 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.</p>
<p>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 <code>Application</code> 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()}.</p>
<p>In summary, to avoid context-related memory leaks, remember the following:</p>
<ul>
<li>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)</li>
<li>Try using the context-application instead of a context-activity</li>
<li>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 <a href="http://android.git.kernel.org/?p=platform/frameworks/base.git;a=blob;f=core/java/android/view/ViewRoot.java;h=9d7a124cb01ab94bf53e34f6e5e8a07f81e2423c;hb=master">ViewRoot</a>
and its W inner class for instance</li>
<li>A garbage collector is not an insurance against memory leaks</li>
</ul>

View File

@@ -0,0 +1,238 @@
page.title=Backward Compatibility for Applications
@jd:body
<p>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 &mdash; 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. </p>
<h3>Setting the minSdkVersion</h3>
<p>If the use of a new API is integral to the application &mdash; perhaps you
need to record video using an API introduced in Android 1.5 (API Level 3)
&mdash; you should add a <a
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code>&lt;android:minSdkVersion&gt;</code></a>
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</a>:</p>
<pre> &lt;manifest&gt;
...
&lt;uses-sdk android:minSdkVersion="3" /&gt;
...
&lt;/manifest&gt;</pre>
<p>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.</p>
<h3>Using reflection</h3>
<p>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.</p>
<p>The simplest way to call the method is through reflection. This requires
doing a one-time lookup and caching the result in a <code>Method</code> object.
Using the method is a matter of calling <code>Method.invoke</code> and un-boxing
the result. Consider the following:</p>
<pre>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");
}
}
}</pre>
<p>This uses a static initializer to call <code>initCompatibility</code>,
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 <code>fiddle</code> 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.</p>
<p>For each additional method you want to call, you would add an additional
private <code>Method</code> field, field initializer, and call wrapper to the
class.</p>
<p>This approach becomes a bit more complex when the method is declared in a
previously undefined class. It's also much slower to call
<code>Method.invoke()</code> than it is to call the method directly. These
issues can be mitigated by using a wrapper class.</p>
<h3>Using a wrapper class</h3>
<p>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.</p>
<p>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.</p>
<p>Suppose this new class were added:</p><pre>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;
}
}</pre>
<p>We would create a wrapper class for it:</p>
<pre>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);
}
}</pre>
<p>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 <code>WrapNewClass</code> fails,
ensuring that the wrapper class can't be used inadvertently. The
<code>checkAvailable</code> method is used as a simple way to force class
initialization. We use it like this:</p>
<pre>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");
}
}
}</pre>
<p>If the call to <code>checkAvailable</code> 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
<code>checkAvailable</code> 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
<code>Class.forName</code>.</p>
<p>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 <code>WrapNewClass</code> would be augmented to do a
one-time check with reflection.</p>
<h3>Testing is key</h3>
<p>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.</p>
<p>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 <a
href={@docRoot}guide/developing/tools/avd.html">in the AVD documentation</a> and
from <code>emulator -help-virtual-device</code>.</p>

View File

@@ -0,0 +1,69 @@
page.title=Can I Use this Intent?
@jd:body
<p>Android offers a very powerful and yet easy-to-use message type called
an <a href="{@docRoot}guide/topics/intents/intents-filters.html">intents</a>.
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. </p>
<p>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
<a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Panoramio">Panoramio</a>
and its RADAR intent.</p>
<p>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. </p>
<pre class="prettyprint">/**
* 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&lt;ResolveInfo&gt; list =
packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() &gt; 0;
}
</pre>
<p>Here is how you could use the helper method:</p>
<pre class="prettyprint">@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);
}
</pre>
<p>In this example, the menu is grayed out if the <em>Barcode Scanner</em>
application is not installed. </p>
<p>Another, simpler, way to do this is to catch the
<code>ActivityNotFoundException</code> when calling <code>startActivity()</code>
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.</p>

View File

@@ -0,0 +1,235 @@
page.title=Creating an Input Method
@jd:body
<p>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.</p>
<p>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.</p>
<p>An input method is packaged like any other application or service. In the
<code>AndroidManifest.xml</code> file, you declare the input method as a
service, with the appropriate intent filter and any associated meta data:</p>
<pre>&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.fastinput"&gt;
&lt;application android:label="@string/app_label"&gt;<br>
&lt;!-- Declares the input method service --&gt;
&lt;service android:name="FastInputIME"
android:label="@string/fast_input_label"
android:permission="android.permission.BIND_INPUT_METHOD"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.view.InputMethod" /&gt;
&lt;/intent-filter&gt;
&lt;meta-data android:name="android.view.im" android:resource="@xml/method" /&gt;
&lt;/service&gt;
&lt;!-- Optional activities. A good idea to have some user settings. --&gt;
&lt;activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings"&gt;
&lt;intent-filter&gt;
&lt;action android:name="android.intent.action.MAIN"/&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>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.</p>
<p>The typical life-cycle of an <code>InputMethodService</code> looks like
this:</p>
<p><img src="images/ime_003.png" style="border: medium none ; width: 374px; height: 871px;"></p>
<h3>Visual Elements</h3>
<p>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.</p>
<h4>Input View</h4>
<p>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, <code>InputMethodService.onCreateInputView()</code> will be called. Create
and return the view hierarchy that you would like to display in the input method
window.</p>
<h4>Candidates View</h4>
<p>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 <code>null</code> from calls to
<code>InputMethodService.onCreateCandidatesView()</code>, which is the default
behavior.</p>
<h3>Designing for the different Input Types</h3>
<p>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.</p>
<p>For example, the LatinIME provided with the Android platform provides
different layouts for text and phone number entry:</p>
<p><img style="margin: 0pt 10px 0pt 0pt; width: 319px; height: 198px;" src="images/ime_002.png"><img style="width: 320px; height: 199px;" src="images/ime.png"></p>
<p><code>InputMethodService.onStartInputView()</code> is called with an<code>
EditorInfo</code> object that contains details about the input type and other
attributes of the application's text field.</p><p>(<code>EditorInfo.inputType
&amp; EditorInfo.TYPE_CLASS_MASK</code>) can be one of many different values,
including:</p>
<ul>
<li><code>TYPE_CLASS_NUMBER</code></li>
<li><code>TYPE_CLASS_DATETIME</code></li>
<li><code>TYPE_CLASS_PHONE</code></li>
<li><code>TYPE_CLASS_TEXT</code></li>
</ul>
<p>See <code>android.text.InputType</code> for more details.</p>
<p><code>EditorInfo.inputType</code> can contain other masked bits that
indicate the class variation and other flags. For example,
<code>TYPE_TEXT_VARIATION_PASSWORD</code> or <code>TYPE_TEXT_VARIATION_URI</code>
or <code>TYPE_TEXT_FLAG_AUTO_COMPLETE</code>.</p>
<h4>Password fields</h4>
<p>Pay
specific attention when sending text to password fields. Make sure that
the password is not visible within your UI &mdash; neither in the input
view or the candidates view. Also, do not save the password anywhere without
explicitly informing the user.</p>
<h3>Landscape vs. portrait</h3>
<p>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.</p>
<h3>Sending text to the application</h3>
<p>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.</p>
<p>To send a key event, you can simply construct KeyEvent objects and call
<code>InputConnection.sendKeyEvent()</code>. Here are some examples:</p>
<pre>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));</pre>
<p>Or use the convenience method:</p>
<pre>InputMethodService.sendDownUpKeyEvents(keyEventCode);</pre>
<p class="note"><strong>Note</strong>:
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.</p>
<p>When editing text in a text field, some of the more useful methods on
<code>android.view.inputmethod.InputConnection</code> are:</p>
<ul>
<li><code>getTextBeforeCursor()</code></li>
<li><code>getTextAfterCursor()</code></li>
<li><code>deleteSurroundingText()</code></li>
<li><code>commitText()</code></li>
</ul>
<p>For example, let's say the text "Fell" is to the left of the cursor
and you want to replace it with "Hello!":</p>
<pre>InputConnection ic = getCurrentInputConnection();
ic.deleteSurroundingText(4, 0);
ic.commitText("Hello", 1);
ic.commitText("!", 1);</pre>
<h4>Composing text before committing</h4>
<p>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.</p>
<pre>InputConnection ic = getCurrentInputConnection();
ic.setComposingText("Composi", 1);
...
ic.setComposingText("Composin", 1);
...
ic.commitText("Composing ", 1);</pre>
<p><img style="width: 320px; height: 98px; margin-bottom: 10px;" src="images/ime_006.png">
<img style="width: 320px; height: 97px; margin-bottom: 10px;" src="images/ime_005.png">
<img style="width: 320px; height: 97px;" src="images/ime_004.png"></p>
<h3>Intercepting hard key events</h3>
<p>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
<code>InputMethodService.onKeyDown()</code> and
<code>InputMethodService.onKeyUp().</code> Remember to call
<code>super.onKey</code>* if you don't want to consume a certain key
yourself.</p>
<h3>Other considerations</h3>
<ul>
<li>Provide a way for the user to easily bring up any associated settings
directly from the input method UI</li>
<li>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.</li>
<li>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.</li>
<li>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.</li>
<li>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.</li>
</ul>
<h3>Samples</h3>
<p>For a real world example, with support for multiple input types and text
prediction, see the <a id="ccpb"
href="http://android.git.kernel.org/?p=platform/packages/inputmethods/LatinIME.
git;a=tree" title="LatinIME source code online">LatinIME source code</a>. The
Android SDK also includes a SoftKeyboard sample as well.</p>

View File

@@ -0,0 +1,91 @@
page.title=Drawable Mutations
@jd:body
<p>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.</p>
<p>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 (<code>android.R.drawable.btn_default</code>). 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.</p>
<p>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:</p>
<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 307px; height: 400px;" src="images/shared_states.png" alt="" id="BLOGGER_PHOTO_ID_5331437883277472082" border="0">
<p>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 <code>getView()</code> method:</p>
<pre>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
}</pre>
<p>Unfortunately, this piece of code yields a rather strange result:
all of the drawables have the same opacity:</p>
<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 267px; height: 400px;" src="images/all_drawables_changed.png" alt="" id="BLOGGER_PHOTO_ID_5331438978390342066" border="0">
<p>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.</p>
<p>Android 1.5 and higher offers a very easy way to solve this issue
with the new {@link android.graphics.drawable.Drawable#mutate()} method</a>.
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 <code>mutate()</code> on a drawable:</p>
<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 307px; height: 400px;" src="images/mutated_states.png" alt="" id="BLOGGER_PHOTO_ID_5331440144116345074" border="0">
<p>Let's update our previous piece of code to make use of <code>mutate()</code>:</p>
<pre>Drawable star = context.getResources().getDrawable(R.drawable.star);
if (book.isFavorite()) {
star.mutate().setAlpha(255); // opaque
} else {
star. mutate().setAlpha(70); // translucent
}</pre>
<p>For convenience, <code>mutate()</code>
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:</p>
<img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 267px; height: 400px;" src="images/correct_drawables.png" alt="" id="BLOGGER_PHOTO_ID_5331440757515573842" border="0">

View File

@@ -0,0 +1,115 @@
page.title=Faster Screen Orientation Change
@jd:body
<p>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.
<div class="sidebox-wrapper">
<div class="sidebox">
<h2>Using the alternate resources framework</h2>
<p>The platform's support for loading orientation-specific
resources at run time is based on the alternate resources framework.</p>
<p>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
<a href="{@docRoot}guide/topics/resources/resources-i18n.html#AlternateResources">
Alternate Resources</a>.
</div>
</div>
<p>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. </p>
<p>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. </p>
<p>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.</p>
<p>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 <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/">Photostream</a>,
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:</p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_9l0GmPwgCzk/SZoGyJyg6-I/AAAAAAAAACU/ItuVwhegPb8/s1600-h/photostream_landscape.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 214px;" src="images/photostream_landscape.png" alt="" id="BLOGGER_PHOTO_ID_5303558969873198050" border="0"></a></p>
<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_9l0GmPwgCzk/SZoGx4I-QlI/AAAAAAAAACM/-GkZR5MUKhY/s1600-h/photostream_portrait.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 214px; height: 320px;" src="images/photostream_portrait.png" alt="" id="BLOGGER_PHOTO_ID_5303558965135557202" border="0"></a></p>
<p>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.</p>
<p>The Activity class has a special method called
{@link android.app.Activity#onRetainNonConfigurationInstance()}. This method
can be used to pass an arbitrary object <em>your future self</em> and Android
is smart enough to call this method only when needed. In the case of Photostream,
the application <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java#226">used this method</a>
to pass the downloaded images to the future activity on orientation change.
The implementation can be summarized like so:</p>
<pre class="prettyprint">&#64;Override
public Object onRetainNonConfigurationInstance() {
final LoadedPhoto[] list = new LoadedPhoto[numberOfPhotos];
keepPhotos(list);
return list;
}
</pre>
<p>In the new activity, in <code>onCreate()</code>, all you have to do to
get your object back is to call {@link android.app.Activity#getLastNonConfigurationInstance()}.
In Photostream, <a href="http://code.google.com/p/apps-for-android/source/browse/trunk/Photostream/src/com/google/android/photostream/PhotostreamActivity.java#251">this method is invoked</a>
and if the returned value is not null, the grid is loaded with the list of
photos from the previous activity:</p>
<pre class="prettyprint">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);
}
}
}
</pre>
<p>Be very careful with the object you pass through
<code>onRetainNonConfigurationChange()</code>, though. If the object you
pass is for some reason tied to the Activity/Context, <a
href="http://www.curious-creature.org/2008/12/18/avoid-memory-leaks-on-android/">you will leak</a>
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
<code>onRetainNonConfigurationChange()</code> should be used only to retain
data that is expensive to load. Otherwise, keep it simple and let Android
do everything.</p>

View File

@@ -0,0 +1,89 @@
page.title=Future-Proofing Your Apps
@jd:body
<p>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.</p>
<p>If your application uses any of the dubious techniques below, break out
your IDE and duct tape, spackle, and patch up the app.</p>
<p><b>Technique to Avoid, #1: Using Internal APIs</b></p>
<p>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. </p>
<p><b>Technique to Avoid, #2: Directly Manipulating Settings</b></p>
<p>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.</p>
<p>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.</p>
<p><b>Technique to Avoid, #3: Going Overboard with Layouts</b></p>
<p>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.</p>
<p><b>Technique to Avoid, #4: Bad Hardware Assumptions</b></p>
<p>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.</p>
<p><b>Technique to Avoid, #5: Incautious Rotations </b></p>
<p>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.</p>
<p>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
<code>android:screenOrientation</code> attribute in the manifest file.)</p>

View File

@@ -0,0 +1,211 @@
page.title=Gestures
@jd:body
<p>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.</p>
<p>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
<code>android.gesture</code> API in your applications. Before going any further,
you should <a
href="http://code.google.com/p/apps-for-android/downloads/detail?name=
GesturesDemos.zip&amp;can=2&amp;q=#makechanges">download the source code
of the examples</a>.</p>
<h3>Creating a gestures library</h3>
<p>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:</p>
<img src="images/gestures_006.png" style="width: 320px; height: 480px;">
<p>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, <code>/sdcard/gestures</code>. This file contains the
description of all the gestures, and you will need to package it inside your
application inside the resources directory, in
<code>/res/raw</code>.</p>
<h3>Loading the gestures library</h3>
<p>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
<code>GestureLibraries</code> class:</p>
<pre class="prettyprint">mLibrary = GestureLibraries.fromRawResource(this, R.raw.spells);
if (!mLibrary.load()) {
finish();
}</pre>
<p>In this example, the gesture library is loaded from the file
<code>/res/raw/spells</code>. 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:</p>
<img src="images/gestures_002.png" style="width: 600px; height: 512px;">
<h3>Recognizing gestures</h3>
<p>To start recognizing gestures in your application, all you have to do
is add a <code>GestureOverlayView</code> to your XML layout:</p>
<pre>&lt;android.gesture.GestureOverlayView
android:id="@+id/gestures"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1.0" /&gt;</pre>
<p>Notice that the <code>GestureOverlayView</code>
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
<code>GestureOverlayView.OnGesturePerformedListener</code>,
which fires whenever a user is done drawing a gesture:</p>
<pre>GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
gestures.addOnGesturePerformedListener(this);</pre>
<p>When the listener fires, you can ask the <code>GestureLibrary</code>
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:</p>
<pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList&lt;prediction&gt; predictions = mLibrary.recognize(gesture);
// We want at least one prediction
if (predictions.size() &gt; 0) {
Prediction prediction = predictions.get(0);
// We want at least some confidence in the result
if (prediction.score &gt; 1.0) {
// Show the spell
Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
}
}
}</pre>
<p>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):</p>
<img src="images/gestures.png" style="width: 320px; height: 480px;">
<h3>Gestures overlay</h3>
<p>In the example above, the <code>GestureOverlayView</code> was used
as a normal view, embedded inside a <code>LinearLayout</code>.
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:</p>
<p><img src="images/gestures_005.png" style="width: 320px; height: 480px;"></p>
<p>And here is what the XML layout looks like:</p>
<pre>&lt;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"&gt;
&lt;ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" /&gt;
&lt;/android.gesture.GestureOverlayView&gt;</pre>
<p>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:</p>
<ul>
<li><code>gestureStrokeType</code>: 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</li>
<li><code>eventsInterceptionEnabled</code>: 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 </li>
<li><code>orientation</code>:
indicates the scroll orientation of the views underneath. In this case
the list scrolls vertically, which means that any horizontal gestures
(like <code>action_delete</code>) 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.</li>
</ul>
<p>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:</p>
<pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList&lt;Prediction&gt; predictions = mLibrary.recognize(gesture);
if (predictions.size() &gt; 0 &amp;&amp; predictions.get(0).score &gt; 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();
}
}
}</pre>
<p>The user is now able to draw his gestures on top of the list without
interfering with the scrolling:</p>
<img src="images/gestures_004.png" style="width: 320px; height: 480px;">
<p>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:</p>
<img src="images/gestures_003.png" style="width: 320px; height: 480px;">
<h3>It's your turn</h3>
<p>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.</p>

View File

@@ -0,0 +1,268 @@
page.title=Introducing GLSurfaceView
@jd:body
<p>The {@link android android.opengl.GLSurfaceView} class makes it
easier for you to use OpenGL ES rendering in your applications by:</p>
<ul>
<li>Providing the glue code to connect OpenGL ES to the {@link
android.view.View} system.</li>
<li>Providing the glue code to make OpenGL ES work with the {@link
android.app.Activity} life-cycle.</li>
<li>Making it easy to choose an appropriate frame buffer pixel format.</li>
<li>Creating and managing a separate rendering thread, to enable smooth
animation.</li>
<li>Providing easy-to-use debugging tools for tracing OpenGL ES API calls and
checking for errors.</li>
</ul>
<p>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 <a
href="http://www.youtube.com/watch?v=4PRfVKzuUJ4&amp;fmt=18" title="Google Maps
StreetView">Google Maps StreetView</a>.</p>
<h3>A simple GLSurfaceView application</h3>
<p>Here's the source code to the simplest possible OpenGL ES application:</p>
<pre>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 {
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new GLSurfaceView(this);
mGLView.setRenderer(new ClearRenderer());
setContentView(mGLView);
}
&#64;Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
&#64;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);
}
}</pre>
<p>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 <code>ClearRenderer.onDrawFrame()</code> method.
Notice that you don't even need to subclass the <code>GLSurfaceView</code> view.</p>
<p>The {@link android.opengl.GLSurfaceView.Renderer} interface has three methods:</p>
<ul>
<li>The
<code>onSurfaceCreated()</code> 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.) <code>OnSurfaceCreated()</code> is a good place to create
long-lived OpenGL resources such as textures.</li>
<li>The <code>onSurfaceChanged()</code>
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.</li>
<li>The <code>onDrawFrame()</code> method is called every frame, and is
responsible for drawing the scene. You would typically start by calling
<code>glClear</code> to clear the framebuffer, followed by other OpenGL ES calls
to draw the current scene.</li>
</ul>
<h3>How about user input?</h3>
<p>If you want an interactive application (such as a game), you will typically
subclass <code>GLSurfaceView</code>, because that's an easy way of obtaining
input events. Here's a slightly longer example showing how to do that:</p>
<pre>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 {
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new ClearGLSurfaceView(this);
setContentView(mGLView);
}
&#64;Override
protected void onPause() {
super.onPause();
mGLView.onPause();
}
&#64;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;
}</pre>
<p>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 <code>queueEvent()</code> in
<code>ClearGLSurfaceView.onTouchEvent()</code>. The <code>queueEvent()</code>
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 <code>Renderer</code> class
itself. However, queueing events is often the simplest way of dealing with
cross-thread communication.</p>
<h3>Other GLSurfaceView samples</h3>
<p>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 <code>GLSurfaceView</code> view:</p>
<ul>
<li>GLSurfaceView - a spinning triangle</li>
<li>Kube - a cube puzzle demo</li>
<li>Translucent GLSurfaceView - shows how to display 3D graphics on a translucent background</li>
<li>Textured Triangle - shows how to draw a textured 3D triangle</li>
<li>Sprite Text - shows how to draw text into a texture and then composite it into a 3D scene</li>
<li>Touch Rotate - shows how to rotate a 3D object in response to user input.</li>
</ul>
<h3>Choosing a surface</h3>
<p><code>GLSurfaceView</code>
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. </p>
<p>By default, <code>GLSurfaceView</code> 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. <code>GLSurfaceView</code>
provides an overloaded <code>setEGLSurfaceChooser()</code> method to give
you control over which surface type is chosen:</p>
<dl>
<dt><code>setEGLConfigChooser(boolean needDepth)</code></dt>
<dd>Choose a config that's closest to R5G6B5 with or without a 16-bit framebuffer</dd>
<dt><code>setEGLConfigChooser(int redSize, int greenSize,int blueSize,
int alphaSize,int depthSize, int stencilSize)</code></dt>
<dd>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.</dd>
<dt><code>setEGLConfigChooser(EGLConfigChooser configChooser)</code></dt>
<dd>Allow total control over choosing a configuration. You pass in your own
implementation of <code>EGLConfigChooser</code>, which gets to inspect the
device's capabilities and choose a configuration.</dd>
</dl>
<h3>Continuous rendering versus render-when-dirty</h3>
<p>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 <code>GLSurfaceView</code> behavior of continuously redrawing the
screen is a waste of time. If you are developing a reactive application, you can
call <code>GLSurfaceView.setRenderMode(RENDERMODE_WHEN_DIRTY)</code>, which
turns off the continuous animation. Then you call
<code>GLSurfaceView.requestRender()</code> whenever you want to re-render.</p>
<h3>Help With debugging</h3>
<p><code>GLSurfaceView</code> has a handy built-in feature for debugging OpenGL ES
applications: the <code>GLSurfaceView.setDebugFlags()</code> method can be used
to enable logging and/or error checking your OpenGL ES calls. Call this method
in your <code>GLSurfaceView</code>'s constructor, before calling
<code>setRenderer()</code>:</p>
<pre>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);
}</pre>

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Some files were not shown because too many files have changed in this diff Show More