android笔记

短信发送

短信发送:(通过获得默认的短信管理器来实现)
android:minLines=3文本输入框显示行数
通知的三种方式:状态栏,对话框,吐司
吐司显示的2个重载方法,一个是传入字符串,一个是传入ID(ID有利于国际化)
Toast.makeText(MainActivity.this,R.string.success,Toast.LENGTH_LONG).show();
Toast.makeText(getApplicationContext(),"success",1).show();
代码中引入资源:R.string.success;XML中引入资源android:text="@string/success";
用模拟器接收中文短信会出现乱码,但手机上不会。如果文本内容过多,则会自动分条发送。

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button button=(Button) this.findViewById(R.id.button);
        button.setOnClickListener(new ButtonClickListener());
    }
    private class ButtonClickListener implements View.OnClickListener{

  @Override
  public void onClick(View v) {
   EditText mobileText=(EditText) findViewById(R.id.mobile);
   EditText contentText=(EditText) findViewById(R.id.content);
   String mobile=mobileText.getText().toString();
   String content=contentText.getText().toString();
   SmsManager smsManager=SmsManager.getDefault();//获得系统短信管理器
   ArrayList<String> texts=smsManager.divideMessage(content);//自动分割文本内容
   for(String text:texts){
    smsManager.sendTextMessage(mobile, null, text, null, null);//参数:接收号码地址,短信中心地址,文本,发送状态,接受状态
   }
   Toast.makeText(getApplicationContext(), R.string.success, 1).show();//传入Activity可用MainActivity.thisgetApplicationContext();10分别代表吐司显示时间的长短,吐司内容可以传入字符串或ID(推荐使用ID,有利于国际化)
  }
     
    }
}

 

 

单元测试

 android:stretchColumns="1"用于表格布局,值为01,1表示单元格可以拉升
单元测试:
1.搭建测试环境,清单中引入测试库(application之下),最后配置启动装置和要测试应用所在的包。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="cn.itcast.action“ android:versionCode="1“  android:versionName="1.0">
 <application android:icon="@drawable/icon" android:label="@string/app_name">
       <uses-library android:name="android.test.runner" />
        ....
 </application>
 <uses-sdk android:minSdkVersion="6" />
 <instrumentation android:name="android.test.InstrumentationTestRunner"
  android:targetPackage="cn.itcast.action" android:label="Tests for My App" />//targetPackage配置被测试应用所在包

2.编写业务类,业务方法
3.编写业务测试用例,测试用例要继承AndroidTestCase,测试用例中,测试方法testSave 等命名,并在方法后抛出异常
public void testSave()throws Throwable{
实例化业务类,并调用方法进行测试
Assert.assertEquals(期望结果,实际结果)可以对比实际结果是否是正确的
}
4.OUTLINE中运行相应的方法查看测试结果。

编写中错误:

没有实例化业务类,没有将结果传入assertEquals方法。

 

 

 

 

日志输出

日志:时间,进程ID, 标志,信息
W ,E 代表查看大于警告,错误的所有日志。
日志过滤器,通过TAG,PID,TYPE查找日志信息。过滤器名任意。
日志输出通过类Log实现:Log.i,Log.e,Log.w输出不同级别的信息
Log.i(tag,msg);tag是当前类名或代表当前类名常量,msg要输出的日志信息
输出日志的另一种方法: System.out.println("xxxxxxxxxxx"); 输出info级别,TAGSystem.out
System.err.println("xxxxxxx"); 输出ERROR 级别的信息,TAGSystem.err
推荐使用Log输出。日志视图输出中文信息会显示乱码。

 

数据存储与访问1

对处理后的数据进行存储,以供再次访问。
android为数据存储提供了5种方式:文件,SharedPreferendes参数,SQLite数据库,ContentProvider 内容提供

