Kb/commontasks

From Android中文网

Android中文网(androidcn.net) 版权申明 : creativecommons licenses
Jump to: navigation, search

目录

[编辑] 共同的任务和如何在Android平台上解决它们


[编辑] 使用Eclipse插件创建一个Android应用。

开始创建一个新的Android应用程序最快和最简单的方式是使用Android Eclipse插件。 插件可以自动地为你的应用生成恰当的项目结构,并且为你自动地编译源代码。

当然知道接下来的也是个好主意。看看Overview of an Android Application以了解一个Android应用工作的原理。

同样也建议你看一看在SDK中samples/文件夹下的ApiDemos应用和其它应用样例.

最后,,Hello AndroidNotepad code tutorials它们都是使用Eclipse开始开发Android的很好的例子。尤其是Hello Android的例子,十分好地介绍用插件来创建一个新的Android应用。


[编辑] 不使用Eclipse插件创建一个Android应用。

这个话题叙述了建立一个Android应用的步骤指南。在阅读这之前,你应当阅读Overview of an Android Application以了解一个Android应用工作的原理。你可能也想看看附带在Android中samples/目录下的的应用样例 ----

这里是一个建立一个应用的基本步骤的清单.

1. 创建你所需要的resource文件 这个文件包含了你的应用需要的AndroidManifest.xml全局描述文件,字符文件,和描述你的用户界面的布局文件。 File List for an Android Application包含了所有那些可选和必需文件和语法详细描述的清单。
2. 设计你的用户界面 查看Implementing a UI以了解Android screen元素的详细资料。
3. 执行你的Activity (这页) 你将在你的应用程序中为每个screen创建一个class/file。Screens会继承android.app类,典型的有basic screens的android.app.Activity,list screens的android.app.ListActivity,或dialog boxes的android.app.Dialog你将执行这些调用来绘制你的screen,查询数据,和提交改变,并且执行任何一种任务比如在设备上显示附加screens或者读取数据。共同的任务,比如从设备创建一个新的screen或读取数据,都在那里描述。在List of Files for an Android Application描述了应用中所需要的文件列表
4. 建立和安置你的包 Android SDK有很好的工具来生成工程和调试代码。

[编辑] 实现Activity回调(Android在它的的生命周期内以多种要素调用activity。你必须知道怎样处理这些中的每一个绘制你的屏幕,初始化类成员和获得数据。)

Android调用许多的回调来让你绘制你的屏幕,在暂停前存储数据,在关闭前更新数据。你必须至少要执行这些方法中的某一个。参考Lifetime of a Screen以学习这些方法是什么时候按照什么样的顺序被调用。这里有一些Android提供的一些screen类的标准类型:

  • android.app.ListActivity - 这是个被用来显示一系列事物列表的screen.它集合了一个ListView对象并包含方法来让你标识那些被选择了的项,当被选择的item改变时返回回调,并且执行其他一系列有关系的动作。
  • android.app.Dialog - 这是个不会在历史堆栈保留下的弹出式小型对话窗口。

[编辑] 开启一个新屏幕

你的Activity会常常需要在它进行时开启另一个Activity 屏幕。这个新的屏幕可能是同一个应用的部分或者是另一个应用的部分,这个新的屏幕可能是浮动或者全屏,它可以返回一个结果,并且你在处理它时你可以决定是否关闭屏幕或者从历史堆栈上移除它,或者使它继续保留在历史堆栈中。下一个部分描述了这些选择.

[编辑] 浮动还是全部?

当你开启一个新屏幕时你可以决定是否使它透明或浮动,或全屏显示。新屏幕的选择影响了旧屏幕的事件中的事件序列(如果新屏幕会使老屏幕模糊,一连串不同的事件会被调用到旧屏幕去,)。详情参考Lifetime of an Activity.

实现透明且浮动窗口的三个标准步骤:

  • 创建一个app.Dialog类
  • 创建一个app.AlertDialog类
  • 在你的AndroidManifest.xml文件中为@android:style/Theme.Dialog设置Theme_Dialog主题属性。例如:
        <activity 
              class="AddRssItem"
              android:label="Add an item" 
              android:theme="@android:style/Theme.Dialog"
              />

