【0067】【项目实战】-【手机安全卫士】-【7】归属地-通信卫士

1. 去电归属地的查询

1.1 效果

 1.2 去电归属地查询的服务

【对于广播的注册方式】

【1】静态的注册方式

【2】动态的注册

【框架】

【源码】

 

【权限的增加】可以使用先不增加权限,等待程序运行出错之后再重警告信息中查询所需要的权限;

【增加权限】

【效果】去电归属地可以查询出来了;

===========================【通信卫士】==========================================================

2.黑名单功能

2.1 功能及效果展示

【1】进入通信卫士中,可以 针对短信/电话/短信+电话一起进行屏蔽;

 并且,拦截的添加内容之后,新添加的内容在第一条出现;

【2】可以删除添加的拦截的条目;

【注意】

【3】需要将设置与业务真正的绑定起来;

2.2 布局的编写

【说明】上面使用的是自定义的样式,然后将文字的显示放在左侧;

 下面使用的是listView;

 

 【主页的跳转】

【创建跳转的activity并且配置清单】

【布局文件的填写】

【布局分析】外部使用线性布局,标题使用相对布局;

【布局源码】

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     <RelativeLayout 
 7         android:layout_width="match_parent"
 8         android:layout_height="wrap_content">
 9         <TextView 
10             style="@style/TitleStyle"
11             android:gravity="left"
12             android:text="黑名单管理"/>  
13         <Button
14             android:id="@+id/bt_add"
15             android:text="添加"
16             android:layout_alignParentRight="true"
17             android:layout_centerVertical="true"
18             android:layout_width="wrap_content"
19             android:layout_height="wrap_content"/>      
20     </RelativeLayout>
21     <ListView 
22         android:id="@+id/lv_blacknumber"
23         android:layout_width="match_parent"
24         android:layout_height="wrap_content">
25     </ListView>
26 </LinearLayout>

2.3 数据库的创建

【说明】需要三个字段:_id 自增长的字段  黑名单号码 拦截类型;

2.3.1 表的创建

【说明】括号和 分号一定要使用 英文样式的,否则会出现问题;

 

2.3.2 在源码中创建类

【说明】在数据的执行语句db.execSQL()语句,一定要现在数据库软件中执行了语句之后再次在源码中书写,否则源码中无法验证语句的正确与否;

 

【表的创建】

【增删改查包的创建】增删改查类的源码

【注意】单例模式的创建步骤

【增】

【删】

【改】

【查】将查询的数据放入到javabean中

【javabean的封装】共有的成员,没有提供get方法,私有的必须提供get方法;

2.4 junit测试

【说明】对完成的数据库进行测试;

【测试工程的建立】主要目标是复制其中的两段关键的代码

【源码的增加】将测试工程的配置的两段源码复制到被测试工程的配置文件中;

【测试源码的书写】

【查看插入的数据】

【查看删除的数据】

【查看更新之后的数据】

2.5 黑名单号码数据适配器

【说明】将数据查出来,然后丢到listView的数据适配器中;

【说明】在数据的初始化中,将所有的数据查询出来显示在listView中;

【listView中的单个条目的布局】

【背景选中的效果的切换】

【数据适配器的完善】

【效果】运行之后可以将数据库中的数据显示出来;

2.6 添加按钮对话框

【对话框的设置的效果】

【框架】

【对话框的布局】

【布局源码】 

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     <TextView 
 7         style="@style/TitleStyle"
 8         android:background="#fcc"
 9         android:text="添加黑名单号码"/>
