- 浏览: 203874 次
- 性别:
- 来自: 湖南
文章分类
最新评论
什么是3G
3G,全称为3rd Generation,中文含义是指第三代数字通信。
所谓3G,是指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统。3G只是一种通信技术标准,符合这个标准的技术有WCDMA、CDMA2000、TD-SCDMA三种制式。中国联通使用的是WCDMA(世界上大部分3G网络都采用的是该标准);中国电信使用的是CDMA2000(日韩和北美使用);中国移动使用的是具有自主知识产权的TD-SCDMA(只有中国才使用)。相对第一代模式制式手机(1G)和第地代GSM、CDMA等数字手机(2G),3G网络能处理图像、音乐、视频等多种媒体形式,提供包括网页浏览、电话会议、电子商务等多种信息服务,第三代与前两代的主要区别是在传输声音和数据的速度上有很大的提供。
由于3G商务需要相当浩大的工程,要从目前的2G迈向3G不可能一下就衔接得上,因此前几年2.5G的手机就出现了。符合2.5G标准的技术有CDMA2000 1X和GPRS,中国联通使用的是CDMA2000 1X标准,中国移动使用的是GPRS标准。目前,我们可以把2.5G移动通信技术看作是2G迈向3G的衔接性技术,在2.5G网络下出现了WAP、蓝牙(Bluetoot)等技术。
智能手机软件平台有:
Symbian,Windows Mobile(c/c#),RIM BlackBery,Android,iPhone(obgs),Palm,Brew,Java/J2ME.
2009年市场份额:
Symbian 51% (c/c++ 诺基亚)
RIM BlackBerry 18% (java)
iPhone 13.3
Windows Mobile 9.3%
linux 4.6%
Android 1.8% (java)
什么是Android
Android一词的本义指“机器人”,Android是Goodle于07年11月5日宣布的基于Linux平台开源手机操作系统名称,该平台由操作系统、中间件、用户界面和应用软件组成。在国内,联想(Ophone)、戴乐、多普达(首选)、飞利浦、中兴、三星、摩托罗拉(其次)、LG、宇龙酷派、海信、TCL等十余家厂商计划将在09年底推出基于Android平台的智能手机。
在3G应用开发领域,Android的发展前景不容小视,也将会成为未来主流的手机操作系统。
b/s 软件 web软件 android web浏览器是Webkit
c/s 桌面网络应用软件(主流应用)
纯桌面软件(单机软件)
如何安装Android SDK和Eclipse插件
所需要开发环境:
JDK5或JDK6
Eclipse3.5(galileo)
下载ADT的Eclipse插件(ADT)
http://dl.gooogle.com/android/ADT-0.9.5.zip
安装Eclipse插件(ADT)
启动Eclipse,选择Help->InstallNew Software,在出现的对话框里,点击add按钮,在对话框的name一栏输入"ADT",然后点击Archive...,浏览和选择已经下载的ADT插件压缩文件。点击OK。返回可用软件的视图,你会看到这个插件,然后选择Developer Tools(会选中下面的“Android Developer Tools“和“Android Editors"),点击Next,最后重启Eclipse.
下载Android SDK:
http://dl.google.com/android-sdk_r04-windows.zip
下载完成SDK后,把zip文件解压到你电脑上合适位置,启动Eclipse,选择window->preferences,在打开的视图左边点击android,在右边的SDK Location中选择Android SDK所在位置。
android目录结构:
src java源代码
gen 开发工具自动生成
assets 打包文件
res 资源文件
drawable 画版
layout 布局
values 文字资源
AndroidManifest.xml 功能清单文件
default.properties 版本文件。
LinearLayout 线性布局(标签内的每一个标签显示站一行)
xmlns:android="http://schemas.android.com/apk/res/android" 命名空间
android:orientation="vertical" 垂直分布
android:layout_width="fill_parent" 全屏 wrap_content包裹内容
android:layout_height="fill_parent"
TextView 显示文本
android:text="@string/hello" 设置文本内容 @访问静态常量。
android:id="@+id/name" +在R文件中添加一个类为id的属性name的常量
AbsoluteLayout 绝对布局(尽量少用)
RelativeLayout 相对布局
TableLayout 表格布局
FrameLayout 帖布局(多个画面)
1)设计界面
2)设计Activity
3)业务层代码
或
1)业务层代码 (Android junit)
2)设计界面
3)设计Activity
电话拨号实例:
测试步骤
1》在eclipes中运行此应用
2》在Dos窗口中进入android SDK安装路征的tools目录,输入以下命令再开启一个Android模拟器emulator -data cl
注:cl为用户数据存取文件,如果该文件不存在,默认在tools目录创建该文件。
3》在电话器中输入现示的电话号码。
短信权限 <uses-permission android:name="android.permission.SEND_SMS"/>
多行文本显示 android:layout_height="wrap_content"
android:maxLines="3"
1)日志输出
在windown->preferences->Android->DDMS->logging level->Info
在视图中调出LogCat,用它来显示日志信息
为了过滤没必要信息,可以添加一个过滤器,在过滤器创建自己需要显示的标签。
2)单元测试
对应用程序进行单元测试
第一步:首先在AndroidManifest.xml中加入下面部分代码:
<uses-library android:name="android.test.runner" />
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="cn.com.log" android:label="Tests for My App"/>
用例:
3)程序Debug
添加一个断点,运行Debug,在Run执行,step Info进入某个方法,step Over执行一行,Run to Line执行到某一行,step Return跳出某个方法。
同时Debug提供了运行时修改某个值,在Varibles 属性-值
4)数据存取与访问
很多时候我们的软件需要处理后的数据进行存储或者再次访问。
Android为数据存储提供了多种方式,分别有如下几种:
文件
SharedPreference (类似软件配置参数)
SQLite数据库
内容提供者(Content provider)
网络
使用文件进行数据存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与J2SE环境中保存数据到文件中是一样的。
openFileOutput()方法的第一参数用于指定文件名,不能包含路征分隔符“/”,如果说文件不存在,Android会自动创建它。创建的文件保存在/data/data/<package name>/files目录,如:/data/data/cn.com.action/files/test.txt,通过点击Eclipes菜单“window“-”show View“-”Other“,在对话窗口中展开android文件夹,选择下面的File Explorer视图中展开/data/data/<package name>/files目录可以看到该文件。
openFileOutput()方法提供了四种模式,分别是:
Content.MODE_PRIVATE = 0 //私有的
Content.MODE_APPEND = 32768 //追加文本
Content.MODE_WORLD_READABLE = 1 //其它用户可读
Content.MODE_WORLD_WRITEABLE = 2 //其它用户可写
Content.MODE_WORLD_READABLE+Content.MODE_WORLD_WRITEABLE //读写功能(模式可以相加)
实例:
Activity还提供了getCacheDir()和getFileDir()方法:
getCacheDir()方法用于获取/data/data/<package name>/cache目录
getFileDir()方法用于获取/data/data/<package name>/files 目录
把文件存放在SDCard
在模拟器中使用SDCard,你需要创建一张SDCard卡,创建SDCard可以在Eclipes创建模拟器时随同创建,也可以使用DOS命令进行创建,如下:
在DOS窗口中进入android SDK安装路征的tools目录,输入以下命令创建一张容量为2G的SDCard,文件后缀可以随便进取,建议使用.img:
mksdcard 2048M D:\AndroidTool\sdcard.img
在程序中访问SDCard,你需要申请访问SDCard的权限。
在AndroidManifest.xml中加入访问SCDCard的权限如下
SDCard保存的数据是可以被任何人访问
使用SAX或者DOM或者pull读取XML文件。
在Android平台可以使用Simple API for XML(SAX)、Document Object Model(DOM)和Android附带的pull解析XML文件。下面是本例子要解析的XML文件。
文件名为:person.xml
例子定义一个javabean用于存放上面解析来的xml内容,这个javabean为Person,代码请见本页下面备注。
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备,SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHander接口。下面是一些ContentHandler接口常用的方法:
startDocument()
当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument()
和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURL,String localName,String qName,Attributes atts)
当读到一个开始标签的时候,会触发这个方法。namespanceURL就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元素等等其它结构相关信息,都是不得而知的,都需要你的程序来完成,这使得SAX在编程处理上没有DOM来得那么方便。
endElement(String url,String localName,String name)
这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch,int start,int length)
这个方法用来处理在XML文件中读到的内容,第一个参数用于存放文件内容,后面两个参数是讲到的字符串在这个对数中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
只要为ASX提供实现ContentHandler接口类,那么该类可以通知事件(实际上是SAX调用了该类中的回调方法)。因为ContenHander是一个接口,使用的时候可能有些不方便,因此,SAX还为其制定一个Helper类:DefalultHander,它实现了这个接口,但是其所有的方法体都为空,在实现的时候,你只需要继承这个类,然后重载相应的方法即可。使用SAX解析person.xml的代码如下:
使用DOM解析(尽量少用,耗能,文件要比较少)
使用pull解析器读取XML文件
除了可以使用SAX和DOM解析XML文件,也可以使用Android内置的pull解析XML文件,pull解析器的运行方式与SAX解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextTest()方法可以获取下一个Text类型元素的值。
使用pull解析器读取person.xml的代码在如下,
pull解析器的源码及文档下载网址:http://www.xmlpull.org/
读取XML,还有最简单的方法是去拼xml,遇到特殊字符要转译。
使用SharedPrefernces进行数据存储
保存软件参数设置功能,使用SharedPrefence类,其背后是用xml文件存放数据,文件存放/data/data/<package name>/shared_prefs目录下:
其它应用访问
使用嵌入式关系型AQLite数据库存取数据
除了可以使用文件或者sharePreferences存储数据,还可以选择使用SQLite数据库存储数据。
在Android平台上,集成了一个嵌入式关系数据库——SQLite,SQLite3支持NULL、INTEGR、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上SQLite3也接受archar(n),char(n),decimal(p,s)等数据类型,只不过在运算或者保存时会转换成对应的五种数据类型。SQLite最大的特点是你可以保存任何类型的数据到任何字段中,无论这列声名的数据类型是什么,但有一种情况例外,定义为INTERER PRINMARY KEY的字段只能存储64位整数,当向这种字段中保存除整数以外的数据时,将会产生错误。另外,SQLite在解析CREATE TABLE语句时,会忽略CREATE TABLE语句中跟在字段名后面的数据类型信息,如下面语句会忽略name字段信息:
create table person(personid integer primary key autoincrement,name varchar(20));
SQLite可以解析大部分标准SQL语句,如:
查询语句:select * from 表名 where 条件语句 group by 分组 having ... order by 排序子句
如:select * from person
select * from person order by id desc
select name from person group by name having count(*)>1
分页SQL与mysql类似,下面SQL语句获取5条记录,跳过前面3条记录。
select * from Account limit 5 offset 3或者select * from Account limit 3,5
插入语句:insert into 表名(字段列表)values(值列表).如:insert into person(name,age) values("张三",20)
更新语句:update 表名 set 字段名=值 where 条件子句。 如:update person set name="李四" where id=10
删除语句:delete from 表名 where 条件子句。如:delete from person where id=10
使用SQLiteDatabase操作SQLite数据库
android提供了一个名为SQLiteDatabse的类,execSQL()方法可以执行insert、delete、update、和create table之类有更改为行为的SQL语句,rowQuery()方法执行select语句。
使用SQLiteOpenHelper对数据库进行版本管理,数据检测与升级
(菜鸟使用)insert(),delete(),update(),query()方法。
insert()方法用于添加数据,各个字段的数据使用ContentValues进行存放。ContentValues类似于MAP。
多条sql语句时需要事务管理.
ListView显示条目
内容提供者(content provider)。
当应用继承ContentProvider类,并重写该类用于提供数据和存储的方法,就可以向其它应用共享其数据。虽然使用其它方法也可以对外共享数据,但数据访问方式而不同,而使用Contentpreferences共享数据的好处是统一了数据访问方式。
当应用需要通过ContentProvider对外共享数据时,第一步需要继承ContentProvider并且重写下面方法:
第二步需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配制,为了能让其他应用找到该ContentProvider,ContentProvider采用了authorites(主机名/域名)对它进行唯一标识,你可以把ContentProvider看作是一个网站,authorities就是他的域名:
<manifest...>
<application...>
<provider android:name=".PersonContentProvider" android:authorities="cn.com.provider.personprovider" />
</application>
注意:一旦应用继承了ContentProider类,后面我们就会把这个应用称为ContentProvider(内容提供者)。
uri代表了要操作的数据,uri主要包括两部分信息:1》需要操作的ContentProvider,2》对ContentProvider中的什么数据进行操作,一个uri由以下几部分组成:
content://cn.com.personprovider/person/10
ContnetProvider(内容提供者)的scheme已经由Android所规定,scheme为:content://主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
路征(path)可以用来表示我们要操作的数据,路征的构建应根据业务而定,如下:
要操作person表中id为10的记录,可以构建这样的路征:/person/10
要操作person表中id为10的记录的name字段, person/10/name
要操作person表中的所有记录,可以构建这样的路征: /person
要操作xxx表中的记录,可以构建这样的路征:/xxx
当然操作xml文件中的person节点下的name节点,可以构建这样的路征:/person/name
要操作xml文件中person节点下的name节点,可以构建这样的路征:/person/name
如果要把一个字符转换成uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://cn.com.provider.personprovider/person")
UriMatcher类使用介绍
因为Uri代表了要要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据,Android系统提供了两个用于操作Uri的工具类,分别为UriMather和ContentUris,掌握它们的使用,会便于我们的开发工作。
UriMatcher类用于匹配Uri,它的用法如下:
首先第一步肥你需要匹配Uri路征全部注册上,如下:
注册完需要匹配的Uri后,就可以使用sMather.mathch(uri)方法对输入的uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://cn.com.provider.personprovider/person路征,返回的匹配码为1
ContentUris类用于获取Uri路征加上后面的ID部分,它有两个比较实用的方法:
withAppendedld(uri,id)用于为路征加上ID部分:
使用ContentProvider共享数据
ContentProvider类主要方法的作用:
public boolean onCreate() {}
该方法在ContentProvider创建后就会被调用,Android在系统启动时就会创建ContentProvider.
public Uri insert(Uri uri, ContentValues values) {}
该方法用于供外部应用往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs) {}
该方法用于供外部应用往ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {}
该方法用于供外部应用更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {}
该方法用于供外部应用往ContentProvider中获取数据。
public String getType(Uri uri) {}
该方法用于返回当前Uri所代表数据的MIME类型,如果操作属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,例如:要得到所有person记录的Uri为content://cn.com.provider.personprovider/person,那么返回的MIME类型字符串应该为"vnd.android.cursor.dir/person".如果要操作的数据属于单一数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,例如:得到id为10的person记录,uri为content://cn.com.provider.personprovider/person/10,那么返回的MIME类型字符串应该为:"vnd.android.cursor.item/person".
权限设置:<provider... android:permission="" />
权限使用:<uses-permission android:name="" />
实例:
3G,全称为3rd Generation,中文含义是指第三代数字通信。
所谓3G,是指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统。3G只是一种通信技术标准,符合这个标准的技术有WCDMA、CDMA2000、TD-SCDMA三种制式。中国联通使用的是WCDMA(世界上大部分3G网络都采用的是该标准);中国电信使用的是CDMA2000(日韩和北美使用);中国移动使用的是具有自主知识产权的TD-SCDMA(只有中国才使用)。相对第一代模式制式手机(1G)和第地代GSM、CDMA等数字手机(2G),3G网络能处理图像、音乐、视频等多种媒体形式,提供包括网页浏览、电话会议、电子商务等多种信息服务,第三代与前两代的主要区别是在传输声音和数据的速度上有很大的提供。
由于3G商务需要相当浩大的工程,要从目前的2G迈向3G不可能一下就衔接得上,因此前几年2.5G的手机就出现了。符合2.5G标准的技术有CDMA2000 1X和GPRS,中国联通使用的是CDMA2000 1X标准,中国移动使用的是GPRS标准。目前,我们可以把2.5G移动通信技术看作是2G迈向3G的衔接性技术,在2.5G网络下出现了WAP、蓝牙(Bluetoot)等技术。
智能手机软件平台有:
Symbian,Windows Mobile(c/c#),RIM BlackBery,Android,iPhone(obgs),Palm,Brew,Java/J2ME.
2009年市场份额:
Symbian 51% (c/c++ 诺基亚)
RIM BlackBerry 18% (java)
iPhone 13.3
Windows Mobile 9.3%
linux 4.6%
Android 1.8% (java)
什么是Android
Android一词的本义指“机器人”,Android是Goodle于07年11月5日宣布的基于Linux平台开源手机操作系统名称,该平台由操作系统、中间件、用户界面和应用软件组成。在国内,联想(Ophone)、戴乐、多普达(首选)、飞利浦、中兴、三星、摩托罗拉(其次)、LG、宇龙酷派、海信、TCL等十余家厂商计划将在09年底推出基于Android平台的智能手机。
在3G应用开发领域,Android的发展前景不容小视,也将会成为未来主流的手机操作系统。
b/s 软件 web软件 android web浏览器是Webkit
c/s 桌面网络应用软件(主流应用)
纯桌面软件(单机软件)
如何安装Android SDK和Eclipse插件
所需要开发环境:
JDK5或JDK6
Eclipse3.5(galileo)
下载ADT的Eclipse插件(ADT)
http://dl.gooogle.com/android/ADT-0.9.5.zip
安装Eclipse插件(ADT)
启动Eclipse,选择Help->InstallNew Software,在出现的对话框里,点击add按钮,在对话框的name一栏输入"ADT",然后点击Archive...,浏览和选择已经下载的ADT插件压缩文件。点击OK。返回可用软件的视图,你会看到这个插件,然后选择Developer Tools(会选中下面的“Android Developer Tools“和“Android Editors"),点击Next,最后重启Eclipse.
下载Android SDK:
http://dl.google.com/android-sdk_r04-windows.zip
下载完成SDK后,把zip文件解压到你电脑上合适位置,启动Eclipse,选择window->preferences,在打开的视图左边点击android,在右边的SDK Location中选择Android SDK所在位置。
android目录结构:
src java源代码
gen 开发工具自动生成
assets 打包文件
res 资源文件
drawable 画版
layout 布局
values 文字资源
AndroidManifest.xml 功能清单文件
default.properties 版本文件。
LinearLayout 线性布局(标签内的每一个标签显示站一行)
xmlns:android="http://schemas.android.com/apk/res/android" 命名空间
android:orientation="vertical" 垂直分布
android:layout_width="fill_parent" 全屏 wrap_content包裹内容
android:layout_height="fill_parent"
TextView 显示文本
android:text="@string/hello" 设置文本内容 @访问静态常量。
android:id="@+id/name" +在R文件中添加一个类为id的属性name的常量
AbsoluteLayout 绝对布局(尽量少用)
RelativeLayout 相对布局
TableLayout 表格布局
FrameLayout 帖布局(多个画面)
1)设计界面
2)设计Activity
3)业务层代码
或
1)业务层代码 (Android junit)
2)设计界面
3)设计Activity
电话拨号实例:
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, HelloWorldActivity!</string> <string name="app_name">电话拨号器</string> <string name="mobile">请输入手机号</string> <string name="button">拨打</string> </resources>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/mobile" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/mobile" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button" android:id="@+id/button" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.com.andriod" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="3" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".HelloWorldActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.CALL_PHONE"/> </manifest>
package cn.com.andriod; import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class PhoneActivity extends Activity { private EditText mobileTest; private Button mobileButton; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); mobileTest = (EditText) this.findViewById(R.id.mobile); mobileButton = (Button) this.findViewById(R.id.button); mobileButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { String mobile = mobileTest.getText().toString(); Intent intent = new Intent(Intent.ACTION_CALL,Uri.parse("tel:"+mobile)); PhoneActivity.this.startActivity(intent); //内部类,访问外部类方法 } }); } }
测试步骤
1》在eclipes中运行此应用
2》在Dos窗口中进入android SDK安装路征的tools目录,输入以下命令再开启一个Android模拟器emulator -data cl
注:cl为用户数据存取文件,如果该文件不存在,默认在tools目录创建该文件。
3》在电话器中输入现示的电话号码。
短信权限 <uses-permission android:name="android.permission.SEND_SMS"/>
多行文本显示 android:layout_height="wrap_content"
android:maxLines="3"
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">发送短信</string> <string name="mobile">请输入手机号</string> <string name="content">请输入短信内容</string> <string name="button">发送短信</string> <string name="info">发送成功!</string> </resources>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/mobile" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/mobile" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/content" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:maxLines="3" android:id="@+id/content" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/button" android:id="@+id/button" /> </LinearLayout>
package cnc.ocm.android; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.telephony.gsm.SmsManager; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class SMSendActivty extends Activity { private EditText moblieText; private EditText contextText; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); moblieText = (EditText) this.findViewById(R.id.mobile); contextText = (EditText) this.findViewById(R.id.content); Button button = (Button) this.findViewById(R.id.button); button.setOnClickListener(new OnClickListener() { public void onClick(View v) { String mobile = moblieText.getText().toString(); String content = contextText.getText().toString(); SmsManager smsManager = SmsManager.getDefault(); if(content.length() > 70){ List<String> contexts = smsManager.divideMessage(content); for(String sms : contexts){ smsManager.sendTextMessage(mobile, null, sms, null, null); } }else{ smsManager.sendTextMessage(mobile, null, content, null, null); }//Ctrl+T contextText.setText(""); Toast.makeText(SMSendActivty.this, R.string.info, Toast.LENGTH_LONG).show(); } }); } }
1)日志输出
在windown->preferences->Android->DDMS->logging level->Info
在视图中调出LogCat,用它来显示日志信息
为了过滤没必要信息,可以添加一个过滤器,在过滤器创建自己需要显示的标签。
package cn.com.log; import android.app.Activity; import android.os.Bundle; import android.util.Log; public class LogActivity extends Activity { private static final String TAG = "LogActivity"; //shift+ctrl+x @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Log.i(TAG, "LogActivity 被创建了!"); //info级别 } }
2)单元测试
对应用程序进行单元测试
第一步:首先在AndroidManifest.xml中加入下面部分代码:
引用
<uses-library android:name="android.test.runner" />
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="cn.com.log" android:label="Tests for My App"/>
用例:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.com.log" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="3" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <uses-library android:name="android.test.runner" /> <activity android:name=".LogActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="cn.com.log" android:label="Tests for My App"/> </manifest>
package cn.com.log; import android.test.AndroidTestCase; import android.util.Log; public class LogTest extends AndroidTestCase { private static final String TAG = "LogTest"; public void testSave() throws Exception{ int i = 1 + 1; Log.i(TAG,"结果为"+i); } }
3)程序Debug
添加一个断点,运行Debug,在Run执行,step Info进入某个方法,step Over执行一行,Run to Line执行到某一行,step Return跳出某个方法。
同时Debug提供了运行时修改某个值,在Varibles 属性-值
4)数据存取与访问
很多时候我们的软件需要处理后的数据进行存储或者再次访问。
Android为数据存储提供了多种方式,分别有如下几种:
文件
SharedPreference (类似软件配置参数)
SQLite数据库
内容提供者(Content provider)
网络
使用文件进行数据存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与J2SE环境中保存数据到文件中是一样的。
openFileOutput()方法的第一参数用于指定文件名,不能包含路征分隔符“/”,如果说文件不存在,Android会自动创建它。创建的文件保存在/data/data/<package name>/files目录,如:/data/data/cn.com.action/files/test.txt,通过点击Eclipes菜单“window“-”show View“-”Other“,在对话窗口中展开android文件夹,选择下面的File Explorer视图中展开/data/data/<package name>/files目录可以看到该文件。
openFileOutput()方法提供了四种模式,分别是:
Content.MODE_PRIVATE = 0 //私有的
Content.MODE_APPEND = 32768 //追加文本
Content.MODE_WORLD_READABLE = 1 //其它用户可读
Content.MODE_WORLD_WRITEABLE = 2 //其它用户可写
Content.MODE_WORLD_READABLE+Content.MODE_WORLD_WRITEABLE //读写功能(模式可以相加)
实例:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.com.file" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="8" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <uses-library android:name="android.test.runner" /> <activity android:name=".FileActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="cn.com.file" android:label="Tests for My App"/> </manifest>
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">文件管理</string> <string name="FileName">文件名称:</string> <string name="content">文件内容</string> <string name="save">保存</string> <string name="error">保存失败</string> <string name="sucess">保存成功</string> <string name="show">显示内容</string> </resources>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/FileName" android:id="@+id/filelable" /> <EditText android:layout_width="150px" android:layout_height="wrap_content" android:layout_toRightOf="@id/filelable" android:layout_alignTop="@id/filelable" android:layout_marginLeft="10px" android:text="test.txt" android:id="@+id/filename" /> </RelativeLayout> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/content" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:maxLines="3" android:id="@+id/content" /> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/save" android:id="@+id/save" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/save" android:layout_alignTop="@id/save" android:layout_marginLeft="10px" android:text="@string/show" android:id="@+id/show" /> </RelativeLayout> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/result" /> </LinearLayout>
package cn.com.service; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class FileService { /** * 保存数据 * @param outputStream * @param content * @throws IOException */ public static void save(OutputStream outputStream,String content) throws IOException{ outputStream.write(content.getBytes()); outputStream.close(); } /** * 读取数据 * @param inputStream * @return * @throws IOException */ public static String read(InputStream inputStream) throws IOException{ ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); byte [] buffer = new byte[1024]; int len = -1; while((len =inputStream.read(buffer)) !=-1){ outputStream.write(buffer,0,len); } byte[] data = outputStream.toByteArray(); outputStream.close(); inputStream.close(); return new String(data); } }
package cn.com.file; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import android.content.Context; import android.test.AndroidTestCase; import android.util.Log; import cn.com.service.FileService; public class FileServiceTest extends AndroidTestCase { private static final String TAG = "FileServiceTest"; public void testSave() throws Exception{ OutputStream outputStream = this.getContext().openFileOutput("test.txt", Context.MODE_PRIVATE); FileService.save(outputStream,"文件保存!"); } public void testRead() throws Exception{ InputStream inputStream = this.getContext().openFileInput("test.txt"); String content = FileService.read(inputStream); Log.i(TAG,content); } //读取其他应用的有文件 public void testPrivateRead() throws Exception{ File file = new File("/data/data/cn.com.file/files/test.txt"); InputStream inputStream = new FileInputStream(file); String result = FileService.read(inputStream); Log.i(TAG,result); } //写入其它应用的文件 public void testPrivatewrite() throws Exception{ File file = new File("/data/data/cn.com.file/files/test.txt"); OutputStream outputStream = new FileOutputStream(file); FileService.save(outputStream, "this is test"); } }
package cn.com.file; import java.io.InputStream; import java.io.OutputStream; import cn.com.service.FileService; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class FileActivity extends Activity { private static final String TAG = "FileActivity"; private EditText filenameText; private EditText contentText; private TextView resultView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); filenameText = (EditText) this.findViewById(R.id.filename); contentText = (EditText) this.findViewById(R.id.content); Button save = (Button) this.findViewById(R.id.save); Button show = (Button) this.findViewById(R.id.show); resultView = (TextView) this.findViewById(R.id.result); save.setOnClickListener(listener); show.setOnClickListener(listener); } private View.OnClickListener listener = new View.OnClickListener() { public void onClick(View v) { Button button = (Button)v; String filename = filenameText.getText().toString(); switch (button.getId()) { case R.id.save: String content = contentText.getText().toString(); int resId = R.string.sucess; try { OutputStream outputStream = FileActivity.this.openFileOutput(filename, Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE); FileService.save(outputStream,content); }catch (Exception e) { Log.i(TAG,e.toString()); resId = R.string.error; } Toast.makeText(FileActivity.this, resId, Toast.LENGTH_LONG).show(); break; case R.id.show: try { InputStream inputStream = FileActivity.this.openFileInput(filename); String contents = FileService.read(inputStream); resultView.setText(contents); } catch (Exception e) { Log.i(TAG,e.toString()); Toast.makeText(FileActivity.this, "读取失败!", Toast.LENGTH_LONG).show(); } break; } } }; }
Activity还提供了getCacheDir()和getFileDir()方法:
getCacheDir()方法用于获取/data/data/<package name>/cache目录
getFileDir()方法用于获取/data/data/<package name>/files 目录
把文件存放在SDCard
在模拟器中使用SDCard,你需要创建一张SDCard卡,创建SDCard可以在Eclipes创建模拟器时随同创建,也可以使用DOS命令进行创建,如下:
在DOS窗口中进入android SDK安装路征的tools目录,输入以下命令创建一张容量为2G的SDCard,文件后缀可以随便进取,建议使用.img:
mksdcard 2048M D:\AndroidTool\sdcard.img
在程序中访问SDCard,你需要申请访问SDCard的权限。
在AndroidManifest.xml中加入访问SCDCard的权限如下
引用
<!--在SDCard中创建与删除文件权限-->
<uses-permission android:name="android.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--往SDCard写入数据权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--往SDCard写入数据权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
SDCard保存的数据是可以被任何人访问
package cn.com.file; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import cn.com.service.FileService; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Environment; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class FileActivity extends Activity { private static final String TAG = "FileActivity"; private EditText filenameText; private EditText contentText; private TextView resultView; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); filenameText = (EditText) this.findViewById(R.id.filename); contentText = (EditText) this.findViewById(R.id.content); Button save = (Button) this.findViewById(R.id.save); Button show = (Button) this.findViewById(R.id.show); resultView = (TextView) this.findViewById(R.id.result); save.setOnClickListener(listener); show.setOnClickListener(listener); } private View.OnClickListener listener = new View.OnClickListener() { public void onClick(View v) { Button button = (Button)v; String filename = filenameText.getText().toString(); File file =new File(Environment.getExternalStorageDirectory(),filename); //===new File("/sdcard"+filename); switch (button.getId()) { case R.id.save: String content = contentText.getText().toString(); int resId = R.string.sucess; if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ //sdkcar存在,并且可以读写 try { /*OutputStream outputStream = FileActivity.this.openFileOutput(filename, Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);*/ FileOutputStream outputStream = new FileOutputStream(file); FileService.save(outputStream,content); }catch (Exception e) { Log.i(TAG,e.toString()); resId = R.string.error; } Toast.makeText(FileActivity.this, resId, Toast.LENGTH_LONG).show(); }else{ Toast.makeText(FileActivity.this, "SDCard不存在或者安全保护!", Toast.LENGTH_LONG).show(); } break; case R.id.show: try { /*InputStream inputStream = FileActivity.this.openFileInput(filename);*/ InputStream inputStream = new FileInputStream(file); String contents = FileService.read(inputStream); resultView.setText(contents); } catch (Exception e) { Log.i(TAG,e.toString()); Toast.makeText(FileActivity.this, "读取失败!", Toast.LENGTH_LONG).show(); } break; } } }; }
使用SAX或者DOM或者pull读取XML文件。
在Android平台可以使用Simple API for XML(SAX)、Document Object Model(DOM)和Android附带的pull解析XML文件。下面是本例子要解析的XML文件。
文件名为:person.xml
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="23"> <name>张三</name> <age>20</age> </person> <person id="24"> <name>李四</name> <age>21</age> </person> </persons>
例子定义一个javabean用于存放上面解析来的xml内容,这个javabean为Person,代码请见本页下面备注。
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备,SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHander接口。下面是一些ContentHandler接口常用的方法:
startDocument()
当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument()
和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURL,String localName,String qName,Attributes atts)
当读到一个开始标签的时候,会触发这个方法。namespanceURL就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元素等等其它结构相关信息,都是不得而知的,都需要你的程序来完成,这使得SAX在编程处理上没有DOM来得那么方便。
endElement(String url,String localName,String name)
这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch,int start,int length)
这个方法用来处理在XML文件中读到的内容,第一个参数用于存放文件内容,后面两个参数是讲到的字符串在这个对数中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
只要为ASX提供实现ContentHandler接口类,那么该类可以通知事件(实际上是SAX调用了该类中的回调方法)。因为ContenHander是一个接口,使用的时候可能有些不方便,因此,SAX还为其制定一个Helper类:DefalultHander,它实现了这个接口,但是其所有的方法体都为空,在实现的时候,你只需要继承这个类,然后重载相应的方法即可。使用SAX解析person.xml的代码如下:
package cn.com.service; import java.util.ArrayList; import java.util.List; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import cn.com.domain.Person; public class XMLContentHandler extends DefaultHandler { private List<Person> persons; private Person person; private String preTag; @Override public void startDocument() throws SAXException { persons = new ArrayList<Person>(); } public List<Person> getPersons() { return persons; } @Override public void characters(char[] ch, int start, int length) throws SAXException { if(person != null){ String data = new String(ch,start,length); if("name".equals(preTag)){ person.setName(data); }else if("age".equals(preTag)){ person.setAge(new Short(data)); } } } public void endElement(String uri, String localName, String qName) throws SAXException { if(person != null && "person".equals(localName)){ persons.add(person); person = null; } preTag = null; } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if("person".equals(localName)){ person = new Person(); person.setId(new Integer(attributes.getValue(0))); } preTag = localName; } }
package cn.com.service; import java.io.InputStream; import java.util.List; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import cn.com.domain.Person; public class SAXPersonService { public static List<Person> readXml(InputStream inputStream) throws Exception { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser saxParser = spf.newSAXParser(); //设置解析器的相关特性,http://xml.org/sax/features/namespace //saxParser.setProperty("http://xml.org/sax/features/namespace", true); //表示开户命名空间特性 XMLContentHandler handler = new XMLContentHandler(); saxParser.parse(inputStream, handler); inputStream.close(); return handler.getPersons(); } }
package cn.com.xml; import java.io.InputStream; import java.util.List; import android.test.AndroidTestCase; import android.util.Log; import cn.com.domain.Person; import cn.com.service.SAXPersonService; public class SAXPersonServiceTest extends AndroidTestCase { private static final String TAG = "SAXPersonServiceTest"; public void testReadXml() throws Exception { InputStream inputStream = SAXPersonServiceTest.class.getClassLoader().getResourceAsStream("person.xml"); List<Person> persons = SAXPersonService.readXml(inputStream); for(Person person : persons){ Log.i(TAG, person.toString()); } } }
使用DOM解析(尽量少用,耗能,文件要比较少)
package cn.com.service; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import cn.com.domain.Person; public class DomPersonService { public static List<Person> readXml(InputStream inStream) throws Exception { List<Person> persons = new ArrayList<Person>(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(inStream); Element root = document.getDocumentElement(); NodeList nodes = root.getElementsByTagName("person"); for(int i=0; i<nodes.getLength();i++){ Element personElement = (Element)nodes.item(i); Person person = new Person(); person.setId(new Integer(personElement.getAttribute("id"))); NodeList childNodes = personElement.getChildNodes(); for(int j=0; j<childNodes.getLength();j++){ Node childNode = childNodes.item(j); if(childNode.getNodeType() == Node.ELEMENT_NODE){ Element childElement = (Element) childNode; if(childElement.getNodeName().equals("name")){ person.setName(childElement.getFirstChild().getNodeValue()); }else if(childElement.getNodeName().equals("age")){ person.setAge(new Short(childElement.getFirstChild().getNodeValue())); } } } persons.add(person); } return persons; } }
使用pull解析器读取XML文件
除了可以使用SAX和DOM解析XML文件,也可以使用Android内置的pull解析XML文件,pull解析器的运行方式与SAX解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextTest()方法可以获取下一个Text类型元素的值。
使用pull解析器读取person.xml的代码在如下,
pull解析器的源码及文档下载网址:http://www.xmlpull.org/
package cn.com.service; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import android.util.Xml; import cn.com.domain.Person; public class PullPersonService { public static List<Person> readXml(InputStream inStream) throws Exception { List<Person> persons = null; XmlPullParser parser = Xml.newPullParser(); parser.setInput(inStream, "UTF-8"); int eventCode = parser.getEventType(); Person person = null; while(eventCode != XmlPullParser.END_DOCUMENT){ switch (eventCode) { case XmlPullParser.START_DOCUMENT: persons = new ArrayList<Person>(); break; case XmlPullParser.START_TAG: if(parser.getName().equals("person")){ person = new Person(); person.setId(new Integer(parser.getAttributeValue(0))); }else if(person != null){ if("name".equals(parser.getName())){ person.setName(parser.nextText()); }else if("age".equals(parser.getName())){ person.setAge(new Short(parser.nextText())); } } break; case XmlPullParser.END_TAG: if("person".equals(parser.getName()) && person != null){ persons.add(person); person = null; } break; } eventCode = parser.next(); } return persons; } }
读取XML,还有最简单的方法是去拼xml,遇到特殊字符要转译。
使用SharedPrefernces进行数据存储
保存软件参数设置功能,使用SharedPrefence类,其背后是用xml文件存放数据,文件存放/data/data/<package name>/shared_prefs目录下:
package cn.com.android; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class PreferencesActivity extends Activity { private OnClickListener listener = new View.OnClickListener() { public void onClick(View v) { Button button = (Button) v; //PreferencesActivity.this.getPreferences(mode);//采用这种方式,保存名称为它PreferencesActivity SharedPreferences pres = PreferencesActivity.this .getSharedPreferences("soft", Context.MODE_PRIVATE); switch (button.getId()) { case R.id.setbutton: String name = nameText.getText().toString(); String age = ageText.getText().toString(); Editor editor = pres.edit(); editor.putString("name", name); editor.putInt("age", Integer.parseInt(age)); editor.commit(); Toast.makeText(PreferencesActivity.this, "保存成功!", Toast.LENGTH_LONG).show(); break; case R.id.showbutton: String nameValue = pres.getString("name", ""); int ageValue = pres.getInt("age", 1); result.setText("性名:"+ nameValue + "\n年龄:" + ageValue); break; } } }; private EditText nameText; private EditText ageText; private TextView result; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button setbutton = (Button) this.findViewById(R.id.setbutton); Button showbutton = (Button) this.findViewById(R.id.showbutton); nameText = (EditText) this.findViewById(R.id.name); ageText = (EditText) this.findViewById(R.id.age); result = (TextView) this.findViewById(R.id.result); setbutton.setOnClickListener(listener); showbutton.setOnClickListener(listener); SharedPreferences pres = PreferencesActivity.this .getSharedPreferences("soft", Context.MODE_PRIVATE); String nameValue = pres.getString("name", ""); int ageValue = pres.getInt("age", 1); nameText.setText(nameValue); ageText.setText(String.valueOf(ageValue)); } }
其它应用访问
package cn.com.log; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; import android.util.Log; public class LogActivity extends Activity { private static final String TAG = "LogActivity"; //shift+ctrl+x public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); try { Context context = this.createPackageContext("cn.com.android", Context.CONTEXT_IGNORE_SECURITY);//构建其它应用 SharedPreferences pres = context.getSharedPreferences("soft", Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE); String nameValue = pres.getString("name", ""); int ageValue = pres.getInt("age", 1); Log.i(TAG, "性名:"+ nameValue + "\n年龄:" + ageValue); //info级别 } catch (Exception e) { Log.e(TAG, e.toString()); } } }
使用嵌入式关系型AQLite数据库存取数据
除了可以使用文件或者sharePreferences存储数据,还可以选择使用SQLite数据库存储数据。
在Android平台上,集成了一个嵌入式关系数据库——SQLite,SQLite3支持NULL、INTEGR、REAL(浮点数字)、TEXT(字符串文本)和BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上SQLite3也接受archar(n),char(n),decimal(p,s)等数据类型,只不过在运算或者保存时会转换成对应的五种数据类型。SQLite最大的特点是你可以保存任何类型的数据到任何字段中,无论这列声名的数据类型是什么,但有一种情况例外,定义为INTERER PRINMARY KEY的字段只能存储64位整数,当向这种字段中保存除整数以外的数据时,将会产生错误。另外,SQLite在解析CREATE TABLE语句时,会忽略CREATE TABLE语句中跟在字段名后面的数据类型信息,如下面语句会忽略name字段信息:
create table person(personid integer primary key autoincrement,name varchar(20));
SQLite可以解析大部分标准SQL语句,如:
查询语句:select * from 表名 where 条件语句 group by 分组 having ... order by 排序子句
如:select * from person
select * from person order by id desc
select name from person group by name having count(*)>1
分页SQL与mysql类似,下面SQL语句获取5条记录,跳过前面3条记录。
select * from Account limit 5 offset 3或者select * from Account limit 3,5
插入语句:insert into 表名(字段列表)values(值列表).如:insert into person(name,age) values("张三",20)
更新语句:update 表名 set 字段名=值 where 条件子句。 如:update person set name="李四" where id=10
删除语句:delete from 表名 where 条件子句。如:delete from person where id=10
使用SQLiteDatabase操作SQLite数据库
android提供了一个名为SQLiteDatabse的类,execSQL()方法可以执行insert、delete、update、和create table之类有更改为行为的SQL语句,rowQuery()方法执行select语句。
使用SQLiteOpenHelper对数据库进行版本管理,数据检测与升级
(菜鸟使用)insert(),delete(),update(),query()方法。
insert()方法用于添加数据,各个字段的数据使用ContentValues进行存放。ContentValues类似于MAP。
多条sql语句时需要事务管理.
package cn.com.domain; public class Person { private Integer personId; private String name; public String toString() { return "personId=" + personId + ", name=" + name + ", age=" + age; } private Short age; public Person(Integer personId, String name, Short age) { super(); this.personId = personId; this.name = name; this.age = age; } public Integer getPersonId() { return personId; } public void setPersonId(Integer personId) { this.personId = personId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Short getAge() { return age; } public void setAge(Short age) { this.age = age; } }
package cn.com.service; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DataBaseOpenHelper extends SQLiteOpenHelper { private static final String DBNAME = "person"; private static final int VERSION = 3; public DataBaseOpenHelper(Context context) { super(context, DBNAME, null, VERSION); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table person(personid integer primary key autoincrement,name varchar(20),age integer)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("drop table if exists person"); onCreate(db); } }
package cn.com.service; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import cn.com.domain.Person; public class PersonService { private DataBaseOpenHelper dbOpenHelper; public PersonService(Context context) { dbOpenHelper = new DataBaseOpenHelper(context); } public void save() { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); database.beginTransaction(); try { database.execSQL("insert into person(name,age)values(?,?)", new Object[] {"张三32r", 20 }); database.execSQL("insert into person(name,age)values(?,?)", new Object[] {"李四", 21 }); database.setTransactionSuccessful(); } catch (SQLException e) { } database.endTransaction(); database.close(); } public void save(Person person) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); database.execSQL("insert into person(name,age)values(?,?)", new Object[] { person.getName(), person.getAge() }); database.close(); } public void update(Person person) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); database.execSQL( "update person set name=?, age=? where personid = ?", new Object[] { person.getName(), person.getAge(), person.getPersonId() }); database.close(); } public Person find(Integer id) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); Cursor cursor = database.rawQuery( "select * from person where personid = ?", new String[] { String.valueOf(id) }); if (cursor.moveToNext()) { return new Person(cursor.getInt(0), cursor.getString(1), cursor.getShort(2)); } database.close(); return null; } @SuppressWarnings("unused") public void delete(Integer... ids) { if (ids.length > 0) { StringBuilder sb = new StringBuilder(); for (Integer id : ids) { sb.append('?').append(','); } sb.deleteCharAt(sb.length() - 1); SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); database.execSQL( "delete from person where personid in(" + sb + ")", (Object[]) ids); database.close(); } } public List<Person> getScrollData(int startResult, int maxRessult) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); Cursor cursor = database.rawQuery( "select * from person limit ?,?", new String[] { String.valueOf(startResult), String.valueOf(maxRessult) }); List<Person> persons = new ArrayList<Person>(); while (cursor.moveToNext()) { persons.add(new Person(cursor.getInt(0), cursor.getString(1), cursor.getShort(2))); } database.close(); return persons; } public long getCount() { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); Cursor cursor = database.rawQuery("select count(*) from person", null); if (cursor.moveToNext()) { return cursor.getLong(0); } database.close(); return 0; } }
package cn.com.service; import java.util.ArrayList; import java.util.List; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import cn.com.domain.Person; public class OtherPersonService { private DataBaseOpenHelper dbOpenHelper; public OtherPersonService(Context context) { dbOpenHelper = new DataBaseOpenHelper(context); } public void save(Person person) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("name", person.getName()); values.put("age", person.getAge()); database.insert("person", "name", values); //当name有值才添加 database.close(); } public void update(Person person) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("name", person.getName()); values.put("age", person.getAge()); database.update("person", values, "personid=?",new String[]{String.valueOf(person.getPersonId())}); database.close(); } public Person find(Integer id) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); Cursor cursor = database.query("person", new String[]{"personid","name","age"}, "personid=?", new String[]{String.valueOf(id)}, null, null, null); if (cursor.moveToNext()) { return new Person(cursor.getInt(0), cursor.getString(1), cursor.getShort(2)); } database.close(); return null; } public void delete(Integer... ids) { if (ids.length > 0) { StringBuilder sb = new StringBuilder(); String[] strId = new String[ids.length]; for (int i =0;i<ids.length;i++) { sb.append('?').append(','); strId[i]=String.valueOf(ids[i]); } sb.deleteCharAt(sb.length() - 1); SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); database.delete("person", "personid in("+sb+")", strId); database.close(); } } public List<Person> getScrollData(int startResult, int maxRessult) { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); Cursor cursor = database.query("person", new String[]{"personid","name","age"}, null, null, null, null, "personid desc", startResult+","+maxRessult); List<Person> persons = new ArrayList<Person>(); while (cursor.moveToNext()) { persons.add(new Person(cursor.getInt(0), cursor.getString(1), cursor.getShort(2))); } database.close(); return persons; } public long getCount() { SQLiteDatabase database = dbOpenHelper.getWritableDatabase(); Cursor cursor = database.query("person", new String[]{"count(*)"}, null, null, null, null, null); if (cursor.moveToNext()) { return cursor.getLong(0); } database.close(); return 0; } }
package cn.com.db; import java.util.List; import android.test.AndroidTestCase; import android.util.Log; import cn.com.domain.Person; import cn.com.service.PersonService; public class PersonServiceTest extends AndroidTestCase { private static final String TAG = "PersonServiceTest"; public void testSaves() { PersonService personService = new PersonService(this.getContext()); personService.save(); } public void testSave() { PersonService personService = new PersonService(this.getContext()); for(int i =0;i<10; i++){ personService.save(new Person(null, "张三"+i, (short) (20+i))); } } public void testUpdate() { PersonService personService = new PersonService(this.getContext()); Person person = personService.find(1); person.setName("李四"); person.setAge((short) 21); personService.update(person); } public void testFind() { PersonService personService = new PersonService(this.getContext()); Person person = personService.find(1); Log.i(TAG, person.toString()); } public void testDelete() { PersonService personService = new PersonService(this.getContext()); personService.delete(1,2,3); } public void testGetScrollData() { PersonService personService = new PersonService(this.getContext()); List<Person> persons = personService.getScrollData(0, 20); for(Person person : persons){ Log.i(TAG,person.toString()); } } public void testGetCount() { PersonService personService = new PersonService(this.getContext()); Log.i(TAG,""+personService.getCount()); } }
package cn.com.db; import java.util.List; import android.test.AndroidTestCase; import android.util.Log; import cn.com.domain.Person; import cn.com.service.OtherPersonService; public class OtherPersonServiceTest extends AndroidTestCase { private static final String TAG = "OtherPersonServiceTest"; public void testSave() { OtherPersonService otherPersonService = new OtherPersonService(this.getContext()); for(int i =0;i<10; i++){ otherPersonService.save(new Person(null, "张三"+i, (short) (20+i))); } } public void testUpdate() { OtherPersonService otherPersonService = new OtherPersonService(this.getContext()); Person person = otherPersonService.find(1); person.setName("李四"); person.setAge((short) 21); otherPersonService.update(person); } public void testFind() { OtherPersonService otherPersonService = new OtherPersonService(this.getContext()); Person person = otherPersonService.find(1); Log.i(TAG, person.toString()); } public void testDelete() { OtherPersonService otherPersonService = new OtherPersonService(this.getContext()); otherPersonService.delete(1,2,3); } public void testGetScrollData() { OtherPersonService otherPersonService = new OtherPersonService(this.getContext()); List<Person> persons = otherPersonService.getScrollData(0, 20); for(Person person : persons){ Log.i(TAG,person.toString()); } } public void testGetCount() { OtherPersonService otherPersonService = new OtherPersonService(this.getContext()); Log.i(TAG,""+otherPersonService.getCount()); } }
ListView显示条目
package cn.com.db; import java.util.HashMap; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.Toast; import cn.com.service.PersonService; public class dbActivity extends Activity { private final static String TAG ="dbActivity"; private ListView listView; private PersonService personService; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); listView = (ListView) this.findViewById(R.id.listView); personService = new PersonService(this); /*List<Person> persons = personService.getScrollData(0, 20); List<HashMap<String, String>> data = new ArrayList<HashMap<String, String>>(); for (Person person : persons) { HashMap<String, String> map = new HashMap<String, String>(); map.put("personid", String.valueOf(person.getPersonId())); map.put("name", person.getName()); map.put("age", String.valueOf(person.getAge())); data.add(map); } SimpleAdapter adapter = new SimpleAdapter(dbActivity.this, data, R.layout.personitem, new String[] { "personid", "name", "age" }, new int[] { R.id.personid, R.id.name, R.id.age });*/ // ArrayAdapter<Integer> // SimpleAdapter // SimpleCursorAdapter Cursor cursor = personService.getRawScrollData(0, 10); SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.personitem, cursor, new String[]{"_id","name","age"}, new int[]{R.id.personid,R.id.name,R.id.age}); listView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() { @SuppressWarnings("unchecked") public void onItemClick(AdapterView<?> parent, View view, int position, long id) { ListView listView = (ListView) parent; HashMap<String, String> itemData = (HashMap<String, String>) listView.getItemAtPosition(position); // String personid = itemData.get("personid"); String personid = itemData.get("_id"); String name = itemData.get("name"); String age = itemData.get("age"); Log.i(TAG,this.getClass().getName()); Toast.makeText(dbActivity.this, "personid="+personid+",name="+name+",age="+age, Toast.LENGTH_LONG).show(); Log.i(TAG,"result="+(position == id)); } }); } }
内容提供者(content provider)。
当应用继承ContentProvider类,并重写该类用于提供数据和存储的方法,就可以向其它应用共享其数据。虽然使用其它方法也可以对外共享数据,但数据访问方式而不同,而使用Contentpreferences共享数据的好处是统一了数据访问方式。
当应用需要通过ContentProvider对外共享数据时,第一步需要继承ContentProvider并且重写下面方法:
public class PersonContentProvider extends ContentProvider { public int delete(Uri arg0, String arg1, String[] arg2) { return 0; } public String getType(Uri uri) { return null; } public Uri insert(Uri uri, ContentValues values) { return null; } public boolean onCreate() { return false; } public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { return null; } public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } }
第二步需要在AndroidManifest.xml使用<provider>对该ContentProvider进行配制,为了能让其他应用找到该ContentProvider,ContentProvider采用了authorites(主机名/域名)对它进行唯一标识,你可以把ContentProvider看作是一个网站,authorities就是他的域名:
引用
<manifest...>
<application...>
<provider android:name=".PersonContentProvider" android:authorities="cn.com.provider.personprovider" />
</application>
注意:一旦应用继承了ContentProider类,后面我们就会把这个应用称为ContentProvider(内容提供者)。
uri代表了要操作的数据,uri主要包括两部分信息:1》需要操作的ContentProvider,2》对ContentProvider中的什么数据进行操作,一个uri由以下几部分组成:
content://cn.com.personprovider/person/10
ContnetProvider(内容提供者)的scheme已经由Android所规定,scheme为:content://主机名(或叫Authority)用于唯一标识这个ContentProvider,外部调用者可以根据这个标识来找到它。
路征(path)可以用来表示我们要操作的数据,路征的构建应根据业务而定,如下:
要操作person表中id为10的记录,可以构建这样的路征:/person/10
要操作person表中id为10的记录的name字段, person/10/name
要操作person表中的所有记录,可以构建这样的路征: /person
要操作xxx表中的记录,可以构建这样的路征:/xxx
当然操作xml文件中的person节点下的name节点,可以构建这样的路征:/person/name
要操作xml文件中person节点下的name节点,可以构建这样的路征:/person/name
如果要把一个字符转换成uri,可以使用Uri类中的parse()方法,如下:
Uri uri = Uri.parse("content://cn.com.provider.personprovider/person")
UriMatcher类使用介绍
因为Uri代表了要要操作的数据,所以我们经常需要解析Uri,并从Uri中获取数据,Android系统提供了两个用于操作Uri的工具类,分别为UriMather和ContentUris,掌握它们的使用,会便于我们的开发工作。
UriMatcher类用于匹配Uri,它的用法如下:
首先第一步肥你需要匹配Uri路征全部注册上,如下:
//常量UriMatcher.NO_MATCH表示不匹配任何路征的返回码: UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH); //如果math()方法匹配content://cn.com.provider.personproider/person路征,返回匹配码为1 sMatcher.addURI("cn.com.provider.personprovider", "person", 1); //添加需要匹配uri,如果匹配就会返回匹配码 //如果math()方法匹配content://cn.com.provider.personproider/person/230路征,返回匹配码为2 sMatcher.addURI("cn.com.provider.personprovider", "person/#", 2);//#号为通配符 switch (sMatcher.match(Uri.parse("content://cn.com.provider.personproider/person/10"))) { case 1: break; case 2: break; default: //不匹配 throw new IllegalArgumentException("Unknow Uri:"+ uri); }
注册完需要匹配的Uri后,就可以使用sMather.mathch(uri)方法对输入的uri进行匹配,如果匹配就返回匹配码,匹配码是调用addURI()方法传入的第三个参数,假设匹配content://cn.com.provider.personprovider/person路征,返回的匹配码为1
ContentUris类用于获取Uri路征加上后面的ID部分,它有两个比较实用的方法:
withAppendedld(uri,id)用于为路征加上ID部分:
引用
Uri uri = Uri.parse("content://cn.com.provider.personprovider/person");
Uri resultUri = ContentUris.withAppendedId(uri,10);
//生成后面的Uri为:content://cn.com.provider.personprovider/person/10
parseId(uri)方法用于从路征中获取ID部分:
Uri uri = Uri.parse("content://cn.com.provider.personprovider/person/10");
long personid = ContentUris.parseId(uri); //获取的结果为:10
Uri resultUri = ContentUris.withAppendedId(uri,10);
//生成后面的Uri为:content://cn.com.provider.personprovider/person/10
parseId(uri)方法用于从路征中获取ID部分:
Uri uri = Uri.parse("content://cn.com.provider.personprovider/person/10");
long personid = ContentUris.parseId(uri); //获取的结果为:10
使用ContentProvider共享数据
ContentProvider类主要方法的作用:
public boolean onCreate() {}
该方法在ContentProvider创建后就会被调用,Android在系统启动时就会创建ContentProvider.
public Uri insert(Uri uri, ContentValues values) {}
该方法用于供外部应用往ContentProvider添加数据。
public int delete(Uri uri, String selection, String[] selectionArgs) {}
该方法用于供外部应用往ContentProvider删除数据。
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {}
该方法用于供外部应用更新ContentProvider中的数据。
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {}
该方法用于供外部应用往ContentProvider中获取数据。
public String getType(Uri uri) {}
该方法用于返回当前Uri所代表数据的MIME类型,如果操作属于集合类型,那么MIME类型字符串应该以vnd.android.cursor.dir/开头,例如:要得到所有person记录的Uri为content://cn.com.provider.personprovider/person,那么返回的MIME类型字符串应该为"vnd.android.cursor.dir/person".如果要操作的数据属于单一数据,那么MIME类型字符串应该以vnd.android.cursor.item/开头,例如:得到id为10的person记录,uri为content://cn.com.provider.personprovider/person/10,那么返回的MIME类型字符串应该为:"vnd.android.cursor.item/person".
权限设置:<provider... android:permission="" />
权限使用:<uses-permission android:name="" />
实例:
package cn.com.user; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.util.Log; public class ContentProviderUserActivity extends Activity { private static final String TAG = "ContentProviderUserActivity"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); ContentResolver contentResolver = this.getContentResolver(); // Uri alluri = Uri // .parse("content://cn.com.provider.personprovider/person"); // ContentValues values = new ContentValues(); // values.put("name", "张三"); // values.put("age", (short)20); // contentResolver.insert(uri, values); // Uri uri = // Uri.parse("content://cn.com.provider.personprovider/person/1"); // contentResolver.update(uri, values, null, null); // Uri uri = Uri // .parse("content://cn.com.provider.personprovider/person/3"); // contentResolver.delete(uri, null, null); // Cursor cursor = contentResolver.query(uri, new String[] {"personid", // "name", "age" }, null, null, "personid desc"); // while (cursor.moveToNext()) { // Log.i(TAG, // "personid=" + cursor.getInt(0) + ",name=" // + cursor.getString(1) + ",age=" // + cursor.getShort(2)); // } // cursor.close(); //查找联系人 Cursor cursor = contentResolver.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); while (cursor.moveToNext()) { int contractid = cursor.getInt(cursor.getColumnIndex(ContactsContract.Contacts._ID)); String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); Log.i(TAG, "contractid=" + contractid + ",name=" + name); Cursor phones = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{String.valueOf(contractid)}, null); StringBuilder sb = new StringBuilder(); while(phones.moveToNext()){ String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); sb.append(phoneNumber).append(" "); Log.i(TAG,sb.toString()); } } cursor.close(); } }
- android_code.rar (359 KB)
- 下载次数: 19
- android.rar (15.6 KB)
- 下载次数: 4
发表评论
-
Android 基于google Zxing实现二维码、条形码扫描,仿微信二维码扫描效果
2015-12-18 22:23 520转载请注明出处:http:// ... -
android arcgis map应用
2013-10-14 20:11 13921 符号渲染 1.1 Symbol Symbol主要是对Gr ... -
lost android 开发教程二
2012-04-19 13:13 1932第二季课程介绍 1、控件使用方法介绍 Sprinner, ... -
android基础
2011-08-10 21:23 1065lost in android Linux 环境 ... -
扫雷游戏
2011-02-25 16:32 1259MineSweeper是一个不错的Android开源扫雷游戏, ... -
应用、permission、资源
2011-02-25 13:45 1488应用 为程序添加Menu菜单 //创建OptionsMenu ... -
文件存取、数据库编程
2011-02-25 13:41 747文件存取、数据库编程 -
新版Android开发可视化UI设计DroidDraw
2011-02-24 15:16 1285新版Android开发可视化UI设计DroidDraw -
Android 基础UI编程4
2011-02-23 11:39 1406Android 基础UI编程 专业相框设计 ImageView ... -
Android UI编程基础3
2011-02-23 09:11 1091Android UI编程基础 EditText 与TextVi ... -
Android 基础UI编程2
2011-02-21 10:29 1080Android 基础UI编程 标题、状态栏的隐藏 标题栏隐藏 ... -
Android 基础UI编程1
2011-02-18 15:45 962Android 基础UI编程 更改与显示文字标签 TextVi ... -
android开发--布局
2011-02-17 16:25 1060Android应用开发3 使用Bundle在Activity间 ... -
Android 模拟器
2011-02-17 15:40 1476Android 模拟器 模拟器参数 参数格式 option 选 ... -
Android开发--Dalvik ADB
2011-02-17 10:41 1543Android虚拟机Dalvik Dalvik冲击 随着Goo ... -
Android开发环境搭建
2011-02-17 09:38 1355Android开发环境搭建 ADV的创建 ADT0.9.1 版 ... -
基础入门一
2011-02-17 09:12 1090开放手机联盟--Open HandsetAlliance 什么 ...
相关推荐
【3G应用开发之Android】 3G,全称为第三代(3rd Generation)数字通信,它是一种将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统。3G的核心特点是能够处理图像、音乐、视频等多种媒体形式,提供网页...
【标题】"3G应用开发之Android.ppt"是一份关于Android平台3G应用程序开发的专业课件,旨在帮助学习者理解和掌握如何在Android系统上构建3G通信相关的应用。这份资料可能涵盖了Android操作系统的基础,3G网络技术,...
【Java培训大纲 - 3G应用开发之Android】 在当今数字化时代,3G(第三代数字通信)技术成为了移动通信领域的重要里程碑。3G系统旨在融合无线通信与互联网,提供包括语音、图像、视频在内的多媒体服务,相比第一代...