调用startActivity()或startSubActivity()将以它自己定义的方法来开启一个新的屏幕(如果定义了主题为浮动就是浮动屏幕,否则它会为全屏)。

[编辑] 开启一个窗口

当你想开启一个新屏幕时,你可以明确地指定一个activity类来打开,或者根据你传入的多个参数和数据来让操作系统决定开启那一个屏幕。调用startActivity并且传入一个为处理屏幕已经指定好了的Intent对象来打开一个新屏幕。为标准的activity调用Intent的setClass或者setClassName来指定一个明确的屏幕。另外,设置更多的值和数据,来让 Android决定开启适当的屏幕。Android会找到和指定所匹配的Activities;它从不会为一个单独的请求开启多个activities。在Intent主题中有更多信息关于Intents和对一个指定类Android是怎样解析的。

[编辑] 一些Intent例子

下面的片段,取自于com.google.android.samples.Animation1 class,and passes it some arbitrary data.:

Intent myIntent = new Intent();
myIntent.component = "com.google.android.samples.Animation1";
myIntent.putExtra("com.google.android.samples.SpecialValue", "Hello, Joe!");
//key/value pair, where key needs current package prefix.
startActivity(myIntent);

下一个片段为要求打开了由一个VIEW 动作指定的网页,并且一个URI字符串头为"http://":

Intent myIntent = new Intent("android.intent.action.VIEW", "http://www.google.com");
myIntent.putExtra("com.google.android.samples.SpecialValue", "Hello, Joe!"); // key/value pair, where key needs current package prefix.

下面是从com.google.android.browser中的AndroidManifest.xml文件筛选的内容:

<intent-filter>
    <action value="android.intent.action.VIEW" />
    <category value="android.intent.category.DEFAULT" />
    <scheme value="http" />
    <scheme value="https" />
    <scheme value="file" />
</intent-filter> 

Android定义了许多标准数值,比如Intent为它的实例定义了一些动作常量。你可以自定义数值,但是访问者和处理者都必须用到它们。

参考AndroidManifest.xml文件的<intent-filter>描述标签为应用程序的manifest语法获得相关信息。

[编辑] 从一个屏幕返回一个结果

一个窗口可以在它关闭之前返回一个结果。这个结果会被传回入到正在被调用的Activity的onActivityResult()方法中,能提供一个整型结果代码,一个数据字符串,和一个任意数据包,随请求代码一起被传入到startSubActivity()。注意你必须调用startSubActivity()方法以接受一个请求参数值来进行回调。下面的代码示范为开启一个新屏幕并返回一个结果。

// Open the new screen.
public void onClick(View v){
    // Start the activity whose result we want to retrieve.  The
    // result will come back with request code GET_CODE.
    Intent intent = new Intent(this, com.example.app.ChooseYourBoxer.class);
    startSubActivity(intent, CHOOSE_FIGHTER);
}

// Listen for results.
protected void onActivityResult(int requestCode, int resultCode,
                                String data, Bundle extras){
    // See which child activity is calling us back.
    switch (resultCode) {
        case CHOOSE_FIGHTER:
            // This is the standard resultCode that is sent back if the
            // activity crashed or didn't doesn't supply an explicit result.
            if (resultCode == RESULT_CANCELED){
                myMessageboxFunction("Fight cancelled");
            } 
            else {
                myFightFunction(data, extras);
            }
        default:
            break;
    }
}

// Class SentResult
// Temporary screen to let the user choose something.
    private OnClickListener mLincolnListener = new OnClickListener(){
        public void onClick(View v) {
            Bundle stats = new Bundle();
            stats.putString("height","6\'4\""); 
            stats.putString("weight", "190 lbs");
            stats.putString("reach", "74\"");
            setResult(RESULT_OK, "Lincoln", stats);
            finish();
        }
    };

    private OnClickListener mWashingtonListener = new OnClickListener() {
        public void onClick(View v){
            Bundle stats = new Bundle();
            stats.putString("height","6\'2\""); 
            stats.putString("weight", "190 lbs");
            stats.putString("reach", "73\"");
            setResult(RESULT_OK, "Washington", Bundle);
            finish();
        }
    };


[编辑] 新界面的生命周期

一个应用可以通过调用Activity.finish()将它自己从历史栈中移除。也可以通过调用Activity.finishSubActivity()关闭任何由它开启的界面。