10     <EditText 
11         android:id="@+id/et_phone"
12         android:hint="请输入拦截号码"
13         android:inputType="phone"
14         android:textColor="#000"
15         android:layout_width="match_parent"
16         android:layout_height="wrap_content"/>
17     <RadioGroup
18         android:id="@+id/rg_group" 
19         android:orientation="horizontal"
20         android:gravity="center"
21         android:layout_width="match_parent"
22         android:layout_height="wrap_content">
23         <RadioButton 
24             android:id="@+id/rb_sms"
25             android:text="短信"
26             android:textColor="#000"
27             android:checked="true"
28             android:layout_width="wrap_content"
29             android:layout_height="wrap_content"/>
30         <RadioButton 
31             android:id="@+id/rb_phone"
32             android:text="电话"
33             android:textColor="#000"
34             android:layout_width="wrap_content"
35             android:layout_height="wrap_content"/>
36         <RadioButton 
37             android:id="@+id/rb_all"
38             android:text="所有"
39             android:textColor="#000"
40             android:layout_width="wrap_content"
41             android:layout_height="wrap_content"/>
42     </RadioGroup>
43     <LinearLayout
44         android:layout_width="match_parent"
45            android:layout_height="wrap_content">
46         <Button
47             android:id="@+id/bt_submit"
48             android:text="确认"
49             android:textColor="#000"
50             android:layout_width="0dp"
51             android:layout_weight="1"
52             android:layout_height="wrap_content"/>
53         <Button
54             android:id="@+id/bt_cancel"
55             android:text="取消"
56             android:textColor="#000"
57             android:layout_width="0dp"
58             android:layout_weight="1"
59             android:layout_height="wrap_content"/>
60     </LinearLayout>
61 </LinearLayout>

【逻辑的完善】

【效果】

 2.7 逻辑对话框的逻辑

 1 protected void showDialog() {
 2         Builder builder = new AlertDialog.Builder(this);
 3         
 4         final AlertDialog dialog = builder.create();
 5         View view = View.inflate(getApplicationContext(), R.layout.dialog_add_blacknumber, null);
 6         dialog.setView(view, 0, 0, 0, 0);
 7         
 8         final EditText et_phone = (EditText) view.findViewById(R.id.et_phone);
 9         RadioGroup rg_group = (RadioGroup) view.findViewById(R.id.rg_group);
10         
11         Button bt_submit = (Button) view.findViewById(R.id.bt_submit);
12         Button bt_cancel = (Button)view.findViewById(R.id.bt_cancel);
13         
14         //监听其选中条目的切换过程
15         rg_group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
16             @Override
17             public void onCheckedChanged(RadioGroup group, int checkedId) {
18                 switch (checkedId) {
19                 case R.id.rb_sms:
20                     //拦截短信
21                     mode = 1;
22                     break;
23                 case R.id.rb_phone:
24                     //拦截电话
25                     mode = 2;
26                     break;
27                 case R.id.rb_all:
28                     //拦截所有
29                     mode = 3;
30                     break;
31                 }
32             }
33         });
34         
35         bt_submit.setOnClickListener(new OnClickListener() {
36             @Override
37             public void onClick(View v) {
38                 //1,获取输入框中的电话号码
39                 String phone = et_phone.getText().toString();
40                 if(!TextUtils.isEmpty(phone)){
41                     //2,数据库插入当前输入的拦截电话号码
42                     mDao.insert(phone, mode+""); 
43                     //3,让数据库和集合保持同步(1.数据库中数据重新读一遍,2.手动向集合中添加一个对象(插入数据构建的对象))
44                     BlackNumberInfo blackNumberInfo = new BlackNumberInfo();
45                     blackNumberInfo.phone = phone;
46                     blackNumberInfo.mode = mode+"";
47                     //4,将对象插入到集合的最顶部
48                     mBlackNumberList.add(0, blackNumberInfo);
49                     //5,通知数据适配器刷新(数据适配器中的数据有改变了)
50                     if(mAdapter!=null){
51                         mAdapter.notifyDataSetChanged();
52                     }
53                     //6,隐藏对话框
54                     dialog.dismiss();
55                 }else{
56                     ToastUtil.show(getApplicationContext(), "请输入拦截号码");
57                 }
58             }
59         });
60         
61         bt_cancel.setOnClickListener(new OnClickListener() {
62             @Override
63             public void onClick(View v) {
64                 dialog.dismiss();
65             }
66         });
67         
68         dialog.show();
69     }

【效果】添加不同类型的号码的时候可以相应增加不同的拦截类型;

 

