1月 212013
 

  我们有时会在开发中,使用按钮的focus选项来实现类似Tab标签页的效果,当用户按下某个按钮后,这个按钮就显示另外一种被按下的效果,以表示用户当前浏览的是哪种类型数据。允许组件有焦点效果首先要设置focusable属性为true,然后把android:focusableInTouchMode属性也设置为true。

  需要注意的是,当设置组件可以获得焦点的时候,这个组件就不能响应android:onClick事件了,如果你把实现功能的代码写到onClick事件里的话,是不能看到程序执行的。那么这时候我们就得用组件的setOnFocusChangeListener来设置一个事件来监听组件获得和失去焦点的状态,然后把相关的代码放到这个事件里。下面是一个代码片断:

 

  其中hasFocus为true时为组件获得焦点,被按下的状态,为false时为其他组件获得焦点此组件失去焦点时触发。

1月 032013
 

使用TabHost的注意事项:

  1. 在API13 Android3.2之后Android的SDK中提供了ActionBar,可以做出TabHost的效果,而且还有很多其他的功能,所以就不推荐使用TabHost了
  2. 使用TabHost的类必须继承自TabActivity,然后通过getTabHost()来获取界面上的TabHost组件
  3. TabHost在Layout.xml中,id属性必须定义为如下格式:android:id=”@android:id/tabhost”

 

12月 302012
 

有的时候我们需要为自己的程序提供几种不同的界面风格以供不同的用户根据喜好选择使用,在桌面程序中我们通常是使用xml或者ini配置文件来存储配置信息并将不同的皮肤相关图片文件放在不同的目录中实现,在web开中是使用不同的CSS文件来进行此类功能的实现,那么在Android中是如何来实现的呢。

Android中提供了类似css的机制,即Style和Theme。Theme是用于某个Activity或者整个程序中的,Style则是用于Activity中的某个View的。

Android中内置了几个主题比如Theme.Black, Theme.Light, Theme.Light.NoTitleBar, Theme.Holo等。

如何设置主题

我们可以通过在项目的AndroidManifest.xml中的Application或者Activity的节点中静态的设置它的主题,为该节点增加一个android:theme属性即可,具体看下面的例子

如果Activity和Application都设置了android:theme属性,则Activity的属性会把Application中的属性覆盖。如果是设置自定义主题则用如下语法

需要注意的是:对于有些系统内置的主题对sdk版本是有要求的,即android:minSdkVersion中设置的版本要大于等于主题对应的版本才可以使用。

添加自定义主题

系统中内置的主题毕竟很少,那么我们平时开发程序时需要定制自己的主题,以丰富程序的界面。我们可以通过在res/values下新建一个styles.xml来添加自己的主题。styles.xml的结构大致如下

根节点resources为固定的节点。style节点中name属性设置自定义主题的名称,parent属性设置该主题继承自哪个主题。item节点中的name属性为要设置的属性的值,节点中的内容为要设置的值。

 

 

12月 272012
 

Sax其实只是一个封装了对XML支持的字符串解析器,sax不像DOM方法要把文件全部加载到内存后再进行解析,而是一边读取文件内容一边对已读取的内容进行解析,它提供的一些方法比如startDocument, startElement等都是在读取到相关的内容后抛出的事件,以便我们可以在此时将数据存到自己的数据结构中。

因为解析XML的时候,要在一个继承自DefaultHandler的类中进行,所以最好对要解析的XML数据定义一个类,创建这个类的实例数组来接收数据。本例中要使用的XML文件如下:

所以,在实现解码前我先定义了一个类用于传递XML数据

与DOM解析类似,要使用Sax解析必须先创建一个SAXParserFactory,并在此对象中设置一此属性。

SAXParserFactory创建后使用此对象创建一个SAXParser

按说这时候我们该用saxP的Parse方法来解析XML了,但是我们还没负责解析的DefaultHanlder类,让我们转过头来创建一个解析某XML的DefaultHanlder类吧。

注意:在characters中,我们使用的是tmpUData.webSite = tmpUData.webSite.concat(str);,并不是将str直接赋给tmpUData.webSite, 这是因为character并不一定能将节点内的数据一次全部读取完毕,对于长数据是分块一点一点读进来的,所以如果是直接赋值可能造成只取到了最后一部分数据。