者,网络
文件存储方式:
文件可存储在手机自带存储空间(1G,200M)或外存储设备(SDCard,36G,要考虑文件的大小来选择。
案例NOTICE:
 文件存储主要用IO实现。存储方法写在业务类中。

public class FileService {
 private Context context;
 public FileService(Context context) {
  this.context = context;
 }
 //存储数据
 public void save(String name, String content) throws Exception {
 FileOutputStream out=context.openFileOutput(name, Context.MODE_PRIVATE);
 out.write(content.getBytes());
 out.close();
 }

//读取数据

public String read(String name)throws Exception{
  ByteArrayOutputStream out=new ByteArrayOutputStream();
  FileInputStream in=context.openFileInput(name);
  int len=0;
  byte[] buf=new byte[1024];
  while((len=in.read(buf))!=-1){
  out.write(buf,0,len);
  }
  byte[] data=out.toByteArray();
  return new String(data);
 }
}
获得输出流:context.openFileOutput(filename,mode);//参数为文件名和操作模式,注意要给context 赋值(构造函数或set
文件操作模式:
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);

context.openFileOutput默认将文件保存在data\data\应用包\files文件夹下。context.openFileInput默认从该文件夹下读取文件

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

 

 

 

 

SDcard文件写入

SD卡的目录:/mnt/sdcard,推荐使用Environment类来得到SD卡路径。(Environment方法试验时失败,还需验证)
SD卡写数据,要在清单文件加创建权限和写入权限

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

判断SD的状态,Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED),存在则创建写入数据。

SD卡写数据方法:

public void send(String name,String content)throws Exception{
  File file=new File(new File("/mnt/sdcard"), name);
  FileOutputStream outStream=new FileOutputStream(file);//区别于手机自带存储的openFileInput
  outStream.write(content.getBytes());
  outStream.close();
 }

保存到SD卡的路径可以供其他应用访问。

 

 

 

 

 

XMLpull解析

Android平台上可以使用Simple API for XML(SAX) 、 Document Object Model(DOM)Android附带的pull解析器解析XML文件。

 Pull解析器是一个开源的java项目,既可以用于android,也可以用于JavaEE

原理:将XML内容读取到一个字符数组中,switch,不同的元素触发不同的事件。
解析XML

为了方便获取,XML文件直接放在SRC目录下

写一个java bean用来存储数据,在业务类中编写解析方法。
调用业务方法进行解析

测试时获得InputStream 类型的XML:this.getClass().getClassLoader().getResourceAsStream("person.xml");

parser.next()可以进入下一个元素并触发相应事件

空白节点属于文本节点,不处理
parser.nextText()可获得下一个文本节点的文本值

public static List<Person>  getPersons(InputStream xml)throws Exception{
 XmlPullParser parser=Xml.newPullParser();
 List<Person> persons=null;
 Person person=null;
 parser.setInput(xml, "UTF-8");
 int event=parser.getEventType();
 while(event!=XmlPullParser.END_DOCUMENT){
  switch(event){
  case XmlPullParser.START_DOCUMENT:
  persons=new ArrayList<Person>();
  break;
  case XmlPullParser.START_TAG:
   if("person".equals(parser.getName())){
    person=new Person();
    Integer id=new Integer(parser.getAttributeValue(0));
    person.setId(id);
   }else if("name".equals(parser.getName())){
    person.setName(parser.nextText());
   }else if("age".equals(parser.getName())){
    person.setAge(new Integer(parser.nextText()));
   }
   break;
  case XmlPullParser.END_TAG:
   if("person".equals(parser.getName())){//这一句,试验时忘了加
    persons.add(person);
    person=null;
   }
  
  break;
  
  }
  event=parser.next();
 }
 return persons;
}
}

案例错误:

业务方法中case XmlPullParsr.END_TAG: 忘了判断"person".equals(parser.getName());

测试时没有在清单文件中添加测试环境。

 

 

pull解析器将数据生成XML文件

生成方式和编写XML的顺序一样,用到类XmlSerializer

测试时getContext().getFilesDir(),用于获得手机自带存储的files文件夹目录

