1、对应用进行单元测试

在实际开发中,开发android软件的过程需要不断地进行测试。而使用Junit测试框架,侧是正规Android开发的必用技术,在Junit中可以得到组件,可以模拟发送事件和检测程序处理的正确性。

第一步:首先在AndroidManifest.xml中加入下面红色代码:

<manifestxmlns:android="http://schemas.android.com/apk/res/android"

package="cn.itcast.actionandroid:versionCode="1android:versionName="1.0">

<applicationandroid:icon="@drawable/icon"android:label="@string/app_name">

<uses-libraryandroid:name="android.test.runner"/>

....

</application>

<uses-sdkandroid:minSdkVersion="6"/>

<instrumentationandroid:name="android.test.InstrumentationTestRunner"

android:targetPackage="cn.itcast.action"android:label="TestsforMyApp"/>

</manifest>

上面targetPackage指定的包要和应用的package相同。

第二步:编写单元测试代码(选择要测试的方法,右键点击“RunAs--AndroidJunitTest”):

importandroid.test.AndroidTestCase;

importandroid.util.Log;

publicclassXMLTestextendsAndroidTestCase{

publicvoidtestSomething()throwsThrowable{

Assert.assertTrue(1+1==3);

}

}

根据是否知道程序的源代码:

白盒测试:知道源代码,根据源代码进行测试.

黑盒测试:没有程序的源代码,只是测试程序的功能.

根据测试的粒度(模块的大小)

单元测试unittest

方法测试functiontest

集成测试intergrationtest

系统测试systemtest

根据测试的次数暴力程度

冒烟测试smoketest

压力测试pressuretest

日志的等级

ERROR>WARN>INFO>DEBUG>VERBOSE

2、数据存储与访问

很多时候我们的软件需要对处理后的数据进行存储或再次访问。Android为数据存储提供了如下几种方式:

1文件

2SharedPreferences(参数)

3SQLite数据库