2.8 黑名单的删除

 【说明】先找条目,再找到相关的垃圾桶按钮,然后响应事件;

【源码框架】

【源码逻辑】

【效果】可以删除,并且最后的数据库的数据只剩下两条;

 

【数据库的访问方式】

3. listView的优化

3.1 存在的bug

 

【出现问题的原因】该方法被调用了不止100遍;view 对象至少创建了100个;

 

【优化】

【再优化】直接将返回的值赋值给convertView即可;view在中间没有实际的作用,只是中间变量的替换,没有实际意义;

【复用的机制】

 

3.2 存在的优化2 Viewholder的使用

【存在的问题】

【解决问题的方法】

 

 【解决办法】相当于一个临时的存储控件,一旦查找好的就可以存在当前的空间ViewHolder中,以便于下次复用;

3.3 ViewHolder的源码编写

 

 

【测试效果】内存的剩余比例不改变;一直都是6%;

3.5 优化三

4. 分页查询

4.1 分页加载20条数据

【说明】在用户的需求中,有时候不需要全部加载所有的数据,只需要加载部分的数据;

 只需要在加载的时候,读取数据库的时候只读取部分数据即可;

 

 【增加分页查询的源码】

 【bug】运行报错-未明确的指定查询的字段;

【修改】指定查询的字段

【效果】只加载了20条数据;再下滑无法出现加载的条目;

 4.2 上滑加载更多

【滚动状态的监听】重点是mIsLoad的理解;

【查询数据库中数据的总个数】