[编辑] 按键监听

按键和其他界面事件的处理请参考[UIDesign 界面设计]中的[ListeningforUINotifications 监听UI通知]一节。

[编辑] 配置窗体的一般属性

窗体有很多属性,诸如是否现实标题栏,是否浮动,是否显示图标等,你可以通过调用View包中Window对象的成员函数来设置它们。示例中包含了通过调用getWindow().requestFeature()(或者替代快捷方法requestWindowFeature(some_feature))来隐藏标题栏的例子。下面就是这个例子:

//Hide the title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);

[编辑] 存储和恢复状态

如果你的应用程序挂起后再被从内存中重新载入,它会丧失所有的界面状态信息,比如checkbox是否被选中,text中的值以及其他所有成员变量的值。在Android挂起一个程序之前,会调用Activity.onFreeze方法,这个方法会掌控一个Bundle对象,用来存储一些名称/值对,这个对象会被持久化,即使应用在挂起期间被从内存移除了,这个对象依然会存在。当你重新调用onCreate()时,Android会将这个Bundle传回给你的应用。这个Bundle是你的应用在被放入历史栈后(无论它是否还在内存中)唯一存在的对象,只有当应用程序结束的时候才会被销毁。在[onFreeze(Bundle)]和[onCreate(Bundle)]中有恢复状态的相关示例。

[Lifetime of an Activity]中有关于应用程序生命周期的进一步讨论。

  • 存储和恢复大的复杂的持久化数据

你的应用程序可以存储文件或更复杂的集合对象,并在需要的时候重新读取它,也可以将这些数据公开给设备上的所有应用。参考[Storing, Retrieving, and Exposing Data]了解如何保存私有数据,如何保存和获取设备通用数据和如果将所有数据公开给设备上的所有应用。

[编辑] 播放音频,视频,still或其它媒体文件

更多详细资料请参考Android Media APIs文档。


[编辑] 监听和发布全局消息,设置提醒(Alarm)

你可以建立一个监听类,当一个特定的系统消息发出时,它能够接收到,甚至是在彼时被实例化。

这种监听类被称作意向(intent)接收器,继承自IntentReceiver类。如果你希望在系统发出特定的意向时将接收器类实例化,你需要在AndroidManifest.xml中定义一个<receiver>标签。如果是由产生意向的类实例化接收器,就不需要这个步骤了。

接收器会调用IntentReceiver.onReceiveIntent()方法。每个接收器都会定义一个<intent-filter>标签,以来说明它能够接受哪种类型的消息。与处理IntentResolver的方式一样,Android也会查找任何符合条件的意向接收器(但是它会将信息发送到所有接收器而不是最合适的)。

要发送意向,调用类需要创建一个Intent对象,然后以这个Intent为参数调用Activity.broadcastIntent()方法,多个接收器可以收到相同的消息,你可以将意向发送给任何应用中的接收器而不仅仅是你自己的应用。 如果一个接收器没有在manifest文件中注册,你也可以通过调用Context.registerReceiver()动态的将它实例化。

接收器可以通过过滤器来确定哪种意向是它所感兴趣的。但是如果你想让一个确定的意向被一个确定的接收器所接收,那么就不需要定义过滤器,而是在调用的时候通过Intent.setClassName()来直接指定接收器的类。这时候,接收器得到的Context对象会指向它自己的包而不是调用者所在的包。

注意:如果一个发送者或接收器具有权限的限制,那么你的应用程序就需要相应的权限才能与之进行交互。可以通过在manifest中定义<uses-permission>标签来请求相应的权限。

下面这段代码演示了一个发送器和一个接收器。代码并没有演示动态创建接收器的方法。更详细的内容请参考ApiDemos中的AlarmService。

发送消息

// We are sending this to a specific recipient, so we will
// only specify the recipient class name. 
Intent intent = new Intent(this, AlarmReceiver.class);
intent.putExtra("message","Wake up.");
broadcastIntent(intent);

接收消息 接收器的AndroidManifest.xml文件(因为没有指定过滤器,它只能接受指定了接收器类的消息):

<receiver class=".AlarmReceiver" />

接收器的Java代码:

public class AlarmReceiver extends IntentReceiver{
   // Display an alert that we've received a message.    
   @Override 
   public void onReceiveIntent(Context context, Intent intent){
       // Send a text notification to the screen.
       NotificationManager nm = (NotificationManager)
       context.getSystemService(Context.NOTIFICATION_SERVICE);
       nm.notifyWithText(R.id.alarm,
                         "Alarm!!!",
                         NotificationManager.LENGTH_SHORT,
                         null);
  }
}


其他的系统消息

你也可以监听Anroid发出的系统消息,比如连接/拔除USB设备,收到短消息或改变时区等等。参考[Intent]中广播消息的列表,所有这些消息都被标示成为“广播动作(Broadcast Action)”。

监听通话事件

[telephony]包的概要部分讲解了如何注册通话事件监听类。

设置提醒

Android提供了一个[提醒管理服务 AlarmManager],通过它,你可以在特定的时间发出一个意向,这个意向一般用来在你所期望的时间启动一个应用。(注意:如果你想将通知发送到一个正在休眠或者运行的应用,请使用句柄来代替意向)

[编辑] 显示提示信息(Alert)

通常有两种情况下需要向客户显示提示信息:(1)通常显示提示信息是为了响应用户的某一个操作,比如当用户试图进行未被允许的操作时。(2)来自程序外部的提示,这些提示被称作通告(notifications),用来提醒用户后台发生的一些事情,比如收到一封信的电子邮件。

[编辑] 通常的提示方式有哪些

Android为你提供了很多在用户使用应用的过程中,向他们显示提示信息的方式。 Android provides a number of ways for you to show popup notifications to your user as they interact with your application.

Class Description
app.Dialog 一种可以使用布局的普通浮动弹出对话框
app.AlertDialog

or

Context.showAlert()
一种显示有两个按钮(通常是OK和Cancle)并带有回调句柄的弹出提示框。你可以单独的创建一个对话框,也可以通过调用Application的辅助方法Context.showAlert()显示一个对话框。查看紧跟此表之后的信息,可以了解更多的细节。
ProgressDialog 一个带有进度条的提示框,用以显示一个操作的进展情况,进度可以是已知的确定值(xing:一般是百分比)也可以是未知的(setProgress(bool))(xing:进度循环显示)。请查看ApiDemos中相关的例程Views > Progress Bar
Activity 通过将Activity的主题设置为android:theme="android:style/Theme.Dialog",你的Activity可以做为一个普通对话框显示,浮动在其他内容之上。通常android:theme属性在AndroidManifest.xml中设置。这种方式比使用Dialog和AlertDialog的优势在于它比对话框对生命周期的控制更好:如果一个对话框被置于后台它就被销毁了,你无法再取得它的状态。但是应用程序可以暴露一个Bundle接口以在onCreate()被调用的时候帮助你保持状态。(xing:参见监听UI事件通知提供的例程)


[编辑] AlertDialog

这是最基础的警告框,你可以为它定制提示信息、按钮和回调处理。你可以通过调用Applicaion的辅助函数Context.showAlert()来显示它,如下所述

private Handler mHandler = new Handler() {
   public void handleMessage(Message msg) {
       switch (msg.what) {
           case ACCEPT_CALL:
           answer(msg.obj);
           break;

case BOUNCE_TO_VOICEMAIL: voicemail(msg.obj); break; } } };

private void IncomingMotherInlawCall(Connection c) { String Text;

// "Answer" callback. Message acceptMsg = Message.obtain(); acceptMsg.target = mHandler; acceptMsg.what = ACCEPT_CALL; acceptMsg.obj = c.getCall();

// "Cancel" callback. Message rejectMsg = Message.obtain(); rejectMsg.target = mHandler; rejectMsg.what = BOUNCE_TO_VOICEMAIL; rejectMsg.obj = c.getCall();

showAlert(null, "Phyllis is calling", "Answer", acceptMsg, true, rejectMsg); }

[编辑] 通知

来自程序之外的提示信息都是由NotificationManager负责显示的,这种通知可以让你提醒忙于当前操作的用户其他一些他们可能关注的信息。通知可以是任何信息,通过一个简化的弹出对话框显示给用户。通过在状态栏上显示图标、震动、响铃或闪烁等方式引起用户的注意。所有这些情况下,如果用户想要与通知进行交互就必须把焦点转移到通知对话框上。