4内容提供者(Contentprovider

5网络

3使用文件进行数据存储

首先给大家介绍使用文件如何对数据进行存储,Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的。

publicclassFileActivityextendsActivity{

@OverridepublicvoidonCreate(BundlesavedInstanceState){

...

FileOutputStreamoutStream=this.openFileOutput("itcast.txt",Context.MODE_PRIVATE);

outStream.write("传智播客".getBytes());

outStream.close();

}

}

openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/”,如果文件不存在,Android会自动创建它。创建的文件保存在/data/data/<packagename>/files目录,如:/data/data/cn.itcast.action/files/itcast.txt,通过点击Eclipse菜单“Window-ShowView-Other”,在对话窗口中展开android文件夹,选择下面的FileExplorer视图,然后在FileExplorer视图中展开/data/data/<packagename>/files目录就可以看到该文件。

openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为:Context.MODE_PRIVATE=0

Context.MODE_APPEND=32768

Context.MODE_WORLD_READABLE=1

Context.MODE_WORLD_WRITEABLE=2

Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND

Context.MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。

Context.MODE_WORLD_READABLEContext.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。

MODE_WORLD_READABLE:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。

如果希望文件被其他应用读和写,可以传入:

openFileOutput("itcast.txt",Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE);

android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源比如文件的时候,就需要userid匹配。默认情况下,任何应用创建的文件,sharedpreferences,数据库都应该是私有的(位于/data/data/<packagename>/files),其他程序无法访问。除非在创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE,只有这样其他程序才能正确访问。

4、读取文件内容

如果要打开存放在/data/data/<packagename>/files目录应用私有的文件,可以使用Activity提供openFileInput()方法。

FileInputStreaminStream=this.getContext().openFileInput("itcast.txt");

Log.i("FileTest",readInStream(inStream));

readInStream()的方法请看本页下面备注。

或者直接使用文件的绝对路径:

Filefile=newFile("/data/data/cn.itcast.action/files/itcast.txt");

FileInputStreaminStream=newFileInputStream(file);

Log.i("FileTest",readInStream(inStream));

注意:上面文件路径中的“cn.itcast.action”为应用所在包,当你在编写代码时应替换为你自己应用使用的包。

对于私有文件只能被创建该文件的应用访问,如果希望文件能被其他应用读和写,可以在创建文件时,指定Context.MODE_WORLD_READABLEContext.MODE_WORLD_WRITEABLE权限。

Activity还提供了getCacheDir()getFilesDir()方法:

getCacheDir()方法用于获取/data/data/<packagename>/cache目录

getFilesDir()方法用于获取/data/data/<packagename>/files目录

publicstaticStringreadInStream(FileInputStreaminStream){

try{

ByteArrayOutputStreamoutStream=newByteArrayOutputStream();

byte[]buffer=newbyte[1024];

intlength=-1;

while((length=inStream.read(buffer))!=-1){

outStream.write(buffer,0,length);

}

outStream.close();

inStream.close();

returnoutStream.toString();

}catch(IOExceptione){

Log.i("FileTest",e.getMessage());

}

returnnull;

}

文件访问模式

context.getFilesDir();/data/data/当前应用程序包名/files

context.getCacheDir();/data/data/当前应用程序包名/cache

安装一个apk后系统拷贝这个apk/data/app/xx.apk

context.getPackageCodePath()

直接获取一个文件的输入流

FileInputStreamfis=context.openFileInput("info.txt");

等价于

Filefile=newFile(context.getFilesDir(),"info.txt");

FileInputStreamfis=newFileInputStream(file);

直接获取一个文件的输出流

context.openFileOutput("info.txt",Context.MODE_PRIVATE);//文件是私有模式

等价于

Filefile=newFile(context.getFilesDir(),"info.txt");//在当前应用程序的目录下创建一个files目录里面有一个文件info.txt

FileOutputStreamfos=newFileOutputStream(file);

文件访问权限

-rw-rw----私有

-rw-rw-r--可读

-rw-rw--w-可写

-rw-rw-rw-可读可写

android系统有一个特点每个应用程序都是一个单独的用户.

一个应用程序创建的文件默认模式是私有的模式,

别的应用程序不可以访问这个应用程序私有的数据.

ctrl+H

文件访问模式

packagecom.itheima.login.service;

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.InputStreamReader;

importandroid.content.Context;

/**

*登陆相关的服务

*

*@authorAdministrator

*

*/

publicclassLoginService{

//上下文其实提供了应用程序的一个详细的环境信息.包括包名是什么/data/data/目录在哪里.

//wedochickenright

/**

*保存用户信息到文件

*

*@paramusername

*用户名

*@parampassword

*密码

*/

publicstaticvoidsaveUserInfoToFile(Contextcontext,Stringusername,Stringpassword,intmode)

throwsException{

FileOutputStreamfos=context.openFileOutput("info.txt",mode);

fos.write((username+"##"+password).getBytes());

fos.close();

}

/**

*读取用户的用户名和密码

*@return//zhangsan##123456

*/

publicstaticStringreadUserInfoFromFile(Contextcontext)throwsException{

Filefile=newFile(context.getFilesDir(),"info.txt");

FileInputStreamfis=newFileInputStream(file);

BufferedReaderbr=newBufferedReader(newInputStreamReader(fis));

Stringline=br.readLine();

fis.close();

br.close();

returnline;

}

}

packagecom.itheima.login;

importcom.itheima.login.service.LoginService;

importandroid.os.Bundle;

importandroid.app.Activity;

importandroid.content.Context;

importandroid.text.TextUtils;

importandroid.view.Menu;

importandroid.view.View;

importandroid.widget.CheckBox;

importandroid.widget.EditText;

importandroid.widget.RadioGroup;

importandroid.widget.Toast;

/**

*activity实际上是上下文的一个子类

*

*@authorAdministrator

*

*/

publicclassMainActivityextendsActivity{

privateEditTextet_username;

privateEditTextet_password;

privateCheckBoxcb_remeber_pwd;

privateRadioGrouprg_mode;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

cb_remeber_pwd=(CheckBox)findViewById(R.id.cb_remeber_pwd);

et_username=(EditText)findViewById(R.id.et_username);

et_password=(EditText)findViewById(R.id.et_password);

try{

Stringresult=LoginService.readUserInfoFromFile(this);

String[]infos=result.split("##");

et_username.setText(infos[0]);

et_password.setText(infos[1]);

}catch(Exceptione){

e.printStackTrace();

}

rg_mode=(RadioGroup)findViewById(R.id.rg_mode);

}

/**

*登陆按钮的点击事件

*

*@paramview

*/

publicvoidlogin(Viewview){

Stringusername=et_username.getText().toString().trim();

Stringpassword=et_password.getText().toString().trim();

if(TextUtils.isEmpty(username)||TextUtils.isEmpty(password)){

Toast.makeText(getApplicationContext(),"用户名或者密码不能为空",0).show();

return;

}

//检查是否勾选了cb

if(cb_remeber_pwd.isChecked()){//记住密码

try{

intrb_id=rg_mode.getCheckedRadioButtonId();//获取哪个id被选中

intmode=Context.MODE_PRIVATE;

switch(rb_id){

caseR.id.rb_private://私有

mode=Context.MODE_PRIVATE;

break;

caseR.id.rb_readable://可读

mode=Context.MODE_WORLD_READABLE;

break;

caseR.id.rb_writeable://可写

mode=Context.MODE_WORLD_WRITEABLE;

break;

caseR.id.rb_public://可读可写

mode=Context.MODE_WORLD_READABLE+Context.MODE_WORLD_WRITEABLE;

break;

}

LoginService.saveUserInfoToFile(this,username,password,mode);

Toast.makeText(this,"保存用户名密码成功",0).show();

}catch(Exceptione){

e.printStackTrace();

Toast.makeText(getApplicationContext(),"保存用户名密码失败",0).show();

}

}

}

}

