---------------------- android培训、java培训、期待与您交流! ----------------------
第二天
1. 单元测试方法:
1、 编写需要测试的类的方法。如:public class PersonService{
public void save(){
String in=”aaa”;
Int b=new Integer(in);} }
2、配置manifest文件:在application标签中加入<uses-library android:name="android.test.runner" />。
在application标签外加入
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="cn.itcast.action" android:label="Tests for My App" />
3、编写单元测试代码。编一个继承AndroidTestCase
类的代码。
public PersonServiceTest{
public void testSave()throws Exception{
PersonService p=new PersonService();
p.save();
}
}
然后运行testSave方法。如果方法出错,则显示红条。否则,显示绿条。
假如方法有返回值,如以上方法返回:return b;则在测试类中,可以用断言判定返回结果是否正确。Assert.assertEquals(23,b);若红条,则说明原方法中油逻辑错误,则导致返回值与预期记过不同。
2.Android日志信息查看:show View ->Other->LogCat。
在测试类中的日志输出int android.util.Log.i(String tag, String msg)
如在测试类中增加Log.i(“PersonService ” , ”result=”+b);也可在日志中输出德debug信息,d方法、错误信息,e方法。用法同i方法。
3. Android为数据存储提供了多种方式,分别有如下几种:文件、SharedPreferences(参数)、SQLite数据库、内容提供者(Content provider)、网络。
文件操作:文件的保存和读取服务类
public class FileService {
Context con;
public FileService(Context con) {
this.con = con; }
public void saveFile(String fName,String fContent) throwsException{
FileOutputStream fos=con.openFileOutput(fName, Context.MODE_PRIVATE );
fos.write(fContent.getBytes());
fos.close(); }
public String readFile(String fName) throws Exception{
FileInputStream fis=con.openFileInput(fName);
ByteArrayOutputStream bao=new ByteArrayOutputStream();
byte buffer[]=new byte[1024];
int hasRead=0;
while((hasRead=fis.read(buffer))!=-1){
bao.write(buffer); }
fis.close();
return bao.toString(); }}
openFileOutput()方法的第二参数用于指定操作模式,有四种模式,分别为:Context.MODE_PRIVATE=0:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可以使用Context.MODE_APPEND
Context.MODE_APPEND= 32768:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
Context.MODE_WORLD_READABLE和Context.MODE_WORLD_WRITEABLE用来控制其他应用是否有权限读写该文件。
MODE_WORLD_READABLE=1:表示当前文件可以被其他应用读取;MODE_WORLD_WRITEABLE=2:表示当前文件可以被其他应用写入。
如果希望文件被其他应用读和写,可以传入:
openFileOutput("itcast.txt", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);
android有一套自己的安全模型,当应用程序(.apk)在安装时系统就会分配给他一个userid,当该应用要去访问其他资源比如文件的时候,就需要userid匹配。默认情况下,任何应用创建的文件,sharedpreferences,数据库都应该是私有的(位于/data/data/<package name>/files),其他程序无法访问。除非在创建时指定了Context.MODE_WORLD_READABLE或者Context.MODE_WORLD_WRITEABLE ,只有这样其他程序才能正确访问。
Activity还提供了getCacheDir()和getFilesDir()方法:
getCacheDir()方法用于获取/data/data/<package name>/cache目录
getFilesDir()方法用于获取/data/data/<package name>/files目录
4.在SDcard中新建文件,并写入、读取数据。
在程序中访问SDCard,你需要申请访问SDCard的权限。
在AndroidManifest.xml中加入访问SDCard的权限如下:
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
要往SDCard存放文件,程序必须先判断手机是否装有SDCard,并且可以进行读写。
注意:访问SDCard必须在AndroidManifest.xml中加入访问SDCard的权限
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
File sdCardDir = Environment.getExternalStorageDirectory();//获取SDCard目录
File saveFile = new File(sdCardDir, “itcast.txt”);
FileOutputStream outStream = new FileOutputStream(saveFile);
outStream.write("传智播客".getBytes());
outStream.close();
}
Environment.getExternalStorageState()方法用于获取SDCard的状态,如果手机装有SDCard,并且可以进行读写,那么方法返回的状态等于Environment.MEDIA_MOUNTED。
Environment.getExternalStorageDirectory()方法用于获取SDCard的目录,当然要获取SDCard的目录,你也可以这样写:
File sdCardDir = new File("/mnt/sdcard"); //获取SDCard目录
File saveFile = new File(sdCardDir, "itcast.txt");
//上面两句代码可以合成一句: File saveFile = new File("/mnt/sdcard/itcast.txt");
FileOutputStream outStream = new FileOutputStream(saveFile);
outStream.write("传智播客test".getBytes());
outStream.close();
读取数据:
File f = Environment.getExternalStorageDirectory();
StringBuilder str = new StringBuilder();
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
File sf = new File(f, "lx.txt");
FileInputStream fis = new FileInputStream(sf);
byte[] buffer = new byte[1024];
int hread = 0;
while ((hread = fis.read(buffer)) > 0) {
str.append(new String(buffer, 0, hread));
}
fis.close();
}
5.使用sax技术解析xml文件:SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。下面是一些ContentHandler接口常用的方法:
startDocument()
当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。
endDocument()
和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。
startElement(String namespaceURI, String localName, String qName, Attributes atts)
当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。
endElement(String uri, String localName, String name)
这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。
characters(char[] ch, int start, int length)
这个方法用来处理在XML文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
<?xml version="1.0" encoding="UTF-8"?>
<persons>
<person id="23">
<name>liming</name>
<age>30</age>
</person>
<person id="20">
<name>lixiangmei</name>
<age>25</age>
</person>
</persons>
解析:
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
…………
public class SAXParsePerson {
public List<Person> getPersons(InputStream inStream) throws Exception,
SAXException {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parse = factory.newSAXParser();
PersonParse pparse = new PersonParse();
parse.parse(inStream, pparse);
inStream.close();
return pparse.getPersons(); }
final class PersonParse extends DefaultHandler {
private Person p = null;
private List<Person> persons = null;
private String tag = null;
public List<Person> getPersons() {
return persons; }
@Override
public void startDocument() throws SAXException {
persons = new ArrayList<Person>(); }
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
if ("person".equals(localName)) {
p = new Person();
p.setId(new Integer(attributes.getValue(0))); }
tag = localName; }
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("person".equals(localName)) {
persons.add(p);
p = null; }
tag = null; }
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (tag != null && "name".equals(tag)) {
p.setName(new String(ch, start, length)); }
if (tag != null && "age".equals(tag)) {
p.setAge(new Short(new String(ch, start, length)));
} } }}
6.用DOM解析XML。接口Node获取子节点的方法:NodeList getChildNodes()、getFirstChild()、getLastChild()、getNodeName()、getNodeValue()。
Document继承Node接口,方法:Element getElementById(String elementId)、getElementByTagName()。
Element继承Node接口,方法:NodeList getElementByTagName(String name)
解析:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
…………
import org.w3c.dom.Element;
public class DOMParsePerson {
public static List<Person> getPersons(InputStream inStream)
throws Exception {
List<Person> persons = new ArrayList<Person>();
DocumentBuilderFactory builderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document doc = builder.parse(inStream);
Element root = (Element) doc.getDocumentElement();
NodeList personNode = root.getElementsByTagName("person");
for (int i = 0; i < personNode.getLength(); i++) {
Person p = new Person();
Element person = (Element) personNode.item(i);
p.setId(new Integer(person.getAttribute("id")));
NodeList childNodes = person.getChildNodes();
for (int j = 0; j < childNodes.getLength(); j++) {
if ("name".equals(childNodes.item(j).getNodeName())) {
p.setName(childNodes.item(j).getFirstChild().getNodeValue());
} else if ("age".equals(childNodes.item(j).getNodeName())) {
p.setAge(new Short(childNodes.item(j).getFirstChild()
.getNodeValue())); } }
persons.add(p); }
return persons; }}
7. 生成XML文件的方法有很多,如:可以只使用一个StringBuilder组拼XML内容,然后把内容写入到文件中;或者使用DOM API生成XML文件,或者也可以使用pull解析器生成XML文件,这里推荐大家使用Pull解析器。
import org.xmlpull.v1.XmlSerializer;
import android.util.Xml;
…………
public class XMLBuild {
public void BuildXML(ArrayList<Person> list, Writer writer)
throws IOException {
XmlSerializer x = Xml.newSerializer();
x.setOutput(writer);
x.startDocument("UTF-8", true);
for (Person p : list) {
x.startTag(null, "person");
x.attribute(null, "id", p.getId().toString());
x.startTag(null, "name");
x.text(p.getName());
x.endTag(null, "name");
x.startTag(null, "age");
x.text(p.getAge() + "");
x.endTag(null, "age");
x.endTag(null, "person"); }
x.startTag(null, "person");
x.endTag(null, "person");
x.endDocument();
writer.close(); }}
测试方法:
public void testBuildXML() throws IOException{
XMLBuild b=new XMLBuild();
ArrayList<Person> ps=new ArrayList<Person>();
Person p=null;
for(short i=0;i<4;i++){
p=new Person();
p.setId(1+i);
p.setName(i+"name");
p.setAge((short)(i+20));
ps.add(p);
p=null;
}
b.BuildXML(ps, new FileWriter(new File(this.getContext().getFilesDir(), "xml.txt")));
}
8.用shared preference保存配置参数。shared preference位于Activity级别,如果在普通类中创建则需要传入某个Activity。SharedPreferences类位于android.content包中,它可以为应用程序共享。当然,某个Activity也可以拥有私有shared preference。私有shared preference创建方法:
SharedPreferences sp=getPreference(MODE_PEIVATE);
非私有SharedPreferences创建方法:
SharedPreferences sp=getSharedPreferences(String name, int mode)
应用可以创建多个不同的SharedPreferences。
如果想在其他应用中访问本应用中得SharedPreferences,可以在其他应用中取得本应用的SharedPreferences。取得方法:
Context con=new
AndroidTestCase().getContext().createPackageContext(packageName, flags);
在通过con取得SharedPreferences。
使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<package name>/shared_prefs目录下。
SharedPreferences用法:Perso
SharedPreferences sharedPreferences =
getSharedPreferences("itcast", Context.MODE_PRIVATE);
Editor editor = sharedPreferences.edit();//获取编辑器
editor.putString("name", "传智播客");
editor.putInt("age", 4);
editor.commit();//提交修改
生成的itcast.xml文件内容如下:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="name">传智播客</string>
<int name="age" value="4" />
</map>
SharedPreferences接口中的常用方法:
boolean | contains(String key) |
edit() | |
getAll() | |
boolean | getBoolean(String key, boolean defValue) |
float | getFloat(String key, float defValue) |
int | getInt(String key, int defValue) |
long | getLong(String key, long defValue) |
getString(String key, String defValue) |
SharedPreferences.Editor接口中得常用方法:
clear() | |
boolean | commit() |
putBoolean(String key, boolean value) | |
putFloat(String key, float value) | |
putInt(String key, int value) | |
putLong(String key, long value) | |
putString(String key, String value) | |
remove(String key) |
---------------------- android培训、java培训、期待与您交流! ----------------------