第八章 Android数据存储于IO
SharedPreference的概念和作用
使用SharedPreference保存程序的参数、选项
读写其他应用的SharedPreference
Android的文件IO
读写SD卡上的文件
了解SQLite数据库
使用Android的API操作SQLite数据库
使用sqlite3工具管理SQLite数据库
SQLiteOpenHelper类的功能和用法
Android手势支持
手势监测
向手势库中添加手势
识别用户手势
1、使用SharedPreference
SharedPreference保存的数据主要是类似于配置信息格式的数据,因此它保存的数据主要是简单类型的key-value对。
SharedPreference是一个接口,它主要负责读取应用程序中的Preference数据:
boolean contains(String key):判断SharedPreference是否包含特定key的数据
abstract Map<String,?> getAll():获取SharedPreference数据中全部的key-value对。
boolean getXxx(String key,XXX defValue):
SharedPreference接口本身没有写入数据的能,是通过SharedPreference的内部接口,调用edit()方法即可获取它所对应的Editor对象。Editor提供了向SharedPreference写入数据的方法:
SharedPreference.Editor clear():情况SharedPreference里所有的数据。
SharedPreference.Editor putXxx(String key,XXX value):向SharedPreference存入指定key对应的数据,value可以是boolean float int long String等基本数据类型
SharedPreference.Editor remove(String key):删除指定key对应的数据。
boolean commit():当Editor编辑完成后,调用该方法提交修改
从用法上看,SharedPreference和SharedPreference.Editor组合起来非常像Map,其中SharedPreference负责根据key读取数据,SharedPreference.Editor则用于写入数据
SharedPreference本身是一个接口,程序无法直接创建实例,只能通过Context提供的getSharedPreference(String name,int mode)方法获取它的实例,第二个参数支持如下值:
Context.MODE_PRIVATE:指定该SharedPreference数据只能被本程序读写
Context.MODE_WORLD_READABLE:指定该SharedPreference数据能被其他应用读,但不能写
Context.MODE_WORLD_WRITEABLE_READABLE:指定该SharedPreference数据能被其他应用读写。
Note:从Android4.2开始,Android不在推荐使用Context.MODE_WORLD_READABLE、Context.MODE_WORLD_WRITEABLE_READABLE这两种模式,容易导致安全漏洞。如果应用程序需要把内部数据暴漏出去供其他应用访问,则应该使用ContentProvide。
SharedPreference数据总是保存在/data/data//shared_prefs目录下,以XML格式保存。
2、File存储
读写应用程序数据文件夹里的文件
Context提供了连个方法来打开应用程序的数据文件夹里的文件IO流:
FileInputStream openFileInput(String name):打开应用程序的数据文件夹下的那么文件对应的输入流。
FileOutputStream openFileOutput(String name,int mode):打开应用程序的数据文件夹下的name文件对应的输出流。。
mode参数:
MODE_PROVATE:该文件只能被当前程序读写
MODE_APPEND:以追加方式打开该文件,应用程序可以向该文件中追加内容
MODE_WORLD_READABLE:该文件的内容可以被其他应用读取
MODE_WORLD_WRITEABLE:该文件可由其他应用程序读写
4.2后不推荐使用全局可读写模式
除此之外,Context还提供了如下方法来访问应用程序的数据文件夹:
getDir(String name,int mode):在应用程序的数据文件夹下获取或创建name对应的子目录
File getFilesDir():获取应用程序的数据文件夹的绝对路径
String[] fileList():返回应用程序的数据文件夹下的全部文件
deleteFile(String name):删除应用程序的数据文件夹下的指定文件
应用程序的数据文件默认保存在/data/data//files目录下
读写SD卡上的文件
需要首先声明读写SD卡的权限:
<!--在SD卡中创建与删除文件权限-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--向SD卡写入数据权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
步骤:
调用Environment的getExternalStorageState()方法判断手机是否插入SD卡,
调用Environment的getExternalStorageDirectory()方法获取外部存储器,也就是SD卡的目录
使用FileInputStream、FileOutputStream、FileReader或FileWriter读写SD卡里的文件。
3、SQLite数据库
SQLite数据库是Android系统集成的一个轻量级的数据库,支持绝大部分的SQL 92语法,也允许开发者使用SQL语句操作数据库中的数据,但是SQLite不像Oracle、MySQL数据库那样需要安装、启动服务器进程,SQLite数据库只是一个文件。
SQLiteDatabase
Android提供了SQLiteDatabase代表一个数据库(底层就是一个数据库文件),一旦应用获取了代表指定数据库的SQLiteDatabase对象,接下来就可以通过SQLiteDatabase对象来管理、操作数据库了。
SQLiteDatabase提供了静态方法来打开一个文件对应的数据库:
static SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags):打开path文件所代表的SQLite数据库
static SQLiteDatabase openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory):打开或创建(如果不存在)path文件所代表的SQLite数据库
static SQLiteDatabase openOrCreateDatabase(File file, SQLiteDatabase.CursorFactory factory)打开或创建(如果不存在)file文件所代表的SQLite数据库
获取了SQLiteDatabase对象之后,就可以调用SQLiteDatabase的方法操作数据库了:
增删改查、开关事务
创建数据库和表
SQLiteDatabase.openOrCreateDatabase("/mnt/db/temp.db3",null);
上面的代码就用于打开或创建一个SQLite数据库,如果/mnt/db/目录下的temp.db3文件(其实就是一个数据库)存在,那么程序就打开该数据库;如果不存在,则上面的代码就会在该目录下创建temp.db3文件(即对应于数据库)。
上面代码没有指定SQLiteDatabase.CursorFactory参数,该参数是一个用于返回Cursor的工厂,如果为null,意味着使用默认工厂。
上面代码会返回一个SQLiteDatabase对象,该对象就可进行操作数据库
使用SQL语句操作SQLite数据库
SQLiteDatabase的execSQL()方法可执行任意的SQL语句,包括带占位符的SQL语句。但由于该方法没有返回值,因此一般用于执行DDL语句或DML语句;如果需要执行查询语句,则可调用SQLiteDatabase的rawQuary(String sql,String[] selectionArgs)方法。
db.execSQL("insert into news_inf values(null,?,?)",new String[]{title,content});
使用SQLiteDatabase进行数据库操作的步骤:
获取SQLiteDatabase对象,它代表有数据库的链接。
调用SQLiteDatabase的方法执行SQL语句
操作SQL语句的执行结果
关闭SQLiteDatabase,回收资源
使用sqlite3工具
在Android SDK的platform-tools目录下提供了一个sqlite3.exe文件,它是一个简单的Sqlite数据库管理工具,类似于MySQL提供的命令行窗口。
sqlite3常用命令:
.database:查看当前数据库
.tables:查看当前数据库里的数据表
.help:查看sqlite3支持的命令
事务
beginTransaction():开始事务
endTransaction():结束事务
inTransaction():判断当前上下文是否处于事务环境中;处于事务中 返回true 否则返回false
当执行endTransaction()方法时将会结束事务——那到底是提交事务,还是回滚事务呢?这取决于SQLiteDatabase是否调用了setTransationSuccessful()方法来设置事务标志,如果程序在事务执行中调用该方法设置了事务成功则提交事务;否则程序将会回滚事务。
SQLiteOpenHelper
实际项目中很少使用SQLiteDatabase的方式打开数据库,通常都会继承SQLiteOpenHelper开发子类,并通过该子类的getReadableDatabase()、getWritableDatabase()方法打开数据库。
SQLiteOpenHelper是Android提供的一个管理数据的工具,可用于管理数据库的创建和版本更新。一般用法是创建SQLiteOpenHelper的子类,并扩展它的onCreate(SQLiteDatabase db)和onUpdgrade(SQLiteDatabase db,int oldVersion,int newVersion)方法。
SQLiteOpenHelper常用方法:
SQLiteDatabase getReadableDatabase():以读写的方式打开数据库对应的SQLiteDatabase对象
SQLiteDatabase getWritableDatabase():以写的方式打开数据库对应的SQLiteDatabase对象
abstract void onCreate(SQLiteDatabase db):当第一次创建数据库时回调该方法,做一下生成数据库表结构,添加应用使用到的一些初始化数据的操作
abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):当数据库版本更新时回调该方法;更新表结构
synchronized void close():关闭所有打开的SQLiteDatabase对象
getReadableDatabase()和getWritableDatabase()的区别:
getWritableDatabase()方法以写的方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,这种方式打开数据库就会报错;getReadableDatabase()方式先以读写方式打开数据库,如果数据库磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。
4、手势(Gesture)
手势监测
Android为手势监测提供了一个GestureDetector类,GestureDetector实例代表一个手势检测器,创建GestureDetector时需要传入一个GestureDetector.OnGestureListener实例,GestureDetector.OnGestureListener就是一个监视器,负责对用户手势行为提供相应
GestureDetector.OnGestureListener:
boolean onDown(MotionEvent e):
boolean onFling(MotionEvent e1,Motion Event e2,float velocityX,float velocityY):当用户手指在屏幕上"拖动"时触发该方法,其中velocityX、velocityY代表“拖过”动作在横向、纵向上的速度。
abstract void onLongPress(MotionEvent e):
boolean onScroll(MotionEvent e1,MotionEvent e2,float distanceX,float distanceY):当用户手指在屏幕上"滚动"时触发该方法
void onShowPress(MotionEvent e):当用户手指在屏幕上按下,而且还为移动和松开时触发该方法
boolean onSingleTapUp(MotionEvent e):用户手指在触摸屏上的轻击事件将会触发该方法
使用Android的手势监测只需两个步骤:
创建一个GestureDetector对象。创建对象时必须实现一个GestureDetector.OnGestureListener监听器实例
为应用程序的Activity(偶尔也为特定组件)的TouchEvent事件绑定监听器,在事件处理中把Activity(或特定组件)上的TouchEvent事件交给GestureDetector处理
public class GestureActivity extends AppCompatActivity{
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesture);
gestureDetector = new GestureDetector(this,new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
}
增加手势
Android处理提供手势监测之外,还允许应用程序把用户手势(多个持续的触摸事件在屏幕上形成的特定的形状)添加到制定文件中,以备以后使用——当程序需要,当用户下次再次画出该手势时,系统可识别该手势:
Android使用GestureLibrary来代表手势库,并提供了GestureLibraries工具类来创建手势库
GestureLibraries提供了4个静态方法从不同位置加载手势库:
static GestureLibrary fromFile(String path):从path代表的文件中加载手势库
static GestureLibrary fromFile(File path):从path代表的文件中加载手势库
static GestureLibrary fromPrivateFile(Context context,String name):从指定应用程序的数据文件夹的name文件中加载手势库
static GestureLibrary fromRawResource(Context context,int resourceId):从resourceId所代表的资源中加载手势库
一旦程序获得了GestureLibrary对象之后,该对象提供了添加、识别、保存手势的方法
Android处理提供了GestureLibrary、GestureLibraries来管理手势之外,还提供了一个专门的手势编辑组件:GestureOverlayView,该组件就像一个"绘图组件",只是用户在组件上绘制的不是图形,而是手势
为了监听GestureOverlayView组件上的手势事件,Android为它提供了OnGestureListener、onGesturePerformedListener、onGesturingListener三个监视器接口,这些监视器所包含的方法分别用于响应手势开始、结束、完成、取消等事件,可根据开发要求选择不同的监视器——一般来说,onGesturePerformedListener是最常用的监视器,它用来在手势事件完成时提供相应
<android.gesture.GestureOverlayView
android:id="@+id/gesture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gestureStrokeType="multiple"
/>
android:gestureStrokeType=""参数控制手势是否需要多一笔完成,single表示只要一笔就可以完成,multiple表示需要多笔完成。
识别手势
GestureLibrary提供了recognize(Gesture ges)方法来识别手势,该方法返回该手势库中所有与ges匹配的手势——两个手势的图形越相似,相似度越高。
recognize(Gesture ges)方法的返回值为ArrayList<Prediction>,其中Prediction封装了手势的匹配信息,Prediction对象的name属性代表了匹配的手势名,score属性代表了手势的相似度。
自动朗读(TTS)
Android提供了自动朗读的功能
自动朗读支持可以对指定文本内容进行朗读,从而发出声音;不仅如此,Android的自动朗读支持还允许吧文本对应的音频录制成音频文件,方便以后播放。这种自动朗读支持的英文名称为TextToSpeech,简称TTS。借助于TTS的支持,可以在应用程序中动态地增加音频输出,改善用户体验。
Android的自动朗读支持主要通过TextToSpeech完成:
TextToSpeech(Context context,TextToSpeech.OnInitListener listener)
目前Android的TTS暂不支持中文。