public class XmlService {
 public void save(List<Person> persons, OutputStream out) throws Exception {
  XmlSerializer ser = Xml.newSerializer();
  ser.setOutput(out, "UTF-8");
  ser.startDocument("UTF-8", true);// 指定文档开始编码和文档是否能够独立存在
  ser.startTag(null, "persons");
  for (Person person : persons) {//编写时写错了for 循环的位置
   ser.startTag(null, "person");// 指定开始元素的域名空间,和元素名
   ser.attribute(null, "id", person.getId().toString());//javaBean时,数据类型推荐使用包装类型Integer,Short
   ser.startTag(null, "name");
   ser.text(person.getName());
   ser.endTag(null, "name");
   ser.startTag(null, "age");
   ser.text(person.getAge().toString());
   ser.endTag(null, "age");
   ser.endTag(null, "person");
   ser.startTag(null, "person");
   ser.startTag(null, "name");
   ser.text(person.getName());
   ser.endTag(null, "name");
   ser.startTag(null, "age");
   ser.text(person.getAge().toString());
   ser.endTag(null, "age");
   ser.endTag(null, "person");
  }
  ser.endTag(null, "persons");
  ser.endDocument();
  out.flush();
  out.close();
 }

 

 

SharedPreferences参数存储

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

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

public class PreferenceService {
private Context context;
 public PreferenceService(Context context) {
 this.context = context;
}
 public void save(String name, int age) {
  SharedPreferences sp=context.getSharedPreferences("person", Context.MODE_PRIVATE);//获得参数类型对象并设置存储到 xml,XML的文件名,不用加后缀

 Editor editor=sp.edit();// 获得编辑器
  editor.putString("name", name);
  editor.putInt("age", age);
  editor.commit();//将内存的数据写入XML文件
 }

}

2.从存储的XML中读取参数回显

onClick()方法中为EditText设置回显值即可。nametext.setText(sp.getString("name"));

public Map<String ,String> read(){
 Map<String,String> map=new HashMap<String,String>();
 SharedPreferences sp=context.getSharedPreferences("person", Context.MODE_PRIVATE);
 map.put("name", sp.getString("name", ""));
 map.put("age", String.valueOf(sp.getInt("age", 0)));//操作时,类型转换出现过错误
 return map;
}

 

 

SQLite数据库存储数据

SQLite Android 系统内置的一种嵌入式关系数据库。SQLite可以解析大部分标准SQL语句

SQLite3支持 NULLINTEGERREAL(浮点数字)、TEXT(字符串文本)BLOB(二进制对象)数据类型,虽然它支持的类型只有五种,但实际上sqlite3也接受varchar(n)char(n)decimal(p,s) 等数据类型,只不过在运算或保存时会转成对应的五种数据类型。 SQLite最大的特点是你可以把各种类型的数据保存到任何字段中,而不用关心字段声明的数据类型是什么。例如:可以在Integer类型的字段中存放字符串,或者在布尔型字段中存放浮点数,或者在字符型字段中存放日期型值。 但有一种情况例外:定义为INTEGER PRIMARY KEY的字段只能存储64位整数, 当向这种字段保存除整数以外的数据时,将会产生错误。 另外,在编写CREATE TABLE 语句时,你可以省略跟在字段名称后面的数据类型信息。

创建数据库:

1写一个业务类继承SQLiteOpenHelper,一般在业务类的onCreate()方法中编写创建表代码,onUpdate()方法中编写数据库更新操作。这两个方法都由系统调用。

2.在业务类实例调用getWritableDatabase() getReadableDatabase()时完成数据库创建。

public class DBOpen extends SQLiteOpenHelper {
 public DBOpen(Context context) {
  super(context, "hd.db", null, 1);//显示调用父类构造方法,参数:上下文,数据库名,游标工厂,版本号
 }

 @Override
 public void onCreate(SQLiteDatabase db) {//当数据库创建时系统调用
db.execSQL("CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))");//创建表
 }

