手机安全卫士第五天
手機安全衛士第五天實現的功能:
1.黑名單號碼的增加,刪除,修改。
2.黑名單listView的優化。
3.黑名單號碼短信的攔截。
首先創建一個數據庫類,然后實現了創建一個數據庫和一張張關于黑名單的表,然后再創建一個類BlackNumberDao,在該類實現關于表的增刪改查。
在該類的構造方法中創建,數據庫,然后第一次創建數據庫的時候創建一張表:
<span style="font-size:14px;">public class BlackNumberDao {private final BlackNumberOpenHelper mHelper;public BlackNumberDao(Context context) {mHelper = new BlackNumberOpenHelper(context);} }</span> <pre name="code" class="java"> <span style="font-size:14px;">public BlackNumberOpenHelper(Context context) {super(context, "safe.db", null, 1);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL("create table blacknumber " +"(_id integer primary key autoincrement,number varchar(20),mode varchar(2))");} </span>
? 然后在該類中實現增刪改查方法, /*** 增加黑名單號碼** @param number 號碼* @param mode 攔截方式* @return*/public boolean add(String number, String mode) {SQLiteDatabase db = mHelper.getWritableDatabase();ContentValues values = new ContentValues();values.put("number", number);values.put("mode", mode);long blacknumber = db.insert("blacknumber", null, values);if (blacknumber == -1) {return false;} else {return true;}}/*** 刪除黑名單號碼** @param number 要刪除的號碼* @return*/public boolean delete(String number) {SQLiteDatabase db = mHelper.getWritableDatabase();int blacknumber = db.delete("blacknumber", "number=?", new String[]{number});if (blacknumber == 0) {return false;} else {return true;}}/*** 修改攔截方式** @param number* @param mode* @return*/public boolean changeNumberMode(String number, String mode) {SQLiteDatabase db = mHelper.getWritableDatabase();ContentValues values = new ContentValues();values.put("mode", mode);int blacknumber = db.update("blacknumber", values, "number=?", new String[]{number});if (blacknumber == 0) {return false;} else {return true;}}/*** 返回一個黑名單號碼攔截模式** @param number* @return*/public String find(String number) {String mode = "";SQLiteDatabase db = mHelper.getReadableDatabase();Cursor cursor = db.query("blacknumber",new String[]{"mode"}, "number=?", new String[]{number}, null, null, null);if (cursor.moveToNext()) {mode = cursor.getColumnName(0);}cursor.close();db.close();return mode;}/*** 查找全部黑名單** @return*/public List<BlackNumberInfo> findAll() {SQLiteDatabase db = mHelper.getReadableDatabase();List<BlackNumberInfo> blackNumberInfos = new ArrayList<BlackNumberInfo>();Cursor cursor = db.query("blacknumber",new String[]{"number", "mode"}, null, null, null, null, null);while (cursor.moveToNext()) {BlackNumberInfo blackNumberInfo = new BlackNumberInfo();blackNumberInfo.setNumber(cursor.getString(0));blackNumberInfo.setMode(cursor.getString(1));blackNumberInfos.add(blackNumberInfo);}cursor.close();db.close();SystemClock.sleep(3000);return blackNumberInfos;}
為了優化黑名單的listView,先后創建了,在表中分段查找數據和分批查找數據,利用分段,分批查找數據,可以動態的對黑名單ListView進行顯示。
分批加載的好處:不用等待太久、節約流量、慢慢引導用戶看感興趣內容,分批處理?解決了時間的等待問題,但是不能解決內存占用問題。
<span style="font-size:14px;">/*** 分頁加載數據** @param pageNumber 表示當前是哪一頁* @param pageSize 表示每一頁有多少條數據* @return limit 表示限制當前有多少數據* offset 表示跳過 從第幾條開始*/public List<BlackNumberInfo> findPar(int pageNumber, int pageSize) {SQLiteDatabase db = mHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select number,mode from blacknumber limit ? offset ?", new String[]{String.valueOf(pageSize),String.valueOf(pageSize * pageNumber)});List<BlackNumberInfo> blackNumberInfos = new ArrayList<BlackNumberInfo>();while (cursor.moveToNext()) {BlackNumberInfo blackNumberInfo = new BlackNumberInfo();blackNumberInfo.setMode(cursor.getString(1));blackNumberInfo.setNumber(cursor.getString(0));blackNumberInfos.add(blackNumberInfo);}cursor.close();db.close();return blackNumberInfos;}/*** 分批加載數據** @param startIndex 開始的位置* @param maxCount 每頁展示的最大的條目* @return*/public List<BlackNumberInfo> findPar2(int startIndex, int maxCount) {SQLiteDatabase db = mHelper.getReadableDatabase();Cursor cursor = db.rawQuery("select number,mode from blacknumber limit ? offset ?",new String[]{String.valueOf(maxCount), String.valueOf(startIndex)});List<BlackNumberInfo> blackNumberInfos = new ArrayList<BlackNumberInfo>();while (cursor.moveToNext()) {BlackNumberInfo blackNumberInfo = new BlackNumberInfo();blackNumberInfo.setMode(cursor.getString(1));blackNumberInfo.setNumber(cursor.getString(0));blackNumberInfos.add(blackNumberInfo);}cursor.close();db.close();return blackNumberInfos;}</span>在類BlackNumberDao寫好了增刪改查方法之后,進入顯示黑名單的界面,進去界面之后,利用分段和分批加載數據庫中的數據,實現了一次顯示20個數據,往下拉到底,可以動態的顯示數據,如果是從網絡上獲取數據,為了程序的友好性,應該在界面加一個ProgressBar用來提示用戶以免加載時間過長。優化的顯示數據代碼如下:
<span style="font-size:14px;"></span><pre name="code" class="java">public class CallSafeActivity extends AppCompatActivity {private ListView list_view;private List<BlackNumberInfo> blackNumberInfos;private LinearLayout ll_pb;private BlackNumberDao dao;private CallSafeAdapter adapter;//開始的位置private int mStartIndex = 0;// 每頁展示20條數據private int maxCount = 20;//一共有多少頁面private int totalPage;private int totalNumber;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_call_safe);initUI();initData();}private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {ll_pb.setVisibility(View.INVISIBLE);if (adapter == null) {adapter = new CallSafeAdapter(blackNumberInfos, CallSafeActivity.this);list_view.setAdapter(adapter);} else {adapter.notifyDataSetChanged();}}};private void initData() {dao = new BlackNumberDao(CallSafeActivity.this);//一共有多少條數據totalNumber = dao.getTotalNumber();new Thread() {@Overridepublic void run() {//分批加載數據if (blackNumberInfos == null) {blackNumberInfos = dao.findPar2(mStartIndex, maxCount);} else {//把后面的數據。追加到blackNumberInfos集合里面。防止黑名單被覆蓋blackNumberInfos.addAll(dao.findPar2(mStartIndex, maxCount));}handler.sendEmptyMessage(0);}}.start();} private void initUI() { <span style="font-size:14px;"> ll_pb = (LinearLayout) findViewById(R.id.ll_pb);//展示加載的圓圈ll_pb.setVisibility(View.VISIBLE);list_view = (ListView) findViewById(R.id.list_view);//設置listview的滾動監聽list_view.setOnScrollListener(new AbsListView.OnScrollListener() {//狀態改變時候回調的方法/*** @param view* @param scrollState 表示滾動的狀態* AbsListView.OnScrollListener.SCROLL_STATE_IDLE 閑置狀態* AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL 手指觸摸的時候的狀態* AbsListView.OnScrollListener.SCROLL_STATE_FLING 慣性*/@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {switch (scrollState) {case AbsListView.OnScrollListener.SCROLL_STATE_IDLE://獲取到最后一條顯示的數據int lastVisiblePosition = list_view.getLastVisiblePosition();if (lastVisiblePosition == blackNumberInfos.size() - 1) {// 加載更多的數據。 更改加載數據的開始位置mStartIndex += maxCount;if (mStartIndex >= totalNumber) {Toast.makeText(getApplicationContext(),"沒有更多的數據了。", Toast.LENGTH_SHORT).show();return;}initData();}break;}}//listview滾動的時候調用的方法//時時調用。當我們的手指觸摸的屏幕的時候就調用@Overridepublic void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {}});}private class CallSafeAdapter extends MyBaseAdapter<BlackNumberInfo> {private CallSafeAdapter(List lists, Context mContext) {super(lists, mContext);}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if (convertView == null) {convertView = View.inflate(CallSafeActivity.this, R.layout.item_call_safe, null);holder = new ViewHolder();holder.tv_number = (TextView) convertView.findViewById(R.id.tv_number);holder.tv_mode = (TextView) convertView.findViewById(R.id.tv_mode);holder.iv_delete = (ImageView) convertView.findViewById(R.id.iv_delete);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.tv_number.setText(lists.get(position).getNumber());String mode = lists.get(position).getMode();if (mode.equals("1")) {holder.tv_mode.setText("來電攔截+短信");} else if (mode.equals("2")) {holder.tv_mode.setText("電話攔截");} else if (mode.equals("3")) {holder.tv_mode.setText("短信攔截");}final BlackNumberInfo info = lists.get(position);holder.iv_delete.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String number = info.getNumber();boolean result = dao.delete(number);if (result) {Toast.makeText(CallSafeActivity.this, "刪除成功", Toast.LENGTH_SHORT).show();lists.remove(info);//刷新界面adapter.notifyDataSetChanged();} else {Toast.makeText(CallSafeActivity.this, "刪除失敗", Toast.LENGTH_SHORT).show();}}});return convertView;}}static class ViewHolder {TextView tv_number;TextView tv_mode;ImageView iv_delete;} }</span><span style="font-size:14px;"> </span>
這里除了動態的加載數據之外還使用了一個容器:ViewHolder 用來節省內存,就不用一次性new很多的數據了,這也是ListView優化的常用方法之一,上面代碼中,還寫了刪除號碼的代碼,利用圖片的點擊事件,然后使用BlackNumberDao中的delete方法來刪除數據 ,首先根據用戶點擊的行號得到該行的電話號碼,然后傳入delete方法中進行刪除。
在該界面中,實現了一個增加的功能,在標題欄創建了一個按鈕,單擊按鈕彈出一個對話框,對話框使用了自定義的布局,包括了一個EditText,兩個CheckBox和兩個按鈕,分別用來得到用戶輸入的號碼,和得到哪個攔截模式,然后點擊確定按鈕進行調用add方法并輸入號碼和模式進行添加,并顯示在ListView中的第一個數據
/*** 添加黑名單** @param view*/public void addBlackNumber(View view) {AlertDialog.Builder builder = new AlertDialog.Builder(this);final AlertDialog dialog = builder.create();View dialog_view = View.inflate(this, R.layout.dialog_add_black_number, null);final EditText et_number = (EditText) dialog_view.findViewById(R.id.et_number);Button btn_ok = (Button) dialog_view.findViewById(R.id.btn_ok);Button btn_cancel = (Button) dialog_view.findViewById(R.id.btn_cancel);final CheckBox cb_phone = (CheckBox) dialog_view.findViewById(R.id.cb_phone);final CheckBox cb_sms = (CheckBox) dialog_view.findViewById(R.id.cb_sms);btn_cancel.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {dialog.dismiss();}});btn_ok.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {String str_number = et_number.getText().toString().trim();if (TextUtils.isEmpty(str_number)) {Toast.makeText(CallSafeActivity.this, "請輸入黑名單號碼", Toast.LENGTH_SHORT).show();return;}String mode = "";if (cb_phone.isChecked() && cb_sms.isChecked()) {mode = "1";} else if (cb_phone.isChecked()) {mode = "2";} else if (cb_sms.isChecked()) {mode = "3";} else {Toast.makeText(CallSafeActivity.this, "請勾選攔截模式", Toast.LENGTH_SHORT).show();return;}BlackNumberInfo blackNumberInfo = new BlackNumberInfo();blackNumberInfo.setNumber(str_number);blackNumberInfo.setMode(mode);blackNumberInfos.add(0, blackNumberInfo);//把電話號碼和攔截模式添加到數據庫。dao.add(str_number, mode);if (adapter == null) {adapter = new CallSafeAdapter(blackNumberInfos, CallSafeActivity.this);list_view.setAdapter(adapter);} else {adapter.notifyDataSetChanged();}dialog.dismiss();}});dialog.setView(dialog_view);dialog.show();}
最后就是開啟黑名單的服務,并實現對黑名單數據庫里面的號碼進行攔截,開啟黑名單的服務和第三天開啟來電監聽服務一樣,使用了自定義控件,然后在界面上勾選開啟關閉選項,開啟服務后,起一個廣播,在廣播中監聽來短信廣播,并判斷是否是數據庫中一樣的號碼,如果是,則攔截該號碼,如果不是則顯示給用戶。 public class CallSafeService extends Service {private BlackNumberDao mDao;public CallSafeService() {}@Overridepublic IBinder onBind(Intent intent) {throw new UnsupportedOperationException("Not yet implemented");}@Overridepublic void onCreate() {super.onCreate();mDao = new BlackNumberDao(this);InnerReceiver receiver = new InnerReceiver();IntentFilter intentFilter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");intentFilter.setPriority(Integer.MAX_VALUE);registerReceiver(receiver, intentFilter);}class InnerReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {//拿到短信包Object[] objects = (Object[]) intent.getExtras().get("pdus");for (Object object : objects) {// 短信最多140字節,// 超出的話,會分為多條短信發送,所以是一個數組,因為我們的短信指令很短,所以for循環只執行一次SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) object);String number = smsMessage.getOriginatingAddress();// 短信來源號碼//通過短信的電話號碼查詢攔截的模式/*** 黑名單攔截模式* 1 全部攔截 電話攔截 + 短信攔截* 2 電話攔截* 3 短信攔截*/String mode = mDao.find(number);if (mode.equals("1")){abortBroadcast();}else if (mode.equals("3")){abortBroadcast();}}}} }
總結
- 上一篇: 安卓APP测试要怎么测,测试流程和重点有
- 下一篇: iOS 苹果官方Demo合集