【效果】滚动条在不断的减小,因为数据加载更多了;

 【源码】/mobilesafe74/src/com/itheima/mobilesafe74/activity/BlackNumberActivity.java

  1 package com.itheima.mobilesafe74.activity;
  2 
  3 import java.util.List;
  4 
  5 import com.itheima.mobilesafe74.R;
  6 import com.itheima.mobilesafe74.db.dao.BlackNumberDao;
  7 import com.itheima.mobilesafe74.db.domain.BlackNumberInfo;
  8 import com.itheima.mobilesafe74.utils.ToastUtil;
  9 
 10 import android.app.Activity;
 11 import android.app.AlertDialog;
 12 import android.app.AlertDialog.Builder;
 13 import android.os.Bundle;
 14 import android.os.Handler;
 15 import android.text.TextUtils;
 16 import android.view.View;
 17 import android.view.View.OnClickListener;
 18 import android.view.ViewGroup;
 19 import android.widget.AbsListView;
 20 import android.widget.AbsListView.OnScrollListener;
 21 import android.widget.BaseAdapter;
 22 import android.widget.Button;
 23 import android.widget.EditText;
 24 import android.widget.ImageView;
 25 import android.widget.ListView;
 26 import android.widget.RadioGroup;
 27 import android.widget.RadioGroup.OnCheckedChangeListener;
 28 import android.widget.TextView;
 29 
 30 //1,复用convertView
 31 //2,对findViewById次数的优化,使用ViewHolder
 32 //3,将ViewHolder定义成静态,不会去创建多个对象
 33 //4,listView如果有多个条目的时候,可以做分页算法,每一次加载20条,逆序返回
 34 
 35 public class BlackNumberActivity extends Activity {
 36     private Button bt_add;
 37     private ListView lv_blacknumber;
 38     private BlackNumberDao mDao;
 39     private List<BlackNumberInfo> mBlackNumberList;
 40     private MyAdapter mAdapter;
 41     private int mode = 1;
 42     private boolean mIsLoad = false;
 43     private int mCount;
 44     
 45     private Handler mHandler = new Handler(){
 46         public void handleMessage(android.os.Message msg) {
 47             //4,告知listView可以去设置数据适配器
 48             if(mAdapter == null){
 49                 mAdapter = new MyAdapter();
 50                 lv_blacknumber.setAdapter(mAdapter);
 51             }else{
 52                 mAdapter.notifyDataSetChanged();
 53             }
 54         };
 55     };
 56     
 57     class MyAdapter extends BaseAdapter{
 58         @Override
 59         public int getCount() {
 60             return mBlackNumberList.size();
 61         }
 62 
 63         @Override
 64         public Object getItem(int position) {
 65             return mBlackNumberList.get(position);
 66         }
 67 
 68         @Override
 69         public long getItemId(int position) {
 70             return position;
 71         }
 72 
 73         @Override
 74         public View getView(final int position, View convertView, ViewGroup parent) {
 75 //            View view = null;
 76 /*            if(convertView == null){
 77                 view = View.inflate(getApplicationContext(), R.layout.listview_blacknumber_item, null);
 78             }else{
 79                 view = convertView;
 80             }*/
 81             
 82             //1,复用convertView
 83             
 84             //复用viewHolder步骤一
 85             ViewHolder holder = null;
 86             if(convertView == null){
 87                 convertView = View.inflate(getApplicationContext(), R.layout.listview_blacknumber_item, null);
 88                 //2,减少findViewById()次数
 89                 //复用viewHolder步骤三
 90                 holder = new ViewHolder();
 91                 //复用viewHolder步骤四
 92                 holder.tv_phone = (TextView) convertView.findViewById(R.id.tv_phone);
 93                 holder.tv_mode = (TextView)convertView.findViewById(R.id.tv_mode);
 94                 holder.iv_delete = (ImageView)convertView.findViewById(R.id.iv_delete);
 95                 //复用viewHolder步骤五
 96                 convertView.setTag(holder);
 97             }else{
 98                 holder = (ViewHolder) convertView.getTag();
 99             }
100             
101             holder.iv_delete.setOnClickListener(new OnClickListener() {
102                 @Override
103                 public void onClick(View v) {
104                     //1,数据库删除
105                     mDao.delete(mBlackNumberList.get(position).phone);
106                     //2,集合中的删除
107                     mBlackNumberList.remove(position);
108                     //3,通知数据适配器刷新
109                     if(mAdapter!=null){
110                         mAdapter.notifyDataSetChanged();
111                     }
112                 }
113             });
114             
115             holder.tv_phone.setText(mBlackNumberList.get(position).phone);
116             int mode = Integer.parseInt(mBlackNumberList.get(position).mode);
117             switch (mode) {
118             case 1:
119                 holder.tv_mode.setText("拦截短信");
120                 break;
121             case 2:
122                 holder.tv_mode.setText("拦截电话");
123                 break;
124             case 3:
125                 holder.tv_mode.setText("拦截所有");
126                 break;
127             }
128             return convertView;
129         }
130     }
131     //复用viewHolder步骤二
132     static class ViewHolder{
133         TextView tv_phone;
134         TextView tv_mode;
135         ImageView iv_delete;
136     }
137 
138     @Override
139     protected void onCreate(Bundle savedInstanceState) {
140         super.onCreate(savedInstanceState);
141         setContentView(R.layout.activity_blacknumber);
142         
143         initUI();
144         initData();
145     }
146 
147     private void initData() {
148         //获取数据库中所有电话号码
149         new Thread(){
150             public void run() {
151                 //1,获取操作黑名单数据库的对象
152                 mDao = BlackNumberDao.getInstance(getApplicationContext());
153                 //2,查询部分数据
154                 mBlackNumberList = mDao.find(0);
155                 mCount = mDao.getCount();
156                 
157                 //3,通过消息机制告知主线程可以去使用包含数据的集合
158                 mHandler.sendEmptyMessage(0);
159             }
160         }.start();
161     }
162 
163     private void initUI() {
164         bt_add = (Button) findViewById(R.id.bt_add);
165         lv_blacknumber = (ListView) findViewById(R.id.lv_blacknumber);
166         
167         bt_add.setOnClickListener(new OnClickListener() {
168             @Override
169             public void onClick(View v) {
170                 showDialog();
171             }
172         });
173         
174         //监听其滚动状态
175         lv_blacknumber.setOnScrollListener(new OnScrollListener() {
176             //滚动过程中,状态发生改变调用方法()
177             @Override
178             public void onScrollStateChanged(AbsListView view, int scrollState) {
179 //                OnScrollListener.SCROLL_STATE_FLING    飞速滚动
180 //                OnScrollListener.SCROLL_STATE_IDLE     空闲状态
181 //                OnScrollListener.SCROLL_STATE_TOUCH_SCROLL    拿手触摸着去滚动状态
182                 
183                 if(mBlackNumberList!=null){
184                     //条件一:滚动到停止状态
185                     //条件二:最后一个条目可见(最后一个条目的索引值>=数据适配器中集合的总条目个数-1)
186                     if(scrollState == OnScrollListener.SCROLL_STATE_IDLE
187                             && lv_blacknumber.getLastVisiblePosition()>=mBlackNumberList.size()-1
188                             && !mIsLoad){
189                         /*mIsLoad防止重复加载的变量
190                         如果当前正在加载mIsLoad就会为true,本次加载完毕后,再将mIsLoad改为false
191                         如果下一次加载需要去做执行的时候,会判断上诉mIsLoad变量,是否为false,如果为true,就需要等待上一次加载完成,将其值
192                         改为false后再去加载*/
193                         
194                         //如果条目总数大于集合大小的时,才可以去继续加载更多
195                         if(mCount>mBlackNumberList.size()){
196                             //加载下一页数据
197                             new Thread(){
198                                 public void run() {
199                                     //1,获取操作黑名单数据库的对象
200                                     mDao = BlackNumberDao.getInstance(getApplicationContext());
201                                     //2,查询部分数据
202                                     List<BlackNumberInfo> moreData = mDao.find(mBlackNumberList.size());
203                                     //3,添加下一页数据的过程
204                                     mBlackNumberList.addAll(moreData);
205                                     //4,通知数据适配器刷新
206                                     mHandler.sendEmptyMessage(0);
207                                 }
208                             }.start();
209                         }
210                     }
211                 }
212                 
213             }
214             
215             //滚动过程中调用方法
216             @Override
217             public void onScroll(AbsListView view, int firstVisibleItem,
218                     int visibleItemCount, int totalItemCount) {
219                 
220             }
221         });
222     }
223 
224     protected void showDialog() {
225         Builder builder = new AlertDialog.Builder(this);
226         
227         final AlertDialog dialog = builder.create();
228         View view = View.inflate(getApplicationContext(), R.layout.dialog_add_blacknumber, null);
229         dialog.setView(view, 0, 0, 0, 0);
230         
231         final EditText et_phone = (EditText) view.findViewById(R.id.et_phone);
232         RadioGroup rg_group = (RadioGroup) view.findViewById(R.id.rg_group);
233         
234         Button bt_submit = (Button) view.findViewById(R.id.bt_submit);
235         Button bt_cancel = (Button)view.findViewById(R.id.bt_cancel);
236         
237         //监听其选中条目的切换过程
238         rg_group.setOnCheckedChangeListener(new OnCheckedChangeListener() {
239             @Override
240             public void onCheckedChanged(RadioGroup group, int checkedId) {
241                 switch (checkedId) {
242                 case R.id.rb_sms:
243                     //拦截短信
244                     mode = 1;
245                     break;
246                 case R.id.rb_phone:
247                     //拦截电话
248                     mode = 2;
249                     break;
250                 case R.id.rb_all:
251                     //拦截所有
252                     mode = 3;
253                     break;
254                 }
255             }
256         });
257         
258         bt_submit.setOnClickListener(new OnClickListener() {
259             @Override
260             public void onClick(View v) {
261                 //1,获取输入框中的电话号码
262                 String phone = et_phone.getText().toString();
263                 if(!TextUtils.isEmpty(phone)){
264                     //2,数据库插入当前输入的拦截电话号码
265                     mDao.insert(phone, mode+""); 
266                     //3,让数据库和集合保持同步(1.数据库中数据重新读一遍,2.手动向集合中添加一个对象(插入数据构建的对象))
267                     BlackNumberInfo blackNumberInfo = new BlackNumberInfo();
268                     blackNumberInfo.phone = phone;
269                     blackNumberInfo.mode = mode+"";
270                     //4,将对象插入到集合的最顶部
271                     mBlackNumberList.add(0, blackNumberInfo);
272                     //5,通知数据适配器刷新(数据适配器中的数据有改变了)
273                     if(mAdapter!=null){
274                         mAdapter.notifyDataSetChanged();
275                     }
276                     //6,隐藏对话框
277                     dialog.dismiss();
278                 }else{
279                     ToastUtil.show(getApplicationContext(), "请输入拦截号码");
280                 }
281             }
282         });
283         
284         bt_cancel.setOnClickListener(new OnClickListener() {
285             @Override
286             public void onClick(View v) {
287                 dialog.dismiss();
288             }
289         });
290         
291         dialog.show();
292     }
293 }    