用于解析的DefaultHandler类创建好后,我们就可以继续来解析XML文件了,具体代码如下:

 

 

 

 Posted by on 2012-12-27
12月 252012
 

在Android开发中我们可以通过DOM、Sax、Pull这几种方法来操作XML。其中DOM是大家都比较熟悉的方法,如果使用过其他开发工具的人肯定也都用过相应的DOM方法来解析过XML。

要在Android中操作XML必须先要定义一个DocumentBuilderFactory实例,此实例用于设置一些解析时相关的属性,比如是否解析comment类型的节点、是否忽略xml文件内容中的空白字符等,另外比较重要的一点是,它的newDocumentBuilder函数是用来创建一个DocumentBuilder对象的。该类的实例由它本身的一个静态函数newInstance来创建。

创建了DocumentBuilderFactory并设置相关的属性(如果需要)后,我们就可以创建一个DocumentBuilder对象了。DocumentBuilder对象是用来从各种源(输入流、文件、URL、InputSource)中载入XML文档的类,并不负责操作XML中的各节点和属性。

有了DocumentBuilder我们就可以从不同的源中载入xml文档了,我们需要使用Parse函数。如:

如果是要从一个xml字符串中加载xml则可以使用如下方法

也许你是要创建一个全新的XML文档并在此基础上添加数据,那么你可以使用如下代码:

下面代码介绍如何读取XML中的内容,XML文件内容如下:

下面的代码读取XML内容并显示到一个EditText中

 

其中的几个常用的函数为:
getChildNodes(): 获取某节点下的所有子节点
getNodeName(): 获取节点的名称
getAttributes().getNamedItem(“ID”).getNodeValue(): 获取节点中属性名为ID的值
getFirstChild(): 获取某节点下的第一个子节点
getNextSibling(): 获取某个节点的紧邻的下一个节点
getNodeType(): 获取节点的类型,通过需要判断节点类型为Node.ELEMENT_NODE才继续解析,关于xml的节点类型请参考此文章
getTextContent(): 获取某节点中所包括的文本内容

向XML文件中添加数据的代码

 

其他问题:

1. 使用该方法解析xml时出现Unexpected token (position:TEXT @1:2 in java.io.StringReader@40e31480) 的错误,解决办法:因为要解析的xml文件使用的是UTF8带BOM的格式,所以在解析的时候出现错误,将xml的编码格式改为UTF8无BOM格式后问题解决。

 

12月 252012
 

Pull也是一个轻量级的解析xml的类,类似sax,边取边读,占用内存小,避免让app产生oom的问题。

解析使用的类为XmlPullParser,XmlPullParser分节点读取,每到节点的开始或者结尾时会触发相应的事件(event),开发人员可以在这些事件中处理数据,常用到的事件有:START_DOCUMENT、END_DOCUMENT、START_TAG、END_TAG。

Pull方式和sax的区别如下:
1. Pull的解析放在一个函数中就可以了,而sax必须新建一个Handler类来处理xml.
2. 正因为sax需要一个Handler来处理事件,它本身无法控制何时停止解析,而Pull在不需要后面数据的时候可以停止事件处理,退出解析

下面是一个测试xml文件:

下面是使用XmlPullParser解析xml的代码:

 

 

 Posted by on 2012-12-25
11月 092012
 

1. 下载和安装JDK

下载地址:http://www.oracle.com/technetwork/java/javase/downloads/index.html

jdk_down_list

点击链接进入下载页面

接受授权协议并点击相应的版本进行下载

install jdk

运行安装程序,并根据提示一步一步进行安装

2.下载Android SDK

打开页面http://developer.android.com/sdk/index.html下载并安装Android SDK

3. 下载Eclipse

Eclipse下载地址http://www.eclipse.org/downloads/,打开页面根据自己的需要选择相应的版本,初学者可能会对Eclipse的版本非常的迷惑,下面笔者做些简单的介绍

eclipse download list
eclipse download list
A. 安装包的种类

在下载页面,大家可以看到Eclipse IDE for Java EE Developers、Eclipse IDE for Java Developers、Eclipse IDE for C/C++ Developers等等,其实这些不同的安装包都是用的一样的Eclipse核心,不同的是各个包所包含的模块各不相同,具体的模块包含情况大家可以查看这个页面http://www.eclipse.org/downloads/compare.php。大家可以选择适合自己的包进行下载,如果需要其他的模块以后是可以在Eclipse中进行更新下载的。

