当前位置: 网学 > 编程文档 > Android > 正文

android学习笔记

来源:Http://myeducs.cn 联系QQ:点击这里给我发消息 作者: myeducs.cn 发布时间: 13/03/17

【网学网提醒】:网学会员为广大网友收集整理了,android学习笔记,希望对大家有所帮助!


    Android学习笔记(byquqi99)收藏
    Android学习笔记(byquqi99)
    作者:张华发表于:2007-12-04(blog.csdn.net/quqi99)
    版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明。
    
    (注:有些内容来自androidcn.net)
    
    Androidplatform是一个用于开发移动程序的软件包,它包括了操作系统、中间件及一些关键应用。开发者能使用androidSDK为Androidplatform开发应用,这些应用使用JAVA语言书写,运行在虚拟机Dalvik(一个专为手机程序开发的基于linux内核的JAVA虚拟机)。
    androidcn.net/wiki/index.php?title=%E7%BF%BB%E8%AF%91%E4%BB%BB%E5%8A%A1%E9%A2%86%E5%8F%96&;printable=yes
    androidcn.net/forumdisplay.php?fid=2
    1什么是Android
    1.1Android的特性
    ü应用框架,让一些基础设施得以重用
    üDalvik虚拟机,专为开发移动程序优化
    ü集成的浏览器,(基于WebKit引擎)
    ü优化的图形库,(2D图形库以及基于OpenGLES1.0规范的3D图形库)
    üSQLite,用于结构化数据的存储,是一个数据库
    ü多媒体支持,支持多种音频,视频格式(MPEG4,H.264,MP3,AAC,AMR,JPG,PNG,GIF)
    üGSM技术(依赖具体硬件)
    üBluetooth,EDGE,3G,WiFi(依赖具体硬件)
    üCamera,GPS,compass,accelerometer(依赖具体硬件)
    ü丰富的开发环境(DEBUG工具,内存及性能工具,Eclipse的插件等)
    1.2Android的架构
    Android操作系统的模块如下:
    
    ?应用:Android已集成了一些应用,如邮件客户端,SMS程序,日历,地图,浏览器等
    ?应用框架:
    ?程序库:
    ?例行程序
    ?Linux内核
    2Andvoid起步
    2.1开发环境配置
    使用Eclipse+AndroidDevelopmentTools(ADT)插件。在Help>SoftwareUpdates>FindandInstall....中键入更新地址:
    https://dl-ssl.google/android/eclipse/
    2.2运行第一个Andvoid程序
    使用Eclipse插件
    1、建立的工程类型为:AndvoidProject
    2、建立LaunchConfiguration.Run>OpenRunDialog...orRun>OpenDebugDialog
    命令行运行程序
    1、创建工程activityCreatoryour.package.name.ActivityName
    2、编译。在build.xml所在的目录ant一下。
    3、启动模拟器.运行命令:emulator
    4、在模拟器中,切换到主屏幕。
    5、在命令行输入:adbinstallmyproject/bin/.apk将其上载至模拟器。
    6、在模拟器中选择程序并启动。
    
    Android需要专门的编译工具来正确的编译资源文件和Android程序的其他部分。基于此,你需要为你的程序准备一个专门的编译环境。
    Andorid的编译过
    程通常包括编译XML和其他资源文件、创建正确的输入格式。经过编译的Android程序是一个.apk文件,.apk文件是一个压缩文件,它其中包含了.dex文件、资源文件、rawdata文件和其他文件。
    Andoriod暂时还不支持用本地代码(C/C++)开发第三方程序。
    
    移除Andorid程序
    要移除你安装在模拟器上的程序,你需要通过runadb并删除相应的.apk文件。通过adbshell命令在模拟器上打开一个UNIXshell,进入目录data/app/,通过命令rm你程序的名称.apk来移除文件。
    2.3调试程序
    Andvoid用于调试的手段有:
    DDMS,DDMS是一个图形化的程序,支持端口转发(因此你可以在程序中设置断点),支持模拟器上的截屏,支持线程和堆栈信息和其他的一些特性。
    Logcat,Dump一份系统消息的日志。这些消息包括模拟器抛出错误时的堆栈跟踪。
    AndroidLog,打印日志的类,用来将消息写入模拟器上的日志文件中。如Log.v()用于打印verbose级别的日志
    Traceview,Android可以保存一个日志用来记录被调用的方法以及该方法被调用的次数,通过Traceview你可以在一个图形化的界面中查看这个日志文件。
    可接解设置emulator的设置以方便调试,
    
    模拟器上调试和测试的设置
    Android提供了众多的设置使你可以更容易的调试和测试程序。要进入开发设置页面,在模拟器中转到DevTools>DevelopmentSettings。在该设置页面有以下选项:
    Debugapp:选择要调试的程序。你不需要设定其关联至调试器,但是设定这个值有两个效果:
    在调试的时候,如果你在一个断点处暂停了过长的时间,这个设定会防止Android抛出一个错误
    这个设定使你可以选择“等待调试器”选项,使程序只有在调试器关联上之后才启动
    WaitforDebugger:阻塞所选的程序的加载直到有调试器关联上,这样你就可以在onCreate()中设置断点,这对于调试一个Activity的启动进程是非常重要的。当你对该选项进行了更改,任何正在运行的程序的实例都会被终止。你只有在上面的选项中选择了一个调试程序才能够选中该选项。你一也可以在代码中添加waitForDebugger()来实现同样的功能。
    Immediatelydestroyactivities:告诉系统一旦一个activity停止了就销毁该activity(例如当Android释放内存的时候)。这对于测试代码onFreeze(Bundle)/onCreate(android.os.Bundle)是非常有用的,否则会比较困难。如果你的程序没有保存状态,那么选择这个选项很可能会引发很多问题
    Showscreenupdates:对于任何正在被重绘的screensections都会在其上闪现一个粉红色的矩形。这对于发现不必要的screen绘制是很有必要的。
    ShowCPUusage:在屏幕上方显示CPU信息,显示有多少CPU资源正在
    被使用。上方红色条显示总的CPU使用率,它下方绿色的条显示CPU用在compositingthescreen上的时间。注意:在没有重启模拟器之前,一旦你开启了该功能就不能关闭。
    ShowscreenFPS:显示当前的帧率。这对于查看游戏达到的总的帧率是非常有用的。注意:在没有重启模拟器之前,一旦你开启了该功能就不能关闭。
    Showbackground:当没有activityscreens可见时,显示一个背景模式。一般是不会出现的,仅仅在Debug的时候会出现。
    设定的选项在模拟器重启之后仍然有效,如果要取消设定的选项,在取消设定以后还要重启模拟器,才能生效。
    2.4andvoid中的概念
    一个andvoid应用包括四个部分:
    nActivity活动(个人认为:类似于JSP,也相当于SWT中的Shell,View则相当于wegiet)
    nIntentReceiver(个人认为:类似于Strutsaction)
    nService(个人认为:类似于Servlet)
    nContentProvider(个人认为:用于持久化)
    用上面哪些组件,要在AndroidManifest.xml文件中声明。
    1、Activity.一个activity是应用中的一个单一的屏幕,它继承自Activity类,它将显示由Views组成的UI以及响应事件。(个人理解,相当于JSP)
    2、Intent与IntentFilters.Intent用于从一个屏幕跳到别一个屏幕,描述一个应用想做什么,它的数据结构包括action与data两部分,它是一个消息操作对象,一个被动的数据结构。action如MAIN、VIEW、PICK、EDIT等等,data被表达成一个URI;IntentFilter相当于告诉跳到哪个activity,;IntentReceiver用于响应事件,虽然它不显示UI,但它可以用NotificationManager去通知用户。它需要在AndroidManifest.xml文件中注册,或者是用Context.registerReceiver()硬编码。
    3、Service是一段有生命周期的无UI的代码。
    4、ContentProvider,持久化,例如存储在文件系统中,或者存储在SQLite数据库中。
    2.5例子
    1,下载例子工程。code.google/android/intro/codelab/NotepadCodeLab.zip
    例如:Notepadv1工程是问题工程,Notepadv1Solution则是相应的解决工程。
    2,3个例子的函义如下:
    通过练习1>
    1.数据库对象的例子程序
    2.如何在一个Activity初始化的时候创建数据库对象
    3.如何为一个Activity创建一个pop菜单
    4.如何得到一个用户在POP菜单中选择的ITEM的ID
    5.如何向一个ListView中写入数据
    通过练习2>
    1.如何取得数据集中被选择数据行的ID,注意rows是java的一个listarray对象,所以它有它的getSelection()的方法
    2.如何调用一个SubActivity以及在调用一个SubActivity之前应该做些事情。
    3.要实现一个方法,当SubA
    ctivity返回后,应该做些什么
    4.关于layout。由于Android采用MVC的模式,所以屏幕的布局采用了XML进行定义。一个好的布局会让程序显的更漂亮。可以参考code.google/android/reference/view-gallery.html,有很多的布局模式可供利用。
    5.如何创建一个开始的时候代码中不含onCreate()的类,因为到目前为止还没有创建过自己的类,以前看到的类和修改的方法都是已经写好的了。不过这个类也是一个从android.app.Activity继承的。创建后还是要通过SourceOverride一个onCreate的
    6.从一个SubActivity返回时,在返回之前应该做哪些事情
    7.如何在AndroidManifest.xml中声明一个新的Activity
    8.如何创建一个内部隐含的onClickLister及实现其应有的功能。
    通过练习3>
    1.除了onCreate()还有哪些和lifecycle有关的方法
    a.onFreeze():
    b.onPause()
    c.onResume()
    等等…
    2.大部分程序都有必要考虑lifecycle的问题,应该把下面的这个图记住:
    3.为了不丢失需要保存的信息,要明确的理解Activity的各个状态,并相应的给出在各个状态的行为。
    4.开始的时候对于onFreeze()和onPause()有些理解上的困难,要多读几遍DOC来会理解。通过额外练习>
    进一步的理解lifecycle和通过手机按键进行操作时的时间和程序状态关系
    另外,SDK目录下也有一些例子。
    练习目标:
    1.使用ListActivities,并使用菜单
    2.学习使用操作SQLite数据库
    3.使用ArrayAdapter绑定数据到ListView中
    4.掌握一些基本的操作,如菜单的显示,菜单命令的处理,增加数据项等。
    第一步:
    在SDK中下载获得Notepadv1的代码,并导入到Eclipse中。导入步骤:
    a.在PackageExplorer中,右键选择Import.../General/ExistingProjectsintoWorkspace
    b.点Browse按钮,选择Notepadv1的目录,并点OK
    c.你将会看到Notepadv1被列在项目区中,默认会被打勾,如果没有打勾,请手动勾上。
    d.点Finish
    e.Notepadv1将被列在PackageExplorer中
    f.如果有提示关于AndroidManifest.xml的错误,请选中此项目,并右键选择AndroidTools->FixProject,他将会自动帮你修复错误。
    第二步:
    看一下数据库操作类:DBHelper,还是比较简单的,自己看去:)。
    第三步:
    打开res/layout/notepad_list.xml这个文件,快速的看下就可以了:
    a.,XML文件的固定头
    b.一个Layout的定义,这里是LinearLayout,但不一定是这个,可以是其他的Layout
    第四步:
    在上面的那个文件中加入:
        android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
        android:layout_width="wrap_content"
    
    android:layout_height="wrap_content"
    android:text="@string/no_notes"/>
    a.ListView和TextView不会同是显示,如果没有数据,则默认显示TextView(这个View里会显示一个字符串)。如果有数据,则会显示ListView。
    b.@是默认的关键字,XML解析器将会自动替换这个符号后面的ID
    c.android:list和android:empty是android平台预定义好的ID,如果你想显示空的TextView,可以调用setEmptyView().
    第五步:
    建立一个新文件res/layout/notes_row.xml,文件内容如下:
    
        xmlns:android="schemas.android/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
    然后保存,R.java下将会自动刷新。
    第六步
    改变继承类
    publicclassNotepadv1extendsListActivity
    第七步:
    看一下这三个事件:
    onCreate():界面初始化的时候调用
    onCreateOptionsMenu():按了Menu按钮的时候调用
    onOptionsItemSelected():选择了一个菜单项的时候调用
    第八步:
    改写OnCreate函数:
    
    privateDBHelperdbHelper;
    @Override
    publicvoidonCreate(Bundleicicle)
    {
    super.onCreate(icicle);
    setContentView(R.layout.notepad_list);
    dbHelper=newDBHelper(this);
    fillData();
    }
    第九步:
    在strings.xml中增加:AddItem
    并在Notepadv1类中加入:publicstaticfinalintINSERT_ID=Menu.FIRST;
    改写onCreateOptionsMenu()
    @Override
    publicbooleanonCreateOptionsMenu(Menumenu){
    booleanresult=super.onCreateOptionsMenu(menu);
    menu.add(0,INSERT_ID,R.string.menu_insert);
    returnresult;
    }
    第十步:
    改写onOptionsItemSelected()
    @Override
    publicbooleanonOptionsItemSelected(Itemitem){
    switch(item.getId()){
    caseINSERT_ID:
    createNote();
    break;
    }
    
    returnsuper.onOptionsItemSelected(item);
    }
    第十一步:
    实现两个函数:
    privatevoidcreateNote(){
    StringnoteName="Note"+noteNumber++;
    dbHelper.createRow(noteName,"");
    fillData();
    }
    privatevoidfillData(){
    //Weneedalistofstringsforthelistitems
    Listitems=newArrayList();
    //Getalloftherowsfromthedatabaseandcreatetheitemlist
    Listrows=dbHelper.fetchAllRows();
    for(Rowrow:rows){
    items.add(row.title);
    }
    
    //Nowcreateanarrayadapterandsetittodisplayusingourrow
    ArrayAdapternotes=
    newArrayAdapter(this,R.layout.notes_row,items);//指定notes_row视图,作为数据容器。
    setListAdapter(notes);
    
    }
    第十二步:
    运行:RunAs->AndroidApplication
    2.6开发工具
    2.6.1仿真器
    仿真器是在计算机中运行的一个虚拟的移动装置,用它来设计、调试应用。
    2.6.2ADT
    ADT是一个用于开发andvoid应用的确良eclipse插件,它方便了我们的开发。例如,它让我们方便从eclipse内部访问DDMS工具(可用于截屏,管理port-forwarding,设断点,查看线程和进程信息)
    2.6.3DDMS
    DDMS(DalvikDebugMonitorService)和Dalvik虚拟机集成,将在IDE和模拟器起到一个转发服务。用它能管理仿填器或者设备的进程,并且辅助调试。你可用它杀死进程,选择某一进程去DEBUG,产生TRACE数据,查看堆和线程信息等等。
    2.6.4ADB
    ADB(AndvoidDebugBridge)。在命令行操作。它能安装.apk文件到仿真器上等等。用于将文件发送到仿真器。adb(AndroidDebugBridge)是Android提供的一个通用的调试工具,借助这个工具,我们可以管理设备或手机模拟器的状态。还可以进行以下的操作:
    1、快速更新设备或手机模拟器中的代码,如应用或Android系统升级;
    2、在设备上运行shell命令;
    3、管理设备或手机模拟器上的预定端口;
    4、在设备或手机模拟器上复制或粘贴文件;
    以下为一些常用的操作:
    1、安装应用到模拟器:
    adbinstall
    比较郁闷的是,Android并没有提供一个卸载应用的命令,只能自己手动删除:
    adbshell
    cd/data/app
    rmapp.apk
    2、进入设备或模拟器的shell:
    adbshell
    通过上面的命令,就可以进入设备或模拟器的shell环境中,在这个LinuxShell中,你可以执行各种Linux的命令,另外如果只想执行一条shell命令,可以采用以下的方式:
    adbshell[command]
    如:adbshelldmesg会打印出内核的调试信息。
    3、发布端口:
    你可以设置任意的端口号,做为主机向模拟器或设备的请求端口。如:
    adbforwardtcp:5555tcp:8000
    4、复制文件:
    你可向一个设备或从一个设备中复制文件,
    复制一个文件或目录到设备或模拟器上:
    adbpush
    如:adbpushtest.txt/tmp/test.txt
    从设备或模拟器上复制一个文件或目录:
    adbpull
    如:adbpull/addroid/lib/libwebcore.so.
    5、搜索模拟器/设备的实例:
    取得当前运行的模拟器/设备的实例的列表及每个实例的状态:
    adbdevices
    6、查看bug报告:
    adbbugreport
    7、记录无线通讯日志:
    一般来说,无线通讯的日志非常多,在运行时没必要去记录,但我们还是可以通过命令,设置记录:
    adbshell
    logcat-bradio
    8、获取设备的ID和序列号:
    adbget-product
    adbget-serialno
    9、访问数据库SQLite3
    adbshell
    sqlite3
    2.6.5aapt
    Aapt(AndvoidAssetPackagingTool),用于创建.apk文件。
    2.6.6aidl
    Aidl(And
    voidInterfaceDescriptionLanguage)用于产生代码。
    2.6.7sqlite3
    用于访问SQLite数据文件。
    2.6.8Traceview
    查看LOG信息
    2.6.9mksdcard
    Helpsyoucreateadiskimagethatyoucanusewiththeemulator,tosimulatethepresenceofanexternalstoragecard(suchasanSDcard
    2.6.10dx
    Dx工具用于重写.class字节码到Andvoid字节码
    2.6.11activityCreator
    用于产生ant文件的脚本。当然,若用eclipse插件就不需要它了。
    2.7Andvoid应用的生命周期
    在大部份情况下,每个Android应用都将运行在自己的Linux进程当中。当这个应用的某些代码需要执行时,进程就会被创建,并且将保持运行,直到该进程不再需要,而系统需要释放它所占用的内存,为其他应用所用时,才停止。
    Android一个重要并且特殊的特性就是,一个应用的进程的生命周期不是由应用自身直接控制的,而是由系统,根据运行中的应用的一些特征来决定的,包括:这些应用对用户的重要性、系统的全部可用内存。
    对于应用开发者来说,理解不同的应用组件(特别是Activity、Service、IntentReceiver)对应用进程的生命周期的影响,这是非常重要的。如果没有正确地使用这些组件,将会导致当应用正在处理重要的工作时,进程却被系统消毁的后果。
    对于进程生命周期,一个普遍的错误就是:当一个IntentReceiver在它的onReceiveIntent()方法中,接收到一个intent后,就会从这个方法中返回。而一旦从这个方法返回后,系统将会认为这个IntentReceiver不再处于活动状态了,也就会认为它的宿主进程不需要了(除非宿主进程中还存在其它的应用组件)。从而,系统随时都会消毁这个进程,收回内存,并中止其中还在运行的子线程。问题的解决办法就是,在IntentReceiver中,启动一个Service,这样系统就会知道在这个进程中,还有活动的工作正在执行。
    为了决定在内存不足情况下消毁哪个进程,Android会根据这些进程内运行的组件及这些组件的状态,把这些进程划分出一个“重要性层次”。这个层次按顺序如下:
    1、前端进程是拥有一个显示在屏幕最前端并与使用者做交互的Activity(它的onResume已被调用)的进程,也可能是一个拥有正在运行的IntentReceiver(它的onReceiveIntent()方法正在运行)的进程。在系统中,这种进程是很少的,只有当内存低到不足于支持这些进程的继续运行,才会将这些进程消毁。通常这时候,设备已经达到了需要进行内存整理的状态,为了保障用户界面不停止响应,只能消毁这些进程;
    2、可视进程是拥有一个用户在屏幕上可见的,但并没有在前端显示的Activity(它的onPause已被调用)的进程。例如:一个以对话
    框显示的前端activity在屏幕上显示,而它后面的上一级activity仍然是可见的。这样的进程是非常重要的,一般不会被消毁,除非为了保障所有的前端进程正常运行,才会被消毁。
    3、服务进程是拥有一个由startService()方法启动的Service的进程。尽管这些进程对于使用者是不可见的,但他们做的通常是使用者所关注的事情(如后台MP3播放器或后台上传下载数据的网络服务)。因此,除非为了保障前端进程和可视进程的正常运行,系统才会消毁这种进程。
    4、后台进程是拥有一个用户不可见的Activity(onStop()方法已经被调用)的进程。这些进程不直接影响用户的体验。如果这些进程正确地完成了自己的生命周期(详细参考Activity类),系统会为了以上三种类型进程,而随时消毁这种进程以释放内存。通常会有很多这样的进程在运行着,因些这些进程会被保存在一个LRU列表中,以保证在内存不足时,用户最后看到的进程将在最后才被消毁。
    5、空进程是那些不拥有任何活动的应用组件的进程。保留这些进程的唯一理由是,做为一个缓存,在它所属的应用的组件下一次需要时,缩短启动的时间。同样的,为了在这些缓存的空进程和底层的核心缓存之间平衡系统资源,系统会经常消毁这些空进程。
    当要对一个进程进行分类时,系统会选择在这个进程中所有活动的组件中重要等级最高的那个做为依据。可以参考Activity、Service、IntentReceiver文档,了解这些组件如何影响进程整个生命周期的更多细节。这些类的文档都对他们如何影响他们所属的应用的整个生命周期,做了详细的描述。
    
    2开发应用
    2.1前端UI
    2.1.1.屏幕元素的层次
    1.Views
    一个View是android.view.View基础类的一个对象,它是一个有屏幕上特定的一个矩形内布局和内容属性的数据结构。一个View对象处理测量和布局,绘图,焦点变换,滚动条,还有屏幕区域自己表现的按键和手势。
    View类作为一个基类为widget(窗体部件)服务,widget--是一组用于绘制交互屏幕元素的完全实现子类。Widget处理它们自己的测距和绘图,所以你可以更快速地用它们去构建你的UI。可用到的widget包括Text,EditText,InputMethod,Button,RadioButton,Checkbox,和ScrollView。
    2.Viewgroups
    一个ViewGroup是一个android.view.Viewgroup类的对象。一个viewgroup是一个特殊的view对象,它的功能是去装载和管理一组下层的view和其他viewgroup,Viewgroup让你可以为你的UI增加结构并且将复杂的屏幕元素构建成一个独立的实体。
    Viewgroup类作为一个基类为layout(布局)服务,layout--是一组提供屏幕界面通用类型的完全实现子类
    。layout让你可以为一组view构建一个结构。
    3.ATree-StructuredUI
    在Android平台上,你用view树和viewgroup节点来定义一个Activity的UI,就如同下面图表一样。这个树可以如你需要那样简单或者复杂,并且你可以使用Android的预定义widget和layout或者你自定义的view类型来构建它。
    
    要将屏幕绑定一个树以便于渲染,你的Activity调用它的setContentView()方法并且传递一个参数给根节点对象。一旦Android系统获得了根节点的参数,它就可以直接通过节点来无效化,测距和绘制树。当你的Activity被激活并且获得焦点时,系统会通知你的activity并且请求根节点去测距并绘制树,根节点就会请求它的子节点去绘制它们自己。每个树上的viewgroup节点都为它的子节点的绘制负责。
    正如之前提到的,每个viewgroup都有测量它的有效空间,布局它的子对象,并且调用每个子对象的Draw()方法去绘制它们自己。子对象可能会请求获得一个它们在父对象中的大小和位置,但是父对象对于每个子对象的大小和位置有最终的决定权。
    4.LayoutParams:一个子对象如何指定它的位置和大小
    每个viewgroup类都会使用一个继承于Viewgroup.LayoutParams的嵌套类。这个子类包含了包含了定义一个子对象位置和大小的属性类型,并且需适用于viewgroup类。
    
    要注意的是,每个LayoutParams子类都有它自己赋值的语法。每个子元素必须定义适用于它们父对象的LayoutParams,尽管父对象可能会为子元素定义不同的LayoutParams。
    所有的viewgroup都包括宽和高。很多还包括边界的定义(margin和border)。你可以非常精确地描述宽和高,尽管你并不想经常这么做。更多时候你希望你的view自行调整到适应内容大小,或者适应容器大小。
    2.1.2.通用布局对象(最普遍的viewgroups)
    1.FrameLayout(上下压着的那种)
    FrameLayout是最简单的一个布局对象。它被定制为你屏幕上的一个空白备用区域,之后你可以在其中填充一个单一对象—比如,一张你要发布的图片。所有的子元素将会固定在屏幕的左上角;你不能为FrameLayout中的一个子元素指定一个位置。后一个子元素将会直接在前一个子元素之上进行覆盖填充,把它们部份或全部挡住(除非后一个子元素是透明的)。
    2.LinearLayout
    LinearLayout以你为它设置的垂直或水平的属性值,来排列所有的子元素。所有的子元素都被堆放在其它元素之后,因此一个垂直列表的每一行只会有一个元素,而不管他们有多宽,而一个水平列表将会只有一个行高(高度为最高子元素的高度加上边框高度)。LinearLayout保持子元素之间的间隔以及互相对齐(相对一个元素
    的右对齐、中间对齐或者左对齐)。
    LinearLayout还支持为单独的子元素指定weight。好处就是允许子元素可以填充屏幕上的剩余空间。这也避免了在一个大屏幕中,一串小对象挤成一堆的情况,而是允许他们放大填充空白。子元素指定一个weight值,剩余的空间就会按这些子元素指定的weight比例分配给这些子元素。默认的weight值为0。例如,如果有三个文本框,其中两个指定了weight值为1,那么,这两个文本框将等比例地放大,并填满剩余的空间,而第三个文本框不会放大。
    Tip:为了在屏幕上创建一个按比例安排大小的layout,需要根据这个屏幕上每个元素将按什么比例显示,创建一个指定fill_parent,子元素的height或width为0,且为每一个子元素分配weight值的容器对象。
    下面的两个窗体采用LinearLayout,包含一组的元素:一个按钮,几个标签,几个文本框。两个窗体都为布局做了一番修饰。文本框的width被设置为FILL_PARENT;其它元素的width被设置为WRAP_CONTENT。默认的对齐方式为左对齐。左边的窗体没有设置weight(默认为0);右边的窗体的comments文本框weight被设置为1。如果Name文本框也被设置为1,那么Name和Comments这两个文本框将会有同样的高度。
    
    在一个水平排列的LinearLayout中,各项按他们的文本基线进行排列(第一列第一行的元素,即最上或最左,被设定为参考基线)。因此,人们在一个窗体中检索元素时,就不需要七上八下地读元素的文本了。我们可以在layout的XML中设置android:baselineAligned="false",来关闭这个设置。
    3.TableLayout
    TableLayout将子元素的位置分配到行或列中。一个TableLayout由许多的TableRow组成,每个TableRow都会定义一个row(事实上,你可以定义其它的子对象,这在下面会解释到)。TableLayout容器不会显示row、cloumns或cell的边框线。每个row拥有0个或多个的cell;每个cell拥有一个View对象。表格由列和行组成许多的单元格。表格允许单元格为空。单元格不能跨列,这与HTML中的不一样。下图显示了一个TableLayout,图中的虚线代表不可视的单元格边框。
    
    列可以被隐藏,也可以被设置为伸展的从而填充可利用的屏幕空间,也可以被设置为强制列收缩直到表格匹配屏幕大小。对于更详细信息,可以查看这个类的参考文档。
    4.AbsoluteLayout
    AbsoluteLayout可以让子元素指定准确的x/y坐标值,并显示在屏幕上。(0,0)为左上角,当向下或向右移动时,坐标值将变大。AbsoluteLayout没有页边框,允许元素之间互相重叠(尽管不推荐)。我们通常不推荐使用AbsoluteLayout,除非你有正当理由要使用它,因为它使界面代码太过刚性,
    以至于在不同的设备上可能不能很好地工作。
    5.RelativeLayout
    RelativeLayout允许子元素指定他们相对于其它元素或父元素的位置(通过ID指定)。因此,你可以以右对齐,或上下,或置于屏幕中央的形式来排列两个元素。元素按顺序排列,因此如果第一个元素在屏幕的中央,那么相对于这个元素的其它元素将以屏幕中央的相对位置来排列。如果使用XML来指定这个layout,在你定义它之前,被关联的元素必须定义。
    这是一个RelativeLayout例子,其中有可视的和不可视的元素。基础的屏幕layout对象是一个RelativeLayout对象。
    
    这个视图显示了屏幕元素的类名称,下面是每个元素的属性列表。这些属性一部份是由元素直接提供,另一部份是由容器的LayoutParams成员(RelativeLayout的子类)提供。RelativeLayout参数有width,height,below,alignTop,toLeft,padding和marginLeft。注意,这些参数中的一部份,其值是相对于其它子元素而言的,所以才RelativeLayout。这些参数包括toLeft,alignTop和below,用来指定相对于其它元素的左,上和下的位置。
    6.SummaryofImportantViewGroups
    重要ViewGroup摘要,这些对象拥有UI子元素。一些提供可视的UI,另一些只处理子元素的布局。
    
    2.1.3数据绑定
    这部分会提及UI有的一些Viewgroups,些组成对象是经典AdapterView类的子类.例如包括图像,数层结构表现.这些对象有2个通用的任务:数据层的填充与用户操作选择
    1.数据层填充
    ThisistypicallydonebybindingtheclasstoanAdapterthatgetsitsdatafromsomewhere—eitheralistthatthecodesupplies,orqueryresultsfromthedevice'sdatabase.
    //GetaspinnerandbindittoanArrayAdapterthat
    //referencesaStringarray.
    privateString[]fruit={"apples","oranges","lemons"}
    Spinners1=(Spinner)findViewById(R.id.fruitlist);
    s1.setAdapter(newArrayAdapter(this,mStrings));
    
    //LoadaSpinnerandbindittoadataquery.
    privateString[]cols={android.provider.Contacts.PeopleColumns.NAME};
    privateCursorcur=managedQuery(android.provider.Contacts.People.CONTENT_URL,cols,null,null);
    s2.setAdapter(newCursorAdapter(cur,this));
    2.用户操作选择
    设置类的AdapterView.OnItemClickListener方法监听和捕捉用户的操作事件.
    //Createamessagehandlingobjectasananonymousclass.
    privateOnItemClickListenermMessageClickedHandler=newOnItemClickListener(){
    publicvoidonItemClick(AdapterViewparent,Viewv,intposition,longid)
    {
    //Displayamessagebox.
    showAlert("You'vegotanevent","Clickedme!","ok",false);
    }
    };
    //NowhookintoourobjectandsetitsonItemClickListenermember
    //toourclasshandlerobject.
    mHistoryView=(ListView)findViewById(R.id.accept_button);
    mHi
    storyView.setOnItemClickListener(mMessageClickedHandler);
    2.1.4使用XML设计你的屏幕显示
    1.Android定义了大量的自定义元素,各自代表了特定的Android显示子类。
    2.你可以象创建HTML文档一样,通过保存在应用res/layout/目录下的XML文件中一系列的嵌套标签来设计你的屏幕显示。
    3.每个文档描述一个android.view.View这个元素既可以是
    一个简单的显示元素,也可以是一个在子节点中包含了一个集合的版面设计的元素,当Android编译你的应用时,他将每个文件都编译进android系统。你可以在代码Activity.onCreate()实现中通过调用setContentView(R.layout.layout_file_name)方法加载显示资源。
    2.1.5在屏幕元素中设置句柄
    1.您可以使用Activity.findViewById来取得屏幕上的元素的句柄.使用该句柄您可以设置或获取任何该对象外露的值.
    TextViewmsgTextView=(TextView)findViewById(R.id.msg);
    msgTextView.setText(R.string.push_me);
    2.2构建组成模块
    Android应用是由各种各样的组件来构成.这些组件大部分都是松散联接,你可以精确的描述它们的联接程度,所以组建的联合比单个程序更有结合力.显然,所有的组件运行在同一个系统进程里面.在这个进程里面创建多线程是可以允许的,并且是常见的.如果你需要,也可以对刚才那个系统进程创建相互独立的子进程.即使会有很多实例运行,但是他们之间互不干扰,这个是很难得的,因为Android可以确保代码是进程间透明的.以下部分是很重要的AndroidAPIs;
    AndroidManifest.xml是控制文件,告诉所有由高级组件构成的系统可以做什么.这些高级的组件包括(特殊activities,服务,接收器,第三方提供商).控制文件用来告诉系统如何使用你所创建的组件.
    Activity是一个有生命周期的对象.一个Activity做一些工作需要相当大的数量的代码;如必要的话,这部分工作还可能包括对用户UI界面的显示,也可能是没有UI界面.代表性地解释Activity就是,你必须标明你应用程序的入口点.
    视图(Views)可以将其自身绘制到屏幕(screen)上。Android的接口都是由一组以树的形式出现的视图组成的。开发者可以通过创建一个新的视图的方法来使用自定义的图形处理技术(比如开发游戏,或者是使用了不常用的用户图形(UI)窗口界面(widget))。
    Intents是一个消息操作对象.如果一个应用程序想要显示一个网页,那么它表示为Intent,我们可以通过Intent实例创建一个URI视图并且可以手工断开系统.系统设置一些代码(例如浏览器),可以让我们知道如果去操作Intent并且运行它.Intents也可以被用于广播系统范围内的有效事件(例如播发一则通知).
    服务是运行在后台的一段代码.它可以运行在它自己的进程,也可以运行在其他应用程序的
    进程里面,这要取决于自身的需要.其他组件绑定到这个服务上面,并且可以请求远程方法调用.例如媒体播放器的服务,甚至当用户退出媒体用户向导界面,音乐依然可以持续播放.甚至当用户界面关闭,音乐播放依然继续.
    通知将以小图标的形式呈现在状态栏里.收到消息以后,用户可以与图标进行交互式操作.大部分熟知的通知是以短信息,通话记录,语音邮件的形式创建出来.通知是提请用户注意的重要机制.
    ContentProvider是访问数据设备的提供者.典型的例子是访问用户联系列表.你的应用程序需要访问的数据可以由ContentProvider来支持.并且你也可以定义自己专用数据的ContentProviders.
    
    2.2.1AndroidManifest.xml文件
    AndroidManifest.xml是每一个应用都需要的文件.位于应用根目录下,描述了程序包的一个全局变量,包括暴露的应用组件(activities,services等等)和为每个组件的实现类,什么样的数据可以操作,以及在什么地方运行.
    这个文件的一个重要方面(概念)是其中的intent过滤器.这个过滤器描述了何时何种情况下让activity启动.当一个activity(或是操作系统)想要执行一个动作,例如打开一个Web页或是打开一个联系人选取屏幕,会创建一个Intent对象.该对象包含了很多的描述信息,描述了你想做什么操作,你想处理什么数据,数据的类型,以及一些其他的重要信息.Android拿这个Intent的信息与所有应用暴露的intent过滤器比较,找到一个最能恰当处理请求者要求的数据和action的activity.intents的更多信息在Intent页.
    另外还要声明您的应用的Activities,ContentProviders,Services,和IntentReceivers,你也可以在AndroidManifest.xml文件中指定权限和instrumentation(安全控制和测试).请查看AndroidManifest,了解这个标签和他们的属性.
    一个AndroidManifest.xml文件的例子:
    
    
    
    
    
    
    
    

    
    
    
    下面列出了AndroidManifest.xml这个文件详细的结构大纲,描述了所有可用标签.
    
    Therootnodeofthefile,describingthecompletecontentsofthepackage.Underityoucanplace:
    文件根节点,描述了程序包的所有内容.在其节点下面内可以放置:
    
    Requestsasecuritypermissionthatyourpackagemustbegrantedinorderforit
    tooperatecorrectly.SeetheSecurityModeldocumentformoreinformationonpermissions.Amanifestcancontainzeroormoreoftheseelements.
    请求一个安全授权,必须被授予该权限,您的程序包才能正确的操作.查看安全模块文档,了解有关授权的更多信息.一个manifest可以包含零个或多个这样的节点.
    
    Declaresasecuritypermissionthatcanbeusedtorestrictwhichapplicationscanaccesscomponentsorfeaturesinyour(oranother)package.SeetheSecurityModeldocumentformoreinformationonpermissions.Amanifestcancontainzeroormoreoftheseelements.
    声明一个安全授权,用来限制哪些应用可以访问您的程序包内的组件和特有机制.查看安全模块文档,了解有关授权的更多信息.一个manifest可以包含零个或多个这样的节点.
    
    Declaresthecodeofaninstrumentationcomponentthatisavailabletotestthefunctionalityofthisoranotherpackage.SeeInstrumentationformoredetails.Amanifestcancontainzeroormoreoftheseelements.
    TODO
    
    Rootelementcontainingdeclarationsoftheapplication-levelcomponentscontainedinthepackage.Thiselementcanalsoincludeglobaland/ordefaultattributesfortheapplication,suchasalabel,icon,theme,requiredpermission,etc.Amanifestcancontainzerooroneoftheseelements(morethanoneapplicationtagisnotallowed).Underityoucanplacezeroormoreofeachofthefollowingcomponentdeclarations:
    描述程序包内应用级别组件的根节点.该节点能够描述应用程序的全局(和/或)默认属性,例如标签,图标,主题,需要的授权,等等.一个manifest可以包含零个或一个这样的节点(多个application节点是不允许的).在该节点下,可以包含零个或多个以下每个组件的声明:
    
    AnActivityistheprimaryfacilityforanapplicationtointeractwiththeuser.Theinitialscreentheuserseeswhenlaunchinganapplicationisanactivity,andmostotherscreenstheyusewillbeimplementedasseparateactivitiesdeclaredwithadditionalactivitytags.
    Activity是应用于用户交互的最主要机制.当一个应用运行的时候,用户看到的第一个屏幕就是activity,并且,用户所使用的其他绝大多数屏幕(界面)也会是
    Note:EveryActivitymusthaveantaginthemanifestwhetheritisexposedtotheworldorintendedforuseonlywithinitsownpackage.IfanActivityhasnomatchingtaginthemanifest,youwon'tbeabletolaunchit.
    Optionally,tosupportlateruntimelookupofyouractivity,youcanincludeoneormoreelementstodescribetheactionstheactivitysupports:
    
    DeclaresaspecificsetofIntentvaluesthatacomponentsupports,intheformofanIntentFilter.Inadditiontothevariouskindsofvaluesthatcanbespecifiedunderthiselement,attri
    butescanbegivenheretosupplyauniquelabel,icon,andotherinformationfortheactionbeingdescribed.
    
    AnIntentactionthatthecomponentsupports.
    
    AnIntentcategorythatthecomponentsupports.
    
    AnIntentdataMIMEtypethatthecomponentsupports.
    
    AnIntentdataURIschemethatthecomponentsupports.
    
    AnIntentdataURIauthoritythatthecomponentsupports.
    
    AnIntentdataURIpaththatthecomponentsupports.
    
    AnIntentReceiverallowsanapplicationtobetoldaboutchangestodataoractionsthathappen,evenifitisnotcurrentlyrunning.Aswiththeactivitytag,youcanoptionallyincludeoneormoreelementsthatthereceiversupports;seetheactivity'sdescriptionformoreinformation.
    一个IntentReceiver可以让应用接收到一次数据变化和一次行为发生的通知,甚至这个应用没有在运行也可以.同activity标签一样,你可以选择包含一个或多个元素;查看activity的标签描述了解更多信息.
    
    AServiceisacomponentthatcanruninthebackgroundforanarbitraryamountoftime.Aswiththeactivitytag,youcanoptionallyincludeoneormoreelementsthatthereceiversupports;seetheactivity'sdescriptionformoreinformation.
    Service是一个在后台任意时刻都可以运行的组件.同activity标签一样,你可以选择包含一个或多个元素;查看activity的标签描述了解更多信息.
    
    AContentProviderisacomponentthatmanagespersistentdataandpublishesitforaccessbyotherapplications.
    ContentProvider组件是用来管理数据持久化及数据发布的,发布的数据可以被其他的应用访问.
    2.2.2Activity
    2.2.3View
    android.view
    公有类
    android.view.View
    java.lang.Object
    android.view.ViewDrawable.CallbackKeyEvent.Callback
    视图(View)类代表了一种基本的用户界面组成模块。一个视图占据了屏幕上的一个矩形区域,并响应绘制图形和事件处理。视图类是窗体类(Widget)的基类,而窗体类用来生成可交互的用户图形接口(interactiveGUI)。
    视图类的使用窗口中所有的视图构成一个树形结构。要想增加视图,既可以用直接添加代码的方法,也可以在一个或者多个XML文件中声明新视图构成的树。在视图类的子类中,有的可以用来控制,有的具有显示文字、图片或者其他内容的功能。
    当视图树被创建后,以下这若干种通用操作将可以被使用:1.设置属性(properties):比如,可以设置TextView类的一个实例的文本内容。不同的子类可以用来设置的属性与方法不同。注意:只有编译时能够检测到的属性才可以在XML布局管理(layout)文件中设置。
    2.设置输入焦点(focus):
    为了响应用户输入,整个框架将处理移动的焦点。如果想把焦点强制指向某一个特定的视图,必须调用requestFocus()方法。
    3.设置监听器(listener):在视图中,允许设置监听器来捕获用户感兴趣的某些事件。比如说,在所有的视图中,无论视图是获得焦点还是失去焦点,都可以通过设置监听器来捕获。可以通过调用setOnFocusChangeListener(View.OnFocusChangeListener)来注册一个监听器。在其他视图子类中,提供了一些更加特殊的监听器。比如,一个按键(Button)可以触发按键被按下的事件。
    4.设置是否可视(visibility):可以通过调用setVisibility(int)来显示或者隐藏视图。
    2.2.4Intent
    Intent介绍
    Intent是对被执行操作的抽象描述。调用startActivity(Intent),可以启动Activity;调用broadcastIntent(Intent),可以把Intent发送给任何相关的IntentReceiver组件;调用startService(Intent,Bundle)以及bindService(Intent,String,ServiceConnection,int)可以让应用和后台服务进行通信。
    Intent提供了一个在不同应用的代码之间进行晚绑定(lateruntimebinding)的机制。它主要被用来启动Activities,因此可以被看作是Activities之间的粘合剂。Intent大体上是一个被动数据结构,该数据结构包括被执行动作的抽象描述。Intent中的主要内容有:
    üaction--需要被执行的动作。比如VIEW_ACTION,EDIT_ACTION,MAIN_ACTION等。
    üdata--执行动作要操作的数据,在Intent里用指向数据记录的URI(ContentURI)表示。比如联系人数据库中的一个联系人记录。
    译注:被动数据结构:只能由外部线程或者进程改变的数据结构。与能够通过相关的线程或者进程执行内部操作从而产生外部行为的主动数据结构相对应。
    下面是一些action/data对的例子:
    üVIEW_ACTIONcontent://contacts/1--显示标识符为"1"的联系人的信息。
    üEDIT_ACTIONcontent://contacts/1--编辑标识符为"1"的联系人的信息。
    üVIEW_ACTIONcontent://contacts/--显示可遍历的联系人列表。这是用来进入联系人应用主界面(顶级入口,top-levelentry)的典型方法。在这个界面中察看某个联系人会产生一个新的Intent:{VIEW_ACTIONcontent://contacts/N},用来启动新的Activity,显示该联系人的详细信息。
    üPICK_ACTIONcontent://contacts/--先是可遍历的联系人列表,并且允许用户在列表中选择一个联系人,然后把这个联系人返回给"上级活动"(parentactivity)。例如:电子邮件客户端可以使用这个Intent,要求用户在联系人列表中选择一个联系人。
    除了action,data两个主要属性,Intent还具有一些其它属性,这些属性也可以被用在Intent里:
    category--类别,被执行动作的
    附加信息。例如LAUNCHER_CATEGORY表示Intent的接受者应该在Launcher中作为顶级应用出现;而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个,这些动作可以在同一块数据上执行。
    type--数据类型,显式指定Intent的数据类型(MIME)。一般上Intent的数据类型能够根据数据本身进行判定,但是通过设置这个属性,可以强制采用显式指定的类型而不再进行推导。
    component--组件,为使用Intent的组件类指定名称。通常会根据Intent中包含的其它信息——比如action,data/type,categories——进行查找,最终找到一个与之匹配的组件。如果这个属性存在的话,将直接使用它指定的组件,不再执行上述查找过程。指定了这个属性以后,Intent的其它所有属性都是可选的。
    extras--额外的附加信息,是其它所有附加信息的集合。使用extras可以为组件提供扩展信息,比如,如果要发送电子邮件,也就是要执行“发送电子邮件”的动作,可以将电子邮件的标题、正文等保存在extras里。
    在Intent类里定义了多种标准action和category常量(字符串),同时应用也可以根据自己的需要进行定义。这些字符串使用JAVA风格的scoping,从而保证它们的唯一性。比如标准VIEW_ACTION的定义是“android.app.action.VIEW”。
    概括而言,“动作”、“数据类型”、“类别”(译注:Intent的action类型)和“附加数据”一起形成了一种语言。这种语言使得系统能够理解诸如“打john的手机”之类的短语。随着应用不断的加入到系统中,它们可以添加新的“动作”、“数据类型”、“类别”来扩展这种语言。应用也可以提供自己的activities来处理已经存在的“短语”,从而改变这些“短语”的行为。
    
    Intent解析
    Intent有两种主要形式:
    ü显式意图(直接意图?)。显式意图是指定了component属性的intents。调用setComponent(ComponentName)或者setClass(Context,Class)可以为intents设定component属性——指定具体的组件类。这些intents一般不包括包括其它任何信息,它们通常只是用来通知应用启动内部的activities作为该应用的(当前)用户界面。
    ü隐式意图(含蓄意图?)。隐式意图是没有指明comonent的intents。这些intents必须包括足够的信息,这样系统才能确定在所有的可用组件中,对一个intent来说运行哪一个组件才是最合适的。
    在使用implicitintents的时候,对于一个任意的intent,我们需要知道用它来做什么。“Intent解析过程”用来处理这个问题。“Intent解析过程”将intent映射到可以处理它的activity,IntentReceiver或者service。
    Intent解析机制主要是
    将已安装应用程序包里的Intent-Filter描述和Intent进行匹配。如果使用广播发送Intent,还要在已经注册的IntentReceiver中尽心匹配。更多的相关描述可以在IntentFilter中找到。
    在解析Intent的过程中要用到Intent的三个属性:动作、数据类型和类别。使用这些属性,就可以PackageManager上查询能够处理当前intent的合适组件。组件是否合适由AndroidManifest.xml文件中提供的intent信息决定。判断的方法如下:
    1、如果intent指明了要执行的action,组件action列表中就必须包含着个action,否则不能匹配;
    2、如果Intent没有提供数据类型(type),系统从数据(data)中得到数据类型。和action一样,组件的数据类型列表中必须包含intent的数据类型,否则不能匹配。
    3、如果Intent中的数据不是content:类型的URL,而且Intent也没有明确指定它的数据类型,将根据Intent中数据的scheme(比如http:ormailto:)进行匹配。同上,Intent的scheme必须出现在组件的scheme列表中。
    4、如果Intent指定了一个或多个类别,这些类别必须全部出现在组建的类别列表中。比如intent中包含了两个类别:LAUNCHER_CATEGORY和ALTERNATIVE_CATEGORY,解析得到的组件必须至少包含这两个类别。
    以一个应用实例作为例子,这个应用可以让用户浏览便笺列表、查看每一个便笺的详细信息:
        package="com.google.android.notepad">
        android:label="@string/app_name">
        android:authorities="com.google.provider.NotePad"/>
    
    
    
    
    
    

    
    
    
    
    
    
    

    
    
    
    
    

    

    
    
    
    
    
    
    
    
    
    
    
    

    

        android:theme="@android:style/Theme.Dialog">
    
    
    
    
    
    
    
    
    

    

    
    例子中的第一个activity是com.google.android.notepad.NotesList。它是进入应用的主入口(mainentry),具有三种功能,分别由三个intent模板进行描述。
    1、第一个功能是进入便笺应用的顶级入口。它的类型是android.app.category.LAUNCHER,说明这个应用应该在Launcher中被列出。
    2、第二个功能用来浏览可用的便笺,或者让用户选择一个特定的便笺并且把这个便笺返回给调用者。当数据类型是vnd.android.cursor.dir/vnd.google.note(便笺记录的目录)的时候,执行动作android.app.action.VIEW可以浏览可用的便笺;执行动作android.app.action.PICK可以让用户选择便笺。
    3、第三个功能返回给调用者一个用户选择的便笺。当数据类型是vnd.android.cursor.dir/vnd.google.note的时候,执行动作android.app.action.GET_COUTENT调用者不需要知道
    有了这些功能,就能够将下列intents匹配到NotesList的activity:
    {action=android.app.action.MAIN}.如果activities能够被用作进入应用的顶级入口,就可以和这个intent进行匹配。
    {action=android.app.action.MAIN,category=android.app.category.LAUNCHER}.这是目前Launcher实际使用的intent,构成了它的顶级列表。
    问题:怎么构成??
    {action=android.app.action.VIEWdata=content://com.google.provider.NotePad/notes}.显示"content://com.google.provider.NotePad/notes"下所有便笺的列表,用户可以遍历这个列表
    ,并且察看便笺的详情。
    {action=android.app.action.PICKdata=content://com.google.provider.NotePad/notes}.让用户在"content://com.google.provider.NotePad/notes"之下的便笺列表中选择一个,然后将这个便笺的URL返回给调用者。
    {action=android.app.action.GET_CONTENTtype=vnd.android.cursor.item/vnd.google.note}.这个intent和上面的pick动作类似,不同的是这个intent允许调用者(仅仅)指定它们需要的数据类型(,而不需要了解数据存放的详细位置,即数据的URI)。系统根据这个数据类型选择恰当的activity,然后让用户选择某些数据。
    
    第二个activity是com.google.android.notepad.NoteEditor,它为用户显示一个单独的便笺,并且允许用户对这个便笺进行修改。它具有两个intent模板,所以具有两个功能。第一个操作是主要的操作,允许用户察看和编辑一个便签(执行android.app.action.VIEW和android.app.action.EDIT动作,数据类型是vnd.android.cursor.item/vnd.google.note)。第二个模板可以让调用者显示创建新便笺的用户界面,并且将新便笺插入到便笺列表中(执行android.app.action.INSERT动作,数据类型是vnd.android.cursor.dir/vnd.google.note)。
    有了这两个功能,下列intents就能够匹配到NotesList的activity:
    {action=android.app.action.VIEWdata=content://com.google.provider.NotePad/notes/{ID}}向用户显示标识为ID的便笺。将标识为ID的便笺缩写为note{ID},下同。
    {action=android.app.action.EDITdata=content://com.google.provider.NotePad/notes/{ID}}让用户能够编辑notes{ID}。
    {action=android.app.action.INSERTdata=content://com.google.provider.NotePad/notes}创建一个新的便笺,新便笺被创建在“content://com.google.provider.NotePad/notes”所表示的便笺列表中。用户可以编辑这个便签。当用户保存这个便笺后,这个新便笺的URI将会返回给调用者。
    
    最后一个activity是com.google.android.notepad.TitleEditor,它可以让用户编辑便笺的标题。它可以被实现为一个类,在intent中明确设定component属性后,应用可以直接调用这个类;不过在这里我们展示的是如何在已有数据上发布可选操作。这个activity只有一个单独的intent模板,它具有一个私有action:com.google.android.notepad.action.EDIT_TITLE,允许用户编辑便笺的标题。和前面的view和edit动作一样,调用这个intent的时候,也必须指定具体的便笺。不一样的是,这里显示和编辑的只是便笺数据中的标题。
    除了支持确省类别(defaultcategory,android.intent.category.DEFAULT,原文是android.intent.category.VIEW,有误),标题编辑器还支持另外两个标准类别:android.intent.category.ALTERNATIVE和android.intent.category.SELECTED_ALTERNATIVE。实现了这两个类别之后
    ,其它activities可以调用函数queryIntentActivityOptions(ComponentName,Intent[],Intent,int)查询这个activity支持的actions,而不需要了解它的具体实现;或者调用addIntentOptions(int,int,ComponentName,Intent[],Intent,int,Menu.Item[])建立动态菜单。需要说明的是,这个intent模板有一个明确的名称(通过android:label="@string/resolve_title"指定)。在用户浏览数据的时候,如果这个activity是数据的一个可选操作,指定明确的名称可以为用户提供一个更好控制界面。有了这个功能,下列intents就能够匹配到NotesList的activity:{action=com.google.android.notepad.action.EDIT_TITLEdata=content://com.google.provider.NotePad/notes/{ID}}显示并且允许用户编辑note{ID}的标题。
    
    Activity的标准动作(Actions)
    下面是Intent为启动activities定义的标准动作,一般使用startActivity(Intent)启动activities。其中最重要也是最经常使用的是MAIN_ACTION和EDIT_ACTION.
    üMAIN_ACTION
    üVIEW_ACTION
    üEDIT_ACTION
    üPICK_ACTION
    üGET_CONTENT_ACTION
    üDIAL_ACTION
    üCALL_ACTION
    üSENDTO_ACTION
    üANSWER_ACTION
    üINSERT_ACTION
    üDELETE_ACTION
    üRUN_ACTION
    üLOGIN_ACTION
    üCLEAR_CREDENTIALS_ACTION
    üSYNC_ACTION
    üPICK_ACTIVITY_ACTION
    üWEB_SEARCH_ACTION
    
    标准的广播动作(broadcaseactions)
    下面是Intent为接收广播而定义的动作。可以通过registerReceiver(IntentReceiver,IntentFilter),或者在manifest中增加receiver标记来注册。
    üTIME_TICK_ACTION
    üTIME_CHANGED_ACTION
    üTIMEZONE_CHANGED_ACTION
    üBOOT_COMPLETED_ACTION
    üPACKAGE_ADDED_ACTION
    üPACKAGE_REMOVED_ACTION
    üBATTERY_CHANGED_ACTION
    
    标准类别
    下面是已定义的标准类别。通过addCategory(String)可以为I, ntent设置类别。
    üDEFAULT_CATEGORY
    üBROWSABLE_CATEGORY
    üTAB_CATEGORY
    üALTERNATIVE_CATEGORY
    üSELECTED_ALTERNATIVE_CATEGORY
    üLAUNCHER_CATEGORY
    üHOME_CATEGORY
    üPREFERENCE_CATEGORY
    üGADGET_CATEGORY
    üTEST_CATEGORY
    
    标准附加数据
    下面是已定义的标准字段,用来在putExtra(String,Object)中为Intent设置附加数据。
    üTEMPLATE_EXTRA
    üINTENT_EXTRA
    
    启动标记(launchflags)
    下面是Intent中可能用到的启动标记,通过setLaunchFlags(int)和addLaunchFlags(int)使用这些标记。
    üNO_HISTORY_LAUNCH
    üSINGLE_TOP_LAUNCH
    üNEW_TASK_LAUNCH
    üMULTIPLE_TASK_LAUNCH
    üFORWARD_RESULT_LAUNCH
    
    嵌套类
    Intent.FilterComparison持有一个Intent对象,并且为
    过滤实现了Intent的比较操作。
    
    常量
    Values
    StringADD_SHORTCUT_ACTION动作:在系统中添加一个快捷方式。."android.intent.action.ADD_SHORTCUT"
    StringALL_APPS_ACTION动作:列举所有可用的应用。
    输入:无。"android.intent.action.ALL_APPS"
    StringALTERNATIVE_CATEGORY类别:说明activity是用户正在浏览的数据的一个可选操作。"android.intent.category.ALTERNATIVE"
    StringANSWER_ACTION动作:处理拨入的电话。"android.intent.action.ANSWER"
    StringBATTERY_CHANGED_ACTION广播:充电状态,或者电池的电量发生变化。"android.intent.action.BATTERY_CHANGED"
    StringBOOT_COMPLETED_ACTION广播:在系统启动后,这个动作被广播一次(只有一次)。"android.intent.action.BOOT_COMPLETED"
    StringBROWSABLE_CATEGORY类别:能够被浏览器安全使用的activities必须支持这个类别。"android.intent.category.BROWSABLE"
    StringBUG_REPORT_ACTION动作:显示activity报告错误。"android.intent.action.BUG_REPORT"
    StringCALL_ACTION动作:拨打电话,被呼叫的联系人在数据中指定。"android.intent.action.CALL"
    StringCALL_FORWARDING_STATE_CHANGED_ACTION广播:语音电话的呼叫转移状态已经改变。"android.intent.action.CFF"
    StringCLEAR_CREDENTIALS_ACTION动作:清除登陆凭证(credential)。"android.intent.action.CLEAR_CREDENTIALS"
    StringCONFIGURATION_CHANGED_ACTION广播:设备的配置信息已经改变,参见Resources.Configuration."android.intent.action.CONFIGURATION_CHANGED"
    CreatorCREATOR无无
    StringDATA_ACTIVITY_STATE_CHANGED_ACTION广播:电话的数据活动(dataactivity)状态(即收发数据的状态)已经改变。"android.intent.action.DATA_ACTIVITY"
    StringDATA_CONNECTION_STATE_CHANGED_ACTION广播:电话的数据连接状态已经改变。"android.intent.action.DATA_STATE"
    StringDATE_CHANGED_ACTION广播:日期被改变。"android.intent.action.DATE_CHANGED"
    StringDEFAULT_ACTION动作:和VIEW_ACTION相同,是在数据上执行的标准动作。"android.intent.action.VIEW"
    StringDEFAULT_CATEGORY类别:如果activity是对数据执行确省动作(点击,centerpress)的一个选项,需要设置这个类别。"android.intent.category.DEFAULT"
    StringDELETE_ACTION动作:从容器中删除给定的数据。"android.intent.action.DELETE"
    StringDEVELOPMENT_PREFERENCE_CATEGORY类别:说明activity是一个设置面板(developmentpreferencepanel)."android.intent.category.DEVELOPMENT_PREFERENCE"
    StringDIAL_ACTION动作:拨打数据中指定的电话号码。"android.intent.action.DIAL"
    StringEDIT_ACTION动作:为制定的数据显示可编辑界面。"android.intent.action.EDIT"
    StringEMBED_CATEGORY类别:能够在上级(父)activity中运行。"android.intent.catego
    ry.EMBED"
    StringEMERGENCY_DIAL_ACTION动作:拨打紧急电话号码。"android.intent.action.EMERGENCY_DIAL"
    intFORWARD_RESULT_LAUNCH启动标记:如果这个标记被设置,而且被一个已经存在的activity用来启动新的activity,已有activity的回复目标(replytarget)会被转移给新的activity。160x00000010
    StringFOTA_CANCEL_ACTION广播:取消所有被挂起的(pending)更新下载。"android.server.checkin.FOTA_CANCEL"
    StringFOTA_INSTALL_ACTION广播:更新已经被确认,马上就要开始安装。"android.server.checkin.FOTA_INSTALL"
    StringFOTA_READY_ACTION广播:更新已经被下载,可以开始安装。"android.server.checkin.FOTA_READY"
    StringFOTA_RESTART_ACTION广播:恢复已经停止的更新下载。"android.server.checkin.FOTA_RESTART"
    StringFOTA_UPDATE_ACTION广播:通过OTA下载并安装操作系统更新。"android.server.checkin.FOTA_UPDATE"
    StringFRAMEWORK_INSTRUMENTATION_TEST_CATEGORY类别:Tobeusedascodeundertestforframeworkinstrumentationtests."android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST"
    StringGADGET_CATEGORY类别:这个activity可以被嵌入宿主activity(activitythatishostinggadgets)。"android.intent.category.GADGET"
    StringGET_CONTENT_ACTION动作:让用户选择数据并返回。"android.intent.action.GET_CONTENT"
    StringHOME_CATEGORY类别:主屏幕(activity),设备启动后显示的第一个activity。"android.intent.category.HOME"
    StringINSERT_ACTION动作:在容器中插入一个空项(item)。"android.intent.action.INSERT"
    StringINTENT_EXTRA附加数据:和PICK_ACTIVITY_ACTION一起使用时,说明用户选择的用来显示的activity;和ADD_SHORTCUT_ACTION一起使用的时候,描述要添加的快捷方式。"android.intent.extra.INTENT"
    StringLABEL_EXTRA附加数据:大写字母开头的字符标签,和ADD_SHORTCUT_ACTION一起使用。"android.intent.extra.LABEL"
    StringLAUNCHER_CATEGORY类别:Activity应该被显示在顶级的launcher中。"android.intent.category.LAUNCHER"
    StringLOGIN_ACTION动作:获取登录凭证。"android.intent.action.LOGIN"
    StringMAIN_ACTION动作:作为主入口点启动,不需要数据。"android.intent.action.MAIN"
    StringMEDIABUTTON_ACTION广播:用户按下了“MediaButton”。"android.intent.action.MEDIABUTTON"
    StringMEDIA_BAD_REMOVAL_ACTION广播:扩展介质(扩展卡)已经从SD卡插槽拔出,但是挂载点(mountpoint)还没解除(unmount)。"android.intent.action.MEDIA_BAD_REMOVAL"
    StringMEDIA_EJECT_ACTION广播:用户想要移除扩展介质(拔掉扩展卡)。"android.intent.action.MEDIA_EJECT"
    StringMEDIA_MOUNTED_ACTION广播:扩展介质被插入,而且已经被挂载。"android.intent.action.MEDIA_MOUNTED"
    StringMEDIA_REMOV
    ED_ACTION广播:扩展介质被移除。"android.intent.action.MEDIA_REMOVED"
    StringMEDIA_SCANNER_FINISHED_ACTION广播:已经扫描完介质的一个目录。"android.intent.action.MEDIA_SCANNER_FINISHED"
    StringMEDIA_SCANNER_STARTED_ACTION广播:开始扫描介质的一个目录。"android.intent.action.MEDIA_SCANNER_STARTED"
    StringMEDIA_SHARED_ACTION广播:扩展介质的挂载被解除(unmount),因为它已经作为USB大容量存储被共享。"android.intent.action.MEDIA_SHARED"
    StringMEDIA_UNMOUNTED_ACTION广播:扩展介质存在,但是还没有被挂载(mount)。"android.intent.action.MEDIA_UNMOUNTED"
    StringMESSAGE_WAITING_STATE_CHANGED_ACTION广播:电话的消息等待(语音邮件)状态已经改变。"android.intent.action.MWI"
    intMULTIPLE_TASK_LAUNCH启动标记:和NEW_TASK_LAUNCH联合使用,禁止将已有的任务改变为前景任务(foreground)。80x00000008
    StringNETWORK_TICKLE_RECEIVED_ACTION广播:设备收到了新的网络"tickle"通知。"android.intent.action.NETWORK_TICKLE_RECEIVED"
    intNEW_TASK_LAUNCH启动标记:设置以后,activity将成为历史堆栈中的第一个新任务(栈顶)。40x00000004
    intNO_HISTORY_LAUNCH启动标记:设置以后,新的activity不会被保存在历史堆栈中。10x00000001
    StringPACKAGE_ADDED_ACTION广播:设备上新安装了一个应用程序包。"android.intent.action.PACKAGE_ADDED"
    StringPACKAGE_REMOVED_ACTION广播:设备上删除了一个应用程序包。"android.intent.action.PACKAGE_REMOVED"
    StringPHONE_STATE_CHANGED_ACTION广播:电话状态已经改变。"android.intent.action.PHONE_STATE"
    StringPICK_ACTION动作:从数据中选择一个项目(item),将被选中的项目返回。"android.intent.action.PICK"
    StringPICK_ACTIVITY_ACTION动作:选择一个activity,返回被选择的activity的类(名)。"android.intent.action.PICK_ACTIVITY"
    StringPREFERENCE_CATEGORY类别:activity是一个设置面板(preferencepanel)。"android.intent.category.PREFERENCE"
    StringPROVIDER_CHANGED_ACTION广播:更新将要(真正)被安装。"android.intent.action.PROVIDER_CHANGED"
    StringPROVISIONING_CHECK_ACTION广播:要求pollingofprovisioningservice下载最新的设置。"android.intent.action.PROVISIONING_CHECK"
    StringRUN_ACTION动作:运行数据(指定的应用),无论它(应用)是什么。"android.intent.action.RUN"
    StringSAMPLE_CODE_CATEGORY类别:Tobeusedasansamplecodeexample(notpartofthenormaluserexperience)."android.intent.category.SAMPLE_CODE"
    StringSCREEN_OFF_ACTION广播:屏幕被关闭。"android.intent.action.SCREEN_OFF"
    StringSCREEN_ON_ACTION广播:屏幕已经被打开。"android.intent.action.SCREEN_ON"
    StringSELECTED_ALTERNATIVE_CATEGORY类别:对于被用
    户选中的数据,activity是它的一个可选操作。"android.intent.category.SELECTED_ALTERNATIVE"
    StringSENDTO_ACTION动作:向data指定的接收者发送一个消息。"android.intent.action.SENDTO"
    StringSERVICE_STATE_CHANGED_ACTION广播:电话服务的状态已经改变。"android.intent.action.SERVICE_STATE"
    StringSETTINGS_ACTION动作:显示系统设置。输入:无。"android.intent.action.SETTINGS"
    StringSIGNAL_STRENGTH_CHANGED_ACTION广播:电话的信号强度已经改变。"android.intent.action.SIG_STR"
    intSINGLE_TOP_LAUNCH启动标记:设置以后,如果activity已经启动,而且位于历史堆栈的顶端,将不再启动(不重新启动)activity。20x00000002
    StringSTATISTICS_REPORT_ACTION广播:要求receivers报告自己的统计信息。"android.intent.action.STATISTICS_REPORT"
    StringSTATISTICS_STATE_CHANGED_ACTION广播:统计信息服务的状态已经改变。"android.intent.action.STATISTICS_STATE_CHANGED"
    StringSYNC_ACTION动作:执行数据同步。"android.intent.action.SYNC"
    StringTAB_CATEGORY类别:这个activity应该在TabActivity中作为一个tab使用。"android.intent.category.TAB"
    StringTEMPLATE_EXTRA附加数据:新记录的初始化模板。"android.intent.extra.TEMPLATE"
    StringTEST_CATEGORY类别:作为测试目的使用,不是正常的用户体验的一部分。"android.intent.category.TEST"
    StringTIMEZONE_CHANGED_ACTION广播:时区已经改变。"android.intent.action.TIMEZONE_CHANGED"
    StringTIME_CHANGED_ACTION广播:时间已经改变(重新设置)。"android.intent.action.TIME_SET"
    StringTIME_TICK_ACTION广播:当前时间已经变化(正常的时间流逝)。"android.intent.action.TIME_TICK"
    StringUMS_CONNECTED_ACTION广播:设备进入USB大容量存储模式。"android.intent.action.UMS_CONNECTED"
    StringUMS_DISCONNECTED_ACTION广播:设备从USB大容量存储模式退出。"android.intent.action.UMS_DISCONNECTED"
    StringUNIT_TEST_CATEGORY类别:应该被用作单元测试(通过testharness运行)。"android.intent.category.UNIT_TEST"
    StringVIEW_ACTION动作:向用户显示数据。"android.intent.action.VIEW"
    StringWALLPAPER_CATEGORY类别:这个activity能过为设备设置墙纸。"android.intent.category.WALLPAPER"
    StringWALLPAPER_CHANGED_ACTION广播:系统的墙纸已经改变。"android.intent.action.WALLPAPER_CHANGED"
    StringWALLPAPER_SETTINGS_ACTION动作:显示选择墙纸的设置界面。输入:无。"android.intent.action.WALLPAPER_SETTINGS"
    StringWEB_SEARCH_ACTION动作:执行web搜索。"android.intent.action.WEB_SEARCH"
    StringXMPP_CONNECTED_ACTION广播:XMPP连接已经被建立。"android.intent.action.XMPP_CONNECTED"
    StringXMPP_DISCONNECTED_ACTION广播:XMPP连接
    已经被断开。"android.intent.action.XMPP_DISCONNECTED"
    [编辑公共构造函数]
    PublicConstructor
    Intent()创建空的intent对象。
    Intent(Intento)拷贝构造函数。
    Intent(Stringaction)用指定的动作创建intent对象。
    Intent(Stringaction,ContentURIuri)创建intent对象,指定动作和数据(URI)。
    Intent(ContextpackageContext,Classcls)创建intent对象,指定component。
    Intent(Stringaction,ContentURIuri,ContextpackageContext,Classcls)创建intent对象,指定动作、数据和组件。
    
    公共方法
    PublicConstructor
    IntentaddCategory(Stringcategory)向intent添加新的类别。
    IntentaddLaunchFlags(intflags)向intent添加新的启动标记。
    booleanfilterEquals(Intentother)判断两个intent是否相等:检查他们是否有完全相同的意图(用于过滤)。
    intfilterHashCode()生成intent的哈希代码,该代码与filterEquals有同样的语义,即能用于进行intent比较。
    StringgetAction()获取intent要执行的动作,如:VIEW_ACTION。
    SetgetCategories()获取intent对象所属的所有类别(集合)。
    ComponentNamegetComponent()获取intent关联的具体组件。
    ContentURIgetData()获取intent对象要操作的数据(URI)。
    ObjectgetExtra(Stringname,Objectdef)获取intent的扩展数据。
    ObjectgetExtra(Stringname)获取intent的扩展数据。
    BundlegetExtras()获取intent的扩展数据map。
    staticIntentgetIntent(Stringuri)由URI创建Intent。
    intgetLaunchFlags()获取intent的所有启动标记。
    StringgetScheme()获取intent中数据的sheme。
    StringgetType()获取intent明确声明的数据类型(显式声明的MIME类型,不是推导出来的类型)。
    booleanhasCategory(Stringcategory)Intent是否指定了类别。
    IntentputExtra(Stringname,Objectvalue)向intent添加扩展数据。
    voidputExtras(Intentsrc)将src中的所有扩展数据复制到intent中。
    voidputExtras(Bundleextras)向intent添加扩展数据。
    voidreadFromParcel(Parcelin)无。
    voidremoveCategory(Stringcategory)从intent删除一个类别。
    voidremoveExtra(Stringname)从intent删除扩展数据。
    ComponentNameresolveActivity(PackageManagerpm)取得用来处理这个intent的activity组件。
    ActivityInforesolveActivityInfo(PackageManagerpm)取得用来处理这个intent的activity的信息(PackageManager.ActivityInfo)。
    StringresolveType(ContentResolverresolver)取得intent的MIME数据类型。(判断顺序:intent明确指定的类型;intent数据隐式包含的数据类型)
    StringresolveType(Contextcontext)取得intent的MIME数据类型。(判断顺序:intent明确指定的类型;intent数据隐式包含的数据类型)
    StringresolveTypeIfN
    eeded(ContentResolverresolver)如果resolver需要,返回intent的数据类型,否则返回空。
    IntentsetAction(Stringaction)设置intent要执行的动作。
    IntentsetClass(ContextpackageContext,Classcls)设置运行intent的组件,和setComponent功能相同。
    IntentsetClassName(StringpackageName,StringclassName)设置运行intent的组件,和setComponent功能相同。
    IntentsetClassName(ContextpackageContext,StringclassName)设置运行intent的组件,和setComponent功能相同。
    IntentsetComponent(ComponentNamecomponent)设置运行intent的组件。
    IntentsetData(ContentURIdata)设置处理intent的时候要操作的数据。
    IntentsetDataAndType(ContentURIdata,Stringtype)设置intent的数据和数据类型(MIME)。
    IntentsetLaunchFlags(intflags)设置启动标记(用来控制intent被处理的方式)。
    IntentsetType(Stringtype)设置明确的MIME数据类型。
    StringtoString()为intent生成一个可读的字符串描述。
    StringtoURI()无
    voidwriteToParcel(Parcelout)无
    2.2.5Service
    服务是在后台长时间运行的应用组件,不和用户直接进行交互。在每一个服务类的包的AndroidManifest.xml文件中,必须有一个相应的声明。服务必须用Context.startService()或者Context.bindService()启动。
    和其它应用对象一样,服务运行在它们宿主进程的主线程里。这意味着,如果一个服务需要执行阻塞操作(比如网络操作)或者CPU敏感的操作(比如MP3播放器),它应该分离出一个线程来执行这样的操作。
    服务类是应用程序的生命周期中的一个重要部分。在这里要讨论的内容有:
    ?服务的生命周期
    ?访问权限
    ?进程生命周期
    服务的生命周期
    启动服务有两种方法。
    ü如果客户调用Context.startService(),系统将获得服务(如果服务不存在,系统创建服务,然后调用它的onCreate()方法),然后使用调用者提供的参数调用服务的onStart(int,Bundle)方法。从此以后,服务开始持续运行,直到Context.stopService()或者stopSelf()被调用。注意:多次调用Context.startService()虽然会导致onStart()被多次调用,但是服务本身不会嵌套(原文如此,应该是说服务的实例只有一个,不会启动多个服务)。所以无论调用多少次Context.startService(),只要调用一次Context.stopService()或者stopSelf(),服务就会停止运行。
    ü客户也可以调用Context.bindService()获得到服务的永久连接。如果服务之前没有启动,一样会创建服务然后调用它的onCreate()方法;但是不会调用它的onStart()方法。服务调用它的getBinder()方法,并且将返回的IBinder对象传递给客户。连接建立以后,
    不管客户是否保留这个IBinder对象的引用,只要连接还存在,服务都会持续运行。通常返回的IBinder对象是一个由AIDL实现的复杂接口。
    服务可以同时被启动和绑定多个连接。在这种情况下,只要服务被启动,或者存在着到这个服务的连接,服务都会持续运行。当两个条件都不满足时,系统调用服务的onDestroy()方法,服务从此被终止。当onDestroy()返回的时候,所有的清理工作(停止线程,取消已经注册的receivers)都已经完成。
    
    访问权限
    对服务的全局访问权限可以通过服务的manifest中的元素指定。这样,其它应用需要在它们的manifest中声明对应的元素,这样才能启动、停止和绑定到服务。
    同时,在执行IPC调用之前,服务可以调用checkCallingPermission(String)对这次IPC调用的权限进行检查。
    关于权限和安全方面的信息,请参考安全模型文档。
    
    进程生命周期
    只要服务被启动或者被客户绑定(建立连接),Android系统就尽可能维护一个进程来作这个服务的宿主。当系统内存不足的时候,系统需要杀死进程来出让内存。这时候在下列情况下,服务的宿主进程具有较高的优先级:
    如果服务已经被启动,它的宿主进程比任何在屏幕上对用户可见的进程都具有更低的优先级;但是比其它所有不可见的进程都具有更高的优先级。通常对用户可见的进程的数量非常少,所以正在运行的服务在绝大多数时候不会被杀死——除非系统的可用内存极其匮乏。
    如果有客户绑定在服务上,服务的宿主进程的优先级至少和客户的优先级一样(不会比客户更低)。这意味着如果客户对用户可见,那么服务本身也会被系统认为对用户可见。
    在服务的宿主进程中运行有其它应用组件,比如activity,可以提高整个进程的优先级,而不是仅仅提高服务本身的优先级。
    [编辑概要]
    [编辑常量]
    Values
    StringTAG"Service"
    [编辑从类android.content.Context继承的常量:]
    ALARM_SERVICE,BIND_AUTO_CREATE,CONTEXT_IGNORE_SECURITY,CONTEXT_INCLUDE_CODE,INFLATE_SERVICE,KEYGUARD_SERVICE,LOCATION_SERVICE,MODE_APPEND,MODE_PRIVATE,MODE_WORLD_READABLE,MODE_WORLD_WRITEABLE,NOTIFICATION_SERVICE,POWER_SERVICE,WINDOW_SERVICE
    [编辑公共构造函数]
    Service()
    Service()
    [编辑公共成员函数]
    公共成员函数
    finalApplicationgetApplication()返回拥有这个服务的应用。
    abstractIBindergetBinder()返回到这个服务的通信通道(communicationchannel)。
    finalvoidstopSelf(intstartId)停止服务,如果它最后一次启动的ID是startID。
    finalvoidstopSelf()如果服务已经启动,则停止服务。
    
    [编辑保护成
    员函数]
    保护成员函数
    voidonCreate()在服务第一次被创建的时候被调用。
    voidonDestroy()在服务不再被使用,需要被删除时被调用。
    voidonStart(intstartId,Bundlearguments)客户调用startService(Intent,Bundle)直接启动服务的时候被调用。Bundle是客户提供的参数,startID是这次服务启动的唯一标识。
    [编辑从类android.app.ApplicationContext继承的方法:]
    applyThemeResource,bindService,broadcastIntent,broadcastIntent,broadcastIntent,checkCallingOrSelfPermission,checkCallingPermission,checkPermission,clearWallpaper,closeExternalStorageFiles,createDatabase,createPackageContext,deleteDatabase,deleteFile,fileList,getAssets,getClassLoader,getContentResolver,getDataDir,getFileStreamPath,getPackageManager,getPackageName,getPackagePath,getResources,getSharedPreferences,getSystemService,getTheme,getWallpaper,openDatabase,openFileInput,openFileOutput,peekWallpaper,registerExternalStorageListener,registerReceiver,registerReceiver,setTheme,setWallpaper,setWallpaper,showAlert,showAlert,showAlert,showAlert,startActivity,startInstrumentation,startService,stopService,unbindService,unregisterReceiver
    [编辑从类android.content.Context继承的方法:]
    bindService,broadcastIntent,broadcastIntent,broadcastIntent,checkCallingOrSelfPermission,checkCallingPermission,checkPermission,clearWallpaper,createDatabase,createPackageContext,deleteDatabase,deleteFile,fileList,getAssets,getClassLoader,getContentResolver,getDataDir,getFileStreamPath,getPackageManager,getPackageName,getResources,getSharedPreferences,getString,getSystemService,getText,getTheme,getWallpaper,obtainStyledAttributes,obtainStyledAttributes,obtainStyledAttributes,obtainStyledAttributes,openDatabase,openFileInput,openFileOutput,peekWallpaper,registerReceiver,registerReceiver,setTheme,setWallpaper,setWallpaper,showAlert,showAlert,showAlert,showAlert,startActivity,startInstrumentation,startService,stopService,unbindService,unregisterReceiver
    [编辑从类java.lang.Object继承的方法:]
    clone,equals,finalize,getClass,hashCode,notify,notifyAll,toString,wait,wait,wait
    [编辑详细资料]
    [编辑常数]
    [编辑]publicstaticfinalStringTAG
    常数值:"Service"
    [编辑公共构造函数]
    [编辑]publicService()
    无
    [编辑公共成员函数]
    [编辑]publicfinalApplicationgetApplication()
    返回拥有这个服务的应用。
    [编辑]publicabstractIBindergetBinder()
    返回到服务的通信通道(communicationchannel)。如果客户没有绑定到服务,返回null。IBinder通常是一个复杂接口(参见AIDL)。
    返回值返回一个IBinder对象,客户可以通过它调用服务(的功能)。
    [编辑]publicfinalvoidstopSelf(intstartId)
    如果服务最后一次启动的ID是startID,则停止服
    务。这个函数和调用stopService(Intent)有同样的结果,但是如果客户发起了新的启动请求,而请求还没有进入到onStart(int,Bundle),这个函数可以避免停止服务。
    参数startId:最后一次启动时在onStart(int,Bundle)中收到的启动标识(ID)。
    参考stopSelf()
    [编辑]publicfinalvoidstopSelf()
    如果服务已经被启动,则停止服务,和stopService(Intent)有同样的效果。参见stopSelf(int)
    [编辑保护成员函数]
    [编辑]protectedvoidonCreate()
    在服务第一次被创建时被调用。
    [编辑]protectedvoidonDestroy()
    服务不再被使用而且需要被删除的时候被调用。服务在这里清理所有它占有的资源,包括线程、已经注册的receivers等。函数返回后,不应该再调用这个服务的任何方法。事实上,服务已经中止。
    [编辑]protectedvoidonStart(intstartId,Bundlearguments)
    在客户每次调用startService(Intent,Bundle)直接启动服务的时候被调用。
    参数startId:表示这次启动请求的整数标识。可以用在stopSelf(int)中。arguments:客户在startService(Intent,Bundle)中提供的Bundle。可以为空。
    参见stopSelf(int)
    2.2.6NotificationManager
    2.2.7ContentProvider
    Contentproviders是Andorid应用的重要构建模块,它提供应用间共享所需要的数据。ContentProviders数据封装后,通过ContentResolver接口给应用进行访问。只有在应用间共享数据时,Contentprovider才是需要的。例如,联系人信息可能被很多应用引用,这时,有必要将数据保存在ContentProvider中。如果不需要在应用间共享数据,你可直接将通过SQLiteDatabase保持在数据库中。
    
    2.3数据存储与检索(共享数据的方法)
    典型的桌面操作系统提供一种公共文件系统——任何应用软件可以使用它来存储和读取文件,该文件也可以被其它的应用软件所读取(也许会有一些权限控制设定)。Andorid采用了一种不同的系统:在Android,所有的应用软件数据(包括文件)为该应用软件所私有。然而,Android同样也提供了一种标准方式供应用软件将私有数据开放给其它应用软件。这一章节描述一个应用软件存储和获取数据、开放数据给其它应用软件、从其他应用软件请求数据并且开放它们的多种方式
    Android提供如下机制以存储和获取数据。
    参数
    一个轻量级的存储和获取机制,采用一对简单的数据类型:key和value。它的典型应用是存储应用软件参数。
    文件
    你可以将文件存储在手机或可移动存储媒介中。默认其他程序不可访问这些文件。
    数据库
    AndroidAPI包含有对SQLite的支持。你的应用程序可以创建并使用一个私有SQLite数据库。每个数据库为创建它的包所私有。
    内容提
    供器
    内容提供器是一个开放私有数据读写权限的可选组件。受限于该私有数据想施加的任何约束。内容提供器执行标准的数据请求语句、通过标准的数据访问机制返回数据。Android提供了多种针对标准数据类型的内容提供器,例如个人通讯录。
    网络
    不要忘记你同样可以使用网络来存储和获取数据
    2.3.1参数
    你可以存储应用软件启动时需要载入的参数,例如默认问候语或文本字体。调用Context.getSharedPreferences()读取和写入参数值,如果你想将参数共享给包内的其它组件,请为参数分配一个名字。或者使用Activity.getPreferences()和无名参数以对调用保持私有。你不能跨越包将参数共享。
    这里是一个为计算器静音按键模式设置用户参数的例子。
    publicclassCalcextendsActivity{
    publicstaticfinalStringPREFS_NAME="MyPrefsFile";
    ...
    @Override
    protectedvoidonCreate(Bundlestate){
    super.onCreate(state);
    
    ...
    
    //Restorepreferences
    SharedPreferencessettings=getSharedPreferences(PREFS_NAME,0);
    booleansilent=settings.getBoolean("silentMode",false);
    setSilent(silent);
    }
    
    @Override
    protectedvoidonStop(){
    super.onStop();
    
    //Saveuserpreferences.WeneedanEditorobjectto
    //makechanges.Allobjectsarefromandroid.context.Context
    SharedPreferencessettings=getSharedPreferences(PREFS_NAME,0);
    SharedPreferences.Editoreditor=settings.edit();
    editor.putBoolean("silentMode",mSilentMode);
    //Don'tforgettocommityouredits!!!
    editormit();
    }
    }
    
    2.3.2使用文件
    Android提供接口去读写一个软件的本地文件的streams。调用Context.openFileOutput()和Context.openFileInput(),使用本地文件名和路径去读写文件。另一个软件调用这些方法时使用同样的文件名和路径字符串将无法工作。你只能访问本地文件。如果你有静态文件需要在编译时同软件一起打包,你可以把文件保存在工程的res/raw/下,并且可以用Resources.openRawResource(R.raw.mydatafile)来获取它。
    取自"androidcn.net/wiki/index.php/Devel/data/files"
    2.3.3SQLite数据库
    Android支持SQLite数据库系统并开放数据库管理函数,这使你可以将复杂的数据集合储存到有用的对象中。例如,Android定义了一种由字符串型、字符串型地址、数字型电话号码、一个位图图像和多种其它个人信息描述字段组成的通讯录数据类型。使用Context.createDatabase()和Context.openDatabase()创建读写数据库和适当的读写数据(注意:位图这样的文件数据与本地文件路径一样,以文件路径字符串值形式存放在数据库中)
    Android整合sqlite3数据库工具,允许你在SQLite数
    据库中浏览表内容、运行SQL命令并执行其它有用的函数。
    SQLite及其它的所有的数据库,被储存于/data/data//databases
    创建多少表、包含多少字段、如何连接,已经超越了这篇文档的讨论范围,但是Android没有施加任何越过SQLiteconcepts的限制。我们极力推荐包含一个如唯一ID的自增字段以快速查找记录。对于私有数据,这并不需要。但是如果你使用一个内容提供器,你必须包括一个类似唯一ID的字段。请参考NotePad示例程序中的示例类NotePadProvider.java,那是一个创建和组装新数据库的例子。任何数据库可以凭借数据库名被该软件中的任何一个类访问,但不能在该软件范围外访问。
    2.3.4内容提供器
    访问内容提供器
    如果希望公开你的数据,你可以创建(或调用)一个内容提供器。这是一个可以从所有应用软件中存储和获取数据的对象。这也是穿越包共享数据的唯一方式——没有供所有包共享数据的公共存储区域。Android整合了基于多种公共数据类型(音频、视频、图像、个人通讯录信息等等)的内容提供器。你可以在provider包中看到许多Android自带的内容提供器。
    实际数据储存的方式取决于它对接口的具体实现。但是所有内容提供器必须执行公共协议去请求数据和返回结果。内容提供器可以使用自定义帮助器功能使被开放的指定数据更容易被存储/获取。
    使用内容提供器存储和获取数据
    这一节阐述你或其他任何人如何使用内容提供器存储和获取数据。Adnroid为广泛的数据类型开放了多种数据提供器,从音乐文件、图像文件到电话号码。你可以从有用的android.provider包中看到一个开放的内容提供器列表。
    Android的内容提供器被客户端宽松地连接。每一个内容提供器开放一个唯一的字符串(URI)来识别将要操作的数据类型,客户端必须使用该字符串来存储和获取相应类型的数据。在《数据请求》章节中我们将对此做更多解释。
    这一节请求下列内容
    请求数据
    制作请求
    请求的返还值
    请求文件
    读取获得的数据
    修改数据
    添加记录
    删除记录
    数据请求
    每一种内容提供器开放一个唯一公共URI(由ContentURI封装),它将被客户端用于从内容提供器请求/添加/更新/删除数据。URI有2种形式:一是指出该类型数据的所有值(例如所有个人通讯录),二是指出该类型数据的特定记录(例如乔?史密斯的联络信息)
    content://contacts/people/从设备返回通讯录列表
    content://contacts/people/23返回通讯录中ID=23的单行记录
    当应用将请求发送到设备,要求获取整体数据(所有电话号码)或指定数据(鲍勃的电话号码)。Android将返回一个包含指定
    行的记录集游标。让我们来看一个假定的请求字符串和结果集(结果已被调整的更清晰一些)。
    请求字符串=content://contacts/people/
    结果:
    _ID_COUNTNUMBERNUMBER_KEYLABELNAMETYPE
    134(425)55566774255556677CaliforniaofficeBullyPulpitWork
    444(212)555-12342125551234NYapartmentAlanVainHome
    454(212)555-66572125556657DowntownofficeAlanVainWork
    534201.555.44332015554433LoveNestRexCarsHome
    
    注意请求字符串不是一个标准的SQL请求,URI字符串描述了返回数据的类型。这个URI由3部分组成:字符串“content://”;一个描述数据类型的段;一个可选的在特定内容范围内某特定记录的ID。这里有一些请求字符串的例子:
    content://media/images从设备返回所有图像的URI
    content://contacts/people/从设备返回通讯录中所有列表的URI
    content://contacts/people/23返回通讯录中ID=23的单行记录
    2.3.5Android网络存储
    除了选择基于设备的存储,你还可以从可用网络存储和恢复数据。要操作网络,你需要使用下列包:
    ·java.net.*
    ·android.net.*
    3开发工具箱
    3.1创建自定义android组件
    Android提供了一套可靠的可视化组件(Viewcomponents,视图组件?)集合,你可以在此基础上构建自己的应用,这个集合中包括的组件有:Button,TextView,EditText,ListView,CheckBox,RadioButton,Gallery,Spinner等等,甚至还包括很多高级的、有着特殊用途的可视化组件,例如AutoCompleteTextView,ImageSwitcher和TextSwitcher.各种布局管理器,如LinearLayout,FrameLayout等等,也派生自View类结构(译注:原文中意指,各种布局管理器以及控制器也可以看作是可视化组件).
    在你的应用程序中,你可以综合运用(combine,联合)这些布局和控制器,让他们展现在屏幕上.在大多数情况下,这对于开发者来说已经足够用了,但是你应该意识到,其实你是可以通过继承来自己扩展这些Views,Layouts甚至是高级的控制器的,而且你也可以创建自己的自定义组件.
    androidcn.net/wiki/index.php/Toolbox/custom-components
    3.2Android中可选的API
    3.2.1定位服务
    3.2.2媒体API
    媒体API可以用来回放MP3或其它音频文件,或是从web上下载的视频。而且媒体API还支持“播放URI”,也就是说,能够播放网络上的流媒体内容。
    code.google/android/toolbox/apis/media.html
    3.2.3OpenGL3D
    Android的主要用户界面框架是一个典型的面向widget的类继承体系。但这只是表面,实际上这个用户界面的底层是一个非常快的带硬件加速的2D和3D的复合引擎。应用程序可以OpenGLESAPI来访问系统的3D功能。
    
    3.2.4底层硬件访问
    Android提供了API来方便应用程序访问底层硬件,例如Bluetooth和WiFi。
    然而,目前SDK还不包括这些API。当发布这些API时,文档也会被相应地更新。
    3.3Android平台的GoogleAPI和Service
    既然Android是一个开放的手机平台,那么任何人都可以DIY他们自己的设备来运行核心Android操作系统。没有任何规定要求运行Android的手机一定要安装Google的软件或一定要和Google有某种关联。
    然而,一些机构或许需要从Google获得一套可选用户应用程序的授权,这些可选的程序使得你能够在你的应用程序中访问Google服务。通常来说,这些可选的用户程序是一套包含在Android的系统基础映像(basesystemimage)中的软件,并随手机一起发行。
    很多设备都会包括这些库,为了方便开发者,我们这里提供了这些API相关的信息。然而,请明确下述列表中的API并不是在所有的Android设备上都可用。如果手机没有安装Google的软件,那么这些库和类也不会在手机上。这样做的结果是,如果你的应用程序需要使用这些API而必要的库又不存在时,你的应用可能就无法安装或正确运行。
    
    MapView
    MapView是一个Android的View对象,通过它第三方的代码可以在手机屏幕上显示和控制GoogleMap。Google的地图应用程序也提供了MapActivity对象,通过这个对象,其它的Activity能够显示某个位置的地图,MapView是MapActivity的一个补充,都可以用来显示地图。下表归纳了这两种方式的区别。
    MapActivity和MapView特性对照表
    特性MapActivityMapView
    Layout嵌入支持不支持(仅支持独立显示)支持
    用户控制的导航支持支持
    代码控制的导航不支持支持
    触发事件被用户代码捕捉不支持支持
    与Activity相比,使用MapView带来的好处是你能够把Map和你的Layout更紧密地集成在一起;例如,你可以封装MapView,形成自定义的控件,也可以在MapView的基础上添加很炫的交互方式(比方说用一个倾斜度传感器来探测用户倾斜设备的角度,从而相应以不同的方向来滚动地图)。MapView的缺点是你需要写更多的代码来使用它;如果你只是想简单地在一个标准的UI控件上显示GoogleMap,那么使用Activity要简单得多。
    
    采用XMPP的P2P服务
    一些应用程序需要在设备与设备之间频繁地交换信息。例如,你可能希望两个设备可以相互发送消息来实现一个交互式的Checker游戏。或者,你也许会开发一个社交应用程序(IM等)来发送一条消息给你的好友。
    实现这种功能的一种途径是发送短消息给其它的手机。通过IntentReceiver,你的手机来接收到数据时,系统会收到通知,转而去检查这些数据是否包含你的应用程序所需要的数据,如果包含,那么系统就将该数据发送给你的应用程序,同时阻止其它应用
    程序直接看到这部分数据。这种机制工作得很好,但是存在两个主要的不足:SMS消息有时候需要好几分钟才能被对方收到,而且用户发送和接受需要付一定费用。如果你在SMS的基础上开发在线游戏,这款游戏很可能慢得让人沮丧,而且对用户来说玩游戏需要花很多钱。
    作为SMS的替代方案,Google提供了一组采用XMPP协议传输消息的API。XMPP包括在线状态通知功能,这就为手机提供了一种很便捷的途径去通知彼此是否在线或是否可以互相发送消息。XMPP还提供了一个和SMS消息传递类似的编程模型,其中消息发送者调用一个Service的一个方法来发送一条消息,接收者通过广播一个Intent来接收消息到达通知。但由于XMPP采用的是一个持续的套接字连接,响应时间要比SMS短得多,从而提供十分流畅的用户体验。
    XMPP仅维持一个到XMPP服务器的连接,所有的XMPP流量--包括标准的XMPP及时消息和点对点的消息传递系统控制命令都在这个连接上进行传输。
    API编程举例
    1SQLite
    1、创建数据库
    SQLiteDatabasedb=Context.createDatabase(DATABASE_NAME,DATABASE_VERSION,0,null);
    2、打开数据库
    Context.openDatabase(DATABASE_NAME,null);
    3、建表
    Db.execSQL();
    4、插入一行
    ContentValuesinitialValues=newContentValues();
    initialValues.put("title",title);
    initialValues.put("body",body);
    db.insert(DATABASE_TABLE,null,initialValues);
    5、删除一行
    Db.delete(DATABASE_TABLE,”rowed=”+rowed,null);
    6、查询所有
    Cursorc=
    db.query(DATABASE_TABLE,newString[]{
    "rowid","title","body"},null,null,null,null,null);
    intnumRows=c.count();
    c.first();
    for(inti=0;i    Rowrow=newRow();
    row.rowId=c.getLong(0);
    row.title=c.getString(1);
    row.body=c.getString(2);
    ret.add(row);
    c.next();
    }
    7、查询一行
    Cursorc=
    db.query(true,DATABASE_TABLE,newString[]{
    "rowid","title","body"},"rowid="+rowId,null,null,
    null,null);
    if(c.count()>0){
    c.first();
    row.rowId=c.getLong(0);
    row.title=c.getString(1);
    row.body=c.getString(2);
    returnrow;
    }else{
    row.rowId=-1;
    row.body=row.title=null;
    }
    8、更新
    ContentValuesargs=newContentValues();
    args.put("title",title);
    args.put("body",body);
    db.update(DATABASE_TABLE,args,"rowid="+rowId,null);
    9、调用
    可在Activity中如此调用:dbHelper=newDBHelper(this)
    学
    习过程中遇到的问题
    1,eclipse中debug与DDMS的关系?DDMS怎么用?
    2,每次应用启动时,模拟器要模拟连网,速度挺慢,能不能省去这步?
    3,有时不能Debug?难道有2个的上限吗?
    4,书写资源文件时如何提示?
    5,DEBUG时表现怪异,不能跟踪源代码?
    本文来自CSDN博客,转载请标明出处:blog.csdn.net/quqi99/archive/2007/12/04/1916553.aspx
    
  • 上一篇资讯: android学习笔记0.0.29
  • 下一篇资讯: Android学习笔记(二)
  • 网学推荐

    免费论文

    原创论文

    浏览:
    设为首页 | 加入收藏 | 论文首页 | 论文专题 | 设计下载 | 网学软件 | 论文模板 | 论文资源 | 程序设计 | 关于网学 | 站内搜索 | 网学留言 | 友情链接 | 资料中心
    版权所有 QQ:3710167 邮箱:3710167@qq.com 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2015 myeducs.Cn www.myeducs.Cn All Rights Reserved
    湘ICP备09003080号