【源码】/mobilesafe74/src/com/itheima/mobilesafe74/db/dao/BlackNumberDao.java

  1 package com.itheima.mobilesafe74.db.dao;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 import android.content.ContentValues;
  7 import android.content.Context;
  8 import android.database.Cursor;
  9 import android.database.sqlite.SQLiteDatabase;
 10 
 11 import com.itheima.mobilesafe74.db.BlackNumberOpenHelper;
 12 import com.itheima.mobilesafe74.db.domain.BlackNumberInfo;
 13 
 14 public class BlackNumberDao {
 15     private BlackNumberOpenHelper blackNumberOpenHelper;
 16     //BlackNumberDao单例模式
 17     //1,私有化构造方法
 18     private BlackNumberDao(Context context){
 19         //创建数据库已经其表机构
 20         blackNumberOpenHelper = new BlackNumberOpenHelper(context);
 21     }
 22     //2,声明一个当前类的对象
 23     private static BlackNumberDao blackNumberDao = null;
 24     //3,提供一个静态方法,如果当前类的对象为空,创建一个新的
 25     public static BlackNumberDao getInstance(Context context){
 26         if(blackNumberDao == null){
 27             blackNumberDao = new BlackNumberDao(context);
 28         }
 29         return blackNumberDao;
 30     }
 31     
 32     /**增加一个条目
 33      * @param phone    拦截的电话号码
 34      * @param mode    拦截类型(1:短信    2:电话    3:拦截所有(短信+电话))
 35      */
 36     public void insert(String phone,String mode){
 37         //1,开启数据库,准备做写入操作
 38         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 39 
 40         ContentValues values = new ContentValues();
 41         values.put("phone", phone);
 42         values.put("mode", mode);
 43         db.insert("blacknumber", null, values);
 44         
 45         db.close();
 46     }
 47     
 48     /**从数据库中删除一条电话号码
 49      * @param phone    删除电话号码
 50      */
 51     public void delete(String phone){
 52         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 53 
 54         db.delete("blacknumber", "phone = ?", new String[]{phone});
 55         
 56         db.close();
 57     }
 58     
 59     /**
 60      * 根据电话号码去,更新拦截模式
 61      * @param phone    更新拦截模式的电话号码
 62      * @param mode    要更新为的模式(1:短信    2:电话    3:拦截所有(短信+电话)
 63      */
 64     public void update(String phone,String mode){
 65         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 66 
 67         ContentValues contentValues = new ContentValues();
 68         contentValues.put("mode", mode);
 69         
 70         db.update("blacknumber", contentValues, "phone = ?", new String[]{phone});
 71         
 72         db.close();
 73     }
 74     
 75     /**
 76      * @return    查询到数据库中所有的号码以及拦截类型所在的集合
 77      */
 78     public List<BlackNumberInfo> findAll(){
 79         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 80 
 81         Cursor cursor = db.query("blacknumber", new String[]{"phone","mode"}, null, null, null, null, "_id desc");
 82         List<BlackNumberInfo> blackNumberList = new ArrayList<BlackNumberInfo>();
 83         while(cursor.moveToNext()){
 84             BlackNumberInfo blackNumberInfo = new BlackNumberInfo();
 85             blackNumberInfo.phone = cursor.getString(0);
 86             blackNumberInfo.mode = cursor.getString(1);
 87             blackNumberList.add(blackNumberInfo);
 88         }
 89         cursor.close();
 90         db.close();
 91         
 92         return blackNumberList;
 93     }
 94     
 95     /**
 96      * 每次查询20条数据
 97      * @param index    查询的索引值
 98      */
 99     public List<BlackNumberInfo> find(int index){
100         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
101 
102         Cursor cursor = db.rawQuery("select phone,mode from blacknumber order by _id desc limit ?,20;", new String[]{index+""});
103         
104         List<BlackNumberInfo> blackNumberList = new ArrayList<BlackNumberInfo>();
105         while(cursor.moveToNext()){
106             BlackNumberInfo blackNumberInfo = new BlackNumberInfo();
107             blackNumberInfo.phone = cursor.getString(0);
108             blackNumberInfo.mode = cursor.getString(1);
109             blackNumberList.add(blackNumberInfo);
110         }
111         cursor.close();
112         db.close();
113         
114         return blackNumberList;
115     }
116     
117     /**
118      * @return    数据库中数据的总条目个数,返回0代表没有数据或异常
119      */
120     public int getCount(){
121         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
122         int count = 0;
123         Cursor cursor = db.rawQuery("select count(*) from blacknumber;", null);
124         if(cursor.moveToNext()){
125             count = cursor.getInt(0);
126         }
127         
128         cursor.close();
129         db.close();
130         return count;
131     }
132     
133     /**
134      * @param phone    作为查询条件的电话号码
135      * @return    传入电话号码的拦截模式    1:短信    2:电话    3:所有    0:没有此条数据
136      */
137     public int getMode(String phone){
138         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
139         int mode = 0;
140         Cursor cursor = db.query("blacknumber", new String[]{"mode"}, "phone = ?", new String[]{phone}, null, null,null);
141         if(cursor.moveToNext()){
142             mode = cursor.getInt(0);
143         }
144         
145         cursor.close();
146         db.close();
147         return mode;
148     }
149 }

 5. 黑名单服务的开启