登录案例

packagecom.itheima.login.service;

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.InputStreamReader;

importandroid.content.Context;

/**

*登陆相关的服务

*

*@authorAdministrator

*

*/

publicclassLoginService{

//上下文其实提供了应用程序的一个详细的环境信息.包括包名是什么/data/data/目录在哪里.

//wedochickenright

/**

*保存用户信息到文件

*

*@paramusername

*用户名

*@parampassword

*密码

*/

publicstaticvoidsaveUserInfoToFile(Contextcontext,Stringusername,Stringpassword)

throwsException{

//Filefile=newFile("/data/data/com.itheima.login/info.txt");

// Filefile=newFile(context.getFilesDir(),"info.txt");//在当前应用程序的目录下创建一个files目录里面有一个文件info.txt

// FileOutputStreamfos=newFileOutputStream(file);

FileOutputStreamfos=context.openFileOutput("info.txt",Context.MODE_PRIVATE);//追加模式

//zhangsan##123456

fos.write((username+"##"+password).getBytes());

fos.close();

}

/**

*读取用户的用户名和密码

*@return//zhangsan##123456

*/

publicstaticStringreadUserInfoFromFile(Contextcontext)throwsException{

Filefile=newFile(context.getFilesDir(),"info.txt");

FileInputStreamfis=newFileInputStream(file);

BufferedReaderbr=newBufferedReader(newInputStreamReader(fis));

Stringline=br.readLine();

fis.close();

br.close();

returnline;

}

}

packagecom.itheima.login;

importcom.itheima.login.service.LoginService;

importandroid.os.Bundle;

importandroid.app.Activity;

importandroid.text.TextUtils;

importandroid.view.Menu;

importandroid.view.View;

importandroid.widget.CheckBox;

importandroid.widget.EditText;

importandroid.widget.Toast;

/**

*activity实际上是上下文的一个子类

*@authorAdministrator

*

*/

publicclassMainActivityextendsActivity{

privateEditTextet_username;

privateEditTextet_password;

privateCheckBoxcb_remeber_pwd;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

cb_remeber_pwd=(CheckBox)findViewById(R.id.cb_remeber_pwd);

et_username=(EditText)findViewById(R.id.et_username);

et_password=(EditText)findViewById(R.id.et_password);

try{

Stringresult=LoginService.readUserInfoFromFile(this);

String[]infos=result.split("##");

et_username.setText(infos[0]);

et_password.setText(infos[1]);

}catch(Exceptione){

e.printStackTrace();

}

}

/**

*登陆按钮的点击事件

*@paramview

*/

