2010.10.28———Android 02

内容一
*************************************
单元测试
************************************

开发android时 错误原因不太好找 可以使用android只带的单元测试

1、引入单元测试库,在AndroidManifest.xml里面加入
<
uses-library android:name="android.test.runner" />

要放到application里面 activity外面

2、通过那个类来启动单元测试 这个是和uses-sdk同目录 在xml根目录下面
<instrumentation android:name="android.test.InstrumentationTestRunner"  android:targetPackage="lp.test" android:label="Tests for My App" /> targetPackage指定的包名 应该和应用的package一样 android:label 是名字 可有可无


3、编写单元测试代码 和activity同目录 在上面android:targetPackage包下面

 a:继承AndroidTestCase b:方法名为test**** c:方法为public void


AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="lp.junit"      android:versionCode="1"      android:versionName="1.0">    <application android:icon="@drawable/icon" android:label="@string/app_name">    <uses-library android:name="android.test.runner" />        <activity android:name=".MainActivity"                  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-sdk android:minSdkVersion="8" /><instrumentation android:name="android.test.InstrumentationTestRunner"  android:targetPackage="lp.junit" android:label="Tests for My App" /></manifest> 




TestServiceTest.java

package lp.junit;import junit.framework.Assert;import lp.service.TestService;import android.test.AndroidTestCase;public class TestServiceTest extends AndroidTestCase {public void test_save(){TestService service = new TestService();service.save();}public void test_add(){TestService service = new TestService();int result = service.add(1,1);//单元测试可以判断执行结果Assert.assertEquals(2, result);}}



在单元测试里面可以输出不同级别的控制信息

log.v()全部信息log.i() info以上级别信息log.d()debug以上级别信息log.w()warning以上级别信息log.e() error以上级别信息


可以在LogCat里面配置不同的过滤器 来显示特定的信息

除了用log以外 我们还可以用
System.out.println()
System.err.println();
不过 一般建议用log来输出日志信息



内容二
******************************
存储方式——文件
******************************
文件存储位置 一般有两种1.SDCard2.自带的存储空间


********************************
把内容保存到手机自带的存储空间内
********************************


需要文件输出流

public void saveFile(String fileName,String content) throws Exception{FileOutputStream fos = this.context.openFileOutput(fileName, Context.MODE_PRIVATE);fos.write(content.getBytes());fos.close();}

openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,
如果文件不存在,Android 会自动创建它。
创建的文件保存在/data/data/<package name>/files目录,
如: /data/data/lp.file/files/itcast.txt ,
通过点击Eclipse菜单“Window”-“Show View”-“Other”,
在对话窗口中展开android文件夹,选择下面的File Explorer视图,
然后在File Explorer视图中展开/data/data/<package name>/files目录就可以看到该文件。
要想看文件的内容 必须把文件从android系统导入到我们的window系统中来

第二个参数 文件操作模式:

Context.MODE_PRIVATE 私有模式
1、此文件仅能被本应用访问
2、采用覆盖方式存储 也就是说以前有数据 后来存储的将覆盖原来的
Context.MODE_APPEND 追加模式
1、仅能被本应用访问
2、采用追加方式存储 文件不存在 就创建 存在 就追加内容
MODE_WORLD_READABLE
当前文件可以被其他应用所读取
MODE_WORLD_WRITEABLE
当前文件可以被其他应用写 但不能读

如果希望文件被其他应用读和写,可以传入:
openFileOutput("itcast.txt", Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE);

相当于
openFileOutput("itcast.txt", 3);


因为:
Context.MODE_PRIVATE    =  0Context.MODE_APPEND    =  32768Context.MODE_WORLD_READABLE =  1Context.MODE_WORLD_WRITEABLE =  2



读取文件

要读取/data/data/<package name>/files目录下的文件 可以

public String readFile(String fileName) throws Exception{StringBuffer sb = new StringBuffer();FileInputStream fis = this.context.openFileInput(fileName);BufferedReader br = new BufferedReader(new InputStreamReader(fis));String line = null;while((line=br.readLine())!=null){sb.append(line);}return sb.toString();}


但是 如果要访问其他应用的文件时 即必须写绝对路径了
String path = "/data/data/应用名/files/文件名;File file = new File(path);FileInputStream  fis = new FileInputStream(file);ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;whiel(len=fis.read(buffer))!=-1){baos.wrtite(buffer,0.len);}String result = new String(baos.toByteArray());fis.close();baos.close();


另外:

Activity还提供了getCacheDir()和getFilesDir()方法:getCacheDir()方法用于获取当前应用的cache文件夹,/data/data/<package name>/cache目录getFilesDir()方法用于获取当前应用的files文件夹,/data/data/<package name>/files目录




******************************
SDCard存数据
******************************

1、获得sdcard的权限
如果要往sdcard写入数据 就必须获得sdcard的权限 仅仅读的话 不需要

<!-- 在SDCard中创建与删除文件权限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><!-- 往SDCard写入数据权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


2、 写读取方法

2.2的sdcard的路径是/mnt/sdcard
各个版本的sdcard路径 不是统一的 所以 最好不要再应用中使用绝对路径
Environment.getExternalStorageDirectory()
Android为我们提供的方法 获得sdcard的路径

public void saveFileToSDCard(String fileName,String content) throws Exception{//String path = "/mnt/sdcard";File file = new File(Environment.getExternalStorageDirectory(),fileName);FileOutputStream fos = new FileOutputStream(file);fos.write(content.getBytes());fos.close();}



3、开始存储文件

因为是SDcard 所以 我们不知道用户手机是否有SDcard 所以 开始之前 必须先判断一下

if(Environment.getExternalStorageState.equals(Environment.MEDIA_MOUNTED)){}else{Toast.makeText(Activity.this,"SDCard没有插入或者写保护",1).show();}



代码:

工具类
FileUtil.java



package lp.util;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStreamReader;import android.content.Context;import android.os.Environment;public class FileUtil {private Context context;public FileUtil(Context context){this.context = context;}/** * 在SDCard上保存文件 * @param fileName * @param content * @throws Exception */public void saveFileToSDCard(String fileName,String content) throws Exception{//String path = "/mnt/sdcard";File file = new File(Environment.getExternalStorageDirectory(),fileName);FileOutputStream fos = new FileOutputStream(file);fos.write(content.getBytes());fos.close();}/** * 保存指定文本到指定文件 * @param fileName * @param content * @throws Exception */public void saveFile(String fileName,String content) throws Exception{FileOutputStream fos = this.context.openFileOutput(fileName, Context.MODE_PRIVATE);fos.write(content.getBytes());fos.close();}/** * 读取指定文件 * @param fileName * @return * @throws Exception */public String readFile(String fileName) throws Exception{StringBuffer sb = new StringBuffer();FileInputStream fis = this.context.openFileInput(fileName);BufferedReader br = new BufferedReader(new InputStreamReader(fis));String line = null;while((line=br.readLine())!=null){sb.append(line);}return sb.toString();}}


清单文件
AndroidManifest.xml


<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"      package="lp.file"      android:versionCode="1"      android:versionName="1.0">    <application android:icon="@drawable/icon" android:label="@string/app_name">    <uses-library android:name="android.test.runner" />        <activity android:name=".MainActivity"                  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-sdk android:minSdkVersion="8" />    <instrumentation android:name="android.test.InstrumentationTestRunner"  android:targetPackage="lp.file" android:label="Tests for My App" /><!-- 在SDCard中创建与删除文件权限 --><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/><!-- 往SDCard写入数据权限 --><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/></manifest> 



MainActivity.java

this.save.setOnClickListener(new OnClickListener() {        /*         * 在手机上存储文件@Overridepublic void onClick(View v) {String file = MainActivity.this.fileName.getText().toString();String text = MainActivity.this.content.getText().toString();//FileOutputStream fos = null;try {//如果文件不存在,Android 会自动创建它。//创建的文件保存在/data/data/<package name>/files目录//如: /data/data/cn.itcast.action/files/itcast.txt //业务方法 应该抽取出去//fos = MainActivity.this.openFileOutput(file, MODE_PRIVATE);//fos.write(text.getBytes());util.saveFile(file, text);Toast.makeText(MainActivity.this, R.string.success, 1).show();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();Toast.makeText(MainActivity.this, R.string.error, 1).show();Log.e(TAG, e.toString());}//}finally{//try {//fos.close();//} catch (IOException e) {//// TODO Auto-generated catch block//e.printStackTrace();//}//}}*/                //在SDCard上存储文件        @Overridepublic void onClick(View v) {        String file = MainActivity.this.fileName.getText().toString();String text = MainActivity.this.content.getText().toString();try {//往SDCard上存储数据 首先应该判断存储卡是否存在if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){util.saveFileToSDCard(file, text);Toast.makeText(MainActivity.this, R.string.success, 1).show();}else{Toast.makeText(MainActivity.this, "没有插入SD卡或者写保护", 1).show();}}catch(Exception e){e.printStackTrace();Toast.makeText(MainActivity.this, R.string.error, 1).show();Log.e(TAG, e.toString());}}});



内容三

***********************
解析xml
**********************

欲解析的文件

person.xml

<?xml version="1.0" encoding="UTF-8"?><persons><person id="23"><name>liming</name><age>30</age></person><person id="20"><name>zhangxiaoxiao</name><age>25</age></person></persons>



解析xml有三种 SAX DOM pull

1、SAX解析:速度快 内存下 事件驱动

package lp.util;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import lp.pojo.Person;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;/** * SAX解析XML文件 * @param is * @return * @throws Exception */public class SAXParserUtil {public List<Person> getPersons(InputStream is) throws Exception{SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser parser = factory.newSAXParser();PersonHandler handler = new PersonHandler();//将会按照PersonHandler里面的事件来解析xmlparser.parse(is, handler);return handler.getList();}private class PersonHandler extends DefaultHandler{private List<Person> list;private String parentTag;private Person bean = null;public List<Person> getList(){return list;}@Overridepublic void startDocument() throws SAXException {list = new ArrayList<Person>();}@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {if("person".equals(localName)){bean = new Person();bean.setId(Integer.parseInt(attributes.getValue(0)));}parentTag = localName;}@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {if(parentTag!=null){String data = new String(ch,start,length);if(parentTag.equals("name")){bean.setName(data);}else if(parentTag.equals("age")){bean.setAge(Integer.parseInt(data));}}}@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {if("person".equals(localName)){list.add(bean);bean = null;}parentTag = null;}@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stubsuper.endDocument();}}}



2、DOM解析:内存大 所有内容以文档树方式存放在内存 操作简单


package lp.util;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import lp.pojo.Person;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;/** * DOM解析xml * @author Administrator * */public class DomParserUtil {public List<Person> getPersons(InputStream is) throws Exception{List<Person> list = new ArrayList<Person>();DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(is);Element root = document.getDocumentElement();NodeList personNodes = root.getElementsByTagName("person");for(int i=0;i<personNodes.getLength();i++){Person bean = new Person();Element person = (Element)personNodes.item(i);bean.setId(Integer.parseInt(person.getAttribute("id")));NodeList children = person.getChildNodes();for(int k=0;k<children.getLength();k++){Node node = children.item(k);if(node.getNodeType()==Node.ELEMENT_NODE){if(node.getNodeName().equals("name")){bean.setName(node.getFirstChild().getNodeValue());}else if(node.getNodeName().equals("age")){bean.setAge(new Integer(node.getFirstChild().getNodeValue()));}}}list.add(bean);}return list;}}



3、pull解析器解析 开源的java项目 android已经集成了 和SAX类似 也是事件驱动
但是 需要手动调用parser.next()进入下一个元素 而不是自动的
而且 Pull解析器产生的事件是一个数字


package lp.util;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;import java.util.List;import lp.pojo.Person;import org.xmlpull.v1.XmlPullParser;import org.xmlpull.v1.XmlSerializer;import android.util.Xml;/** * pull解析xml文件 * @author Administrator * */public class PullParserUtil {/** * 解析 * @param is * @return * @throws Exception */public List<Person> getPersons(InputStream is) throws Exception{List<Person> list = null;Person bean = null;XmlPullParser pull = Xml.newPullParser();pull.setInput(is, "UTF-8");//得到数字事件int event = pull.getEventType();//事件不等于文档结束事件 就一直执行while(event!=XmlPullParser.END_DOCUMENT){switch(event){case XmlPullParser.START_DOCUMENT :list = new ArrayList<Person>();break;case XmlPullParser.START_TAG :if(pull.getName().equals("person")){bean = new Person();bean.setId(new Integer(pull.getAttributeValue(0)));}if(bean!=null){if(pull.getName().equals("name")){bean.setName(pull.nextText());}else if(pull.getName().equals("age")){bean.setAge(new Integer(pull.nextText()));}}break;case XmlPullParser.END_TAG :if(pull.getName().equals("person")){list.add(bean);bean = null;}break;default : break;}event = pull.next();}return list;}}



另外 还有就是介绍一下用pull来生成xml 这种方式很简单 就跟我们手写xml文件一样

/** * pull解析器生成xml文件 * @param list * @param os * @throws IOException  * @throws IllegalStateException  * @throws IllegalArgumentException  */public void save(List<Person> list,OutputStream os) throws Exception{XmlSerializer serializer = Xml.newSerializer();serializer.setOutput(os, "UTF-8");//生成xml开始部分//<?xml version="1.0" encoding="UTF-8"?>serializer.startDocument("UTF-8", true);//生成<persons>//第一个参数是前缀serializer.startTag(null, "persons");for(Person person : list){//生成<person id="23">serializer.startTag(null, "person");serializer.attribute(null, "id", person.getId()+"");//生成<name>serializer.startTag(null, "name");//生成lipengserializer.text(person.getName());//生成</name>serializer.endTag(null, "name");//生成<age>serializer.startTag(null, "age");//生成22serializer.text(person.getAge()+"");//生成</age>serializer.endTag(null, "age");//生成</person>serializer.endTag(null, "person");}//生成</persons>serializer.endTag(null, "persons");serializer.endDocument();os.close();}




内容四
******************************
存储方式——SharedPreferences
******************************


作用是向用户提供软件的参数设置功能

使用SharedPreferences保存数据,其背后是用xml文件存放数据,
文件存放在/data/data/<package name>/shared_prefs目录下


1、存参数
2、取参数


/* * 存参数 */public void save(String name,int age){//第一个参数 xml文件的名字 第二个参数 文件操作模式SharedPreferences preferences = this.context.getSharedPreferences("person", Context.MODE_PRIVATE);//通过编辑器来存入数据Editor editor = preferences.edit();//editor提供的一系列方法 editor.putString("name", name);editor.putInt("age", age);//把内存中数据保存到文件中editor.commit();}



现在 我们已经设置了参数了 我们需要在下一次启动应用时
这些参数应该回显在界面上

/** * 取参数 * @return */public Map<String,String> get(){Map<String,String> map = new HashMap<String,String>();//取的参数xml 要和你存的时候的文件名一样SharedPreferences preferences = this.context.getSharedPreferences("person", Context.MODE_PRIVATE);//第二个参数 是一个默认值 当xml中name不存在时 String name = preferences.getString("name", "");int age = preferences.getInt("age", 18);map.put("name",name);map.put("age",age+"");return map;}



主界面
MainActivity.java


package lp.SharedPreferences;import java.util.Map;import lp.service.PreferenceService;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.Toast;public class MainActivity extends Activity {    /** Called when the activity is first created. */private EditText name ;private EditText age;private Button set;private PreferenceService service;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        this.name = (EditText) this.findViewById(R.id.name);        this.age = (EditText) this.findViewById(R.id.age);        this.set = (Button) this.findViewById(R.id.set);                service = new PreferenceService(this);        Map<String,String> map = service.get();        this.name.setText(map.get("name"));        this.age.setText(map.get("age"));        this.set.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {String name_str = MainActivity.this.name.getText().toString();String age_str = age.getText().toString();service.save(name_str, new Integer(age_str));Toast.makeText(MainActivity.this, R.string.success, 1).show();}});    }}




另外 还有一个方法 getPrefences(文件操作模式);

它可以在Activity里面直接调用

SharedPreferences sharedPreferences = this.getPrefences(Context.MODE_PRIVATE);
这个方法没有文件名参数 所以 默认的xml存放名字就是此Activity的名字


















更多相关文章

  1. Android实际分辨率(android:anyDensity="false"的情况下的获取方
  2. [android]android自动化测试七之动态AVD硬件参数

随机推荐

  1. android使用ImageView加载本地SdCard图片
  2. 观摩Android的多层框架体系
  3. Android客户端处理服务器端返回的Json格
  4. onTouchEvent、onClick和onLongClick的调
  5. android SharedPreference的简单使用(登陆
  6. ScrollView can host only one direct ch
  7. Android 内部存储相关的函数(getCacheDir,
  8. Android(安卓)Studio maven-metadata.xml
  9. android Fragment实现
  10. android 蓝牙源码分析