默认放在第一个的是Eclipse IDE for Java EE Developers,如果不知道选择哪个包就选择这个就可以了。

B. Eclipse的版本和别名
  • Eclipse Juno(2012 – V4.2)
  • Eclipse Indigo(2011 – V3.7)
  • Eclipse Helios(2010 – V3.6)
  • Eclipse Galileo(2009 – V3.5)
  • Eclipse Ganymede(2008 – V3.4)
  • Eclipse Europa(2007 – V3.3)
eclipse download version list
eclipse download version list

具体细节大家可以看这个页面http://wiki.eclipse.org/Older_Versions_Of_Eclipse

4. 下载Eclipse插件For Android

JDK安装完毕,解压Eclipse压缩包,可以启动Eclipse啦!下面介绍如何在Eclipse中下载和安装Android插件的方法。

打开Eclipse,第一次打开的时候后提醒你设置WorkSpace路径,即项目文件默认的存放目录,设置成你自己使用的路径即可。Eclipse打开后,执行菜单Help->Install New SoftWare,这时弹出一个Install窗口,在Work WIth里输入https://dl-ssl.google.com/android/eclipse/,然后点击右边的“ADD”按钮,在弹出的窗口中输入这个更新的名字,名字随意,笔者输入的为”Android SDK”,点“确定”按钮。

此时在Install窗口中间的列表中应该显示可以下载的文件列表,如果列表没有显示出来请使用后面的内容进行处理。

如果列表没有加载进来,说明下载更新信息失败,因为dl-ssl.google.com这个域名在国内被屏蔽了,所以有的时候访问有些问题,可以尝试下面方法解决

a. 修改C:WindowsSystem32driversetchosts文件,在文件内添加一行内74.125.237.1 dl-ssl.google.com

如果下载过程中提示Warning: You are installing software that contains unsigned content. The authenticity or validity of this software cannot be established. Do you want to continue with the installation?直接点OK忽略即可。

选择要安装的项目,点击”Next”按钮,Eclipse检查系统环境,检查完毕再点击“Next”按钮,选中”I accept the terms of the license agreement.”,点击“Finish”按钮就开始下载了。

如果用http地址的方式下载不了,你也可以百度搜索“adt离线包”,点击“Add”按钮后,输入“Name”,然后点击“Archive”按钮,选择下载的离线包进行安装。

其他说明:

1. 如果安装Android SDK时提示没有找到JDK,需要设置环境变量java_home,则按如下方式操作:打开系统环境变量设置,增加系统变量JAVA_HOME值为JDK的路径,如果没有CLASSPATH项,增加CLASSPATH设置值为%JAVA_HOME%lib,如果已经有CLASSPATH则修改此项增加%JAVA_HOME%lib用分号隔开

2. 如果安装完毕后出现一些其他的问题,则下载个旧版本的Eclipse试试

8月 202012
 

* 本例使用ListView和自定义的行部局实现了一个最基本的表格部局
* 和一个可变长度的表格部局
* 并实现的简单的行组件的单击事件

XML文件1 activity_list_view_table.xml

XML文件2 listview_row_basic.xml

XML文件3 listview_row.xml

JAVA代码文件 ListViewTableActivity.java

———————————

点击此下下载源代码

———————————

8月 092012
 

本例主要是使用了Intent对象的隐式调用方式,设置intent的Action, Data和Extra来传递的相关的信息

activity布局代码如下:

类代码如下:

本代码调试环境:

* Eclipse: Indigo Service Release 2
* Android SDK: 4.0(API LEVEL 14)

点击这里下载CallMailApp

注意:

1. 如果你还没有在你的手机或者AVD上创建相关的email帐户,运行此程序时会提示Unsupported action(不支持的Action)!

8月 082012
 

1、为什么要使用service?

在我们开发的应用中,有的时候需要做一些长期运行的任务,比如下载文件、音乐播放器、闹钟或者邮件程序等。由于Android系统会根据系统资源使用情况自动清理闲置的后台程序,所以普通的Activity程序在运行一段时间后就有可能被系统清理掉,不能达到长期运行的效果。而包含service的进程属于优先权比较高的(关于进程的生命周期相关知识请点击这里查看)不容易被系统清理掉,所以对那些应用来说,选择service是必要的。