下面的例子代码演示了一个listening service收到一条短信息之后如何通过NotificationManager向用户显示一条提示信息并显示当前短信的总数。你也可以在ApiDemos中发现更多的相关例程。(在app/下命名为notification*.java的文件)

static void setNewMessageIndicator(Context context, int messageCount){
  // Get the static global NotificationManager object.
  NotificationManager nm = NotificationManager.getDefault();

// If we're being called because a new message has been received, // then display an icon and a count. Otherwise, delete the persistent // message. if (messageCount > 0) { nm.notifyWithText(myApp.NOTIFICATION_GUID, // ID for this notification. messageCount + " new message" + messageCount > 1 ? "s":"", // Text to display. NotificationManager.LENGTH_SHORT); // Show it for a short time only. } }

想在状态栏(status bar)中显示一个通知并在用户选择这条通知的时候连接到一个intent,可以调用函数NotificationManager.notify(),震动模式、要显示在状态栏的图标以及跟通知关联的Intents都可以作为这个函数的参数。


[编辑] 显示进度条(ProgressBar)

活动可以通过进度条告知客户它现在正在做什么。要在屏幕上显示一个进度条,只需调用Activity.requestWindowFeature(Window.FEATURE_PROGRESS)方法。而Activity.getWindow().setFeatureInt(Window.FEATURE_PROGRESS, level)方法可以用来设置进度。进度值可以设置为0到9999之间的任何数,如果你将进度设为10000,进度条就消失不见了。

你也可以使用进度对话框(ProgressDialog),对话框上同样有一个进度条,来告知用户“我正在努力工作呢”。


[编辑] 将应用添加到“我的最爱”

你(应用程序)不可以那么做,只有用户自己才可以。


[编辑] 在应用程序的缺省菜单中增加新条目

每一个Android屏幕都有一个默认菜单,里面有一些通用操作,例如将一个activity加入到收藏夹菜单中。你可以通过实现Activity.onCreateOptionsMenu()或者Activity.onPrepareOptions()方法,将默认的菜单项关联到你提供的入口,并可在你的菜单中加入自定义菜单项。可以通过实现Activity.onOptionsItemSelected()来处理菜单操作。当然,你也可以自己实现一个Runnable类(作为消息句柄),但运行效率会比较低,不推荐这样做。

一个应用在启动时接收一个回调,这样它就可以生成它的菜单。另外,在使用者显示选择的菜单时,应用也会接收回调,从而让你可以执行一些与上下文相关的菜单修改。在启动时生成菜单,需要重载Activity.onCreateOptionsMenu()方法;在菜单被调用时生成菜单(效率较低),需要重载Activity.onPrepareOptionsMenu()方法。每一个Activity都有它自己的菜单列。

尽管你可以在Menu.add方法的参数中对菜单项进行分组标识,但菜单项还是会按添加的顺序号进行显示。以下的代码片段在默认的菜单选项中加入三个菜单项,并通过重载Activity.onOptionsItemSelected()方法来处理它们。你可以通过调用setItemShown()或者setGroupShown()来显示或隐藏菜单项。

// 菜单在第一次显示的时候才调用。
// 创建菜单入口。
// 菜单按显示的顺序依次添加菜单项。

@Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu);

// Parameters for menu.add are: // group -- Not used here. // id -- Used only when you want to handle and identify the click yourself. // title menu.add(0, 0, "Zoom"); menu.add(0, 1, "Settings"); menu.add(0, 2, "Other"); return true; }

// Activity回调允许你在类中处理菜单项的选择。 // 如果你想处理这个菜单请求,则返回true,否则返回false,让另外一个被声明的 // 句柄来处理这个请求(这种方式由于效率较低,并不推荐)。

@Override public boolean onOptionsItemSelected(Menu.Item item){ switch (item.getId()) { case 0: showAlert("Menu Item Clicked", "Zoom", "ok", null, false, null); return true; case 1: showAlert("Menu Item Clicked", "Settings", "ok", null, false, null); return true; case 2: showAlert("Menu Item Clicked", "Other", "ok", null, false, null); return true; } return false; }

