首先,还是展示一下部分目录结构: 

在节日短信送祝福的功能实现方面,为了能够方便直观展示实现过程,小编我以Java文件为基础,一个一个来展示,免得到时候这个java文件写点,一下又跳到另外一个java文件写点,毕竟这不像教学视频那样直观。


因为在功能方面涉及到了显示已经发送短信的历史记录,那么,毫无疑问,要用到数据库,但是在定义SQLiteOpenHelper之前先定义一个”已经发送的短信的实体类”(SendedMsg):

SendedMsg.java

public class SendedMsg {
private int id;
private String content;
private String numbers;//发送的联系人号码(可能有多个联系人的号码,拼接成一个String)
private String names;//发送的联系人名单(可能有多个联系人,拼接成一个String)
private String festivalName;
private Date date;
private String dateStr;//主要为了方便
private DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm"); public static final String TABLE_NAME="tb_sended_msg";
public static final String COLUMN_CONTENT="content";
public static final String COLUMN_NUMBERS="numbers";
public static final String COLUMN_NAMES="names";
public static final String COLUMN_FESTIVAL_NAME="festival_name";
public static final String COLUMN_DATE="date_str"; public Date getDate() {
return date;
} public void setDate(Date date) {
this.date = date;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public String getNumbers() {
return numbers;
} public void setNumbers(String numbers) {
this.numbers = numbers;
} public String getNames() {
return names;
} public void setNames(String names) {
this.names = names;
} public String getFestivalName() {
return festivalName;
} public void setFestivalName(String festivalName) {
this.festivalName = festivalName;
} public String getDataStr() {
dateStr=df.format(date);
return dateStr;
}
}

可以注意到,在实体类中还定义了一些常量,这是为了避免在对数据库进行操作时出错,可以直接引用。

SmsDBOpenHelper.java(单例模式)

public class SmsDBOpenHelper extends SQLiteOpenHelper{
private static final String DB_NAME="sms.db";
private static final int DB_VERSION=; private static SmsDBOpenHelper mHelper; private SmsDBOpenHelper(Context context) {
super(context.getApplicationContext(), DB_NAME, null, DB_VERSION);
} //传入的context有可能是一个Activity
//所以在构造方法中用context.getApplicationContext()尽量得到Application的context
//避免造成内存泄露的问题
public static SmsDBOpenHelper getInstance(Context context) {
if(mHelper==null) {
synchronized (SmsDBOpenHelper.class) {
if(mHelper==null) {
mHelper=new SmsDBOpenHelper(context);
}
}
}
return mHelper;
} @Override
public void onCreate(SQLiteDatabase db) {
String sql="create table "+ SendedMsg.TABLE_NAME+" ( "+
"_id integer primary key autoincrement, "+
SendedMsg.COLUMN_DATE+" integer, "+
SendedMsg.COLUMN_FESTIVAL_NAME+" text,"+
SendedMsg.COLUMN_CONTENT+" text,"+
SendedMsg.COLUMN_NAMES+" text,"+
SendedMsg.COLUMN_NUMBERS+" text )";
db.execSQL(sql);
} @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}

注意:在建表的时候,有一个”_id”的主键,这是因为在后面会讲到一个用于展示短信历史记录的Fragment,里面会涉及CursorAdapter,而CursorAdapter里面会用到一个cursor,该cursor必须要有个名为 _id的列

在私有构造方法中的context.getApplicationContext()这点是值得注意与学习的。

接着是自定义的ContentProvider.java

public class SmsProvider extends ContentProvider{
private static final String AUTHORITY="com.just.sms.provider.SmsProvider";
public static final Uri URI_SMS_ALL=Uri.parse("content://"+AUTHORITY+"/sms"); private static UriMatcher mMatcher; private static final int SMS_ALL=;//表示访问表中的所有数据
private static final int SMS_ONE=;//表示访问表中的单条数据 //在静态代码块中完成mMatcher的初始化及uri的添加
static {
mMatcher=new UriMatcher(UriMatcher.NO_MATCH); //addURI接收三个参数,可以分别把权限、路径和一个自定义代码传进去
//*:表示匹配任意长度的任意字符;#:表示匹配任意长度的数字
mMatcher.addURI(AUTHORITY,"sms",SMS_ALL);
mMatcher.addURI(AUTHORITY,"sms/#",SMS_ONE);
} private SmsDBOpenHelper mHelper;
private SQLiteDatabase mDB; @Override
public boolean onCreate() {
mHelper=SmsDBOpenHelper.getInstance(getContext());
return true;
} @Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
int match=mMatcher.match(uri);
switch (match) {
case SMS_ALL:
break;
case SMS_ONE://本案例用不到,但展示一下代码逻辑
long id=ContentUris.parseId(uri);//从路径中中获取id
selection="_id = ?";
selectionArgs=new String[]{String.valueOf(id)};
break;
default:
throw new IllegalArgumentException("Wrong URI:"+uri.toString());
}
mDB=mHelper.getReadableDatabase();
Cursor cursor=mDB.query(SendedMsg.TABLE_NAME,projection,selection,selectionArgs,null,null,sortOrder); //用来在后台检测数据的变化,如果有变化就会有返回(因为在SmsHistoryFragment中使用了Loader)
cursor.setNotificationUri(getContext().getContentResolver(),URI_SMS_ALL); return cursor;
} @Override
public Uri insert(Uri uri, ContentValues values) {
int match=mMatcher.match(uri);
if(match!=SMS_ALL) {
throw new IllegalArgumentException("Wrong URI:"+uri.toString());
}
mDB=mHelper.getWritableDatabase(); //第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般我们用不到这个功能,直接传入null 即可
long rowId=mDB.insert(SendedMsg.TABLE_NAME,null,values);
if(rowId>) {//如果添加数据成功
notifyDataSetChanged();
return ContentUris.withAppendedId(uri,rowId);//为传入的uri加上id
}
return uri;
} private void notifyDataSetChanged() {
getContext().getContentResolver().notifyChange(URI_SMS_ALL,null);//通知监听器关于数据更新的信息
} @Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
return ;
} @Override
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
return ;
} @Override
public String getType(Uri uri) {
return null;
}
}