publicvoidlogin(Viewview){

Stringusername=et_username.getText().toString().trim();

Stringpassword=et_password.getText().toString().trim();

if(TextUtils.isEmpty(username)||TextUtils.isEmpty(password)){

Toast.makeText(getApplicationContext(),"用户名或者密码不能为空",0).show();

return;

}

//检查是否勾选了cb

if(cb_remeber_pwd.isChecked()){//记住密码

try{

LoginService.saveUserInfoToFile(this,username,password);

Toast.makeText(this,"保存用户名密码成功",0).show();

}catch(Exceptione){

e.printStackTrace();

Toast.makeText(getApplicationContext(),"保存用户名密码失败",0).show();

}

}

}

}

5、把文件存放在SDCard

使用ActivityopenFileOutput()方法保存文件,文件是存放在手机空间上,一般手机的存储空间不是很大,存放些小文件还行,如果要存放像视频这样的大文件,是不可行的。对于像视频这样的大文件,我们可以把它存放在SDCardSDCard是干什么的?你可以把它看作是移动硬盘或U盘。

在模拟器中使用SDCard,你需要先创建一张SDCard卡(当然不是真的SDCard,只是镜像文件)。创建SDCard可以在Eclipse创建模拟器时随同创建,也可以使用DOS命令进行创建,如下:

Dos窗口中进入androidSDK安装路径的tools目录,输入以下命令创建一张容量为2GSDCard,文件后缀可以随便取,建议使用.img

mksdcard2048MD:\AndroidTool\sdcard.img

在程序中访问SDCard,你需要申请访问SDCard的权限。

AndroidManifest.xml中加入访问SDCard的权限如下:

<!--SDCard中创建与删除文件权限-->

<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

<!--SDCard写入数据权限-->

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

要往SDCard存放文件,程序必须先判断手机是否装有SDCard,并且可以进行读写。

注意:访问SDCard必须在AndroidManifest.xml中加入访问SDCard的权限

if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){

FilesdCardDir=Environment.getExternalStorageDirectory();//获取SDCard目录

FilesaveFile=newFile(sdCardDir,itcast.txt);

FileOutputStreamoutStream=newFileOutputStream(saveFile);

outStream.write("传智播客".getBytes());

outStream.close();

}

Environment.getExternalStorageState()方法用于获取SDCard的状态,如果手机装有SDCard,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED

Environment.getExternalStorageDirectory()方法用于获取SDCard的目录,当然要获取SDCard的目录,你也可以这样写:

FilesdCardDir=newFile("/mnt/sdcard");//获取SDCard目录

FilesaveFile=newFile(sdCardDir,"itcast.txt");

//上面两句代码可以合成一句:FilesaveFile=newFile("/mnt/sdcard/itcast.txt");

FileOutputStreamoutStream=newFileOutputStream(saveFile);

outStream.write("传智播客test".getBytes());

outStream.close();

}

packagecom.itheima.login.service;

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.InputStreamReader;

importandroid.content.Context;

importandroid.content.SharedPreferences;

importandroid.content.SharedPreferences.Editor;

/**

*登陆相关的服务

*

*@authorAdministrator

*

*/

publicclassLoginService{

//上下文其实提供了应用程序的一个详细的环境信息.包括包名是什么/data/data/目录在哪里.

//wedochickenright

/**

*保存用户信息到文件

*

*@paramusername

*用户名

*@parampassword

*密码

*/

publicstaticvoidsaveUserInfoToFile(Contextcontext,Stringusername,

Stringpassword)throwsException{

SharedPreferencessp=context.getSharedPreferences("config",

Context.MODE_PRIVATE);

Editoreditor=sp.edit();

editor.putString("username",username);

editor.putString("password",password);

editor.commit();

}

/**

*读取用户的用户名和密码

*

*@return//zhangsan##123456

*/

publicstaticString[]readUserInfoFromFile(Contextcontext)

{

SharedPreferencessp=context.getSharedPreferences("config",

Context.MODE_PRIVATE);

Stringusername=sp.getString("username","");

Stringpassword=sp.getString("password","");

String[]infos=newString[2];

infos[0]=username;

infos[1]=password;

returninfos;

}

}

获取SD卡空间

packagecom.itheima.getsize;

importjava.io.File;

importandroid.os.Bundle;

importandroid.os.Environment;

importandroid.os.StatFs;

importandroid.app.Activity;

importandroid.text.format.Formatter;

importandroid.view.Menu;

importandroid.widget.TextView;