你可以调用Item.setAlphabeticShortcut()方法或者Item.setNumericShortcut()方法来增加快捷键,以下代码将为菜单项增加一个“C”快捷方式:

thisItem.setAlphabeticShortcut(0, 'c');

[编辑] 新增子菜单

可以通过Menu.addSubMenu()方法为菜单增加一个子菜单,方法返回一个SubMenu对象,你可以向这个子菜单中添加新的条目。菜单只能有一级子菜单,你可以自定义子菜单的样式。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
   super.onCreateOptionsMenu(menu);

// Parameters for menu.add are: // group -- Not used here. // id -- Used only when you want to handle and identify the click yourself. // title menu.add(0, 0, "Send message"); menu.add(0, 1, "Settings"); menu.add(0, 2, "Local handler"); menu.add(0, 3, "Launch contact picker");

// Add our submenu. SubMenu sub = menu.addSubMenu(1, 4, "Days of the week"); sub.add(0, 5, "Monday"); sub.add(0, 6, "Tuesday"); sub.add(0, 7, "Wednesday"); sub.add(0, 8, "Thursday"); sub.add(0, 9, "Friday"); sub.add(0, 10, "Saturday"); sub.add(0, 11, "Sunday"); return true; }

[编辑] 把你的应用添加到其他应用程序的菜单中

你可以发布你的Activity中的服务,这样其他应用程序就可以把你的activity添加到他自己的菜单中。举例说,你制作了一个可以收缩图形文件的工具,你很乐意将它发布出来给所有其他的图形处理程序。要达到这个目的,首先你要把应用的这种能力发布到manifest文件的intent filter中。如果任何处理图片的应用向其他应用请求图片处理的操作,Android会处理这个意向,找到你的应用然后将它加入到这个应用的菜单中。

[编辑] 作为提供者的应用程序

The offering application 提供服务的应用必须在他的manifest文件中定义一个<intent-filter>标签,intent filter描述了服务能够完成的所有功能。 比如<type>标签用来描述程序可以处理的MIME类型,一个可以自定义的<action>标签用来描述应用的功能(这样别的程序通过intent启动它时,它就知道自己应该做什么了),另外还包含了一个最重要的标签 <category>,它的值是android.intent.category.ALTERNATIVE 和/或 android.intent.category.SELECTED_ALTERNATIVE (SELECTED_ALTERNATIVE表示只处理当前被选中的项目而不能处理被全屏显示的项目)(xing:这里的说法比较拗口,但是按照原文也就是这个意思。如果大家不懂,可以参照SDK提供的notepad例程,其中titleEditor就是一个提供者,在intent filter的定义中包含了这两个选项,如果去掉ALTERNATIVE,那么当你在列表界面打开菜单的时候有Edit Title选项,当进入内容页面打开菜单的时候就没有这项了。如果去掉SELECTED_ALTERNATIVE则正好相反,在列表界面没有选项,而内容界面有。)

Here's an example of a snip of a manifest that advertises picture shrinking technology for both selected items and the whole screen. 下面是manifest文件的一个片断,用来发布一个收缩图片的功能。

<activity class="PictureShrink">                 
   <intent-filter label="Shrink picture">      
       <action value="com.example.sampleapp.SHRINK_IT" />
       <type value="image/*" />                 
       <category value="android.intent.category.ALTERNATIVE " />
       <category value="android.intent.category.SELECTED_ALTERNATIVE" />
   </intent-filter>
</activity>

[编辑] 作为显示者的应用程序

一个应用程序如果想要把外部服务显示到自己的菜单中,就必须重写创建菜单的回调函数。在这个回调函数中,要重建一个intent,将category设置为Intent.ALTERNATIVE_CATEGORY 和/或 Intent.SELECTED_ALTERNATIVE,the MIME type currently selected, and any other requirements, the same way as it would satisfy an intent filter to open a new Activity. 然后调用 menu.addIntentOptions() ,让Android去查找符合要求的服务,就可以有选择的将这些服务添加到菜单当中了。

最好在onPrepareOptionsMenu()实现这些操作,而不是在onCreateOptionsMenu()中,因为当应用启动之后,根据用户不同的操作,菜单项也许会改变。

下面的代码演示了一个图片处理程序如何将额外的服务显示在自己的菜单中。

