Android基础——02数据存储和界面展现
2015-10-09 19:50
603 查看
测试介绍
好的软件不是写出来, 测出来的.1、根据测试的时候 是否有源代码:
白盒测试: 写测试代码 测试源代码里面的业务方法
黑盒测试: 不知道源代码, 测试应用程序的业务逻辑.
2、根据测试的粒度
方法测试 function test
单元测试 unit test junit测试框架
集成测试 integration test
系统测试 system test
3、根据测试的暴力程度
冒烟测试 smoke test
压力测试 pressure test
android中的压力测试:
–>adb shell
–>monkey 5000
单元测试
【1】定义一个类继承AndroidTestCase【2】在清单文件配置uses-library和instrumentation
在没有笔记的情况下,该怎么配置清单信息呢?
自己手动创建一个Android的测试工程,在测试工程里面会自动配置好
单元测试的步骤是:
先创建一个类,里面有个计算和的方法
package com.itheima.unit; public class Calc { /** * 定义一个计算器相机的方法 */ public int add(int x,int y){ return x + y; } }
然后再定义一个类,继承AndroidTestCase,里面写上要测试的方法和数据,并写明断言,如果断言正确,则说明单元测试显示正确结果,否则显示错误结果
package com.itheima.unit; import android.test.AndroidTestCase; public class CalcTest extends AndroidTestCase { //写测试方法 public void testAdd(){ Calc calc = new Calc(); int result = calc.add(5, 3); //断言 assertEquals(8, result); } }
在清单文件中这样配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.itheima.unit" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17" /> <!--配置要测试的包名--> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.itheima.unit" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- 配置函数库 --> <uses-library android:name="android.test.runner" /> <activity android:name="com.itheima.unit.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> </manifest>
出此案绿色的条就说明单元测试成功了
日志猫的使用
通常通过打Log的方式,日志信息会打印在日志猫上,以此来查看程序的错误package com.itheima.logcat; import android.os.Bundle; import android.app.Activity; import android.util.Log; import android.view.Menu; public class MainActivity extends Activity { private static final String tag = "MainActivity"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.v(tag, "我是v级别"); Log.i(tag, "我是info级别"); Log.d(tag, "我是debug级别"); Log.w(tag, "我是warn级别"); Log.e(tag, "我是error级别"); System.out.println("哈哈哈哈"); } }
verbose是黑色的
debug是蓝色的
info是绿色的
warn是黄色的
error是红色的
system.out是绿色的
Login登陆案例
【1】画UI实现以上UI的代码是:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <EditText android:id="@+id/et_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入用户名" /> <EditText android:id="@+id/et_userpassword" android:layout_width="match_parent" android:layout_height="wrap_content" android:password="true" android:hint="请输入密码" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginTop="20dp" > <CheckBox android:id="@+id/cb_ischeck" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="记住用户名密码" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="login" android:layout_alignParentRight="true" android:text="登录" /> </RelativeLayout> </LinearLayout>
【2】写业务逻辑:
想要实现的需求是在写上用户名密码之后,当勾选记住用户名密码的时候,点击登录,就会把用户输入的用户名密码写入到手机的内存中,
而且在下一次启动的时候,会先读取内存中的用户的信息,然后将内存中的信息显示到屏幕上
package com.itheima.login; import java.util.Map; import android.os.Bundle; import android.app.Activity; import android.text.TextUtils; import android.view.Menu; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { private EditText et_name; private EditText et_userpassword; private CheckBox cb_ischeck; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //[1]找到我们关心的控件 et_name = (EditText) findViewById(R.id.et_username); et_userpassword = (EditText) findViewById(R.id.et_userpassword); cb_ischeck = (CheckBox) findViewById(R.id.cb_ischeck); //[1.1]读取 data/data 下 info.txt信息 Map<String, String> maps = UserInfoUtils.readInfo(); if (maps!=null) { //把name 和 pwd 取出来 String name = maps.get("name"); String pwd = maps.get("pwd"); //[1.2]把name 和pwd 显示到editText控件上 et_name.setText(name); et_userpassword.setText(pwd); } } //[2]写按钮的点击事件 public void login(View v){ //[2.1]获取用户名和密码 String name = et_name.getText().toString().trim(); String pwd = et_userpassword.getText().toString().trim(); //[2.2]判断name 和 pwd 是否为空 if (TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd)) { Toast.makeText(MainActivity.this, "用户名或密码不能为空", 1).show(); }else { //[2.3]进行登录的逻辑 System.out.println("连接服务器 进行登录 等我们讲到 第四天 网络 编程 在说"); if (cb_ischeck.isChecked()) { //[2.4]把用户名和密码的数据给我存起来 boolean result = UserInfoUtils.saveInfo(name, pwd); if (result) { Toast.makeText(MainActivity.this, "保存成功", 1).show(); }else{ Toast.makeText(MainActivity.this, "保存失败", 1).show(); } }else { Toast.makeText(MainActivity.this, "请勾选cb", 1).show(); } } } }
中间需要有一个把用户名和密码写入到内存中的操作,我们单独给他封装成一个工具类,然后直接使用工具类的方法来进行写入操作,代码如下:
package com.itheima.login; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import android.content.Context; public class UserInfoUtils { // 保存用户名和密码的业务方法 public static boolean saveInfo(String username, String pwd) { try { String result = username + "##" + pwd; // [1]创建file类指定我们要把数据存储的位置 File file = new File("/data/data/com.itheima.login/info.txt"); // [2]创建一个文件输出流 FileOutputStream fos = new FileOutputStream(file); fos.write(result.getBytes()); fos.close(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } // 读取用户的信息 public static Map<String, String> readInfo() { // [1]定义map try { Map<String, String> maps = new HashMap<String, String>(); File file = new File("/data/data/com.itheima.login/info.txt"); FileInputStream fis = new FileInputStream(file); BufferedReader bufr = new BufferedReader(new InputStreamReader(fis)); String content = bufr.readLine(); // 读取数据 // 切割字符串 封装到map集合中 String[] splits = content.split("##"); String name = splits[0]; String pwd = splits[1]; // 把name 和 pwd 放入map中 maps.put("name", name); maps.put("pwd", pwd); fis.close(); return maps; } catch (Exception e) { e.printStackTrace(); return null; } } }
使用上下文获取到文件目录
在上边的例子中如果写一个要保存的文件的路径会非常的麻烦,/data/data/com.itheima.login/info.txt
如果使用上下文的话就会非常的省事
context.getFileDir.getPath();
这样就获取到了本工程所在的目录/data/data/com.itheima.login,还会在包下自己创建一个文件夹/data/data/com.itheima.login/files,比硬编码方便的多。
使用上下文还可以直接获取到本工程的输出流,
上边的例子用上下文获取到输出流的方式来进行实现的话,就会很方便:
package com.itheima.login; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import android.content.Context; public class UserInfoUtils { // 保存用户名和密码的业务方法 public static boolean saveInfo(Context context,String username, String pwd) { try { String result = username + "##" + pwd; // [3]通过上下文获取FileOutputStream FileOutputStream fos = context.openFileOutput("infoo.txt", 0); fos.write(result.getBytes()); fos.close(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } // 读取用户的信息 public static Map<String, String> readInfo(Context context) { // [1]定义map try { Map<String, String> maps = new HashMap<String, String>(); FileInputStream fis = context.openFileInput("infoo.txt"); BufferedReader bufr = new BufferedReader(new InputStreamReader(fis)); String content = bufr.readLine(); // 读取数据 // 切割字符串 封装到map集合中 String[] splits = content.split("##"); String name = splits[0]; String pwd = splits[1]; // 把name 和 pwd 放入map中 maps.put("name", name); maps.put("pwd", pwd); fis.close(); return maps; } catch (Exception e) { e.printStackTrace(); return null; } } }
把数据保存到sd卡中
【1】第一种方法:就是直接把路径写死了,“/mnt/sdcard/info.txt”
这里需要注意的是往sd卡中写数据的时候,需要先给用户一个权限,
这样才能把数据写入到sd卡上
【2】第二种方法:使用Environment对象获取到sd卡的目录:
使用这样的一个类不仅可以直接拿到sd卡的目录,还可以获取到sd卡的状态(是挂载的还是卸载的)使代码更具有健壮性
代码如下:
package com.itheima.login; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import android.content.Context; import android.os.Environment; public class UserInfoUtils { // 保存用户名和密码的业务方法 public static boolean saveInfo(String username, String pwd) { try { String result = username + "##" + pwd; // [1]创建file类指定我们要把数据存储的位置 把数据保存到sd卡 String sdPath = Environment.getExternalStorageDirectory().getPath(); File file = new File(sdPath,"haha.txt"); // [2]创建一个文件输出流 FileOutputStream fos = new FileOutputStream(file); fos.write(result.getBytes()); fos.close(); return true; } catch (Exception e) { e.printStackTrace(); return false; } } // 读取用户的信息 public static Map<String, String> readInfo() { // [1]定义map try { Map<String, String> maps = new HashMap<String, String>(); String sdPath = Environment.getExternalStorageDirectory().getPath(); File file = new File(sdPath,"haha.txt"); FileInputStream fis = new FileInputStream(file); BufferedReader bufr = new BufferedReader(new InputStreamReader(fis)); String content = bufr.readLine(); // 读取数据 // 切割字符串 封装到map集合中 String[] splits = content.split("##"); String name = splits[0]; String pwd = splits[1]; // 把name 和 pwd 放入map中 maps.put("name", name); maps.put("pwd", pwd); fis.close(); return maps; } catch (Exception e) { e.printStackTrace(); return null; } } }
获取sd卡的可用空间
先要将sd卡获取到的目录封装成一个file对象,然后file对象里面有获取最大值和可用值的方法,返回的是是个long类型的单位为字节的大小然后使格式化的类Formatter里面的formatFileSize方法来讲byte单位的大小转换为正常格式的字符串,
将获取到的正常格式的sd卡的大小显示在手机屏幕上
代码如下:
package com.itheima.getsdcarddata; import java.io.File; import android.os.Bundle; import android.os.Environment; import android.annotation.SuppressLint; import android.app.Activity; import android.text.format.Formatter; import android.view.Menu; import android.view.View; import android.widget.TextView; public class MainActivity extends Activity { @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //[1]找到我们关心的控件 TextView tv_total_size = (TextView) findViewById(R.id.textView1); TextView tv_useable_size = (TextView) findViewById(R.id.textView2); //[2]获取sd卡总大小 和可用空间 File file = Environment.getExternalStorageDirectory(); long totalSpace = file.getTotalSpace(); //总大小 long usableSpace = file.getUsableSpace(); //可用空间 //[3]转换数据格式 String formatToatalSpace = Formatter.formatFileSize(this, totalSpace); String formatusableSpace = Formatter.formatFileSize(this,usableSpace); //[4]展示到textview上 tv_total_size.setText("总大小:"+formatToatalSpace); tv_useable_size.setText("可用的:"+formatusableSpace); } }
文件权限的介绍
文件的权限有四种:私有:private
可追加的:append
可读的:read
可写的write
创建四种权限模式的文件
先创建四个按钮,按钮上绑定事件生成各自对应的文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click1" android:text="private" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click2" android:text="append" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click3" android:text="read" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="click4" android:text="write" /> </LinearLayout>
开始写生成文件的业务逻辑:
package com.itheima.pri; import java.io.FileNotFoundException; import java.io.FileOutputStream; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //点击按钮 生成一个私有的文件 public void click1(View v){ try { FileOutputStream fos = openFileOutput("private.txt", MODE_PRIVATE); // fos.write("private".getBytes()); fos.write("haha".getBytes()); fos.close(); } catch (Exception e) { e.printStackTrace(); } } //点击按钮 使用MODE_APPEND模式 生成一个append.txt文件 public void click2(View v){ try { FileOutputStream fos = openFileOutput("append.txt", MODE_APPEND); // fos.write("append".getBytes()); fos.write("hehe".getBytes()); fos.close(); } catch (Exception e) { e.printStackTrace(); } } //点击按钮 使用MODE_WORLD_READABLE 模式 生成一个read.txt 文件 public void click3(View v){ try { FileOutputStream fos = openFileOutput("read.txt", MODE_WORLD_READABLE); fos.write("read".getBytes()); fos.close(); } catch (Exception e) { e.printStackTrace(); } } //点击按钮 使用这个模式MODE_WORLD_WRITEABLE 生成一个write.txt文件 public void click4(View v){ try { FileOutputStream fos = openFileOutput("write.txt", MODE_WORLD_WRITEABLE); fos.write("write".getBytes()); fos.close(); } catch (Exception e) { e.printStackTrace(); } } }
生成的文件如下图所示:
解释一下后边的rw-的意思:只用一张图来说
想要使用读取到之前创建好的文件的内容呢?
新创建一个工程,创建读取流,读取目标文件下的文件:
package com.itheima.readfile; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { File file = new File("/data/data/com.itheima.pri/files/write.txt"); FileInputStream fis = new FileInputStream(file); BufferedReader bufr = new BufferedReader(new InputStreamReader(fis)); String content = bufr.readLine(); System.out.println("content:"+content); } catch (Exception e) { e.printStackTrace(); } } }
这里记住,只有可读权限的文件可以被读取到,其他类型的文件因为权限不够,所以读取不到。
修改已经存在的文件的权限:
进入到文件所在的目录:
找到对应的包找到对应的文件夹:
开始修改文件的权限:
这样文件权限就修改成功了,777表示三个阶段的文件权限都给了所有的权限,有权限就用1表示,没权限就用0表示,以此来算下的二进制码来表示的
SharedPreference介绍
在之前的存储用户信息的过程中,一直使用的是流来进行操作的,在Android中完全可以不用流来进行操作,就是使用SharedPreference来操作:步骤是:根据上下文获取到SharedPreference对象,然后使用sp调用edit方法获取到Editor对象,使用Editer对象进行put操作,最后进行commit提交数据。
在获取数据的时候同样是得到sp对象,然后直接调用get方法获取到数据
代码示例:
package com.itheima.login; import java.util.Map; import android.os.Bundle; import android.app.Activity; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.text.TextUtils; import android.view.Menu; import android.view.View; import android.widget.CheckBox; import android.widget.EditText; import android.widget.Toast; import com.itheima.sptest.R; public class MainActivity extends Activity { private EditText et_name; private EditText et_userpassword; private CheckBox cb_ischeck; private SharedPreferences sp; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //[0] 先初始化 sp 的实例 /** * name 会帮助我们生成一个xml文件 * mode 模式 */ sp = getSharedPreferences("config", 0); //[1]找到我们关心的控件 et_name = (EditText) findViewById(R.id.et_username); et_userpassword = (EditText) findViewById(R.id.et_userpassword); cb_ischeck = (CheckBox) findViewById(R.id.cb_ischeck); //[2]在 config.xml文件中把我们关心的数据取出来 然后显示到edittext控件上 String name = sp.getString("name", ""); String pwd = sp.getString("pwd", ""); //[3]把name 和 pwd 设置到edittext上 et_name.setText(name); et_userpassword.setText(pwd); //TODO 把checkbox状态逻辑给我写好 } //[2]写按钮的点击事件 public void login(View v){ //[2.1]获取用户名和密码 String name = et_name.getText().toString().trim(); String pwd = et_userpassword.getText().toString().trim(); //[2.2]判断name 和 pwd 是否为空 if (TextUtils.isEmpty(name)||TextUtils.isEmpty(pwd)) { Toast.makeText(MainActivity.this, "用户名或密码不能为空", 1).show(); }else { //[2.3]进行登录的逻辑 System.out.println("连接服务器 进行登录 等我们讲到 第四天 网络 编程 在说"); if (cb_ischeck.isChecked()) { //2.4 使用SharedPreferences 去保存数据 拿到sp的实例 //[2.5]获取sp的编辑器 Editor edit = sp.edit(); edit.putString("name", name); edit.putString("pwd", pwd); //[2.6]记得把edit 进行提交 edit.commit(); }else { Toast.makeText(MainActivity.this, "请勾选cb", 1).show(); } } } }
生成xml文件的第一种方式
就是传统的方式:通过sb组拼字符串的方式慢慢的写成一个xml文件的格式将数据封装成对象,存进集合当中,在组拼字符串的时候直接遍历集合取出对象,然后取出对象里面的数据就好了
代码示例
先来一个数据封装成的对象:
package com.itheima.generatexml; public class Sms { private String address; private String body; private String date; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } }
开始组拼xml文档的字符串:
package com.itheima.generatexml; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.view.Menu; import android.view.View; public class MainActivity extends Activity { private List<Sms> smsLists; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //[1]初始化我们要备份的数据 smsLists = new ArrayList<Sms>(); for (int i = 0; i < 10; i++) { Sms sms =new Sms(); sms.setAddress("10008"+i); sms.setBody("nihao"+i); sms.setDate("201"+i); //[2]把sms对象加入到 集合中 smsLists.add(sms); } } //点击按钮 通过StringBuffer 的方式生成一个xml文件 public void click(View v){ //[1]创建sb对象 StringBuffer sb = new StringBuffer(); //[2]开始组拼xml文件头 sb.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>"); //[3]开始组拼xml根节点 sb.append("<smss>"); //[4]开始组拼sms节点 for (Sms sms : smsLists) { sb.append("<sms>"); //[5]开始组拼address节点 sb.append("<address>"); sb.append(sms.getAddress()); sb.append("</address>"); //[6]开始组拼body节点 sb.append("<body>"); sb.append(sms.getBody()); sb.append("</body>"); //[7]开始组拼date节点 sb.append("<date>"); sb.append(sms.getDate()); sb.append("</date>"); sb.append("</sms>"); } sb.append("</smss>"); //[8]把数据保存到sd卡中 try { File file = new File(Environment.getExternalStorageDirectory().getPath(),"smsbackup.xml"); FileOutputStream fos = new FileOutputStream(file); fos.write(sb.toString().getBytes()); fos.close();//关闭流 } catch (Exception e) { e.printStackTrace(); } } }
最后记住,因为在代码中要将数据写入到sd卡中,所以需要给一个权限:
这样一个xml文件就形成了。
生成xml文件的第二种方式
使用XmlSerializer类里面的方法进行操作首先获取XmlSerializer对象,使用Xml.newSerializer()方法生成对象
设置序列化参数:setOutput()
设置文档开头startDocument()
设置开始标签startTag();
设置结束节点endTag();
设置节点中的文字text();
结束文档endDocument();
代码示例:
数据还是那个数据,集合还是那个集合
package com.itheima.generatexml; public class Sms { private String address; private String body; private String date; public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } }
开始生成xml文件
package com.itheima.generatexml; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlSerializer; import android.os.Bundle; import android.os.Environment; import android.app.Activity; import android.util.Xml; import android.view.Menu; import android.view.View; import com.itheima.generatexml2.R; public class MainActivity extends Activity { private List<Sms> smsLists; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //[1]初始化我们要备份的数据 smsLists = new ArrayList<Sms>(); for (int i = 0; i < 10; i++) { Sms sms =new Sms(); sms.setAddress("10008"+i); sms.setBody("nihao"+i); sms.setDate("201"+i); //[2]把sms对象加入到 集合中 smsLists.add(sms); } } //点击按钮 通过的XmlSerializer方式生成一个xml文件 public void click(View v){ try { //[1]获取XmlSerializer 类的实例 通过Xml这个工具类去获取 XmlSerializer serializer = Xml.newSerializer(); //[2]设置 xmlserializer序列化器参数 File file = new File(Environment.getExternalStorageDirectory().getPath(),"smsbackup2.xml"); FileOutputStream fos = new FileOutputStream(file); serializer.setOutput(fos, "utf-8"); //[3]开始写xml文档开头 serializer.startDocument("utf-8", true); //[4]写 xml的根节点 namespace 命名空间 serializer.startTag(null, "smss"); //[5]循环写 sms节点 for (Sms sms : smsLists) { serializer.startTag(null, "sms"); // [6]开始address节点 serializer.startTag(null, "address"); serializer.text(sms.getAddress()); serializer.endTag(null,"address"); // [7]开始body节点 serializer.startTag(null, "body"); serializer.text(sms.getBody()); serializer.endTag(null,"body"); // [8]开始date节点 serializer.startTag(null, "date"); serializer.text(sms.getDate()); serializer.endTag(null,"date"); //sms节点结束 serializer.endTag(null, "sms"); } serializer.endTag(null, "smss"); //写文档结尾 serializer.endDocument(); fos.close();//关闭流 } catch (Exception e) { e.printStackTrace(); } } }
因为数据是写入到sd卡中的,所以要在清单文件中给一个权限
对xml文件进行解析
就是通过XmlPullParser工具类来进行解析的这个类的来源也是通过Xml类获取到的
获取到parser对象之后,通过setInput方法来设置要读取的xml文件和要使用的编码方式
解析xml文件的时候是按照指针的方式一行一行的往下读取的,针对每一行都有自己对应的事件
获取这样的事件的方法就是getEventType
指针一行一行的往下走是要依赖一个next方法的。
然后开始通过判断获取到的事件对象(int值)来判断指针指到的节点是开始节点开始结束节点,还可以获取到所在节点的名称和内容,还有属性
详情见代码
获取资产目录里面的文件可以使用上下文对象,getAsses().open(“资产目录中的文件名”)返回的是一个流对象
代码:
想要将xml文件中的内容显示到一个textView中,画UI
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <TextView android:id="@+id/tv_weather" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </RelativeLayout>
创建bean
package com.itheima.xmpparser; public class Channel { private String id; private String city; private String temp; private String wind; private String pm250; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getTemp() { return temp; } public void setTemp(String temp) { this.temp = temp; } public String getWind() { return wind; } public void setWind(String wind) { this.wind = wind; } public String getPm250() { return pm250; } public void setPm250(String pm250) { this.pm250 = pm250; } @Override public String toString() { return "Channel [id=" + id + ", city=" + city + ", temp=" + temp + ", wind=" + wind + ", pm250=" + pm250 + "]"; } }
创建解析xml文件的工具类:
package com.itheima.xmpparser; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import android.util.Xml; public class WeatherParser { /** * 服务器是以流的形式把数据返回的 * @return */ public static List<Channel> parserXml(InputStream in) throws Exception{ //[0]声明集合对象 List<Channel> weatherLists = null; Channel channel = null; //[1]获取XmlPullParser 解析的实例 XmlPullParser parser = Xml.newPullParser(); //[2]设置XmlPullParser 的参数 parser.setInput(in, "utf-8"); //[3]获取事件类型 int type = parser.getEventType(); while(type!= XmlPullParser.END_DOCUMENT){ switch (type) { case XmlPullParser.START_TAG: //解析开始标签 //[4]具体判断一下 解析到是哪个开始标志 if ("weather".equals(parser.getName())) { //[5]创建一个集合对象 weatherLists = new ArrayList<Channel>(); }else if("channel".equals(parser.getName())){ //[6]创建Channel对象 channel = new Channel(); //[7]获取id值 String id = parser.getAttributeValue(0); channel.setId(id); }else if("city".equals(parser.getName())){ //[8]获取city的数据 String city = parser.nextText(); channel.setCity(city); }else if("temp".equals(parser.getName())){ //[8]获取city的数据 String temp = parser.nextText(); channel.setTemp(temp); }else if("wind".equals(parser.getName())){ //[8]获取city的数据 String wind = parser.nextText(); channel.setWind(wind); }else if("pm250".equals(parser.getName())){ //[8]获取city的数据 String pm250 = parser.nextText(); channel.setPm250(pm250); } break; case XmlPullParser.END_TAG: //解析结束标志 //判断要解析的结束标签 if ("channel".equals(parser.getName())) { //把javabean对象存到集合中 weatherLists.add(channel); } break; } //不停的向下解析 type = parser.next(); } return weatherLists; } }
在主函数中解析xml文件
package com.itheima.xmpparser; import java.io.InputStream; import java.util.List; import android.os.Bundle; import android.app.Activity; import android.widget.TextView; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); try { //[1]显示天气信息 TextView tv_weather = (TextView) findViewById(R.id.tv_weather); //[1.1]获取资产的管理者 通过上下文 InputStream inputStream = getAssets().open("weather.xml"); //[2]调用我们定义的解析xml业务方法 List<Channel> weatherlists = WeatherParser.parserXml(inputStream); StringBuffer sb = new StringBuffer(); for (Channel channel : weatherlists) { sb.append(channel.toString()); } //[3]把数据展示到textviwe上 tv_weather.setText(sb.toString()); } catch (Exception e) { e.printStackTrace(); } } }
相关文章推荐
- Android基础学习之Provider(内容提供器)
- 利用DisplayMetrics类获取Android设备屏幕分辨率
- android开发之使用拼音搜索汉字
- android开发之使用拼音搜索汉字
- android开发之使用拼音搜索汉字
- android开发之使用拼音搜索汉字
- Android必备的Java知识点
- Android中的距离单位
- Android五大布局
- Android 6.0 新增API 简介(1)
- 使用include findViewById 返回null
- Android4.0图库Gallery2代码分析(二) 数据管理和数据加载
- React-native Android Java Module如何暴露自己的方法给js
- Android开发中CheckBox的setOnClickListener和setOnCheckedChangeListener的不同之处在哪?
- android pppoe
- Android使用AIDL与远端服务交互
- android入门
- Android Fragment 真正的完全解析(下)
- Android中联系人和通话记录详解(联系人的增删改查)(3)
- Android抽屉(SlidingDrawer --类似android通知栏下拉效果)