BroadcastReceiver 是android四大组件的一个,本质上是一种全局的监听器,用于监听全局的广播消息。下面实现了后台监听android手机通话记录。本demo分两个程序,第一个程序是设置监听器,然后模拟器重启后就会有一个全局的service在后台监听你的来电显示,大多数通话管理软件都是这么干的,第二个项目是获取通话记录的,由于只是做一个小实验,所以是根据某个项目改的,里面涉及到一些ContentPrivler的知识,还有sqllite数据库,里面定义名称并非其意思。

第一个程序代码配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.android"android:versionCode="1"android:versionName="1.0" >
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name"><service android:name=".TtActivity"></service><!-- 定义一个BroadcastReceiver,监听系统开机广播  --><receiver android:name=".LaunchReceiver">    <intent-filter>    <action android:name="android.intent.action.BOOT_COMPLETED" />   </intent-filter>    </receiver><provider android:name=".DictProvider" android:authorities="org.crazyit.providers.dictprovider"/></application><!-- 授予应用程序访问系统开机事件的权限 --><uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/></manifest>
/*** */
package com.android;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class LaunchReceiver extends BroadcastReceiver
{@Overridepublic void onReceive(Context context, Intent intent){Intent tIntent = new Intent(context , TtActivity.class);// 启动指定Service
        context.startService(tIntent);}
}

/*** */
package com.android;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDatabaseHelper extends SQLiteOpenHelper
{final String CREATE_TABLE_SQL ="create table dict(_id integer primary key autoincrement , word , detail)";/*** @param context* @param name* @param version*/public MyDatabaseHelper(Context context, String name, int version){super(context, name, null, version);}@Overridepublic void onCreate(SQLiteDatabase db){// 第一个使用数据库时自动建表
        db.execSQL(CREATE_TABLE_SQL);}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){System.out.println("--------onUpdate Called--------" + oldVersion + "--->" + newVersion);}
}

package com.android;import java.io.FileNotFoundException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
public class TtActivity extends Service
{   MyDatabaseHelper dbHelper;TelephonyManager tManager;SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String word=format.format(new Date());        @Overridepublic IBinder onBind(Intent intent){return null;}@Overridepublic void onCreate(){tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);dbHelper = new MyDatabaseHelper(this , "myDict.db3" , 1);// 创建一个通话状态监听器PhoneStateListener listener = new PhoneStateListener(){@Overridepublic void onCallStateChanged(int state, String detail){switch (state){// 无任何状态case TelephonyManager.CALL_STATE_IDLE:break;case TelephonyManager.CALL_STATE_OFFHOOK:break;// 来电铃响时case TelephonyManager.CALL_STATE_RINGING:OutputStream os = null;try{os = openFileOutput("phoneList", MODE_APPEND);}catch (FileNotFoundException e){e.printStackTrace();}insertData(dbHelper.getReadableDatabase() , word , detail);
//                            PrintStream ps = new PrintStream(os);
//                            // 将来电号码记录到文件中
//                            ps.println(new Date() + "    来电:" + incomingNumber);
//                            ps.close();break;default:break;}super.onCallStateChanged(state, detail);}};//监听电话通话状态的改变
            tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);}private void insertData(SQLiteDatabase db, String word , String detail){//执行插入语句db.execSQL("insert into dict values(null , ? , ?)", new String[]{word , detail});}@Overridepublic void onDestroy(){super.onDestroy();//退出程序时关闭MyDataBaseHelper里的SQLiteDatabaseif (dbHelper != null){dbHelper.close();}}
}

/*** */
package com.android;import android.net.Uri;
import android.provider.BaseColumns;/*** @version  1.0*/
public final class Words
{// 定义该ContentProvider的Authoritypublic static final String AUTHORITY = "org.crazyit.providers.dictprovider";//定义一个静态内部类public static final class Word implements BaseColumns{// 定义Content所允许操作的3个数据列public final static String _ID = "_id";public final static String WORD = "word";public final static String DETAIL = "detail";// 定义该Content提供服务的两个Uripublic final static Uri DICT_CONTENT_URI = Uri.parse("content://" +  AUTHORITY + "/words");public final static Uri WORD_CONTENT_URI = Uri.parse("content://" +  AUTHORITY + "/word");        }
}