publicclassMainActivityextendsActivity{

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Filepath=Environment.getExternalStorageDirectory();

StatFsstat=newStatFs(path.getPath());

longblockSize=stat.getBlockSize();//得到可用区块大小

longavailableBlocks=stat.getAvailableBlocks();//得到有多少可用区块

longsize=blockSize*availableBlocks;

StringsizeStr=Formatter.formatFileSize(this,size);

TextViewtv_info=(TextView)findViewById(R.id.tv_info);

Filepath1=Environment.getDataDirectory();

StatFsstat1=newStatFs(path1.getPath());

longblockSize1=stat1.getBlockSize();

longavailableBlocks1=stat1.getAvailableBlocks();

tv_info.setText("sd卡可用空间:"+sizeStr+"\n"+"内部存储空间:"+Formatter.formatFileSize(this,blockSize1*availableBlocks1));

}

}

6使用pull解析XML文件

面是本例子要解析的XML文件:

文件名称:itcast.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<persons>

<personid=18">

<name>allen</name>

<age>36</age>

</person>

<personid=28">

<name>james</name>

<age>25</age>

</person>

</persons>

例子定义了一个javabean用于存放上面解析出来的xml内容,这个javabeanPerson,代码请见本页下面备注:

publicclassPerson{

privateIntegerid;

privateStringname;

privateShortage;

publicIntegergetId(){

returnid;

}

publicvoidsetId(Integerid){

this.id=id;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicShortgetAge(){

returnage;

}

publicvoidsetAge(Shortage){

this.age=age;

}

}

7、使用Pull解析器读取XML文件

除了可以使用SAXDOM解析XML文件之外,大家也可以使用Android内置的Pull解析器解析XML文件。Pull解析器是一个开源的java项目,既可以用于android,也可以用于JavaEE。如果用在javaEE需要把其jar文件放入类路径中,因为Android已经集成进了Pull解析器,所以无需添加任何jar文件。android系统本身使用到的各种xml文件,其内部也是采用Pull解析器进行解析的。Pull解析器的运行方式与SAX解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。跟SAX不同的是,Pull解析器产生的事件是一个数字,而非方法,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型节点的值。

使用Pull解析器读取itcast.xml的代码在本页下方备注

Pull解析器的源码及文档下载网址:http://www.xmlpull.org/

importorg.xmlpull.v1.XmlPullParser;

importandroid.util.Xml;

importcn.itcast.xml.domain.Person;

publicclassPullXMLReader{

publicstaticList<Person>readXML(InputStreaminStream){

XmlPullParserparser=Xml.newPullParser();

try{

parser.setInput(inStream,"UTF-8");

inteventType=parser.getEventType();

PersoncurrentPerson=null;

List<Person>persons=null;

while(eventType!=XmlPullParser.END_DOCUMENT){

switch(eventType){

caseXmlPullParser.START_DOCUMENT://文档开始事件,可以进行数据初始化处理

persons=newArrayList<Person>();

break;

caseXmlPullParser.START_TAG://开始元素事件

Stringname=parser.getName();

if(name.equalsIgnoreCase("person")){

currentPerson=newPerson();

currentPerson.setId(newInteger(parser.getAttributeValue(null,"id")));

}elseif(currentPerson!=null){

if(name.equalsIgnoreCase("name")){

currentPerson.setName(parser.nextText());//如果后面是Text节点,即返回它的值

}elseif(name.equalsIgnoreCase("age")){

currentPerson.setAge(newShort(parser.nextText()));

}

}

break;

caseXmlPullParser.END_TAG://结束元素事件

if(parser.getName().equalsIgnoreCase("person")&&currentPerson!=null){

persons.add(currentPerson);

currentPerson=null;

}

break;

}

eventType=parser.next();

}

inStream.close();

returnpersons;

}catch(Exceptione){

e.printStackTrace();

}

returnnull;

}

}

packagecom.itheima.xmlparser;

importjava.util.List;

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.widget.TextView;

importandroid.widget.Toast;

importcom.itheima.xmlparser.domain.CityInfo;

importcom.itheima.xmlparser.service.WeatherService;

publicclassMainActivityextendsActivity{

privateTextViewtv_weatherinfo;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tv_weatherinfo=(TextView)findViewById(R.id.tv_weatherinfo);

try{

List<CityInfo>infos=WeatherService.getCityInfos();

StringBuildersb=newStringBuilder();

for(CityInfoinfo:infos){

Stringweather=info.toString();

sb.append(weather+"\n");

}

tv_weatherinfo.setText(sb.toString());

}catch(Exceptione){

e.printStackTrace();

Toast.makeText(this,"解析天气信息失败",0).show();

}

}

}

