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

在节日短信送祝福的功能实现方面,为了能够方便直观展示实现过程,小编我以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=1;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;}@Overridepublic 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);}@Overridepublic 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=0;//表示访问表中的所有数据private static final int SMS_ONE=1;//表示访问表中的单条数据//在静态代码块中完成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;@Overridepublic boolean onCreate() {mHelper=SmsDBOpenHelper.getInstance(getContext());return true;}@Overridepublic 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);//从路径中中获取idselection="_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;}@Overridepublic 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>0) {//如果添加数据成功
            notifyDataSetChanged();return ContentUris.withAppendedId(uri,rowId);//为传入的uri加上id
        }return uri;}private void notifyDataSetChanged() {getContext().getContentResolver().notifyChange(URI_SMS_ALL,null);//通知监听器关于数据更新的信息
    }@Overridepublic int delete(Uri uri, String selection, String[] selectionArgs) {return 0;}@Overridepublic int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {return 0;}@Overridepublic String getType(Uri uri) {return null;}
}

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

<providerandroid: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的时候再联系起来说明一下。

转载于:https://www.cnblogs.com/zhujiabin/p/6053283.html

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

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

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

  2. android节日祝福短信,Android-节日短信送祝福(UI篇)

    学员1010 2020-03-11 单列模式 第一个null判断 if (mInstance == null) 为了提供效率,多线程没必要每一次进行一次同步 第二个 synchronized(.cla ...

  3. Android-节日短信送祝福(功能篇:1-数据库操作类与自定义ContentProvider)

    郑重声明:[慕课网–中级教程]系列的博文均是根据慕课网上的Android开发中级教程相应的视频,在学习之后写的,文中所涉及的源码与视频中的无太大区别,除开个别地方可能有所改善或者加入了自己的想法.如果 ...

  4. 国际网页短信软件平台后台功能篇|移讯云短信系统开发

    国际网页短信软件后台功能篇|移讯云短信系统开发 平台外放接口介绍 支持接入CMPP接口,支持smpp通道接入,支持外放CMPP接口(其他平台可以通过CMPP接入我平台),支持HTTP API JSON ...

  5. Android-节日短信送祝福(UI篇:1-主布局的基本实现)

    视频地址:http://www.imooc.com/learn/510 这次学习的内容,将会分为两个部分,这里先讲有关UI的部分.而且,Demo是在Android Studio上进行的. 相关素材及源 ...

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

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

  7. android-短信验证功能,Android实现获取短信验证码的功能以及自定义GUI短信验证详解...

    <Android实现获取短信验证码的功能以及自定义GUI短信验证详解>由会员分享,可在线阅读,更多相关<Android实现获取短信验证码的功能以及自定义GUI短信验证详解(8页珍藏版 ...

  8. android+自定义发彩信,Android实现获取短信验证码的功能以及自定义GUI短信验证

    短信验证功能大家都很熟悉了.在很多地方都能见到,注册新用户或者短息验证支付等.短信验证利用短信验证码来注册会员,大大降低了非法注册,很大程度上提高了用户账户的安全性. 目前市面上已经有了很多提供短信验 ...

  9. Android studio 实现打电话发短信浏览网页功能 android开发小实验

    Android studio 实现打电话发短信浏览网页功能 android开发小实验 目标: android studio 实现打电话 发短信 浏览网站的功能 先在布局里面定义几个按钮 分别为 打电话 ...

最新文章

  1. 【C++】C/C++ 中多态情形下的虚函数表查看方法
  2. IBM已“弃疗”,AI医疗研发10年不赚钱,终于打算卖了
  3. JMeter基础之——录制脚本
  4. js jquery Ajax同步
  5. ssh问题:ssh_exchange_identification: Connection closed by remote host
  6. 计算机网络第四章思维导图_初级会计实务的第四章所有者权益的思维导图丨初级讲堂...
  7. php 关闭 ob缓存,php ob缓存主要函数
  8. nginx启动vue_nginx下部署vue项目的方法步骤
  9. TSC打印bmp图片命令
  10. 开源在线客服系统源码h5|thinkphp在线客服完整源码|网页在线客服源码
  11. win8打印机显示服务器脱机,打印机脱机状态 win8处理办法
  12. 量子计算机的算力是多少,我国量子计算机实现算力全球领先
  13. 计算机网络复习(部分)
  14. linux中的怎么添加组,linux中添加用户 添加组
  15. 以太网物理层信号测试与分析
  16. IE加载ocx时提示控件不安全的解决方法
  17. ubuntu安装opencv viz模块
  18. CF1578F Framing Pictures 旋转卡壳+积分
  19. Ubuntu查看系统信息(CPU、GPU信息)
  20. layui字体样式设置_layui如何自定义字体图标?(图文介绍)

热门文章

  1. uniapp全局修改字体
  2. 打开CAD的dwg文件时提示:许可检出超时,您要执行什么操作?AutoCAD将关闭。
  3. 啥是“quoting reference XXX” 递交申请材料时
  4. 用华为手机现在还不知道这5种实用功能,几千块白花了,太浪费了
  5. 类型多样的游戏特效网页特效素材,速来收藏
  6. 瞰见 | 开源,会不会变成开源创业的焦油坑?
  7. 使用pip来对相应的版本进行降低的过程的
  8. My Visual DataBase(数据库编程软件)v5.3免费版
  9. UTON NFT的到来将为摄影师带来全新的未来!
  10. 博图注册表删除方法_回收站被清空文件删除的恢复方法