版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
6.1Activity详解6.1.1Activityi的声明周期Activity中最重要的概念就是Activity的生命周期。图6.1是一张Activity的简图。Activity基本上有三种状态,开始、运行和关闭。当Activity被调用的时候,就是开启状态,这个时候会经过几个过程到达运行状态。当用户进行下一步操作的时候,Activity可能会被暂停或者停止,然后经过一段时间到达关闭状态。下一页返回6.1Activity详解当一个Activity在屏幕前端时状态为激活或正在运行,此时该Activity是用户动作的焦点。如果它仍然对用户可见但并没有被操作,它的状态就会转换为暂停。也就是说,另一个Activity在其上方,并且那个Activity是透明的或者未覆盖整个屏幕,因此这个暂停的Activity仍然有一部分显示出来。一个暂停的Activtly依然是活动的(它保存了所有的状态和成员信息并且和窗口管理器连接),但是可以在内存不足时被系统关闭。当一个Activity被另一个Activity完全掩盖时状态为停止。它仍然保存了所有的状态和成员信息。然而,它对用户来说不再可见,因此它的窗口被隐藏,并且在其他地方需要内存的时候常常会被系统kill.上一页下一页返回6.1Activity详解如果一个Activity处于暂停或停止状态,系统可以通过调用finish()方法或者简单点,直接kill进程来将其从内存中丢弃。当它再次显示给用户时,就必须完全重启,并恢复到原来的状态。当一个activity转换状态时,它会通过调用下面的方法来得知改变:voidonCreate(BundlesavedlnstanceState)voidonStart()voidonRestart()voidonResume()voidonPause()voidonStop()voidonDestroy()上一页下一页返回6.1Activity详解所有这些方法都是可以被重写来做状态改变时做适当工作的钩子。在对象第一次被实例化的时候,所有的Activity必须执行onCreale()方法来做初始化工作。许多Activity也实现onPause()来确认数据改变并准备好停止和用户交互。上一页下一页返回6.1Activity详解6.1.2Activity的四种加载模式Android中的Activity就是呈现给用户的一幅视图,Android的一个应用程序就是一个Activity调转到另外一个Activity。从一个Activity跳转到另一个Activity就涉及了Activity的加载。加载一个Activity有四种模式:standardSingleTopSingleTaskSinglelnstance上一页下一页返回6.1Activity详解默认采用的是标准模式(standard),但是可能有些时候需要对加载模式进行修改,可以直接在AndroidManifesl.xml文件中进行修改。例如需要将某个Activity修改为singleTop模式,可以在Activity中添加如下语句:android:launchMode="singleTop"下面就开始介绍这四种加载模式有什么区别。要了解加载模式必须首先清除Android中的Task的概念。可以理解Task为装载Activity的栈,当由一个Activity转向一个新的Activity的时候,新的Activity就在Task中位于这个Activity的上部,这个时候显示的就是这个新的Activity。上一页下一页返回6.1Activity详解standard模式是系统默认的模式,不需要在代码中进行添加语句设置。这种模式下,每次Activity跳转都是在之前的Task中进行。Activity依次压人Task中上一个Activity之上。每次跳转都会创建一个新的Activity实例,即使这次跳转又跳到了自身。如果设计一个程序,Activity的跳转是跳到自身,那么情况就会如图6.2所示。每次都会创建一个新的实例,这样在一个Task内就会堆积多个同样的实例。上一页下一页返回6.1Activity详解singleTop模式和slandand模式类似,也是每次跳转都会创建一个Activity实例,但是如果要跳转到的Activity在当前的Task的顶部,那么就不会重新创建新的实例。也就是说如果像上面举的例子那样,每次跳转的目的Activity都是自身,那么和上面不同的是,不会创建多个Activity实例。Task的堆栈中只会存在一个Activity实例,如图6.3所示。singleTop模式可以解决栈顶多个重复的Activity问题,如果栈顶已经存在Aclivily实例就不会创建新的实例。但是如果栈顶不存在相同的实例,仍然会创建一个新的实例,如图6.4所示,这种情况下singleTop模式和tlandard模式完全一样。上一页下一页返回6.1Activity详解singleTask模式和后面的singleInslance模式都是只创建一个实例的。当intent到来,从一个Activity调转到另一个Activity的时候,需要创建singleTask模式Activity的时候,系统会检查栈里面是否已经有该Activity的实例,如果有直接将intent发送给它。如图6.5所示,如果一个Task已经有A的实例和B的实例,这个时候要从B跳到A,不沦A是否位于栈顶,都直接使用A的实例。singleInslance模式和singleTask模式类似,不同的是singleInslance模式是用来解决多个Task分享同一个Activtly的情况,上面的singleTask是在一个Task中分享同一个Activity.上一页下一页返回6.1Activity详解6.1.3如何使用Activity下面将以一个例子来详细讲解讲述如何使用Activity.第一步:新建一个Android工程,这里命名为ActivityDemo.所有参数如图6.6所示。上一页下一页返回6.1Activity详解第二步:运行上述工程,效果如图6.7所示:核心在Logcat视窗里,打开应用时先后执行了onCreate()->onStart()->onResume三个方法,看一下Logcat视窗如图6.8所示:BACK键:
当按BACK键时,这个应用程序将结束,这时候将先后调用onPause()->onSlop()->onDestory()三个方法,如图6.9所示:上一页下一页返回6.1Activity详解HOME键:
当打开应用程序时,比如浏览器,我正在浏览NBA新闻,看到一半时,突然想听歌,这时候会选择按HOME键,然后去打开音乐应用程序,而当按HOME的时候,Activity先后执行了onPause()->onSlop()这两个方法,这时候应用程序并没有销毁。如图6.10所示:而当再次启动ActivityDemo应用程序时,则先后分别执行了onReslarl()->onSlarl()->onResume()三个方法,如图6.11所示:上一页返回6.2Android的Service6.2.1简介Android开发中,当需要创建在后台运行的程序的时候,就要使用到Service.Service可以分为无限生命和有限生命两种。特别需要注意的是Service跟Activities是不同的(简单来说可以理解为后台与前台的区别),例如,如果需要使用Service的活,需要调用startService从而利用startService()去调用Service中的OnCreate()和onStart()的方法来启动一个后台的Service.启动一个Service的过程如下:context.startService()->OnCreate()->OnStart()->Servicerunning。其中,oncreate()可以进行一些服务的初始化工作,onstart()则启动服务。下一页返回6.2Android的Service停止一个Service的过程如下:context.stop()->onDestory()->Servicestop接下来的实例是一个利用后台服务播放音乐的小例子,点击start运行服务,点击stop停止服务。上一页下一页返回6.2Android的Service6.2.2如何使用Service接下来用代码来说明一下怎么使用Scrvice,这里要讲的是LocalScrvicc也就是自己的一个Service,也可以操作别的应用程序的Service(如果它允许你那么去做的活),这就涉及一个比较麻烦的东西inlcrproccsscotntnunicalion(IPC),在不同的进程中通信的机制。首先要新建一个Service演示程序,如图6.12所示。上一页下一页返回6.2Android的Service跟Activity一样首先要写一个类继承自android.app.Scrvice,在这里叫它AndroidService.main.xml代码如下:上一页下一页返回6.2Android的Service其中用到Notification是为了明显地表明Scrvice存活的状态,这样看上去直观一点,更多关于Notiflcation的内容在UI部分有介绍,现在知道怎么使用就好了。JavaService主程序AndroidService:上一页下一页返回6.2Android的Service像这样,在Service的几个生命周期函数中加了打印log,的语句,方便测试。这个方法是为了让调用者得到这个Service并操作它。Service本身很简单,需要做了什么就在onCreat和onStart里做好了,比如起线程等。再看一下它的调用者,ServiceDemo。上一页下一页返回6.2Android的Service该程序的运行效果如图6.13所示。这里可以看到两种启动方法:start和bind,当然也是通过intent调用的,在intent中指明指定要启动的Service的名字,stop也一样用来把Activity和特定的Service连接在一起,共同存亡,具体的生命周期细节下一段来讲。上一页下一页返回6.2Android的Service6.2.3Service的声明周期一个Service可以用在两个方面:它可以启动且允许一直运行直到有人停止它,或者它自己停止。在这种模式下,通过调用Context.statlService()启动服务及通过调用Context.stopService()停止服务。服务也可以通过调用Service.stopSelf()或Scrvice.slopSelfResult()停止自己。不管调用了startService多少次,仅需要调用一次stopService()停止服务。上一页下一页返回6.2Android的Service通过使用相关接口可以编程地操作服务。客户端建立与Service对象的一个连接及使用该连接调人服务。连接通过调用ContextbindService()建立,通过调用Contcxt.unbindScrvice()关闭。多个客户端可以绑定到同一个服务。如果服务尚未启动,bindService()可以选择启动它.这两种模式并不是完全分离的。可以绑定到一个用startService()启动的服务。例如,一个后台音乐服务可以通过使用定义了音乐播放的Intent对象调用startService()启动。直到后来,用户可能想对播放器做一些控制或者获取当前歌曲的一些信息,一个活动将调用bindService()与服务建立连接。在这种情况下,实际上直到最后一个绑定关闭stopService()并不会停止。上一页下一页返回6.2Android的Service像活动一样,一个服务也有生命周期方法,可以执行监视它的状态改变。但是比活动的生命周期方法更少,只有三个且它们是公有的(public)而不是受保护的(protected)(说明:活动的生命周期方法是受保护的):voidonCreate()voidonStart(Intentintent)voidonDestory()通过这三个方法,可以监视服务生命周期的两个嵌套循环:上一页下一页返回6.2Android的Service服务的整个生命时间(entirelifetime),从调用onCreate)到相应地调用onDestory().像一个活动一样,服务在onCreate()中做一些初始设置,且在其中释放所有的资源。例如,一个音乐播放服务可以在onCreate()中创建线程,然后在onDestory)中停止线程。服务的活跃生命时间(activelifetime),从调用。onStart()开始。这个方法传递参数是传送给startService()的Intent对象。音乐服务将打开Intent,了解播放哪个音乐并且开始播放。没有相应的回调方法,因为服务停止没有onStop()方法。上一页下一页返回6.2Android的Service如果一个服务允许别的绑定到它,有一些额外的回调方法来实现它:IBinderonBind(Intentintent)booleanonUnbind(Intentintent)voidonRebind(Intentintent)图6.14解释了服务的回调方法.上一页返回6.3BroadcastReceiver6.3.1BroadcastReceiver介绍BroadcastReceiver是对发送出来的Broadcast进行过滤接收井响应的一类组件。Android广泛地使用广播Intent来广播系统事件,如电池电量,网络连接和未读短信,来电等。Intent则是用来连接以上各个组件,并在其间传递消息。BroadcastReceiver用于监听广播Intent。为了激活一个BroadcastReceiver,需要在代码或在程序manifest中注册。当注册一个BroadcastReceiver时,必须使用IntentFiller来指定要监听哪个Intent.下一页返回6.3BroadcastReceiver为了创建一个新的BroadcastReceiver,需要扩展BroadcastRecciver类,并重写onReceiver事件处理函数,如下面的框架代码所示:上一页下一页返回importandroid.content.BroadcastReceiver;importandroid.contentContext;importandroid.contentIntentpublicclassMyBroadcastReceiverextendsBroadcastReceiver{@OverridepublicvoidonReceive(Contextcontext,Intentintent){//TODO:ReacttotheIntentreceived.}}6.3BroadcastReceiver当广播的Intent与注朋1的接收器的IntentFiller匹配时,onReceiver方法会执行。onReceive处理函数必须在5秒内完成,否则会显示应用程序无响应的对活框。在Intent广播的时候,注册有BroadcastReceiver的应用程序不需要正在运行。它们在有匹配的广播Intent时自动启动。这对于资源管理来说,是极好的,因为它允许创建可以被关闭或杀死的事件驱动应用程序,而此刻又以安全的方式对广播事件做出响应。典型的,BroadcastReceiver会更新内容、启动服务、更新Activity的UI或使用通知管理器来通知用户。5秒的执行限制确保了主进程不能或者说不应该在BroadcastReceiver中直接结束。上一页下一页返回6.3BroadcastReceiver一个应用程序可以有任意多个BroadcastReceiver,从而响应这个应用程序认为重要的任何一个广播通知。所有的receiver都继承于BroadcastReceiver这个父类。6.3.2实现一个BroadcastReceiver接下来的例子显示了如何实现一个BroadcastReceiver:上一页下一页返回6.3BroadcastReceiver下面要做的是在程序的manifest中注册。为了在程序的manifest中包含一个BroadcastReceiver,通过在application节点增加一个receiver标签,并指定要注册的BroadcastReceiver的类名。receiver节点需要包含一个intcnt一filer标签来指定要监听的动作字符串,如下面的XML片段所示:上一页下一页返回receiverandroid:name=<Lifeform=etectedBroadcastReceiver"><intent-filter>actionandroid:name=<com.paad.action.NEW_LIFEFORM"/></intent-filter></receiver>6.3BroadcastReceiver以这种方式注册的BroadcastReceiver将总是处于活跃状态。然后就是在代码中注册。可以在代码中控制BroadcastReceiver的注册。这种做法的典型例子就是receiver用来在Activity中更新UI元素。一个好的习惯是当Activity不可见(或不活跃)时,反注册BroadcastReceiver。下面的代码片段显示了如何使用一个IntentFiller注册BroadcastReceiver上一页下一页返回//Createandregisterthebroadcastreceiver.IntentFilterfilter=newIntentFilter(NEW_LIFEFORM_=ETECTE=);Lifeform=etectedBroadcastReceiverr=newLifeform=etectedBroadcastReceiver();registerReceiver(r,filter);6.3BroadcastReceiver为了取消注册一个BroadcastReceiver,在程序上下文中使用unregisterReceiver方法,传人一个BroadcastReceiver实例,如下所示:6.3.3Broadcast的发送和接收过程下面介绍一下Android发送Broadcast和使用BroadcastReceiver过滤接收的过程:上一页下一页返回UnegisteReceive(r);6.3BroadcastReceiver首先在需要发送信息的地方,把要发送的信息和用于过滤的信息(如Action,Category)装人一个Inlent对象,然后通过调用Context.sendBroadcast(),sendOrderBroadcast()或sendStickyBroadcast()方法,把Intent对象以广播方式发送出去。注册BroadcastReceiver有两种方式:静态的在AndroidManifest.xml中用<receiver>标签声明注册,并在标签内用<intent一filler>标签设置过滤器.动态的在代码中先定义并设置好一个InlenlFiller对象,然后在需要注册的地方调Context.registerBroadcast()方法,如果取消时就调用Context.unregisterBroadcast()方法。上一页下一页返回6.3BroadcastReceiver另外,若在使用sendBroadcast()的方法是指定了接收权限,则只有在AndroidManifest.xml中用<uses一permission>标签声明了拥有此权限的BroascastReceiver才会有可能接收到发送来的Broadcast.同样,若在注册BroadcastReceiver时指定了可接收的Broadcast的权限,则只有在包内的AndroidManifest.xtnl中用<uses一permission>标签声明了,拥有此权限的Context对象所发送的Broadcast才能被这个BroadcastReceiver所接收。动态注册上一页下一页返回IntentFilterintentFilter=newIntentFilter();intentFilter.addAction(String);6.3BroadcastReceiver此为BroadcaslReceiver指定(BroadcaslReceiver,intentFiller);action使之用于接收同action的广播registerReceiver一般来说在,onStart中注册一个Receiver,onStop中使用unregisterReceiver来取消注册。发送广播消息使用“extendsService"。指定广播目标action使用如下方法:一旦指定了此action的receiver会接收此广播。在Intent中需传递参数(可选)可以使用putExtra(),最后使用sendBroadcast(Intent)发送一个广播。上一页下一页返回IntentIntent=newIntent(action-String)6.3BroadcastReceiver
BroadcaslReceiver没有UI界面。但是,它们可以启动一个Activity去响应它们接收到的消息。或者,它们用NotificationManager去提示用户。有很多的途径可以提醒用户关注这些Notifications让backlight闪烁,产生手机震动,播放背景声音等等。通常的做法是:在statusbar上面,放置一个不会消失的图标,用户通过这样一个图标,就能够得到这个消息。常见的一个实例是:游戏打开的时候,如何监听来电,让用户去接听电活,基本的代码结构如下:上一页下一页返回6.3BroadcastReceiver在Manifest中添加一些权限和intentFiller:上一页下一页返回6.3BroadcastReceiver6.3.4BroadcastReceiver的例子在此再做两个例子来让读者更深刻的理解BroadcaslReceiver:1.BroadcastReceiver接收系统自带的广播(1)建立一个项目Lesson2lBroadcastReceiver,拷贝一首音乐进res/raw目录。(2)建立Hc1loBroadcaslReceiver.java内容如下:上一页下一页返回6.3BroadcastReceiver(3)在AndroidManifest.xml中注册此receiver上一页下一页返回6.3BroadcastReceiver(4)发布程序,启动模拟器,可以在Logcat中看到如图6.15所示:同时能听到音乐播放的声音,说明确实接收到了系统启动的广播事件,并做出了响应。2.自定义广播下面学习自己制作一个广播。我们接着刚才的例子,继续写下去.(5)在MainBroadcastReceiver.java中填写如下代码:上一页下一页返回6.3BroadcastReceiver(6)更改HelloBroadcastReceiver.java内容如下:上一页下一页返回6.3BroadcastReceiver(7)更改AndroidManifest.xml内容如下:上一页下一页返回6.3BroadcastReceiver(8)运行程序,点击如图6.16中的按钮,查看如图6.17的LogCat,并听听声音。上一页返回第7章Android的数据存储7.1SharedPreferences的使用7.2SQLite的使用7.3ContentProvider的使用7.4文件存储7.5网络存储7.1SharedPreferences的使用SharedPreferences的介绍和使用方法SharedPreferences是几种数据存储方式中最简单的一种。它是以键值对来存储应用程序的配置信息的一种方式,因此只能存储基本数据类型。比如用一个String类型的字符串标识"key”对应一个inl数据“100”组成一个键值对这样的方式来存储信息。SharedPreferences的信息存取是通过读写XML文件的方式进行的,一个程序的XML配置文件只能在本程序所在的包中使用,不能被其他的包读写。SharedPreferences常用在如记录登录系统中的用户名和密码等简单的数据存储。表7.1为获取SharedPreferences对象的两个方法:下一页返回7.1SharedPreferences的使用由表7.1可以看出,获取SharedPreferences对象的方法很简单,只需要使用getPreferences()方法,即可根据传人的模式值和配置文件的文件名参数获取到SharedPreferences对象。在获取到SharedPreferences对象之后才能对对象进行读写操作。如果要读取配置文件信息,直接调用对象的getString()方法,即可根据Key值获取到相应的参数值,而如果要写人配置信息,首先要调用edit()方法使对象处于可编辑状态,这个时候才能调用puIBLring)方法将配置信息写人SharedPreferences对象,配置完成后调用cornrnit()方法提交配置文件,完成SharedPreferences对象的配置。上一页下一页返回7.1SharedPreferences的使用7.1.2SharedPreferences示例程序这里以一个登录框的用户名和密码的例子来介绍如何使用SharedPreferences来存储简单的信息。在DBSharedPreferences的创建过程onCreate()方法中使用getSharedPreferences()方法来获取SharedPreferences对象,并调用getString()来获取到NAME和PWD键值对应的数据值,完成通过SharedPreferences读取配置文件的数据的过程。在对象的onSlop)方法中,获取到SharedPreferences的对象settingsJ占,使用sellings的。edit()方法使对象处于可编辑状态,然后将输人框中输人的用户名和密码通过对象的putString()方法记录在配置文件,最后调用对象的commit()方法完成配置文件的写人。上一页下一页返回7.1SharedPreferences的使用上一页下一页返回7.1SharedPreferences的使用main.xml文件中添加了两个TextView用来显示“用户名”和“密码”,两个EditText用来记录用户名和密码信息。第一次运行程序,结果如图7.1所示:上一页下一页返回7.1SharedPreferences的使用可以看到用户名和密码栏都是空的,在用户名输人123456,密码栏也输人123456。退出后再次运行,效果如图7.2所示:通过DDMS的文件浏览功能可以看到,data/data/com.bit.capture4.SharePrefetneces/sharedprefs目录下有一个记录配置信息的SETTINGInfos.xtnl文件,而文件名正是我们在调用getSharedPreferences()方法时传人的name参数。如图7.3所示:将SETTINGInfos.xml文件导出,查看其中的内容,如图7.4所示,可以看到保存了两个string对象,分别是用户名和密码以及其对应的值。上一页返回7.2SQLite的使用7.2.1SQLite简介
SQLite是一个开源的嵌人式关系数据库,从2000年发布以来已经取得了很大的成功,在很多领域都得到了广泛的应用。SQLite嵌人到使用它的应用程序中,和应用程序共用相同的进程空间,能有效地减少管理数据的开销,还具有可移植性好,容易使用,高效且可靠的特点。Android在运行时(run一tlime)集成了SQLite,所以每个Android应用程序都可以使用SQLile数据库。另外由于SQLite采用了SQL语言,所以对于熟悉SQL语言的人来说,掌握SQLite数据库非常容易。下一页返回7.2SQLiIe的使用7.2.2SQLite的CURDAndroid提供了一个名为SQLiteDataba、的类,该类封装了一些操作数据库的API,使用该类可以完成对数据进行添加(Create}、查询(Retrieve)、更新(Update)和删除(Delete)操作(这些操作简称为CRUD)o学习SQLiteDatabase,应该重点掌握execSQL)和rawQuery()方法。execSQL()方法可以执行inSert,delete,update和CREATETABLE之类有更改行为的SQL语句;rawQuery)方法可以执行select语句。SQLiteDatabase还专门提供了对应于添加、删除、更新、查询的操作方法:insert()、delete()、update()和query()。但是一般都不使用这些方法,直接使用execSQL()和rawQuery()方法执行SQL语句就能完成数据的添加、删除、更新、查询操作。上一页下一页返回7.2SQLiIe的使用7.2.3SQLite创建、更新数据表
Android不自动提供数据库。在Android应用程序中使用SQLite,必须自己创建数据库,然后创建表、索引,填充数据。Android系统为用户提供了一个名为S}SQLiteOpenHelper的类,该类用于对数据库版本进行管理,该类是一个抽象类,必须继承它才能使用。为了实现对数据库版本进行管理,SQLiteOpenHelper类有两种重要的方法,分别是onCreate(SQLiteDatabasedb)和onUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion),用来完成数据库的创建和更新。要对数据库进行创建表、删除表、插人数据和删除数据等操作的时候,需要首先获取一个SQLiteDatabase实例,这可以通过DaltebaseHelper的getWritableDatabase()方法或者getReadableDalabase()方法实现。上一页下一页返回7.2SQLiIe的使用除了这两种方法,还应该特别注意SQLiteOpenHelper的构造函数,SQLiteOpenHelper的构造函数调用父类完成,需要传人四个参数,分别是上下文环境、数据库名字、一个可选的游标工厂(通常是NULL)、一个代表正在使用的数据库模型版本的整数。如下所示:要对数据库进行创建表、删除表、插人数据和删除数据等操作的时候,需要首先获取一个SQLiteDatabase实例,这可以通过DaltebaseHelper的getWritableDatabase()方法或者getReadableDalabase()方法实现。上一页下一页返回Super(Contextcontext,Stringname,SQLiteDatabase.CursorFactoryfactory,intversion)7.2SQLiIe的使用getWritableDatabase()方法用于创建或者打开一个可读写的数据库实例,第一次调用getWritableDatabase()方法来获取一个数据库实例的时候会调用DalebaseHelper的onCreate(SQLiteDatabase),onUpgrade(SQLiteDatabase,int,int)或者onOpen(SQLiteDatabase)方法用来创建、更新或者打开一个数据库实例。数据库对象创建后就会保存在缓存中,方便再次调用。不再使用该数据库对象的时候要调用close)方法从缓存中销毁数据库对象一旦出现没有权限或者磁盘已满的情况,将会导致调用此方法失败,所以需要考虑异常处理。上一页下一页返回7.2SQLiIe的使用getReadableDalabase()和getWritableDatabase()方法一样,会返回一个可读写的数据库实例。不同的是在发生磁盘已满等错误的时候,方法调用并不会失败,而是返回一个只读的数据库实例。如果错误解决后,调用getWritableDatabase()来创建数据库实例,会关闭此只读数据库并创建一个可读写数据库。上一页下一页返回7.2SQLiIe的使用7.2.4SQLite示例程序我们编写一个简单的实例来演示对SQLite的应用。上一页下一页返回7.2SQLiIe的使用</LinearLayout>执行效果如图7.5所示:打开应用程序后进人如图7.5所示的画面:点击“插人两条记录”,会提示插人两条数据失败,这是因为这个时候数据表还没有建立,没法在其中插人记录。需要首先点击“建立数据表”按钮建立数据表,然后才能在数据表里插人记录。插人两条记录后如图7.6所示:插人了两条记录,这个时候查询数据库可以看到数据表里有两条记录,删除一条记录后,再查询,只剩下了一条记录,如图7.7所示。上一页返回7.3ContentProvider的使用7.3.1ContentProvider简介ContentProvider是Android系统中的一种数据共享方式,是Android系统的一个重要组成部分。在前面讲过SharedPreferences保存的数据只能在本包中被使用,而SharedPreferences提供了在应用程序之间共享数据的方式,通过它可以实现不同应用程序之间的数据共享。ContentProvider屏蔽了具体底层数据源的细节,在内部可以用Android支持的任何手段进行数据的存储和操作。例如,通过ContentProvider,可以使用通过SQLiteDatabase数据库在不同应用程序之间共享数据。下一页返回7.3ContentProvider的使用有两种方式来为其他应用程序共享自己的数据:比较直接的方法是通过新建一个ContentProvider的子类的方法创建一个自己的数据共享源;如果已经有一个共享源和自己的数据类型相同并且自己具有写权限,那么就可以考虑将数据添加到已有的共享源上。上一页下一页返回7.3ContentProvider的使用7.3.2ContentResolverContentProvider提供数据I司共享的接口是ContentResolver,ContentResolver类中提供对数据的具体操作的方法,括数据的添加、删除、修改和查询等操作。要获ContentResolver取对象,可以使用Activity提供的getContentResolver()方法,如下所示:上一页下一页返回ContrntRrsolvrrcr=grtContrntRrsolvrr();7.3ContentProvider的使用Android系统会完成所有ContentProvider的实例化工作,不用我们手动来为ContentProvider实例化一个对象。事实上,Android系统为每一种类型的ContentProvider仅实例化了一个对象,但是这个对象可以和多个来自不同应用程序和不同进程的ContentResolver通信。ContentResolver主要使用insert,delete,update,query等方法,来完成数据的操作。这些函数的说明如表7.2所示:7.3.3数据模型和URIContentProvider的数据在数据库中以表的形式存在,每一行代表一条记录,每一列是同一类型和意义的数据。例如一个关于通讯录的表如表7.3所示:上一页下一页返回7.3ContentProvider的使用每一条记录都包含一个唯一标识的ID.ID用来匹配并找到需要的数据,例如通过ID在一张表中找到一个人的电话号码,并在另一张表中找到此人的图片。每一次数据查询返回的Cursor对象可以使用特定方法来读取数据表的任意内容。ContentProvider中另一个很重要的内容就是URI。类似于访问Internet上资源时使用到的URL,URI是ContentProvider对外提供自己数据集的唯一标识符,其他应用程序正是通过URI找到要使用的ContentProvider,Android系统中为所有的数据源定义了一个CONTENTURI常量。例如,代表用户电活号码信息表的URI和代表用户图片信息表的URI(两者都是由Contacts数据提供源控制)如下所示:上一页下一页返回7.3ContentProvider的使用所有的ConlenlProvider的URI都以“content://”开头,一个URI由以下(图7.8)几部分组成:由A和B就唯一地确定了一个ContentProvider,而C是一个ContentProvider下的不同数据,代表一个数据模型表。而D则代表了数据模型表中ID为D的行。其具体定义如下所示:上一页下一页返回android.provider.Contacts.Phones.CONTENT_URIandroid.provider.Contacts.Photos.CONTENT_URI7.3ContentProvider的使用A;URI的标记(scheme):Android中规定ContentProviderr的标记统一为conlenl;//。B:主机名(或Authority:用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。C:路径(path):可以用来表示要操作的数据,路径的构建应根据业务而定。D:标识(ID):用来和路径一起表示具体的数据。如下所示:口要操作conlacl表中ID为10的记录,可以构建这样的路径:/conlacl/10口要操作conlacl表中ID为10的记录的name字段,可以构建这样的路:contact/10/name口要操作conlacl表中的所有记录,可以构建这样的路径:/contact上一页下一页返回7.3ContentProvider的使用7.3.4ContentProvider的查询常用类简介ContentProvider常用到的三个类是UriMatcher,ContentUrist和ContentResolver。其中UriMatcher和ConlcnlUri*是两个用于操作作的方法。下面分别介绍它们如何使URI的工具类,ContentResolver提供对数据的具体操UriMatcher用于匹配URI,在SDK中介绍的UriMalcher包含的方法如表7.4所示:上一页下一页返回7.3ContentProvider的使用使用UriMatcher之前需要首先新建一个UriMatcher对象使用如下方法,常量UriMatcher.NOMATCH表示不匹配任何路径的返回码(一1)。然后才是调用addURI方法添加URI,添加URI涉及两种格式如下:上一页下一页返回UriMatchersURIMatcher=newUriMatcher(UriMatcher.NO_MATCH);UriMatcher.addURI("com.bit.sqlite.provider.contactprovider"contact",1);UriMatcher.addURI("com.bit.sqlite.provider.contactprovider","contact/#",2)7.3ContentProvider的使用其中第一种只要匹配content://com.bit.sqlite.provider.conlaclprovidcr/contact路径,返回匹配码为1;第二种涉及通配符#,就好像Linnx中的*,表示contact路径下的所有ID,返回匹配码为2上一页下一页返回7.3ContentProvider的使用ContentUris类用于获取URI路径后面的ID部分,它包含了两个比较实用的方法wilhAppendedId(Uri,id)和parseId(Uri),分别用户为路径加上ID和获取路径的ID部分,其定义如表7.5所示:其用法如下所示:上一页下一页返回Uriuri=Uri.parse("content://com.test.provider.personproviderXpierson")UriresultUri=ContentUris.withAppendedId(uri,5)&7.3ContentProvider的使用7.3.5示例程序下面介绍一个使用ContentProvider的简单例子,通过调用getContentResolver方法获取到系统的通信录。上一页下一页返回7.3ContentProvider的使用在通信录里加人如下联系人:中国电信:10000;中国联通:10010;中国移动:10086然后就可以进人到应用程序可以看到图7.9所示界面:上一页返回7.4文件存储Android中读取/写人文件的方法,与Java中的I/)是一样的,提供了openFileInput和openFileInput()方法来读取设备上的文件。但是在默认状态下,文件是不能在不同的程序之间共享的,以上两个方法只支持读取自身应用目录下的文件,读取非其自身目录下的文件将会抛出FileNotFoundException异常。创建的文件存放在/data/data/<packagename>/files目录下。(表7.6)下一页返回7.4文件存储本节主要介绍如何对txt文档进行读写操作。Android中采用Java对文件的读写方式,对文件的读取和存储是以数据流的方式进行的,在操作完要关闭数据流。要读取一个文件,使用如下方式:完成了数据的操作之后,要关闭数据流:上一页下一页返回FilelnputStreamfis=openFileInput("textl.txt");fos.close();7.4文件存储要向一个txt文档写人内容,首先使用如下方法获得一个文件输出流,然后使用对象的写方法,将内容写人文件:FileOutputStreamfos=openFileOutput("textl.txt"',MODE_APPEND);写完文件后,同样需要关闭输出流:上一页下一页返回fos.close();7.4文件存储下面以一个简单的例子来讲述如何进行本地文件的读写。在本例中不指定文件的存储目录,采用系统默认的地址。本例中使用了一个菜单栏,在菜单栏中有三个按钮,分别是保存文件、清空屏幕和读取文件。在UI文件中只需定义一个EditView来输人文本和显示文本。main.xml文件如下所示:上一页下一页返回7.4文件存储使用菜单栏,需要在siring中定义菜单中的选项。本例中需要在siring中定义三个用来在菜单栏中显示的字符串。siring.xml文件如下:上一页下一页返回</??xmlversion="l.O"encoding="utf-8"?><resources>stringname="app_name">FileIOO</string>stringname="menu_read">读文件</string>stringname="menu_write">写文件</string>stringname="menu_delete">清空</string></resources>7.4文件存储在定义好了界面和菜单栏对应的字符后,就要开始完成这些菜单的功能,在FileIO.java文件中声明了一个名为FileIO的Activity,在FileIO的onCreate()方法中输出基本的视图。使用了Activity的onCrealeOptionsMenu()来添加三个菜单栏内容,然后使用onMenuIletnSetected()方法来实现当选择菜单栏中某一项的时候,要实现的功能。菜单栏中一共有以下三项:写文件。将文本框中输人的信息保存在设定的txt文件中。清空。用于清空文本输人框。读文件。从保存的txt文件中读取内容,并输出到文本框中。上一页下一页返回7.4文件存储全部代码如下所示:运行效果如图7.10所示:上一页下一页返回7.4文件存储运行完后,我们可以看到在,dala/dala/com.bit.fileio目录下多了一个files目录,目录中有一个名字为fileiotest.txt文件。如图7.11所示:可以使用DDMS的Pull功能把文件拷贝一份出去,查看文件的内容,正是写人的内容清空屏幕后,点击读文件操作,验证是否为写人内容。另外,由于写模式选择的是不覆盖,所以每次写操作都是在前一次的基础上往后添加。上一页返回7.5网络存储前面介绍的几种方法都是将数据存储到本地,除此之外还可以通过网络实现数据的存储和读取。Android的网络处理包如表7.7所示。下面以一个例子讲述如何使用这些数据包。这个例子要完成的功能就是从一个Web页面上获取到文本信息。用户界面主要包括三部分:一个用来输人网址的EditText;一个用来控制获取网页文本的按钮;一个在数据接收后显示文本的TextView.下一页返回7.5网络存储下面是main.xml文件具体内容:上一页下一页返回7.5网络存储下面就要创建一个Activity,来完成这些UI控件的动作,实现网络数据的读取。
Java文件中的开头部分需要引人一些需要用到的数据包,本例中主要引人和网络数据操作相关的一些数据包,这些在上面的表格中都有简单的介绍。其内容如下:上一页下一页返回7.5网络存储在Activity的onCreat()函数中使用findViewById)方法获得使用到的三个UI控件:EditText,TextView和Button.所有的实现都在按钮的OnClick()中实现,这样当用户点击按钮的时候,就能将EditText中输人的网址的文本内容读取出来,并输出到TextView中。上一页下一页返回7.5网络存储可以直接使用TextView的setText()方法来完成,但是在实际的工程开发中通常不这样做。在实际的环境中,当我们要去完成上面的按钮点击事件并显示的时候,可能还有多个线程正在运行。这个时候如果用户点击按钮的事件处理需要较长时间,一个Activity的跳转如果持续5秒没有成功就会被强制中止。因此需要另外启动一个线程来处理长耗时操作,而主线程则不受其影响,在耗时操作完结发送消息给主线程,主线程再做相应处理。那么线程之间的消息传递和异步处理用的就是Handler。本例中就引人了设计模式的思想,创建了一个message对象并将对象发送给一个Handler实例。以下是全部的代码:上一页下一页返回7.5网络存储上一页下一页返回7.5网络存储在这个例子中,Android应用程序正在和HTTPWeb服务器通信,例如Apache(世界使用排名第一的Web服务器软件)或者Internet信息服务器。点击按钮查看运行的效果,如图7.12所示。点击获取网站信息按钮,可以看到在下面的文本框里显示了网站的文本信息,如图7.13所示。上一页返回第8章Android的GPS系统8.1简述8.2获取NMEA文件8.3使用Android位置基础API读取GPS8.4编写Activity部分代码8.5传递坐标到Google地图8.6增加缩放控制8.7三种视图模式8.1简述本章,将介绍如何使用Android定位的API.学习完了本章将会了解到Android系统是如何与GPS硬件一起工作的,如何使用Android系统的位置API来收集手机当前的位置并把它在屏幕上显示出来。本章的最后将会介一个在Google地图来显示当前位置的例子。使用Android位置基础API
Android的SDK包含了一个用来和(}PS硬件运行进行交互的APIo所以可以基于这个API进行GPS系统的开发。Android平台中并不强行要求包含照相机设备,也没有要求一定要包含GPS设备,但是由于Android平台中包含了相关的API,所以很多型号的手机或者平板电脑都包含了照相机和GPS硬件。下一页返回8.1简述如果使用的是模拟器,并没有(}PS硬件,仍然可以使用DDMS的一些功能来模拟GPS硬件设备。Android在adb服务器中提供了一个文件模拟GPS硬件。这个文件放置在<provider>代表位置信息提供者,Android提供的<provider>是上一页下一页返回data/misc/location/<provider>data/misc/location/gps.8.1简述在具体的provider的文件夹内可以用任何数量的文件保留需要的Android使用的坐标信息。当使用Android模拟器时,可以使用下面类型的文件来储存/找回GPS文体的坐标。每个文件类型都有不同的格式来提供信息给Android位置基础API。常用的有以下三种文件:kmlnmeaTrackkml文件kml文件是一种类html文件,Googl。地图就采用了kml文件来记录地理位置信息。在Android平台上,位置基础的API可以解析记录坐标信息.kml文件来模拟一个GPS.上一页下一页返回8.1简述Google地图可以从Google的网站上获取,下载地址为:http://www.Google.com/earth/index.html要从GoogleEarth创建一个.kml文件,打开GoogleEarth并且导航到一个位置。选择文件一保存一将位置另存为,并选择kml文件类型。在本例中,将导航地点定位到北京理工大学中心教学楼并保存kml文件,如图8.1所示。上一页下一页返回8.1简述下面就是保存的.kml文件的内容。仔细查看<coordinates>标签,那就是Android位置基础API会读取的。可以用GoogleEarth来创建自己的.kml文件来模拟不同的位置。当你想要制作一个相同用户不同位置的活动时,这个是非常有用的。创建.kml文件如此简单使得模拟GPS硬件非常的灵活。上一页返回8.2获取NMEA文件Android提供的在gps文件夹里的文件是一个.nmea文件,.nmea文件是美国国家海洋电子协会(NMEA-TheNationalMarineElectronicsAssocia-tion)制定的一套通讯协议。市面上的许多GPS设备都能输出.nmea文件,这些文件是GPS设备的常用格式并且可以包含多重坐标和海拔,来表现行程和轨迹。本节将会讨沦如何获取并打开这些文件。下一页返回8.2获取NMEA文件获取nmea文件要获取nmea文件,首先需要进行一些操作来产生nmea文件,生成nmea文件有以下三种方法:Google地图中进行定位操作使用DDMS的“LocationControls”功能通过telnet登录.使用geofix发送定位信息然后就可以使用adb工具把文件从服务器中pull到计算机上的一个目录下,pull命令如下:上一页下一页返回adbpull<目标文件路径><本地目录>8.2获取NMEA文件GPS生成的nmea文件位于data/misc/location/gps/nmea,将文件pull到D盘的命令如下:在获取到nmea文件后可以使用记事本或者UlltaEdit打开。上面讲述了如何在Windows环境下获取并打开一个nmea文件,Linux环境下获取nmea文件的方法类似,就不多讲述。在获取到nmea文件后,就可以使用Android位置基础API来创建一个完整特性的活动了。上一页返回adbpulldata/misc/location/gpssnmeaD:\8.3使用Android位置基础API读取GPS在知道如何获取nmea文件后,下面将会介绍如何使用nmea文件识别出用户的位置信息。本节主要介绍一个简单的使用位置基础API的例子。下面将会创建一个简单的Activity。这个Activity将会利用nmea文件得到用户当前的GPS位置,然后将GPS的位置在屏幕上显示出来。通过这个过程,将会了解Android位置基础API的一此基本功能和如何使用这些API。下一页返回8.3使用Android位置基础API读取GPS创建一个GPS的Activity,要完成以下四个步骤:调整许可的权限创建活动的布局书写代码来允许活动运行活动下面就分别讲述这四个过程。上一页下一页返回8.3使用Android位置基础API读取GPS调整许可的权限使用Android位置基础API第一步需要完成的就是调整认可的权限。使用Android位置基础API本身不要求任何特别的许可,但是使用位置基础API来获取GPS位置信息就需要在AndroidManifest.xml文件中添加许可。使用Eclipse有两种方式可以设置许可,第一个是视图化的方式,也就是通过AndroidManifest许可向导来完成设置许可。这种方式比较容易操作,首先,在Eclip、中双击AndroidManifest.xml来打开AndroidManifest综览窗口,可以看到下面有Manifest,Application,Permission,Inslrutnenlalion和AndroidManifesl.xml五个窗口。进人Permission窗口点击添加按钮添加一个UserPermission,如图8.2所示。上一页下一页返回8.3使用Android位置基础API读取GPS然后在后边的name栏中选择要添加的Permission名字,如图8.3所示。本例中需要增加ACCESSFINELOCATION,ACCESSMOCKLOCATION和ACCESSLOCATIONEXTRACOMMANDS三个许可。第二种方法是直接修改AndroidManifest.xml的代码,在上一种方法中打开的视图窗口中,进人到AndroidManifest.xml窗口,然后就可以通过手动编辑AndroidManifest.xml文件在Activity中增加许可。你会需要下面的代码行到AndroidManifest.xml中:上一页下一页返回8.3使用Android位置基础API读取GPS添加了许可后,AndroidManifest文件如下所示,经过前面的学习,我们应该非常熟悉这段代码了。此处跟之前唯一不同的就是包含了三个Permission.上一页下一页返回8.3使用Android位置基础API读取GPS创建布局修改完AndroidManifest.xml文件后,就要开始进行布局的设计,此处需要编辑的布局文件是main.xml,在前面的章节中已经介绍过Android的布局元素,此处要使用这些布局元素来增加一个按钮和四个TextView到布局中,按钮可以从GPS呼叫信息并显示到TextViews中。上一页下一页返回8.3使用Android位置基础API读取GPS按照下面设置按钮,也就是在屏幕的顶部并使用“获取我的位置”作为显示文本。然后开始添加4个TextViews,考虑到4个TextViews要显示成两行,第一行显示“经度”和经度值,第二行显示“纬度”和纬度值。所以可以考虑使用TableLayout的方式来完成,把上面的按钮也加到中。两个一行的TextView可以用TableRaw来包围。这样布局如图8.4所示:上一页下一页返回Buttonandroid:id="@+id/gpsButton"android:1ayoutwidth="fiil_parent"android:1ayoutheight=“wrap_content”android:text=<获取我的位置/>8.3使用Android位置基础API读取GPS其对应的XML文件如下所示:上一页返回8.4编写Activity部分代码在完成布局的设计后就要为布局创建一些动作,这就是下面要做的事情。首先需要一个Activity来显示此布局。然后定义按钮的动作,按钮用来从GPS中获取到用户当前的位置,并将位置信息传递给TextView,以便在屏幕上显示。首先,需要声明包的名字和引人需要使用的包。
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 企业内部治理结构规范制度
- 全国中考物理电磁学基础考点与模拟试题真题
- 数控机床功能部件产业园项目可行性研究报告模板-立项拿地
- 护理跌倒安全标准化
- 护理N1级护理职业素养
- 数据库数据的导入和导出教学设计中职专业课-网站数据库应用技术-SQL Server-计算机类-电子与信息大类
- 输液反应、过敏性休克及管道滑脱应急预案考核试题
- 人教版 (新课标)选修37 静电现象的应用教案设计
- 量具选择试题及答案
- 第5课 点撇教学设计小学书法湘美版三年级下册-湘美版
- (正式版)DBJ46-077-2025 海南省市政工程地基基础设计标准
- 长沙市雅礼教育集团2025学年八年级下期中考试语文试题及答案解析
- 2026年北京化学工业集团有限责任公司校园招聘考试参考试题及答案解析
- 2024年广东佛山市南海区大沥镇镇属企业招聘笔试参考题库含答案解析
- 100部经典好看韩国电影大全
- 新版医院住院病案首页
- 2023年华侨、港澳、台联考高考物理试卷(含解析)
- 2023年广东中山市文化广电旅游局所属事业单位(孙中山故居纪念馆)招考聘用笔试题库含答案解析
- 2023化工总控工(高级)技能理论考试核心题库500题(含各题型)
- 轮毂加工工艺规程及专用车夹具设计
- 售楼部装修施工方案设计
评论
0/150
提交评论