packagecom.itheima.xmlparser.service;

importjava.util.ArrayList;

importjava.util.List;

importorg.xmlpull.v1.XmlPullParser;

importandroid.util.Xml;

importcom.itheima.xmlparser.domain.CityInfo;

publicclassWeatherService{

/**

*获取所有城市的天气信息

*

*@return

*/

publicstaticList<CityInfo>getCityInfos()throwsException{

XmlPullParserparser=Xml.newPullParser();

List<CityInfo>cityInfos=null;

CityInfocityInfo=null;

//设置初始化参数解析哪个流里面的内容格式编码

parser.setInput(WeatherService.class.getClassLoader()

.getResourceAsStream("weather.xml"),"utf-8");

inttype=parser.getEventType();

while(type!=XmlPullParser.END_DOCUMENT){

switch(type){

caseXmlPullParser.START_TAG://文本开始标签

if("citys".equals(parser.getName())){

//初始化所有城市信息的集合

cityInfos=newArrayList<CityInfo>();

}elseif("city".equals(parser.getName())){

cityInfo=newCityInfo();

Stringid=parser.getAttributeValue(null,"id");

cityInfo.setId(Integer.parseInt(id));

}elseif("weather".equals(parser.getName())){

Stringweather=parser.nextText();

cityInfo.setWeather(weather);

}elseif("name".equals(parser.getName())){

Stringname=parser.nextText();

cityInfo.setName(name);

}elseif("temp".equals(parser.getName())){

Stringtemp=parser.nextText();

cityInfo.setTemp(temp);

}elseif("wind".equals(parser.getName())){

Stringwind=parser.nextText();

cityInfo.setWind(wind);

}elseif("pm".equals(parser.getName())){

Stringpm=parser.nextText();

cityInfo.setPm(Integer.parseInt(pm));

}

break;

caseXmlPullParser.END_TAG://结束节点

if("city".equals(parser.getName())){

//一个城市的信息解析完毕了.

cityInfos.add(cityInfo);

cityInfo=null;

}

break;

}

//只要事件类型不是文档的结尾,需要不停的解析下一个节点

type=parser.next();

}

returncityInfos;

}

}

8、使用Pull解析器生成XML文件

有些时候,我们需要生成一个XML文件,生成XML文件的方法有很多,如:可以只使用一个StringBuilder组拼XML内容,然后把内容写入到文件中;或者使用DOMAPI生成XML文件,或者也可以使用pull解析器生成XML文件,这里推荐大家使用Pull解析器。

使用Pull解析器生成一个与itcast.xml文件内容相同的myitcast.xml文件,代码在本页下方备注

使用代码如下(生成XML文件):

FilexmlFile=newFile("myitcast.xml");

FileOutputStreamoutStream=newFileOutputStream(xmlFile);

OutputStreamWriteroutStreamWriter=newOutputStreamWriter(outStream,"UTF-8");

BufferedWriterwriter=newBufferedWriter(outStreamWriter);

writeXML(persons,writer);

writer.flush();

writer.close();

如果只想得到生成的xml字符串内容,可以使用StringWriter

StringWriterwriter=newStringWriter();

writeXML(persons,writer);

Stringcontent=writer.toString();

publicstaticStringwriteXML(List<Person>persons,Writerwriter){

XmlSerializerserializer=Xml.newSerializer();

try{

serializer.setOutput(writer);

serializer.startDocument("UTF-8",true);

//第一个参数为命名空间,如果不使用命名空间,可以设置为null

serializer.startTag("","persons");

for(Personperson:persons){

serializer.startTag("","person");

serializer.attribute("","id",person.getId().toString());

serializer.startTag("","name");

serializer.text(person.getName());

serializer.endTag("","name");

serializer.startTag("","age");

serializer.text(person.getAge().toString());

serializer.endTag("","age");

serializer.endTag("","person");

}

serializer.endTag("","persons");

serializer.endDocument();

returnwriter.toString();

}catch(Exceptione){

e.printStackTrace();

}

returnnull;

}