一定要记得在AndroidMainfest.xml中注册

<provider
android:name=".db.SmsProvider"
android:authorities="com.just.sms.provider.
SmsProvider">
</provider>

在ContentProvider中呢,需要注意两行代码(是不可或缺的)。 
一个是query方法中的:

cursor.setNotificationUri(getContext().getContentResolver(),URI_SMS_ALL);

另一个是notifyDataSetChanged方法中的:

getContext().getContentResolver().notifyChange(URI_SMS_ALL,null);

这两行代码的作用可以先暂时搁置一下,等到后面讲SmsHistoryFragment的时候再联系起来说明一下。

Android 节日短信送祝福(功能篇:1-数据库操作类与自定义ContentProvider)的更多相关文章

  1. Android 节日短信送祝福(功能篇:2-短信历史记录Fragment的编写)

    因为用于展示短信记录的是一个ListView,但是为了方便,可以直接继承自ListFragment,就可以免去写ListView对应的布局了,只需要写其item对应的布局即可. item_sended ...

  2. Android 节日短信送祝福(UI篇:3-选择短信与发送短信的Activity的实现)

    一.ChooseMsgActivity的实现 1.布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/ ...

  3. Android获取短信验证码

    Android开发中关于短息验证码的设计层出不穷,越来越多的应用为了更好的提高软件的安全性,开始使用通过服务器向用户发送验证码的方式,来保护用户个人信息的安全性.无论是用户注册时的信息验证还是当用户发 ...

  4. Android之——短信的备份与还原

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47091281 眼下,Android手机中的一些软件能够实现手机短信的备份与还原操作 ...

  5. 完整的Android手机短信验证源码

    短信验证功能我分两个模块来说,短信验证码的后台和代码实现短信验证码的功能. 一.短信验证码的后台      1.注册Mob账号:http://www.mob.com/#/login 2.注册成功之后, ...

  6. android 发送短信的两种方式,以及接收报告和发送报告

               android发送短信,以及接收报告和发送报告          android中发送短信其实有两种方式,这个和打电话类似,大家可以了解一下:    一.调起系统发短信功能    ...

  7. Android开发——短信电话拦截/接听电话

    1.短信拦截 首先需要声明的是,Android4.4版本以上,如果想做到短信拦截,必须成为default sms,把所有短信相关的功能都包揽了,然后再做短信拦截.但这种做法,适配性和兼容性的工作是非常 ...

  8. 用Tasker实现收到Android手机短信自动转发到邮箱

    发送短信到邮箱的原理与 <用Tasker实现收到Android手机短信自动转发到邮箱>有些类似.  发送短信到邮箱是利用Ifttt这个服务将短信转发到邮箱中.Ifttt服务的可扩展性很强, ...

  9. 利用短信通知的方式在Tasker中实现收到Android手机短信自动转发到邮箱

    利用短信的通知实现短信内容转发到微信 code[class*="language-"] { padding: .1em; border-radius: .3em; white-sp ...

随机推荐

  1. java 位操作 bitwise(按位) operation bit

    java 位操作 bitwise(按位) operation bit //一篇对于 原码 反码 补码 的介绍 http://www.cnblogs.com/zhangziqiu/archive/201 ...

  2. 【2017百度之星程序设计大赛 - 复赛】Valley Numer

    [链接]http://acm.hdu.edu.cn/showproblem.php?pid=6148 [题意] 在这里写题意 [题解] 先把1..N里面的山峰数字个数算出来->x 然后用N减去这 ...

  3. Shiro学习总结(2)——Apache Shiro快速入门教程

    第一部分 什么是Apache Shiro 1.什么是 apache shiro : Apache Shiro是一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理 如同 spr ...

  4. RFID的基本组织构成

    RFID技术由3大组件构成, 包括: 阅读器.天线.标签三大组件. 阅读器 为RFID系统最重要也是最复杂的一个组件.因其工作模式一般是主动向标签询问标识信息, 所以有时又被称为询问器(Interro ...

  5. 非常有用的sql脚本

    /*sql 语法学习*/ /*函数的学习---------------------------------------*/ 获取当前时间(时/分/秒):select convert(varchar(1 ...

  6. elasticsearch节点间通信的基础transport

    在前一篇中我们分析了cluster的一些元素.接下来的章节会对cluster的运作机制做详细分析.本节先分析一些transport,它是cluster间通信的基础.它有两种实现,一种是基于netty实 ...

  7. 使用Spring框架的好处

    转自:https://www.cnblogs.com/hoobey/p/6032506.html 在SSH框假中spring充当了管理容器的角色.我们都知道Hibernate用来做持久层,因为它将JD ...

  8. js面向对象1----了解构造函数

    一.构造函数与实例的区别 1 构造函数  构造函数主要是一种用于生成对象的饼干模具,这些对象具有默认属性和属性方法,它可以创建多个共享特定特性和行为的对象.  构造函数只是一个函数,但当函数遇到了ne ...

  9. Fragment事务管理源代码分析

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/53132952 本文出自: [HansChen的博客] 概述 在Fragment使用中 ...

  10. HDU 5071 模拟

    考察英语的题 - -# 按条件模拟,一遍即可了,每一个聊天对象有其价值U.数组模拟队列过程即可,若存在Top标记,则和Top标记的人聊天,否则和队列的第一个人聊天 mark记录队尾,top记录Top操 ...