郑重声明:【慕课网–中级教程】系列的博文均是根据慕课网上的Android开发中级教程相应的视频,在学习之后写的,文中所涉及的源码与视频中的无太大区别,除开个别地方可能有所改善或者加入了自己的想法。如果该系列文章涉及了版权问题,请私信本人,尽可能及时地改正。在此,向慕课网上分享视频的老师以及慕课网平台致以衷心的感谢!

视频地址:http://www.imooc.com/learn/517

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

在节日短信送祝福的功能实现方面,为了能够方便直观展示实现过程,小编我以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中注册

<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 节日短信送祝福(功能篇:1-数据库操作类与自定义ContentProvider)

    首先,还是展示一下部分目录结构:  在节日短信送祝福的功能实现方面,为了能够方便直观展示实现过程,小编我以Java文件为基础,一个一个来展示,免得到时候这个java文件写点,一下又跳到另外一个java ...

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

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

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

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

  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. ACE .i .inl文件(转)
  2. LeeCode_MultiplyStrings
  3. Asp.net中网站级异常捕获
  4. 简述Hadoop和Spark的异同
  5. SQL实战篇:SQL优化问题
  6. java收获_java学习收获
  7. Java枚举根据key获取value
  8. 数字图像处理:特征提取基本概念总结
  9. chmod 777命令_Linux shell命令总结
  10. 传智播客Java常量进制转换数据类型
  11. FFMPEG:MP4封装格式中外挂字幕的提取
  12. 一名优秀项目经理需具备的五种基本素质及八大管理技能
  13. HTML5APP商业开发实战教程——基于WeX5可视化开发平台
  14. Nat学习(sNat和dNat)
  15. php万圣节源码,如何使用纯CSS实现万圣节的toggle控件(附源码)
  16. 前端视角漫谈百度ueditor编辑器前后端分离配置
  17. 图像处理——人脸黑头检测+用户界面
  18. 蓝牙作为智能钥匙的媒介
  19. win10 启动vmware虚拟机就会蓝屏解决方法
  20. HDFS的DN退役以及如何加快DN退役速度

热门文章

  1. 大数据平台之今日头条采集,今日特卖全自动发布,淘宝达人有好货一键上传
  2. The following packages have unmet dependencies错误
  3. conda create创建虚拟环境失败
  4. mysql面试题学校三表查询_mysql经典面试题之学生成绩表
  5. 心灵的吟唱——读《湖海诗情录》
  6. C++ opencv视频处理与保存
  7. MySQL数据库实操教程(25)——权限管理
  8. 菜鸟之如何让项目跑起来(适合小白看,不是小白的不要进来看了,浪费时间)
  9. 数据库公共字段自动填充
  10. Python爬虫 Selenium实现自动登录163邮箱和Locating Elements介绍