2、创建一个Service

在工程节点或者包节点上右键,选择”New->Class”,输入包名,类名称,SuperClass输入或者选择android.app.Service,点击ok,创建一个服务类成功,创建完成后初始化代码如下:

创建完成后还无法使用此服务,需要在AndroidManifestXml中声明该服务类,示例如下:

3、服务类的一些重要方法

getApplication()

Return the application that owns this service.
onBind(Intent intent)

Return the communication channel to the service.
onConfigurationChanged(Configuration newConfig)

Called by the system when the device configuration changes while your component is running.
onCreate()

Called by the system when the service is first created.
onDestroy()

Called by the system to notify a Service that it is no longer used and is being removed.
onLowMemory()

This is called when the overall system is running low on memory, and actively running processes should trim their memory usage.
onRebind(Intent intent)

Called when new clients have connected to the service, after it had previously been notified that all had disconnected in itsonUnbind(Intent).
onStart(Intent intent, int startId)

This method was deprecated in API level 5. Implement onStartCommand(Intent, int, int) instead.
onStartCommand(Intent intent, int flags, int startId)

Called by the system every time a client explicitly starts the service by calling startService(Intent), providing the arguments it supplied and a unique integer token representing the start request.
onTaskRemoved(Intent rootIntent)

This is called if the service is currently running and the user has removed a task that comes from the service’s application.
onTrimMemory(int level)

Called when the operating system has determined that it is a good time for a process to trim unneeded memory from its process.
onUnbind(Intent intent)

Called when all clients have disconnected from a particular interface published by the service.
startForeground(int id, Notification notification)

Make this service run in the foreground, supplying the ongoing notification to be shown to the user while in this state.
stopForeground(boolean removeNotification)

Remove this service from foreground state, allowing it to be killed if more memory is needed.
stopSelf()

Stop the service, if it was previously started.
stopSelf(int startId)

Old version of stopSelfResult(int) that doesn’t return a result.
stopSelfResult(int startId)

Stop the service if the most recent time it was started was startId.

4、Service的调用方法

Service可能通过两种方法启动,一种是通过startService另外一种是通过bindService

1) startServie的声明如下:public abstract ComponentName startService (Intent service)

参数说明:service是你要启动的服务对象,通过Intent构造,你可以在Intent对象中加入其他需要的参数,以在服务中使用。执行此函数后,如果服务未启动则系统会创建此服务并执行,如果执行此函数时服务已经在运行,则服务会继续执行。

每次调用startService时都会触发服务内的android.app.Service.onStartCommand方法,此机制提供一个方便的方法通过Intent参数传入一些需要的参数,以避免必须再使用BindService才能实现的功能。

终止由startService启动的服务方法:一种是可以在服务内部调用stopSelf()来停止服务,另一种是在调用startService的context中通过调用stopService来终止

2) bindService声明如下:public abstract boolean bindService (Intent service, ServiceConnection conn, int flags)

参数说明:
service: 是要绑定的服务的实例标识,
conn: 用于接收成功绑定或者结束绑定时的通知,在连接时可以接收service返回的对象,
flags: 为绑定选项,可能为0, BIND_AUTO_CREATE, BIND_DEBUG_UNBIND, BIND_NOT_FOREGROUND, BIND_ABOVE_CLIENT, BIND_ALLOW_OOM_MANAGEMENT, BIND_WAIVE_PRIORITY.

对于由startService启动的服务,也可以使用此函数进行绑定。如果服务没有启动,可以设置flags为BIND_AUTO_CREATE,这样执行此函数时服务会被自动创建。

只有当调用该服务存在的时候系统才认为该服务有必须继续执行代码,比如当调用该服务的Activity停止或者销毁后它绑定的服务也会停止工作。所以在执行长期操作的时候不要在bindService中执行,即不要在Service的onbind函数中启动相应的定时器,否则当activity结束后,该定时器也会不再执行工作,而应该先用startService启动服务,并在服务的onStartCommand中执行定时器操作。

 

注意:

1、在使用一个service前必须在AndroidManifest.xml中定义该服务类名称,如:<service android:name=”Em8CheckerService”></service>