【使用设置中心的选择框确实有效】

【布局文件的增加】

【开启黑名单的服务】

【说明】一行代码的含义可以代表两行代码,更简洁;

 

【测试效果】

6.拦截短信和拦截电话

6.1 思路分析

【短信的广播】有序广播,在源头进行拦截;

 

 

6.2 短信的拦截

【效果测试】先开启拦截服务,发送拦截号码的短信无法接收;

6.3 电话的拦截

6.3.1 aidl 的使用

【源码查看】

【移植源码】

【aidl文件的拷贝】需要拷贝到同名的包下;

【BUG1】需要拷贝另外的一个aidl文件;

 

拷贝之后没有错误了;

6.3.2 反射的调用

 

 

【源码】使用反射

【BUG】

 

【错误原因】mDao没有赋值;

【解决方法】只要在onCreate一开始就赋值;后期,不管接收短信还是接受来电就都不会是空指针;

【BUG】增加权限

【效果】拨打已经加入黑名单的电话无法来电,直接被挂断;

 【说明】如果说做的完美的话应该将通话记录在数据库中也查询到,然后将其删除;

 

7. 清除通话记录

7.1 找到联系表中的通话记录

7.2 联系人数据库的访问

【说明】需要使用内容解析者;

【在源码中找到对应的内容解析者】查看authorities项对应的设置内容,然后组合Uri的地址;

【源码】 

【增加权限】

7.3 BUG

【bug】之前的拨打的8次电话信息抹掉了,但是现在的刚发生的记录没有抹掉;

 

【解决方法】

【说明】一旦服务关闭,则没有必要再次对数据库的表的内容进行观察;

                                       当然也没有必要对电话进行监听了;

【效果】

 

posted @ 2018-02-04 16:18  OzTaking  阅读(558)  评论(0)    收藏  举报