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.
38
Android.mk
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1754,7 +1754,7 @@ to the current working directory): </p>
|
||||
<p>For emulators running on Mac OS X, if you see an error "Warning: No DNS servers found" 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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 can't compile my app because the build tools generated an expired debug
|
||||
certificate</a>. </p>
|
||||
|
||||
|
||||
@@ -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><uses-
|
||||
sdk></code></a> manifest element documentation and the <a
|
||||
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code><uses-sdk></code></a>
|
||||
manifest element documentation and the <a
|
||||
href="{@docRoot}guide/appendix/api-levels.html">API Levels</a> document.</p>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 <sdk>/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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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="false"</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>
|
||||
|
||||
|
||||
|
||||
@@ -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><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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
116
docs/html/intl/ja/resources/community-groups.jd
Normal 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 グループで登録: <a href="http://groups.google.co.jp/group/android-sdk-japan?hl=ja">android-sdk-japan</a></li>
|
||||
<li>メールで登録: <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 グループで登録: <a href="http://groups.google.com/group/android-beginners?hl=ja">android-beginners</a></li>
|
||||
<li>メールで登録: <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 グループで登録: <a href="http://groups.google.com/group/android-developers?hl=ja">android-developers</a></li>
|
||||
<li>メールで登録: <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 グループで登録: <a href="http://groups.google.com/group/android-discuss?hl=ja">android-discuss</a></li>
|
||||
<li>メールで登録: <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 グループで登録: <a href="http://groups.google.com/group/android-security-discuss?hl=ja">android-security-discuss</a></li>
|
||||
<li>メールで登録: <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 グループで登録: <a href="http://groups.google.com/group/android-security-announce?hl=ja">android-security-announce</a></li>
|
||||
<li>メールで登録: <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: <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>
|
||||
375
docs/html/intl/ja/resources/tutorials/hello-world.jd
Normal 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)] > [[]新規(New)] > [[]プロジェクト(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」 > 「src」 > 「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. */
|
||||
@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. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
<strong>TextView tv = new TextView(this);
|
||||
tv.setText("Hello, Android");
|
||||
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>[[]実行] > [[]実行]</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><?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/hello"/></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><?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:text="@string/hello"/></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>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="hello">Hello, Android! I am a string resource!</string>
|
||||
<string name="app_name">Hello, Android</string>
|
||||
</resources>
|
||||
</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. */
|
||||
@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)] > [[]ヒストリーの実行(Run History)] > [[]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. */
|
||||
@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)] > [[]デバッグ ヒストリー(Debug History)] > [[]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><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>
|
||||
@@ -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><sdk></em>/platforms/<em><platfrom></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>
|
||||
|
||||
|
||||
|
||||
@@ -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><sdk></em>/platforms/<em><platfrom></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>
|
||||
|
||||
|
||||
|
||||
109
docs/html/resources/articles/avoiding-memory-leaks.jd
Normal 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">@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;
|
||||
|
||||
@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>
|
||||
238
docs/html/resources/articles/backward-compatibility.jd
Normal 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 — 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 — perhaps you
|
||||
need to record video using an API introduced in Android 1.5 (API Level 3)
|
||||
— you should add a <a
|
||||
href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"><code><android:minSdkVersion></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> <manifest>
|
||||
...
|
||||
<uses-sdk android:minSdkVersion="3" />
|
||||
...
|
||||
</manifest></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>
|
||||
69
docs/html/resources/articles/can-i-use-this-intent.jd
Normal 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<ResolveInfo> list =
|
||||
packageManager.queryIntentActivities(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY);
|
||||
return list.size() > 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>
|
||||
235
docs/html/resources/articles/creating-input-method.jd
Normal 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><manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.fastinput">
|
||||
|
||||
<application android:label="@string/app_label"><br>
|
||||
<!-- Declares the input method service -->
|
||||
<service android:name="FastInputIME"
|
||||
android:label="@string/fast_input_label"
|
||||
android:permission="android.permission.BIND_INPUT_METHOD">
|
||||
<intent-filter>
|
||||
<action android:name="android.view.InputMethod" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="android.view.im" android:resource="@xml/method" />
|
||||
</service>
|
||||
|
||||
<!-- Optional activities. A good idea to have some user settings. -->
|
||||
<activity android:name="FastInputIMESettings" android:label="@string/fast_input_settings">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
</manifest></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
|
||||
& 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 — 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>
|
||||
91
docs/html/resources/articles/drawable-mutations.jd
Normal 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">
|
||||
115
docs/html/resources/articles/faster-screen-orientation-change.jd
Normal 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">@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>
|
||||
89
docs/html/resources/articles/future-proofing.jd
Normal 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>
|
||||
|
||||
211
docs/html/resources/articles/gestures.jd
Normal 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&can=2&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><android.gesture.GestureOverlayView
|
||||
android:id="@+id/gestures"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dip"
|
||||
android:layout_weight="1.0" /></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<prediction> predictions = mLibrary.recognize(gesture);
|
||||
|
||||
// We want at least one prediction
|
||||
if (predictions.size() > 0) {
|
||||
Prediction prediction = predictions.get(0);
|
||||
// We want at least some confidence in the result
|
||||
if (prediction.score > 1.0) {
|
||||
// Show the spell
|
||||
Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}</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><android.gesture.GestureOverlayView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/gestures"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
|
||||
android:gestureStrokeType="multiple"
|
||||
android:eventsInterceptionEnabled="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ListView
|
||||
android:id="@android:id/list"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent" />
|
||||
|
||||
</android.gesture.GestureOverlayView></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<Prediction> predictions = mLibrary.recognize(gesture);
|
||||
if (predictions.size() > 0 && predictions.get(0).score > 1.0) {
|
||||
String action = predictions.get(0).name;
|
||||
if ("action_add".equals(action)) {
|
||||
Toast.makeText(this, "Adding a contact", Toast.LENGTH_SHORT).show();
|
||||
} else if ("action_delete".equals(action)) {
|
||||
Toast.makeText(this, "Removing a contact", Toast.LENGTH_SHORT).show();
|
||||
} else if ("action_refresh".equals(action)) {
|
||||
Toast.makeText(this, "Reloading contacts", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}</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>
|
||||
268
docs/html/resources/articles/glsurfaceview.jd
Normal 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&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 {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mGLView = new GLSurfaceView(this);
|
||||
mGLView.setRenderer(new ClearRenderer());
|
||||
setContentView(mGLView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mGLView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mGLView.onResume();
|
||||
}
|
||||
|
||||
private GLSurfaceView mGLView;
|
||||
}
|
||||
|
||||
class ClearRenderer implements GLSurfaceView.Renderer {
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
// Do nothing special.
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 gl, int w, int h) {
|
||||
gl.glViewport(0, 0, w, h);
|
||||
}
|
||||
|
||||
public void onDrawFrame(GL10 gl) {
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
}</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 {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mGLView = new ClearGLSurfaceView(this);
|
||||
setContentView(mGLView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
mGLView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mGLView.onResume();
|
||||
}
|
||||
|
||||
private GLSurfaceView mGLView;
|
||||
}
|
||||
|
||||
class ClearGLSurfaceView extends GLSurfaceView {
|
||||
public ClearGLSurfaceView(Context context) {
|
||||
super(context);
|
||||
mRenderer = new ClearRenderer();
|
||||
setRenderer(mRenderer);
|
||||
}
|
||||
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
queueEvent(new Runnable(){
|
||||
public void run() {
|
||||
mRenderer.setColor(event.getX() / getWidth(),
|
||||
event.getY() / getHeight(), 1.0f);
|
||||
}});
|
||||
return true;
|
||||
}
|
||||
|
||||
ClearRenderer mRenderer;
|
||||
}
|
||||
|
||||
class ClearRenderer implements GLSurfaceView.Renderer {
|
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
||||
// Do nothing special.
|
||||
}
|
||||
|
||||
public void onSurfaceChanged(GL10 gl, int w, int h) {
|
||||
gl.glViewport(0, 0, w, h);
|
||||
}
|
||||
|
||||
public void onDrawFrame(GL10 gl) {
|
||||
gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
|
||||
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
public void setColor(float r, float g, float b) {
|
||||
mRed = r;
|
||||
mGreen = g;
|
||||
mBlue = b;
|
||||
}
|
||||
|
||||
private float mRed;
|
||||
private float mGreen;
|
||||
private float mBlue;
|
||||
}</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>
|
||||
BIN
docs/html/resources/articles/images/File.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/html/resources/articles/images/File_002.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
docs/html/resources/articles/images/JFlubber.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
docs/html/resources/articles/images/WikiNotes.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
docs/html/resources/articles/images/all_drawables_changed.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
docs/html/resources/articles/images/android.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
docs/html/resources/articles/images/buttons.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
docs/html/resources/articles/images/contacts.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
docs/html/resources/articles/images/correct_drawables.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
docs/html/resources/articles/images/ddms_allocation_tracker.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
docs/html/resources/articles/images/ddms_allocation_trackerl.png
Normal file
|
After Width: | Height: | Size: 502 KiB |
BIN
docs/html/resources/articles/images/device.png
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
docs/html/resources/articles/images/device_002.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
docs/html/resources/articles/images/gestures.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/html/resources/articles/images/gestures_002.png
Normal file
|
After Width: | Height: | Size: 138 KiB |
BIN
docs/html/resources/articles/images/gestures_003.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/html/resources/articles/images/gestures_004.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
docs/html/resources/articles/images/gestures_005.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/html/resources/articles/images/gestures_006.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/html/resources/articles/images/grid.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
docs/html/resources/articles/images/ime.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/html/resources/articles/images/ime_002.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/html/resources/articles/images/ime_003.png
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
docs/html/resources/articles/images/ime_004.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
docs/html/resources/articles/images/ime_005.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
docs/html/resources/articles/images/ime_006.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/html/resources/articles/images/layouts_comparison_small.png
Normal file
|
After Width: | Height: | Size: 129 KiB |
BIN
docs/html/resources/articles/images/list01.png
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
docs/html/resources/articles/images/list02.png
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
docs/html/resources/articles/images/list_fade_1.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
docs/html/resources/articles/images/list_fade_2.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
docs/html/resources/articles/images/list_fade_3.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
docs/html/resources/articles/images/list_fade_4.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
docs/html/resources/articles/images/merge1.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |
BIN
docs/html/resources/articles/images/merge2.png
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
docs/html/resources/articles/images/merge3.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
docs/html/resources/articles/images/merge4.jpg
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/html/resources/articles/images/merge5.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
docs/html/resources/articles/images/mutated_states.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
docs/html/resources/articles/images/on-screen-inputs.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/html/resources/articles/images/on-screen-inputs_002.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/html/resources/articles/images/on-screen-inputs_003.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/html/resources/articles/images/on-screen-inputs_004.png
Normal file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/html/resources/articles/images/on-screen-inputs_005.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/html/resources/articles/images/on-screen-inputs_006.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/html/resources/articles/images/photostream_landscape.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
docs/html/resources/articles/images/photostream_portrait.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
docs/html/resources/articles/images/qsb.png
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
docs/html/resources/articles/images/qsb_002.png
Normal file
|
After Width: | Height: | Size: 241 KiB |
BIN
docs/html/resources/articles/images/qsb_003.png
Normal file
|
After Width: | Height: | Size: 43 KiB |
BIN
docs/html/resources/articles/images/relativelayout_1.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
docs/html/resources/articles/images/relativelayout_2.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
docs/html/resources/articles/images/relativelayout_3.png
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
docs/html/resources/articles/images/relativelayout_wire_1.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
docs/html/resources/articles/images/relativelayout_wire_2.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
docs/html/resources/articles/images/relativelayout_wire_3.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
docs/html/resources/articles/images/search01.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
BIN
docs/html/resources/articles/images/search02.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
docs/html/resources/articles/images/shared_states.png
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
docs/html/resources/articles/images/shelves2.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
docs/html/resources/articles/images/text_field.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
docs/html/resources/articles/images/ui-1.6.png
Normal file
|
After Width: | Height: | Size: 14 KiB |