9、使用SharedPreferences进行数据存储

很多时候我们开发的软件需要向用户提供软件参数设置功能,例如我们常用的QQ,用户可以设置是否允许陌生人添加自己为好友。对于软件配置参数的保存,如果是window软件通常我们会采用ini文件进行保存,如果是j2se应用,我们会采用properties属性文件或者xml进行保存。如果是Android应用,我们最适合采用什么方式保存软件配置参数呢?Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<packagename>/shared_prefs目录下:

SharedPreferencessharedPreferences=getSharedPreferences("itcast",Context.MODE_PRIVATE);

Editoreditor=sharedPreferences.edit();//获取编辑器

editor.putString("name","传智播客");

editor.putInt("age",4);

editor.commit();//提交修改

生成的itcast.xml文件内容如下:

<?xmlversion='1.0'encoding='utf-8'standalone='yes'?>

<map>

<stringname="name">传智播客</string>

<intname="age"value="4"/>

</map>

因为SharedPreferences背后是使用xml文件保存数据,getSharedPreferences(name,mode)方法的第一个参数用于指定该文件的名称,名称不用带后缀,后缀会由Android自动加上。方法的第二个参数指定文件的操作模式,共有四种操作模式,这四种模式前面介绍使用文件方式保存数据时已经讲解过。如果希望SharedPreferences背后使用的xml文件能被其他应用读和写,可以指定Context.MODE_WORLD_READABLEContext.MODE_WORLD_WRITEABLE权限。

另外Activity还提供了另一个getPreferences(mode)方法操作SharedPreferences,这个方法默认使用当前类不带包名的类名作为文件的名称。

10访问SharedPreferences中的数据

访问SharedPreferences中的数据代码如下:

SharedPreferencessharedPreferences=getSharedPreferences("itcast",Context.MODE_PRIVATE);

//getString()第二个参数为缺省值,如果preference中不存在该key,将返回缺省值

Stringname=sharedPreferences.getString("name","");

intage=sharedPreferences.getInt("age",1);

如果访问其他应用中的Preference,前提条件是:该preference创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE权限。如:有个<packagename>cn.itcast.action的应用使用下面语句创建了preference

getSharedPreferences("itcast",Context.MODE_WORLD_READABLE);

其他应用要访问上面应用的preference,首先需要创建上面应用的Context,然后通过Context访问preference,访问preference时会在应用所在包下的shared_prefs目录找到preference

ContextotherAppsContext=createPackageContext("cn.itcast.action",Context.CONTEXT_IGNORE_SECURITY);

SharedPreferencessharedPreferences=otherAppsContext.getSharedPreferences("itcast",Context.MODE_WORLD_READABLE);

Stringname=sharedPreferences.getString("name","");

intage=sharedPreferences.getInt("age",0);

如果不通过创建Context访问其他应用的preference,也可以以读取xml文件方式直接访问其他应用preference对应的xml文件,如:

FilexmlFile=newFile(/data/data/<packagename>/shared_prefs/itcast.xml);//<packagename>应替换成应用的包名

登录保存到sp

packagecom.itheima.login.service;

importjava.io.BufferedReader;

importjava.io.File;

importjava.io.FileInputStream;

importjava.io.FileOutputStream;

importjava.io.InputStreamReader;

importandroid.content.Context;

importandroid.content.SharedPreferences;

importandroid.content.SharedPreferences.Editor;

/**

*登陆相关的服务

*

*@authorAdministrator

*

*/

publicclassLoginService{

//上下文其实提供了应用程序的一个详细的环境信息.包括包名是什么/data/data/目录在哪里.

//wedochickenright

/**

*保存用户信息到文件

*

*@paramusername

*用户名

*@parampassword

*密码

*/

publicstaticvoidsaveUserInfoToFile(Contextcontext,Stringusername,

Stringpassword)throwsException{

SharedPreferencessp=context.getSharedPreferences("config",

Context.MODE_PRIVATE);

Editoreditor=sp.edit();

editor.putString("username",username);

editor.putString("password",password);

editor.commit();

}

/**

*读取用户的用户名和密码

*

*@return//zhangsan##123456

*/

publicstaticString[]readUserInfoFromFile(Contextcontext)

{

SharedPreferencessp=context.getSharedPreferences("config",

Context.MODE_PRIVATE);

Stringusername=sp.getString("username","");

Stringpassword=sp.getString("password","");

String[]infos=newString[2];

infos[0]=username;

infos[1]=password;

returninfos;

}

}