@Override public boolean
onCreateOptionsMenu(Menu menu){
   super.onCreateOptionsMenu(menu);

// Create an Intent that describes the requirements to fulfill to be included // in our menu. The offering app must include a category value of Intent.ALTERNATIVE_CATEGORY. Intent intent = new Intent(null, getIntent().getData()); intent.addCategory(Intent.ALTERNATIVE_CATEGORY);

// Search for, and populate the menu with, acceptable offering applications. menu.addIntentOptions( 0, // Group 0, // Any unique IDs we might care to add. MySampleClass.class.getName(), // Name of the class displaying the menu--here, its this class. null, // No specifics. intent, // Previously created intent that describes our requirements. 0, // No flags. null); // No specifics.

return true; }

[编辑] 显示Web页

使用webkit.WebView对象即可。


[编辑] 数据绑定

你可以通过一种继承自ListAdapter接口的垫片(Shim)类(或其子类)将一个ListView绑定到后台数据集。ListAdapter的子类可以绑定到多种数据源,并且提供了诸如getItem()、getView()等一组通用的方法。使用这些方法可以获取视图(xing:getView()得到的每个视图都是列表的一项,所以ListAdapter取得的不是数据,而是填充了数据的视图,这点必须要明确才好理解本节的内容),并将其显示在列表中。你也可以实现ListAdapter接口,重载getView()方法,以创建自定义的列表项。要绑定数据,只需要以下两个步骤:

  1. 建立一个ListAdapter对象,为它指定数据源
  2. 将ListAdapter与你的视图列表(ListView)对象相关联

仅此而已!

下面的例子演示了如何将ListActivity与游标查询(cursor query)的结果向绑定。(注意:setListAdapter()方法是对取得活动中的ListView对象,调用ListView对象的setAdapter()方法的一种简化)

// 进行查询,取得查询结果的游标
Cursor c = People.query(this.getContentResolver(), null);
startManagingCursor(c);

// 创建ListAdapter. SimpleCursorAdapter类可以为你做两件事情 // 通过模板中定义的View组件的ID将组件与查询结果列相关联 // 使用XML模板定义列表项 ListAdapter adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, // 视图的模板Use a template that displays a text view c, // 将游标赋给ListAdapter new String[] {People.NAME} , // 将名为people数据表中的“NAME”的列映射到 new String[] {"text1"}); // 名为"text1"的视图,text1在模板中定义 setListAdapter(adapter);

参考ApiDemos中的例子view/list4,了解扩展ListAdapter以使用新的数据类型的方法。


[编辑] 在程序中使用照相机

你可以借助Carmera Device类将照相机镜头扑捉到的内容直接放在自己的画布(Canvas)中。ApiDemos中的Camera Preview应用(Graphics/Camera Preview)为你展示了这个功能并附有源代码。


[编辑] 如何在UI线程中处理开销很大的操作