/*** */
package com.android;import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;/*** @version  1.0*/
public class DictProvider extends ContentProvider
{private static UriMatcher matcher= new UriMatcher(UriMatcher.NO_MATCH);private static final int WORDS = 1;private static final int WORD = 2;private MyDatabaseHelper dbOpenHelper;static{// 为UriMatcher注册两个Urimatcher.addURI(Words.AUTHORITY, "words", WORDS);matcher.addURI(Words.AUTHORITY, "word/#", WORD);}// 第一次调用该DictProvider时,系统先创建DictProvider对象,并回调该方法
    @Overridepublic boolean onCreate(){dbOpenHelper = new MyDatabaseHelper(this.getContext(), "myDict.db3", 1);return true;}// 插入数据方法
    @Overridepublic Uri insert(Uri uri, ContentValues values){// 获得数据库实例SQLiteDatabase db = dbOpenHelper.getReadableDatabase();// 插入数据,返回行IDlong rowId = db.insert("dict", Words.Word._ID, values);// 如果插入成功返回uriif (rowId > 0){// 在已有的 Uri的后面追加ID数据Uri wordUri = ContentUris.withAppendedId(uri, rowId);// 通知数据已经改变getContext().getContentResolver().notifyChange(wordUri, null);return wordUri;}return null;}// 删除数据的方法
    @Overridepublic int delete(Uri uri, String selection, String[] selectionArgs){SQLiteDatabase db = dbOpenHelper.getReadableDatabase();// 记录所删除的记录数int num = 0;// 对于uri进行匹配。switch (matcher.match(uri)){case WORDS:num = db.delete("dict", selection, selectionArgs);break;case WORD:// 解析出所需要删除的记录IDlong id = ContentUris.parseId(uri);String where = Words.Word._ID + "=" + id;// 如果原来的where子句存在,拼接where子句if (selection != null && !selection.equals("")){where = where + " and " + selection;}num = db.delete("dict", where, selectionArgs);break;default:throw new IllegalArgumentException("未知Uri:" + uri);}// 通知数据已经改变getContext().getContentResolver().notifyChange(uri, null);return num;}// 修改数据的方法
    @Overridepublic int update(Uri uri, ContentValues values, String selection,String[] selectionArgs){SQLiteDatabase db = dbOpenHelper.getWritableDatabase();// 记录所修改的记录数int num = 0;switch (matcher.match(uri)){case WORDS:num = db.update("dict", values, selection, selectionArgs);break;case WORD:// 解析出想修改的记录IDlong id = ContentUris.parseId(uri);String where = Words.Word._ID + "=" + id;// 如果原来的where子句存在,拼接where子句if (selection != null && !selection.equals("")){where = where + " and " + selection;}num = db.update("dict", values, where, selectionArgs);break;default:throw new IllegalArgumentException("未知Uri:" + uri);}// 通知数据已经改变getContext().getContentResolver().notifyChange(uri, null);return num;}// 查询数据的方法
    @Overridepublic Cursor query(Uri uri, String[] projection, String selection,String[] selectionArgs, String sortOrder){SQLiteDatabase db = dbOpenHelper.getReadableDatabase();switch (matcher.match(uri)){case WORDS:// 执行查询return db.query("dict", projection, selection, selectionArgs,null, null, sortOrder);case WORD:// 解析出想查询的记录IDlong id = ContentUris.parseId(uri);String where = Words.Word._ID + "=" + id;// 如果原来的where子句存在,拼接where子句if (selection != null && !"".equals(selection)){where = where + " and " + selection;}return db.query("dict", projection, where, selectionArgs, null,null, sortOrder);default:throw new IllegalArgumentException("未知Uri:" + uri);}}// 返回指定uri参数对应的数据的MIME类型
    @Overridepublic String getType(Uri uri){switch (matcher.match(uri)){// 如果操作的数据是多项记录case WORDS:return "vnd.android.cursor.dir/org.crazyit.dict";// 如果操作的数据是单项记录case WORD:return "vnd.android.cursor.item/org.crazyit.dict";default:throw new IllegalArgumentException("未知Uri:" + uri);}}
}

下面贴出第二个程序的代码,调用第一个程序ContentProvidler的接口

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="org.crazyit.resolver"android:versionCode="1"android:versionName="1.0"><application android:icon="@drawable/icon" android:label="@string/app_name"><activity android:name=".DictResolver"android:label="@string/app_name"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activity android:name=".ResultActivity" android:theme="@android:style/Theme.Dialog"android:label="找到的来电记录"></activity></application>
</manifest> 

/*** */
package org.crazyit.content;
import android.net.Uri;
import android.provider.BaseColumns;
/*** @version  1.0*/
public final class Words
{// 定义该ContentProvider的Authoritypublic static final String AUTHORITY = "org.crazyit.providers.dictprovider";//定义一个静态内部类public static final class Word implements BaseColumns{// 定义Content所允许操作的3个数据列public final static String _ID = "_id";public final static String WORD = "word";public final static String DETAIL = "detail";// 定义该Content提供服务的两个Uripublic final static Uri DICT_CONTENT_URI = Uri.parse("content://" +  AUTHORITY + "/words");public final static Uri WORD_CONTENT_URI = Uri.parse("content://" +  AUTHORITY + "/word");        }
}

package org.crazyit.resolver;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;import org.crazyit.content.Words;
import org.crazyit.resolver.R;import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;/*** @author  Yeeku.H.Lee kongyeeku@163.com* @version  1.0*/
public class DictResolver extends Activity
{ContentResolver contentResolver;Button search = null;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.main);// 获取系统的ContentResolver对象contentResolver = getContentResolver();search = (Button)findViewById(R.id.search);    // 为insert按钮的单击事件绑定事件监听器search.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View source){// 获取用户输入String key = "";// 执行查询Cursor cursor = getContentResolver().query(Words.Word.DICT_CONTENT_URI, null , null, null , null);//创建一个Bundle对象Bundle data = new Bundle();data.putSerializable("data", converCursorToList(cursor));//创建一个IntentIntent intent = new Intent(DictResolver.this, ResultActivity.class);intent.putExtras(data);//启动Activity
                startActivity(intent);}});}private ArrayList<Map<String, String>> converCursorToList(Cursor cursor){ArrayList<Map<String, String>> result = new ArrayList<Map<String, String>>();// 遍历Cursor结果集while (cursor.moveToNext()){// 将结果集中的数据存入ArrayList中Map<String, String> map = new HashMap<String, String>();// 取出查询记录中第2列、第3列的值map.put(Words.Word.WORD, cursor.getString(1));map.put(Words.Word.DETAIL, cursor.getString(2));result.add(map);}return result;}
}

/*** */
package org.crazyit.resolver;import java.util.List;
import java.util.Map;import org.crazyit.content.Words;
import org.crazyit.resolver.R;import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.SimpleAdapter;/*** @version  1.0*/
public class ResultActivity extends Activity
{@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.popup);ListView listView = (ListView)findViewById(R.id.show);Intent intent = getIntent();//获取该intent所携带的数据Bundle data = intent.getExtras();//从Bundle数据包中取出数据@SuppressWarnings("unchecked")List<Map<String , String>> list = (List<Map<String , String>>)data.getSerializable("data");//将List封装成SimpleAdapterSimpleAdapter adapter = new SimpleAdapter(ResultActivity.this , list, R.layout.line , new String[]{Words.Word.WORD  , Words.Word.DETAIL}, new int[]{R.id.word , R.id.detail});//填充ListView
        listView.setAdapter(adapter);}
}

android如何使用BroadcastReceiver后台实现来电通话记录的监听并存取到sqllite数据库通过Contentprovilder实现接口...相关推荐

  1. Android实现来电和去电的监听

    写个实例实现Android中来电和去电的监听,来电可以使用PhoneStateListener对电话状态的改变进行监听,去电需要动态或者静态去注册广播接收器,对去电进行监听: 来电: 来电所对应的三种 ...

  2. Android通讯录管理(获取联系人、通话记录、短信消息)(二)

    Android通讯录管理(获取联系人.通话记录.短信消息)(二) 前言:上一篇博客介绍的是获取联系人的实现,本篇博客将介绍通话记录的实现. 同样的,你可以到这里下载源码:http://download ...

  3. Android通讯录管理(获取联系人、通话记录、短信消息)(三)

    Android通讯录管理(获取联系人.通话记录.短信消息)(三) 这是通讯录管理的最后一篇,前面两篇已经把获取联系人和通话记录解决了,短息消息就相对来说要稍微复杂那么一点.我们先来看看效果图: 源码下 ...

  4. Android 第十九课 大喇叭--广播机制----动态注册监听网络变化与静态注册实现开机启动

    为了便于进行 系统级别的消息通知,Android引入了一套广播消息机制. 1.广播机制简介: 因为Android中的每个应用程序都可以对自己感兴趣的广播尽心注册,这样程序只会接收自己所关心的广播内容, ...

  5. android 标题栏颜色渐变和阴影,ScrollView上下滑动监听,及判断scrollView是否滚动到底部

    1.创建  ScrollListener 接口监听滑动距离 public interface ScrollListener {void onScrollChanged(ScrollListenerVi ...

  6. Android中对menu、home、back键的监听

    Android中对menu.home.back键的监听,通过KeyEvent中的常量值来判断用户点击了哪个按钮. 其中对home键的监听需先在manifest文件中添加 <uses-permis ...

  7. android通讯录管理(获取联系人,通话记录,短信消息),Android通讯录管理(获取联系人、通话记录、短信消息)(二)...

    Android通讯录管理(获取联系人.通话记录.短信消息)(二) 前言:上一篇博客介绍的是获取联系人的实现,本篇博客将介绍通话记录的实现. 界面布局: /Contact_Demo/res/layout ...

  8. Android通讯录管理(获取联系人、通话记录、短信消息)

    前言:前阵子主要是记录了如何对联系人的一些操作,比如搜索,全选.反选和删除等在实际开发中可能需要实现的功能,本篇博客是小巫从一个别人开源的一个项目抽取出来的部分内容,把它给简化出来,可以让需要的朋友清 ...

  9. Android删除手机文件,联系人,通话记录

    下面代码作为类可以调用 public class Delete {Context context;private String[] columns = {CallLog.Calls.CACHED_NA ...

最新文章

  1. redis集群之哨兵模式【原】
  2. 文思创新深圳招聘biztalk
  3. HDU 1176 免费馅饼 矩阵取数, dp + 滚动数组
  4. [转]Oracle执行计划的相关概念
  5. raid-6磁盘阵列损坏导致数据丢失的恢复过程(图文教程)
  6. linux的locate工具,linux文本查找工具之locate、find
  7. 从/etc/inetd.conf学习服务(4)
  8. 不好意思昨天断更了,今天聊聊创业
  9. 通过内网穿透 将本地端口 使其外网可以进行访问 使用花生壳内网穿透 网站访问
  10. [导入]16:50论坛终于恢复了
  11. 绘制自己的人际关系图_错综复杂的人际关系,一张图谱一目了然
  12. 奶爸日记17 - 长兴岛橘子
  13. 第21章 DHCP
  14. 字符串练习:手机号码屏蔽,身份证号码信息查看,游戏骂人敏感词替换
  15. 计算机语言怎么学,教你如何学习计算机编程语言
  16. turf:计算面积、折线长度和两点距离
  17. 市面常用芯片对应的ARM架构
  18. Select之多表查询
  19. Unity新手引导(圆形指引、矩形指引)
  20. 踩坑:使用jquery的data()方法获取不到自定义属性的值

热门文章

  1. JavaScript 多线程概念的含义
  2. JAVA常用API或编程工具003--实现pdf在线阅读功能之pdf.js
  3. 多克隆,坚决抵制快照
  4. bz10451045: [HAOI2008] 糖果传递
  5. 杭电5253连接的管道
  6. linux目录表及功能n鸟哥,鸟哥linux学习之-文件属性跟系统目录
  7. mysql udf安全_打造全功能MYSQL入侵UDF
  8. 随想录(scons编译)
  9. 搜索引擎的那些事(web遍历)
  10. stream 定长循环_Java8之Stream流代替For循环操作