Android 利用广播实现指定号码的短信的拦截
根据最近的学习内容,今天实现了利用广播进行指定号码的拦截
步骤:
①、写一个数据库的帮助类,实现对数据库的创建,总共创建两个数据库psms(受保护的短信的数据库)和protectedPhone(受保护的联系人数据库),粘代码:
public class DBHelper extends SQLiteOpenHelper {
private static final String DB_NAME = "protectedSMS.db";
private static final int DB_VERSION = 2;
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
// TODO Auto-generated constructor stub
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
String sql = "create table psms(_id integer primary key autoincrement,address varchar(20),type integer,state integer,body varchar(500),date varchar(20),person varchar(20))";
String sql1 = "create table protectedPhone(_id integer primary key autoincrement,person varchar(20),phone varchar(20))";
db.execSQL(sql);
db.execSQL(sql1);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}
②、写一个类对数据库的增删改查进行封装,代码及注释如下:
/**
* 封装DAO,对数据库进制crud操作
*
* @author Administrator
*
*/
public class ProtectedDAO {
private SQLiteDatabase db;
public ProtectedDAO(Context context) {
DBHelper helper = new DBHelper(context);
db = helper.getWritableDatabase();
}
/**
* 插入数据到中
*
* @param table
* 表名
* @param values
* 对应的键和值
* @return 行号
*/
public long insert(String table, ContentValues values) {
// String sql = "insert into person(name,age) values('zhangsan',21)";
// db.execSQL(sql);
return db.insert(table, null, values);
}
/**
* 更新表中的数据
*
* @param table
* 表名
* @param values
* 修改后的值
* @param whereClause
* 条件语句可以使用占位符 ?
* @param whereArgs
* 使用该数组中的值替换占位符
* @return 受影响数据表的行数
*/
public int update(String table, ContentValues values, String whereClause,
String[] whereArgs) {
return db.update(table, values, whereClause, whereArgs);
}
/**
*
* 删除表中的数据
*
* @param table
* 表名
* @param whereClause
* 条件语句,可以使用占位符
* @param whereArgs
* 使用该数组中的值替换占位符
* @return 受影响数据的行数
*/
public int delete(String table, String whereClause, String[] whereArgs) {
return db.delete(table, whereClause, whereArgs);
}
/**
* 查询数据
*
* @param sql
* sql语句,查询语句,可以包含条件,sql语句不用使用分号结尾,系统自动添加
* @param selectionArgs
* sql的查询条件可以使用占位符,占位符可以使用selectionArgs的值替代
* @return Cursor 游标,可以比作结果集
*/
public Cursor select(String sql, String[] selectionArgs) {
return db.rawQuery(sql, selectionArgs);
}
/**
* 查询数据
*
* @param table
* 表名
* @param columns
* 查询的列(字段)
* @param selection
* where后的条件子句,可以使用占位符
* @param selectionArgs
* 替换占位符的值,
* @param groupBy
* 根据某个字段进行分组
* @param having
* 分组之后再进一步过滤
* @param orderBy
* 排序
* @return Cursor 游标,可以比作结果集
*/
public Cursor select(String table, String[] columns, String selection,
String[] selectionArgs, String groupBy, String having,
String orderBy) {
// distinct: 消除重复数据项(去掉重复项)
// 1、table: 表名
// 2、columns: 查询的列(字段)
// 3、selection: where后的条件子句,可以使用占位符
// 4、selectionArgs: 替换占位符的值
// 5、groupBy: 根据某个字段进行分组
// 6、having: 分组之后再进一步过滤
// 7、orderBy: 排序
// limit: 进行分页查询
return db.query(table, columns, selection, selectionArgs, groupBy,
having, orderBy);
}
public void close() {
if (db != null) {
db.close();
}
}
}
③、创建一个PhoneManagerActivity页面,实现显示,添加及修改,删除受保护的联系人的电话号码及姓名信息
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="@+id/lv_phone"
android:layout_width="match_parent"
android:layout_height="match_parent" />
RelativeLayout>
在ActionBar中添加了添加按钮
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.protect.sms.activity.PhoneManagerActivity" >
<item
android:id="@+id/action_add"
android:icon="@drawable/button_03"
android:orderInCategory="100"
android:showAsAction="always"
android:title="新增"/>
menu>
PhoneManagerActivity页面处理增加的时间,及处理ListView点击和长按弹出菜单的事件
public class PhoneManagerActivity extends Activity {
private ProtectedDAO pd;
private ListView lv_phone;
private SimpleCursorAdapter adapter;
private Cursor cursor;
private int position;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_phone_manager);
pd = new ProtectedDAO(this);
lv_phone = (ListView) findViewById(R.id.lv_phone);
flushList();
registerForContextMenu(lv_phone);
}
private void flushList() {
cursor = pd.select("protectedPhone", new String[] { "_id", "person",
"phone" }, null, null, null, null, null);
adapter = new SimpleCursorAdapter(this, R.layout.phonelist_item,
cursor, new String[] { "person", "phone" }, new int[] {
R.id.tv_phone_name, R.id.tv_phone_address },
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv_phone.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.phone_manager, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_add) {
View view = getLayoutInflater().inflate(R.layout.add_item, null);
final EditText et_phone = (EditText) view
.findViewById(R.id.et_phone);
final EditText et_name = (EditText) view.findViewById(R.id.et_name);
Builder builder = new AlertDialog.Builder(this)
.setIcon(R.drawable.ic_launcher).setTitle("添加受保护的电话号码")
.setView(view)
.setPositiveButton("添加", new OnClickListener() {
@SuppressWarnings("deprecation")
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
String phone = et_phone.getText().toString().trim();
Cursor select = pd.select("protectedPhone",
new String[] { "_id", "person", "phone" },
" phone =?", new String[] { phone }, null,
null, null);
if (select.moveToNext()) {
Toast.makeText(PhoneManagerActivity.this,
"您已添加过该号码,不能重复添加!", Toast.LENGTH_SHORT)
.show();
} else {
String name = et_name.getText().toString();
ProtectedDAO pd = new ProtectedDAO(
PhoneManagerActivity.this);
ContentValues values = new ContentValues();
values.put("person", name);
values.put("phone", phone);
long l = pd.insert("protectedPhone", values);
if (l > 0) {
Toast.makeText(PhoneManagerActivity.this,
"添加保护成功", Toast.LENGTH_LONG).show();
cursor.requery();
}
}
}
}).setNegativeButton("取消", null).setCancelable(false);
builder.show();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if (pd != null) {
pd.close();
}
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
// TODO Auto-generated method stub
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.phone_menu, menu);
AdapterContextMenuInfo acmi = (AdapterContextMenuInfo) menuInfo;
position = acmi.position;
}
@SuppressWarnings("deprecation")
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.action_update:
View view = getLayoutInflater().inflate(R.layout.add_item, null);
final EditText et_phone = (EditText) view
.findViewById(R.id.et_phone);
final EditText et_name = (EditText) view.findViewById(R.id.et_name);
final Cursor c = (Cursor) (adapter.getItem(position));
et_name.setText(c.getString(c.getColumnIndex("person")));
et_phone.setText(c.getString(c.getColumnIndex("phone")));
Builder builder = new AlertDialog.Builder(this)
.setIcon(R.drawable.ic_launcher).setTitle("修改联系人信息")
.setView(view)
.setPositiveButton("修改", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
String phone = et_phone.getText().toString().trim();
Cursor select = pd.select("protectedPhone",
new String[] { "_id", "person", "phone" },
" phone =?", new String[] { phone }, null,
null, null);
if (select.moveToNext()) {
Toast.makeText(PhoneManagerActivity.this,
"您已添加过该号码,不能重复添加!", Toast.LENGTH_SHORT)
.show();
} else {
String name = et_name.getText().toString();
ProtectedDAO pd = new ProtectedDAO(
PhoneManagerActivity.this);
ContentValues values = new ContentValues();
values.put("person", name);
values.put("phone", phone);
long l = pd.update(
"protectedPhone",
values,
" _id = ?",
new String[] { c.getInt(c
.getColumnIndex("_id")) + "" });
if (l > 0) {
Toast.makeText(PhoneManagerActivity.this,
"修改成功", Toast.LENGTH_LONG).show();
cursor.requery();
} else {
Toast.makeText(PhoneManagerActivity.this,
"修改失败", Toast.LENGTH_LONG).show();
}
}
}
}).setNegativeButton("取消", null).setCancelable(false);
builder.show();
break;
case R.id.action_delete:
Builder builder1 = new AlertDialog.Builder(this)
.setIcon(R.drawable.ic_launcher).setTitle("删除联系人信息")
.setMessage("删除该联系人信息以后,您与该联系人之间的短信将不会受到保护,是否继续删除?")
.setPositiveButton("删除", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
Cursor c = (Cursor) (adapter.getItem(position));
pd.delete(
"protectedPhone",
"_id = ?",
new String[] { c.getInt(c
.getColumnIndex("_id")) + "" });
cursor.requery();
}
}).setNegativeButton("取消", null).setCancelable(false);
builder1.show();
break;
}
cursor.requery();
return super.onMenuItemSelected(featureId, item);
}
}
④、静态注册广播接收器,实现广播接收器拦截短信的功能
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.protect.sms.activity"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.VIBRATE" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<receiver android:name=".ProtectedSMSReceiver" >
<intent-filter android:priority="1000" >
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
intent-filter>
receiver>
application>
manifest>
创建广播接收器,处理onReceive()方法,先获取短信的来源地址,即电话号码,根据该电话号码在受保护的联系人数据库(protectedPhone)信息中查询,若查询到该联系人信息,则进行拦截,存储到数据库,否则,不做处理,发送到手机短信
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
if ("android.provider.Telephony.SMS_RECEIVED".equals(action)) {
// StringBuffer sb = new StringBuffer();
// 接收有SMS传递的数据
Bundle bundle = intent.getExtras();
// 判断是否有数据
if (bundle != null) {
// 通过pdus可以获得接收到的所有短信消息
Object[] pdus = (Object[]) bundle.get("pdus");
// 构建短信对象array,并依据收到的对象长度来创建array的大小
SmsMessage[] messages = new SmsMessage[pdus.length];
for (int i = 0; i < pdus.length; i++) {
messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
}
for (SmsMessage message : messages) {
// 获得短信来源
String address = message.getDisplayOriginatingAddress();
if (address.startsWith("+86")) {
address = address.substring(address.indexOf("+86")
+ "+86".length());
}
String person = null;
ProtectedDAO pd = new ProtectedDAO(context);
Cursor cursor = pd.select("protectedPhone", new String[] {
"person", "phone" }, "phone = ?",
new String[] { address }, null, null, null);
if (cursor.moveToNext()) {
String body = message.getDisplayMessageBody();
String date = formatDate(message.getTimestampMillis());
int type = 1;
int state = 0;
person = cursor.getString(cursor
.getColumnIndex("person"));
ContentValues values = new ContentValues();
values.put("address", address);
values.put("type", type);
values.put("state", state);
values.put("body", body);
values.put("date", date);
values.put("person", person);
long l = pd.insert("psms", values);
if (l > 0) {
NotificationCompat.Builder builder = new NotificationCompat.Builder(
context);
builder.setContentTitle((person == null || "null"
.equals(person)) ? address : person);
builder.setContentText(body);
builder.setContentInfo(date);
builder.setDefaults(Notification.DEFAULT_ALL);
builder.setSmallIcon(R.drawable.ic_launcher);
// builder.setSmallIcon(R.drawable.ic_launcher);//设置小图标
// Notification notification = builder.build();//
// 创建通知
// 通过系统服务,创建通知管理器
NotificationManager manager = (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
// 发送通知:参数1:通知的唯一标识,参数2:通知的对象
Intent intent1 = new Intent(context,
DetailsActivity.class);
Bundle bd = new Bundle();
bd.putString("address", address);
bd.putInt("type", type);
bd.putInt("state", state);
bd.putString("body", body);
bd.putString("date", date);
intent1.putExtras(bd);
PendingIntent pIntent = PendingIntent.getActivity(
context, 101, intent1,
PendingIntent.FLAG_ONE_SHOT);
builder.setContentIntent(pIntent);
manager.notify(101, builder.build());
// 中止发送通知
abortBroadcast();
}
}
}
}
}
}
//格式化时间,即将毫秒数转换成“yyyy-MM-dd HH:mm:ss”的时间
@SuppressLint("SimpleDateFormat")
public String formatDate(long millis) {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date = df.format(new Date(millis));
return date;
}
原理就是这样,具体代码过多,这里将不再进行展示。。。。。。
源码下载 :http://download.csdn.net/detail/qq_20538515/9174971
谢谢支持!