请避免在UI线程中直接执行那些运行时间很长的操作(如网络I/O-用户界面线程是一个应用程序的主线程-否则你的程序将被阻塞导致无法响应。下面有一些对于如何处理打开销操作的简单建议:

  1. 在UI线程中创建一个句柄(Handler)对象。
  2. 将打开销的操作分配到各个工作线程中
  3. 使用Runnable对象或者Message对象将工作线程的执行结果反馈给UI线程的句柄
  4. 根据情况更新用户界面中的视图

下面让我们看一个典型的实现:

public class MyActivity extends Activity {

[ . . . ] // Need handler for callbacks to the UI thread final Handler mHandler = new Handler();

// Create runnable for posting final Runnable mUpdateResults = new Runnable() { @Override public void run() { updateResultsInUi(); } };

@Override protected void onCreate(Bundle icicle) { super.onCreate(icicle);

[ . . . ] }

protected void startLongRunningOperation() {

// Fire off a thread to do some work that we shouldn't do directly in the UI thread Thread t = new Thread() { public void run() { mResults = doSomethingExpensive(); mHandler.post(mUpdateResults); } }; t.start(); }

private void updateResultsInUi() {

// Back in the UI thread -- update our UI elements based on the data in mResults [ . . . ] } }

对这个问题的更详细的论述,请参见构造快速响应的Android应用句柄的相关文档。


[编辑] 为文本或文本局部设置样式或让其高亮显示

我们可以将TextView对象中的文本或文本的局部设置为高亮显示,也可以设置它们的样式(xing:字体、字号、颜色等)。有两种方法:

  • 如果你使用了字符串资源,可以通过简单的HTML标记设置文本的样式,如粗体、斜体等。举例来说,你可以在res/values/strings.xml中声明如下内容:
<resource>
    <string>id="@+id/styled_welcome_message">We are so glad to see you.</string>
</resources>
  • 如果想要在运行时设置文本的样式或者高亮显示,你就需要用到下面介绍的Spannable对象了。

要在运行时设置文本的样式,你必须确认你的TextView使用了Spannable对象来容纳文本(如果是EditText,就肯定是这样了)。使用getText()得到文本,然后调用setSpan(Object, int, int, int),将android.text.style包中的样式和选定区域作为参数。

下面这段代码清楚地演示了如何在一段文本中设置局部的高亮显示部分、斜体部分、粗体部分,然后再EditText控件中显示这段文本。

// 获取EditText对象.
EditText vw = (EditText)findViewById(R.id.text);

// 设置EditText中的文字. vw.setText("Italic, highlighted, bold.");

// 如果不是EditText而是TextView,我们得这样做: // vw.setText("Italic, highlighted, bold.", TextView.BufferType.SPANNABLE); // 强制使用Spannable方式存储文本以能够为它设置样式 // 或者我们也可以如前所述在XML中定义。

// 取得EditText中的文字 Spannable str = vw.getText();

// 将文本分成几个区块,每个区块设置不同的样式 str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); str.setSpan(new BackgroundColorSpan(0xFFFFFF00), 8, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 21, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

[编辑] 一个Android应用程序的文件列表

  • ApiDemos应用sample包含了很多,很多普遍的问题和UI特性的列子.查看SDK下的samples/ApiDemos和samples/文件夹下的示例代码
MyApp/  
AndroidManifest.xml (必须) 公开这个应用程序提供的所有画面的细节,它们可以从哪里被加载(在主程序菜单或者其他什么地方),实现了哪一种内容提供者、处理什么类型的数据,实现类是什么,以及其他应用程序范围内的信息。这个文件内标记的详细用法请参见AndroidManifest.xml
src/
/myPackagePath/.../MyClass.java
(必须) 这个文件夹内存放了你的应用程序的所有源文件。它们被放在各自包的子文件夹中。
res/ (必须) 此文件存放着你的应用程序中所有的资源文件。资源文件是在构建时被编译到你的应用程序中的额外的数据文件或描述文件。不同文件夹内的文件会在编译时的处理也不同。所以你必须将各种类型的资源文件放到正确的文件夹中。(参见 Resources
anim/
animation1.xml
...
(可选) 存放所有用来描述动画行为的XML文件,这种文件的格式在Resources一章有具体说明。
drawable/
some_picture.png
some_stretchable.9.png
some_background.xml
...
(可选) 存放将被编译到android.graphics.drawable中作为资源的任意个数文件的文件。这些文件可以是图形文件(png, gif, 等),也可以是用来描述位图或图形参数的XML文件(xing:参见ApiDemos中的ShapeDrawable)。被支持的文件格式有PNG (首选), JPG, 和GIF (不鼓励使用), 和自定义的 9-patch 可延展位图。在Resource中对这些格式都有描述。
layout/
screen_1_layout.xml
...
(可选) 存放用来表述整个界面或者部分界面的XML文件。虽然你可以在Java源程序中创建界面,但是,在XML文件中定义它们通常更简单一些。布局文件用来描述界面和组建的方式与HTML在概念上的很相似。参照实现用户界面获取更多关于布局文件的信息,并了解文件中标示的用法。
values/
arrays
classes.xml
colors.xml
dimens.xml
strings.xml
styles.xml
values.xml
(可选) 存放着用来描述字符串、颜色、样式等额外资源信息的XML文件。对这些文件的命名、数目并没有强制要求。任何XML文件都可以被编译。但是文件的语法是Android已经定义好的,在Resources中有详细的说明。
xml/ (可选) 用来存放在运行时被读取的XML文件。
raw/ (可选) 可以用来存放任何需要copy到设备中的文件。



Personal tools