一、黑名单数据库工具类
public class CallSMSSafeOpenHelper extends SQLiteOpenHelper {
private Context context;
// 电话短信安全的数据库名称,.db后缀只是给人看的
public static final String DB_NAME = "callsmssafe.db";
// 建立黑名单列表的建表语句
public static final String CT_BLACKLIST = "CREATE TABLE black_list ( _id INTEGER PRIMARY KEY AUTOINCREMENT,phone VARCHAR(20), mode INT(2))";
public static final String BLACKLIST_TB_NAME = "black_list";
public CallSMSSafeOpenHelper(Context context, String name,
CursorFactory factory, int version) {
super(context, name, factory, version);
}
/*
* 自定义的默认的构造器
*/
public CallSMSSafeOpenHelper(Context context) {
this(context, DB_NAME, null, 1);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
// 通过带工具类得到数据库实例时数据库不存在会执行该方法
Toast.makeText(context, "数据库不存在,执行建表语句创建数据库和相关的数据表", 1).show();
db.execSQL(CT_BLACKLIST);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Toast.makeText(context,
"数据库版本变化,新版本:" + newVersion + ",旧版本:" + oldVersion, 1).show();
}
}
二、黑名单表的DAO实现
public class DaoBlackList {
private Context context;
public DaoBlackList(Context context) {
this.context = context;
}
public boolean add(BlackPhone bp) {
return this.add(bp.getPhone(), bp.getMode());
}
public boolean add(String phone, int mode) {
// 创建数据库工具类
SQLiteOpenHelper helper = new CallSMSSafeOpenHelper(context);
// 使用工具类得到一个可写的数据库实例
SQLiteDatabase database = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("phone", phone);
values.put("mode", mode);
long result = (long) database.insert(
CallSMSSafeOpenHelper.BLACKLIST_TB_NAME, null, values);
database.close();
if (result != -1)
return true;
return false;
}
public int delete(String phone) {
// 创建数据库工具类
SQLiteOpenHelper helper = new CallSMSSafeOpenHelper(context);
// 使用工具类得到一个可写的数据库实例
SQLiteDatabase database = helper.getWritableDatabase();
int result = database.delete(CallSMSSafeOpenHelper.BLACKLIST_TB_NAME,
"phone=?", new String[] { phone });
database.close();
return result;
}
public int update(String phone, int newMode) {
// 创建数据库工具类
SQLiteOpenHelper helper = new CallSMSSafeOpenHelper(context);
// 使用工具类得到一个可写的数据库实例
SQLiteDatabase database = helper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("mode", newMode);
int result = database.update(CallSMSSafeOpenHelper.BLACKLIST_TB_NAME,
values, "phone=?", new String[] { phone });
database.close();
return result;
}
public BlackPhone list(String phone) {
// 创建数据库工具类
SQLiteOpenHelper helper = new CallSMSSafeOpenHelper(context);
// 使用工具类得到一个可写的数据库实例
SQLiteDatabase database = helper.getWritableDatabase();
Cursor c = database.query(CallSMSSafeOpenHelper.BLACKLIST_TB_NAME,
new String[] { "phone", "mode" }, "phone=?",
new String[] { phone }, null, null, null);
BlackPhone blackPhone = null;
if (c.moveToNext()) {
blackPhone = new BlackPhone();
blackPhone.setMode(c.getInt(c.getColumnIndex("mode")));
blackPhone.setPhone(phone);
}
c.close();
database.close();
return blackPhone;
}
public List<BlackPhone> list() {
// 创建数据库工具类
SQLiteOpenHelper helper = new CallSMSSafeOpenHelper(context);
// 使用工具类得到一个可写的数据库实例
SQLiteDatabase database = helper.getWritableDatabase();
Cursor c = database.query(CallSMSSafeOpenHelper.BLACKLIST_TB_NAME,
new String[] { "phone", "mode" }, null, null, null, null, null);
List<BlackPhone> blackPhones = new ArrayList<BlackPhone>();
BlackPhone blackPhone = null;
while (c.moveToNext()) {
blackPhone = new BlackPhone();
blackPhone.setMode(c.getInt(c.getColumnIndex("mode")));
blackPhone.setPhone(c.getString(c.getColumnIndex("phone")));
blackPhones.add(blackPhone);
}
c.close();
database.close();
return blackPhones;
}
public int getCount() {
// 创建数据库工具类
SQLiteOpenHelper helper = new CallSMSSafeOpenHelper(context);
// 使用工具类得到一个可写的数据库实例
SQLiteDatabase database = helper.getWritableDatabase();
Cursor c = database.query(CallSMSSafeOpenHelper.BLACKLIST_TB_NAME,
new String[] { "phone", "mode" }, null, null, null, null, null);
int count = c.getCount();
c.close();
database.close();
return count;
}
// 分页加载数据
public List<BlackPhone> list(int startIndex, int pageSize) {
// 创建数据库工具类
SQLiteOpenHelper helper = new CallSMSSafeOpenHelper(context);
// 使用工具类得到一个可写的数据库实例
SQLiteDatabase database = helper.getWritableDatabase();
// Cursor c = database.query(CallSMSSafeOpenHelper.BLACKLIST_TB_NAME,
// new String[] { "phone", "mode" }, null, null, null, null, null);
Cursor c = database.rawQuery("select _id,phone,mode from "
+ CallSMSSafeOpenHelper.BLACKLIST_TB_NAME
+ " order by _id desc limit ? offset ? ", new String[] {
pageSize + "", startIndex + "" });
List<BlackPhone> blackPhones = new ArrayList<BlackPhone>();
BlackPhone blackPhone = null;
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (c.moveToNext()) {
blackPhone = new BlackPhone();
blackPhone.setMode(c.getInt(c.getColumnIndex("mode")));
blackPhone.setPhone(c.getString(c.getColumnIndex("phone")));
blackPhones.add(blackPhone);
}
c.close();
database.close();
return blackPhones;
}
}
三、ListView的分批加载
a) 获取第一批数据(20条)
b) 手指滚动到,可见的最后一个条目为该集合的最后一个条目时,加载下一批数据,将其添加到原始集合上(集合会越来越大,因此数据量大到一定程度分批加载会出现内存不足)。然后使用适配器提醒数据发生改变。
c) 集合的总数和数据表的条目数一致时操作结束。
四、ListView的优化
a) 尽可能复用convertView对象
if (convertView != null
&& convertView instanceof RelativeLayout) {
holder = (ViewHolder) convertView.getTag();
} else {
holder = new ViewHolder();
convertView = inflater.inflate(
R.layout.processinfo_item_show, null);
holder.cb_process_check = (CheckBox) convertView
.findViewById(R.id.cb_process_check);
holder.iv_process_icon = (ImageView) convertView
.findViewById(R.id.iv_process_icon);
holder.tv_process_memsize = (TextView) convertView
.findViewById(R.id.tv_process_memsize);
holder.tv_process_name = (TextView) convertView
.findViewById(R.id.tv_process_name);
convertView.setTag(holder);
}
b) 使用ViewHolder将条目需要用到的控件保存下来,只找一次
class MyDapter extends BaseAdapter {
@Override
public int getCount() {
if (sp.getBoolean("isShowSysProcess", true)) {
return sysProcessInfos.size() + userProcessInfos.size() + 1;
}
return userProcessInfos.size();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (position == userProcessInfos.size()) {
TextView tv = new TextView(TaskManagerActivity.this);
tv.setBackgroundColor(Color.BLACK);
tv.setTextColor(Color.WHITE);
tv.setTextSize(16);
tv.setText("系统应用:共" + sysProcessInfos.size() + "个");
return tv;
} else {
if (convertView != null
&& convertView instanceof RelativeLayout) {
holder = (ViewHolder) convertView.getTag();
} else {
holder = new ViewHolder();
convertView = inflater.inflate(
R.layout.processinfo_item_show, null);
holder.cb_process_check = (CheckBox) convertView
.findViewById(R.id.cb_process_check);
holder.iv_process_icon = (ImageView) convertView
.findViewById(R.id.iv_process_icon);
holder.tv_process_memsize = (TextView) convertView
.findViewById(R.id.tv_process_memsize);
holder.tv_process_name = (TextView) convertView
.findViewById(R.id.tv_process_name);
convertView.setTag(holder);
}
if (position < userProcessInfos.size()) {
ProcessInfo info = userProcessInfos.get(position);
holder.cb_process_check.setChecked(info.isChecked());
holder.iv_process_icon.setImageDrawable(userProcessInfos
.get(position).getIcon());
holder.tv_process_memsize.setText(Formatter.formatFileSize(
TaskManagerActivity.this, info.getMemSize()));
holder.tv_process_name.setText(info.getName());
} else {
ProcessInfo info = sysProcessInfos.get(position
- userProcessInfos.size() - 1);
holder.cb_process_check.setChecked(info.isChecked());
holder.iv_process_icon.setImageDrawable(info.getIcon());
holder.tv_process_memsize.setText(Formatter.formatFileSize(
TaskManagerActivity.this, info.getMemSize()));
holder.tv_process_name.setText(info.getName());
}
return convertView;
}
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return null;
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
class ViewHolder {
ImageView iv_process_icon;
TextView tv_process_name;
TextView tv_process_memsize;
CheckBox cb_process_check;
}
}
c) 使用分批加载(不能解决条目太多内存不够用的问题)
d) 使用分页加载(类似于web开发中的分页,用户体验不够好)
五、新增一个条目时为了保证显示在第一个位置需要按照id倒序排列
六、利用发射机制挂断电话
/**
* 利用发射机制挂断电话
*/
public void endCall() {
Class<TelephonyManager> c = TelephonyManager.class;
Method getITelephonyMethod = null;
// 声明ITelephony
ITelephony iTelephony = null;
try {
getITelephonyMethod = c.getDeclaredMethod("getITelephony",
(Class[]) null);
getITelephonyMethod.setAccessible(true);
iTelephony = (ITelephony) getITelephonyMethod.invoke(tm,
(Object[]) null);
iTelephony.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
七、清除呼叫呼叫记录
// 不能直接清除通话记录因为生成通话记录需要一定的时间
getContentResolver().registerContentObserver(
Uri.parse("content://call_log/calss"), true,
new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
deleteCallLog(bp.getPhone());
// 成功晴空通话记录后就不再监听了
getContentResolver()
.unregisterContentObserver(this);
super.onChange(selfChange);
}
});
//根据电话号码删除通话记录的方法
public void deleteCallLog(String phone) {
ContentResolver resolver = getContentResolver();
resolver.delete(Uri.parse("content://call_log/calls"), "number=?",
new String[] { phone });
}