 @Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {//当数据库版本发生变化时系统调用
   db.execSQL(" ALTER TABLE person ADD phone VARCHAR(12) NULL ");//在原表中额外添加新字段
 }

}

 

 

 

SQLite数据CURD操作2种方式

获取数据库操作对象的2个方法的区别:getWritableDatabase()getReadabelDatabase();

getReadabelDatabase();的源代码是先调用getWritableDatabase()获取可写数据库对象,如果获取不到,则再获取只读的数据库。

第一种方式:数据库操作对象SQLiteDatabase调用execSQL()rawQuery()实现,编码简单(推荐使用)

第二种凡是:数据库操作对象调用insert,update,delete,query实现。

public class CRUDService {
 private DBCreate service;
public CRUDService(Context context) {//将对象传入
  service=new DBCreate(context);
 }
public void save(Person person){
 SQLiteDatabase db=service.getWritableDatabase();
 db.execSQL("insert into person(name,phone) values (?,?)", new Object[]{person.getName(),person.getPhone()});
}
public void update(Person person){
 SQLiteDatabase db=service.getWritableDatabase();
 db.execSQL("update person set name=?,phone=? where id=?", new String[]{person.getName(),person.getPhone(),person.getId().toString()});
}
public Person find(Integer personid){
 SQLiteDatabase db=service.getReadableDatabase();
 Cursor cursor=db.rawQuery("select * from person where id=?", new String[]{personid.toString()});
 if(cursor.moveToFirst()){
  int id=cursor.getInt(cursor.getColumnIndex("id"));
  String name=cursor.getString(cursor.getColumnIndex("name"));
  String phone=cursor.getString(cursor.getColumnIndex("phone"));
  cursor.close();
  return new Person(id,name,phone);
 }
  return null;
 
}
public void delete(Integer id){
 SQLiteDatabase db=service.getWritableDatabase();
 db.execSQL("delete from person where id=?",new Object[]{id.toString()});
}
public List<Person> getScroll(int offset,int maxsize){//记录分页代码
 List<Person> persons=new ArrayList<Person>();
 SQLiteDatabase db=service.getReadableDatabase();
 Cursor cursor=db.rawQuery("select * from person limit ?,?", new String[]{String.valueOf(offset),String.valueOf(maxsize)});
 while(cursor.moveToNext()){
  int id=cursor.getInt(cursor.getColumnIndex("id"));
  String name=cursor.getString(cursor.getColumnIndex("name"));
  String phone=cursor.getString(cursor.getColumnIndex("phone"));
  persons.add(new Person(id,name,phone));
  
 }
 cursor.close();
 return persons;
}
public long getCount(){
 
 SQLiteDatabase db=service.getReadableDatabase();
 Cursor cursor=db.rawQuery("select count(*) from person", null);
 cursor.moveToFirst();
 return cursor.getLong(0);
}
}
第二种是拼接SQL语句的方式

pubic void save(Person person){

SQLiteDatabase db=DBCreate.getWritableDatabase();

ContentValues values=new ContentValues();//内容集

values.put("name",person.getName());

values.put("phone",person.getPhone());

db.insert("new",null,values);//参数:表明,空字段名(只有valuesnull时设置值),内容集

}

 db.update("new",values,"personid=?",new String[]{person.getId|().toString()});//参数:表名,内容集,条件,条件值

db.query("new",new String[]{"name","phone"},"personid=?",new String[]{id.toString},null,null,null)//第二个参数,要查询的字段,null表示全部

db.delete("new","personid=?",new String[]{id.toString()});

Cursor cursor =db.query("new",null,null,null,null,null,"personid asc",offset+","+maxsize);分页

db.query("new",new String("conut(*)"),null,null,null,null,null);相当于 count *

 

 

 

 

SQLite 数据库事物操作

public void pay(){

SQLiteDatabase db=dbservice.getWritableDatabase();//有缓存

db.beginTransaction();//开事物。

try{

db.execSQL("update person set amount=amount+100 where id=1");

db.execSQL("update person set amount=amount-100 where id=2");

db.setTransactionSuccessfully();//设置事物标志为True,相当于提交

}finally{

db.endTransaction();//根据事物标志判断是否提交或回滚,默认为false(回滚),并结束事物

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值