packagecom.itheima.login;

importcom.itheima.login.service.LoginService;

importandroid.os.Bundle;

importandroid.app.Activity;

importandroid.text.TextUtils;

importandroid.view.Menu;

importandroid.view.View;

importandroid.widget.CheckBox;

importandroid.widget.EditText;

importandroid.widget.Toast;

/**

*activity实际上是上下文的一个子类

*

*@authorAdministrator

*

*/

publicclassMainActivityextendsActivity{

privateEditTextet_username;

privateEditTextet_password;

privateCheckBoxcb_remeber_pwd;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

cb_remeber_pwd=(CheckBox)findViewById(R.id.cb_remeber_pwd);

et_username=(EditText)findViewById(R.id.et_username);

et_password=(EditText)findViewById(R.id.et_password);

String[]infos=LoginService.readUserInfoFromFile(this);

et_username.setText(infos[0]);

et_password.setText(infos[1]);

}

/**

*登陆按钮的点击事件

*

*@paramview

*/

publicvoidlogin(Viewview){

Stringusername=et_username.getText().toString().trim();

Stringpassword=et_password.getText().toString().trim();

if(TextUtils.isEmpty(username)||TextUtils.isEmpty(password)){

Toast.makeText(getApplicationContext(),"用户名或者密码不能为空",0).show();

return;

}

//检查是否勾选了cb

if(cb_remeber_pwd.isChecked()){//记住密码

try{

LoginService.saveUserInfoToFile(this,username,password);

Toast.makeText(this,"保存用户名密码成功",0).show();

}catch(Exceptione){

e.printStackTrace();

Toast.makeText(getApplicationContext(),"保存用户名密码失败",0).show();

}

}

}

}

设置界面

packagecom.itheima.setting;

importandroid.app.Activity;

importandroid.content.Context;

importandroid.content.SharedPreferences;

importandroid.content.SharedPreferences.Editor;

importandroid.os.Bundle;

importandroid.view.View;

importandroid.view.View.OnClickListener;

importandroid.widget.CheckBox;

importandroid.widget.RelativeLayout;

publicclassMainActivityextendsActivity{

privateRelativeLayoutrl_sound;

privateCheckBoxcb_status;

privateSharedPreferencessp;

@Override

protectedvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

rl_sound=(RelativeLayout)findViewById(R.id.rl_sound);

cb_status=(CheckBox)findViewById(R.id.cb_status);

//初始化sp

sp=this.getSharedPreferences("config",Context.MODE_PRIVATE);

booleanchecked=sp.getBoolean("checked",false);

cb_status.setChecked(checked);

rl_sound.setOnClickListener(newOnClickListener(){

@Override

publicvoidonClick(Viewv){

//创建sharedpreference的编辑器

Editoreditor=sp.edit();

if(cb_status.isChecked()){

editor.putBoolean("checked",false);

cb_status.setChecked(false);

}else{

cb_status.setChecked(true);

editor.putBoolean("checked",true);

}

//操作完参数后一定要记得commit();

editor.commit();

}

});

}

}

更多相关文章

  1. Android HttpClient上传文件与Httpconnection知识小结
  2. iphone/android比较学习之──图片、文件、字符串
  3. Android studio获取证书指纹 (SHA1)的方法
  4. 关于build.gradle配置文件详细参数讲解
  5. eclipse android 设置及修改生成apk的签名文件
  6. Android 解析XML文件方法
  7. Android中读写文件

随机推荐

  1. Android(安卓)控件的显示隐藏上下左右移
  2. android用于打开各种文件的intent
  3. Android中的自定义数据适配器
  4. android 按钮选中效果
  5. Android代码实现APK文件的安装与卸载
  6. Android(安卓)异常处理:java.lang.Illegal
  7. android访问.net发布的webservcie返回的L
  8. Android中Service(二)
  9. Android(安卓)SurfaceView 透明和半透明
  10. Android中使用Bezier曲线