本节引言:
Android入门系列已经写了大半了,学习了这么多理论知识,不练下手怎么行呢?
在实际的开发中我们会遇到更多的问题,同时也能加固我们的基础知识!鉴于
笔者的水平有限,该项目,面对的是初学者,各位大牛路过不喜勿喷!好吧说下第一个
练手项目吧,前几天中秋节今天又是教师节,各种祝福短信满天飞,手打再群发,条条
短信一个样,没意思!直接用别人弄好的短信群发,别人又不知道你是谁,起码加个:
亲爱的XXX.我是隔壁老王,.....别人起码知道你是谁把!好了,废话不多说,开始app
的开发吧!
ps:目前app的基本功能已经实现,效果图如下,如果有需要可以进行下载
到后面会逐步完善相关功能:
效果图:
参考代码下载:
源码下载
正文:
本节要点图:
开发流程详解:
1)创建数据库
创建数据库文件:有两个表,分别为存储联系人的表contacts和存储节日祝福语的表festival
可以直接使用SQLite Expert或者其他SQLite的可视化工具创建表,可以代码创建或者手动创建
代码创建的话执行以下语句生成数据库表:
CREATE TABLE festival(sentence_id INTEGER PRIMARY KEY AUTOINCREMENT,detail)
CREATE TABLE contacts(_id INTEGER PRIMARY KEY,pname,pnumber,pstate)
接着对节日表进行数据的录入,结束的表结构如下:
festival表:
contacts表:
2)应用启动时判断数据库文件是否存在
在完成上述创建数据库的步骤后,接着我们需要把数据库文件复制到assert目录下
这里我们要做什么呢?
在应用启动的时候我们需要判断data/data/<包名>/database下有没有我们的数据库文件
如果不存在的话,我们需要通过代码将数据库文件导入到指定目录下!
①先定义我们的数据库名称以及包名常量:
public static String dbName=my.db;
//数据库的名字private static String DATABASE_PATH=/data/data/com.jay.example.festivalsmshelper/databases/;
②接着定义判断是数据库文件是否存在的方法:
public boolean checkDataBase(){
SQLiteDatabase checkDB = null;
try{
String databaseFilename = DATABASE_PATH+dbName;
checkDB =SQLiteDatabase.openDatabase(databaseFilename, null, SQLiteDatabase.OPEN_READONLY);
}
catch(SQLiteException e){
}
if(checkDB!=null){
checkDB.close();
}
return checkDB !=null?true:false;
}
③假如数据库文件不存在的话我们需要将数据库文件复制到指定目录下:
public void copyDataBase() throws IOException{
String databaseFilenames =DATABASE_PATH+dbName;
File dir = new File(DATABASE_PATH);
if(!dir.exists())//判断文件夹是否存在,不存在就新建一个 dir.mkdir();
FileOutputStream os = null;
try{
os = new FileOutputStream(databaseFilenames);
//得到数据库文件的写入流 }
catch(FileNotFoundException e){
e.printStackTrace();
}
InputStream is = MainActivity.this.getAssets().open(my.db);
byte[] buffer = new byte[4096];
int count = 0;
try{
while((count=is.read(buffer))>0){
os.write(buffer, 0, count);
os.flush();
}
}
catch(IOException e){
e.printStackTrace();
}
is.close();
os.close();
}
④在MainActivity的onCreate()方法中加入下面的代码,用于调用上述两个方法:
boolean dbExist = checkDataBase();
if(dbExist){
}
else{
//不存在就把assert里的数据库写入手机 try{
copyDataBase();
}
catch(IOException e){
throw new Error(复制数据库出错);
}
}
⑤打开File Exploer查看数据库文件是否复制完毕:
如图就说明数据库文件复制完毕,是仅仅有一个my.db文件而已!后面那个my.do-journal是因为执行了
其他的操作生成的!
3)读取系统的联系人目录:
这里的话我们读取的仅仅是联系人的目录,并不包括sim卡中的联系人哦!
这块就涉及到了我们前面所学的使用系统提供的ContentProvider了!
我们先把系统提供的联系人的数据库文件找出来瞅瞅吧!
打开文件浏览器:data/data/com.android.providers.contacts/databases
下面的contacts2.db文件就是存储系统联系人的数据库文件了:
导出以后查看几个重要的基本表,以及相关字段:
contacts表
data表
phone_look_up表
raw_contact表
以上四个就是我们要留意的四个表了
好了,说下我们要获取的数据:联系人id,姓名,一个电话号码
于是我们定义一个类GetPhone类并定义一个读取联系人的方法,将读到数据存储到list集合中:
代码如下:
public static List
getPerson(Context context) {
Listpersons = new ArrayList ();
ContentResolver cr = context.getContentResolver();
Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI,null, null, null, null);
while(cursor.moveToNext()){
Person person = new Person();
//获取联系人id String contatId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
person.setId(Integer.parseInt(contatId));
//获取联系人姓名 String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
person.setName(name);
//因为一个联系人的电话号码可能有几个,但我们这里仅仅是获取一个就够了,所以就不循环遍历了 Cursor phones = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+=+contatId, null, null);
phones.moveToFirst();
String num = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
person.setNumber(num);
person.setState(-1);
persons.add(person);
phones.close();
}
cursor.close();
return persons;
}
4)定义一个插入数据的方法:
该方法的参数是一个Person的对象,我们使用ContentValues来存储从person取出的不同数据!
再调用db.insert(contacts,null,contentValue)将记录插入到contacts表中
代码:
public void insert(Person person){
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(_id, person.getId());
values.put(pname, person.getName());
values.put(pnumber, person.getNumber());
values.put(pstate, person.getState());
db.insert(contacts, null, values);
}
5)在MainActivity中调用获取联系人的方法,插入数据
怕数据太多,出现卡住的情况,加个进度条,用户看着没那么不爽!
再new一个线程,一秒钟后让进度条消失,第一个界面消失,通过intent跳转
到第二个界面中!
代码:
//加个进度条,数据太多可能卡住不好,用户看着不爽 final ProgressDialog dialog = ProgressDialog.show(this, 提示, 读取联系人中, false, true);
GetContactsService getContacts = new GetContactsService(getApplicationContext());
Listpersons = GetPerson.getPerson(MainActivity.this);
Cursor cursor = getContacts.query(select count(*) from contacts, null);
cursor.moveToFirst();
//判断联系人数目是否发生变更,没变更的话就不用调用下面的for循环了 if(persons.size() != cursor.getInt(0)) {
for(Person p : persons) {
System.out.println(p.toString());
getContacts.insert(p);
}
}
//设置让圆形进度条过一秒后消失,以及第一个界面消失,跳转到第二个界面 new Thread() {
public void run() {
try {
sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
dialog.dismiss();
Intent it = new Intent(getApplicationContext(), ChooseActivity.class);
startActivity(it);
finish();
}
;
}
.start();
6)运行后的效果查看:
将my.db文件导出后可以看到contacts表的data已经有数据了,就完成了
另外记得还有个Person类别漏了,定义四个属性:id,name,number,state(记录是否已经发送)
这里就不给出了,另外要创建出第二个Activity完成Intent的跳转哦!不然可是会报错的!
知识点总结:
1.判断app中的数据库文件是否存在?不存在的话如何使用输入流将文件写入到相应目录下
2.如何获得assert里的文件,从而获得输入流对象;
3.哪里可以找到系统保存联系人的数据库;相关表以及字段的了解!
读取表中我们需要的联系人信息!
4.调用database的insert()方法插入ContentValues类型的数据
5.获得数据库表有多少条记录的方法:
Cursor cursor = getContacts.query(select count(*) from contacts, null);
cursor.moveToFirst();
cursor.getInt(0);
6.获取List集合中的数据元素:list.size();
好了这一节就暂且到这里吧,如果对本文有什么建议,批评的,欢迎指出!
不慎感激!项目的代码会随着后面深入慢慢完善的!