这周做了一个来电知了的项目,具体需求如下:
1.可以设置黑名单号码,拒接电话和短信
2.来电归属地查询
在生活中我们用到这些东西的时候感觉挺简单,但是让我们实现这些功能时,还是非常麻烦的。下面是我在做这个项目时的实现过程。
<一>设计首页,显示黑名单号码,并能进行黑名单添加和删除及其归属地查询功能。具体代码如下:
main.xml:主界面的布局文件
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="vertical"
4. android:layout_width="fill_parent"
5. android:layout_height="fill_parent"
6. android:background="#8A2BE2">
7. <TextView
8. android:layout_height="wrap_content"
9. android:layout_width="fill_parent"
10. android:text="黑名单号码"
11. android:id="@+id/tv_blacknumber"
12. android:gravity="center"
13. android:textColor="#ff0000"
14. android:textSize="25px"/>
15. <ListView
16. android:layout_width="fill_parent"
17. android:layout_height="wrap_content"
18. android:id="@android:id/list"
19. android:cacheColorHint="#00000000"
20. android:layout_weight="1"/>
21. <TextView
22. android:id="@android:id/empty"
23. android:layout_width="fill_parent"
24. android:layout_height="fill_parent"
25. android:text="无黑名单号码,请添加!"
26. android:gravity="center"
27. android:textColor="#00CD00"
28. android:textSize="25px"
29. android:layout_weight="1"/>
30. <LinearLayout android:id="@+id/ll_bottom"
31. android:orientation="horizontal"
32. android:layout_width="fill_parent"
33. android:layout_height="wrap_content"
34. android:background="@drawable/buttonbackground">
35. <Button android:id="@+id/btn_add"
36. android:layout_width="wrap_content"
37. android:layout_height="fill_parent"
38. android:layout_weight="1"
39. android:background="@drawable/button_selector"
40. android:text="添 加"/>
41. <Button android:id="@+id/btn_search"
42. android:layout_width="wrap_content"
43. android:layout_height="fill_parent"
44. android:layout_weight="1"
45. android:background="@drawable/button_selector"
46. android:text="归属地查询"/>
47. <Button android:id="@+id/btn_delete"
48. android:layout_width="wrap_content"
49. android:layout_height="fill_parent"
50. android:layout_weight="1"
51. android:background="@drawable/button_selector"
52. android:text="删 除"/>
53. <CheckBox android:id="@+id/cb_select_all"
54. android:layout_width="wrap_content"
55. android:layout_height="fill_parent"
56. android:layout_weight="1"
57. android:text="全 选"/>
58. </LinearLayout>
59. </LinearLayout>
这里我为BUTTON按键设置了一个背景色。代码如下:
button_selector.xml:
1 <?xml version="1.0" encoding="utf-8"?>
2 <selector
3 xmlns:android="http://schemas.android.com/apk/res/android">
4 <item android:state_pressed="true" > <!-- 被按下的情况下 -->
5 <shape>
6 <!-- 渐变 -->
7 <gradient
8 android:startColor="#99FFFF"
9 android:endColor="#33FF00"
10 android:type="linear"
11 android:angle="270"/>
12 <!-- 描边 -->
13 <stroke
14 android:width="2dp"
15 android:color="#CCCC00"
16 android:dashWidth="5dp"
17 android:dashGap="3dp" />
18 <!-- 圆角 -->
19 <corners
20 android:radius="5dp"/>
21 <!-- 内边距 -->
22 <padding
23 android:left="5dp"
24 android:top="5dp"
25 android:right="5dp"
26 android:bottom="5dp" />
27 </shape>
28 </item>
29
30 <item android:state_focused="true" > <!-- 获得焦点的情况下 -->
31 <shape>
32 <gradient
33 android:startColor="#FF0099"
34 android:endColor="#FF0033"
35 android:angle="270" />
36 <stroke
37 android:width="2dp"
38 android:color="#00FFFF" />
39 <corners
40 android:radius="4dp" />
41
42 <padding
43 android:left="5dp"
44 android:top="5dp"
45 android:right="5dp"
46 android:bottom="5dp" />
47 </shape>
48 </item>
49
50 <item> <!-- 一般情况下 -->
51 <shape>
52 <solid android:color="#FFFACD"/>
53 <stroke
54 android:width="4dp"
55 android:color="#00FFFF" />
56 <corners
57 android:topRightRadius="5dp"
58 android:bottomLeftRadius="5dp"
59 android:topLeftRadius="5dp"
60 android:bottomRightRadius="5dp"/>
61 <padding
62 android:left="5dp"
63 android:top="5dp"
64 android:right="5dp"
65 android:bottom="5dp" />
66 </shape>
67 </item>
68 </selector>
ListView的设计:
blacknumber_list_item.xml:
1. <?xml version="1.0" encoding="utf-8"?>
2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="horizontal"
4. android:layout_width="fill_parent"
5. android:layout_height="fill_parent">
6. <TextView android:id="@+id/tv_item_number"
7. android:layout_width="wrap_content"
8. android:layout_height="40dip"
9. android:gravity="center"
10. android:textSize="20sp"
11. android:textColor="@drawable/itemcolor"
12. android:layout_weight="1"
13. android:layout_marginRight="6dip" />
14. <CheckBox
15. android:id="@+id/cb_item_delete"
16. android:layout_width="wrap_content"
17. android:layout_height="40dip"
18. android:layout_weight="1"
19. android:focusable="false"
20. android:checked="false"
21. android:clickable="false"
22. android:layout_alignParentRight="true"
23. android:layout_marginLeft="2dip"/>
24. </RelativeLayout>
下面就是主界面的java代码:
TelPhoneMangerActivity:
1 package cn.yj3g.TelPhoneMangerActivity;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7 import cn.yj3g.TelPhoneMangerDb.TelphoneMangerDBHelper;
8 import cn.yj3g.TelphonemangerService.AddressService;
9 import cn.yj3g.dao.TelphoneDao;
10 import cn.yj3g.entity.TableContanst;
11 import cn.yj3g.entity.Telphone;
12 import android.app.AlertDialog;
13 import android.app.ListActivity;
14 import android.app.ProgressDialog;
15 import android.content.Context;
16 import android.content.DialogInterface;
17 import android.content.Intent;
18 import android.os.Bundle;
19 import android.util.Log;
20 import android.view.LayoutInflater;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.view.View.OnClickListener;
24 import android.widget.Button;
25 import android.widget.CheckBox;
26 import android.widget.EditText;
27 import android.widget.ListView;
28 import android.widget.SimpleAdapter;
29 import android.widget.TextView;
30 import android.widget.Toast;
31
32 public class TelPhoneMangerActivity extends ListActivity implements
33 OnClickListener {
34 private TelphoneDao dao;
35 private TextView backNumberText;
36 private ListView listView;
37 private Button addButton;
38 private Button searchButton;
39 private Button deleteButton;
40 private CheckBox selectAllCheckBox;
41 private EditText numberEditText;
42 private HashMap<String, Boolean> checkBoxStatus;
43 private List<String> selectIds;
44 private AddressService addressService;
45 private ProgressDialog progressDialog;
46 private static final String ACTION = "cn.yj3g.TelphonemangerService.TelphoneMangerListenterService";
47
48 @Override
49 public void onCreate(Bundle savedInstanceState) {
50 super.onCreate(savedInstanceState);
51 setContentView(R.layout.main);
52 dao = new TelphoneDao(new TelphoneMangerDBHelper(this));
53 addressService = new AddressService(this);
54 listView = getListView();
55 regist();
56
57 // 数据库的拷贝事件
58 if (!addressService.dbIsexit()) {
59 new Thread(new DBcopyThread()).start();
60 progressDialog = ProgressDialog.show(this, "初始化", "数据正在初始化,请稍等...",
61 true);
62 }
63
64 // 找到各个按键
65 addButton = (Button) findViewById(R.id.btn_add);
66 searchButton = (Button) findViewById(R.id.btn_search);
67 deleteButton = (Button) findViewById(R.id.btn_delete);
68 selectAllCheckBox = (CheckBox) findViewById(R.id.cb_select_all);
69 backNumberText = (TextView) findViewById(android.R.id.empty);
70 // 为按键设置监听
71 addButton.setOnClickListener(this);
72 searchButton.setOnClickListener(this);
73 deleteButton.setOnClickListener(this);
74 selectAllCheckBox.setOnClickListener(this);
75 backNumberText.setOnClickListener(this);
76 //
77 showListView();
78 }
79
80 /**
81 * 注册来电黑名单拦截
82 */
83 private void regist() {
84 startService(new Intent(ACTION));
85 }
86
87 /**
88 * 拷贝数据库线程,为了避免程序无响应。
89 */
90 private class DBcopyThread implements Runnable {
91 @Override
92 public void run() {
93 try {
94 addressService.copyDB();
95 progressDialog.dismiss();
96 } catch (Exception e) {
97 e.printStackTrace();
98 }
99 }
100 }
101
102 /**
103 * 显示黑名单号码
104 */
105 private void showListView() {
106 List<Map<String, Object>> data = dao.getAllTelphone();
107 if (data.size() != 0) {
108 backNumberText.setClickable(false);
109 } else
110 backNumberText.setClickable(true);
111 String[] from = { TableContanst.NumberColumns.NUMBER, };
112 int[] to = { R.id.tv_item_number };
113 SimpleAdapter adapter = new TelphoneAdpter(this, data,
114 R.layout.blacknumber_list_item, from, to);
115 listView.setAdapter(adapter);
116 }
117
118 /**
119 * 监听事件处理
120 */
121 @Override
122 public void onClick(View v) {
123 if (v == addButton || v == backNumberText) {
124 addTelphoneMethod();
125 } else if (v == deleteButton) {
126 deleteSeleteData();
127 selectAllCheckBox.setChecked(false);
128 } else if (v == searchButton) {
129 Intent intent = new Intent();
130 intent.setClass(TelPhoneMangerActivity.this, SearchActivity.class);
131 startActivity(intent);
132 } else if (v == selectAllCheckBox) {
133 checkOrcancelAllbox(selectAllCheckBox.isChecked());
134 }
135 }
136
137 /**
138 * 提示信息
139 */
140 protected void showToast(String string) {
141 Toast.makeText(this, string, Toast.LENGTH_SHORT).show();
142 }
143
144 /**
145 * 添加黑名单号码
146 */
147 private void addTelphoneMethod() {
148 LayoutInflater inflater = (LayoutInflater) this
149 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
150 final View view = inflater.inflate(R.layout.dialog, null);
151 new AlertDialog.Builder(this)
152 .setTitle("黑名单添加")
153 .setView(view)
154 .setPositiveButton("添加", new DialogInterface.OnClickListener() {
155 @Override
156 public void onClick(DialogInterface dialog, int which) {
157 numberEditText = (EditText) view
158 .findViewById(R.id.et_number);
159 String number = numberEditText.getText().toString();
160 if (number.trim().length() == 0) {
161 TelPhoneMangerActivity.this.showToast("请输入拦截号码!");
162 } else if (dao.findTelphone(number).getCount() != 0) {
163 TelPhoneMangerActivity.this
164 .showToast("输入号码已存在,无需增加!");
165 } else {
166 Telphone telphone = new Telphone(number);
167 long id = dao.addTelphone(telphone);
168 if (id < 0) {
169 TelPhoneMangerActivity.this.showToast("添加失败!");
170 } else {
171 TelPhoneMangerActivity.this.showToast("添加成功!");
172 showListView();
173 }
174 }
175 }
176 })
177 .setNegativeButton("取消", new DialogInterface.OnClickListener() {
178 @Override
179 public void onClick(DialogInterface dialog, int which) {
180 dialog.cancel();
181 }
182 }).show();
183 }
184
185 /**
186 * 黑名单号码删除
187 */
188 private void deleteSeleteData() {
189 AlertDialog.Builder builder = new AlertDialog.Builder(this);
190 builder.setTitle("黑名单删除")
191 .setMessage("确定删除所选号码?")
192 .setCancelable(false)
193 .setPositiveButton("确定", new DialogInterface.OnClickListener() {
194 public void onClick(DialogInterface dialog, int id) {
195 int count = 0;
196 if (selectIds.size() <= 0) {
197 Toast.makeText(TelPhoneMangerActivity.this,
198 "无选中记录,请选择!", Toast.LENGTH_LONG).show();
199 } else {
200 // Log.v("TAG", "selectIds=" + selectIds.size());
201 for (int i = 0; i < selectIds.size(); i++) {
202 String deleteNumber = selectIds.get(i);
203 dao.deleteTelphoneById(deleteNumber);
204 count++;
205 }
206 showListView();
207 if (count > 0) {
208 Toast.makeText(TelPhoneMangerActivity.this,
209 "删除成功!", Toast.LENGTH_LONG).show();
210 } else
211 Toast.makeText(TelPhoneMangerActivity.this,
212 "删除失败!", Toast.LENGTH_LONG).show();
213 }
214 }
215 })
216 .setNegativeButton("取消", new DialogInterface.OnClickListener() {
217 public void onClick(DialogInterface dialog, int id) {
218 dialog.cancel();
219 }
220 });
221 AlertDialog alert = builder.create();
222 alert.show();
223 }
224
225 /**
226 * 点击ListView条目存储被点击的条目
227 */
228 @Override
229 protected void onListItemClick(ListView l, View view, int position, long id) {
230 CheckBox box = (CheckBox) view.findViewById(R.id.cb_item_delete);
231 TextView idView = (TextView) view.findViewById(R.id.tv_item_number);
232 String deleteNumber = idView.getText().toString();
233 box.toggle(); // 改变checkbox的选中状态
234 if (box.isChecked()) {
235 selectIds.add(deleteNumber);
236 checkBoxStatus.put(deleteNumber, true);
237 } else {
238 selectIds.remove(deleteNumber);
239 checkBoxStatus.put(deleteNumber, false);
240 }
241 }
242
243 /**
244 * 全选or取消全选
245 */
246 private void checkOrcancelAllbox(boolean checked) {
247 int itemCount = listView.getCount();
248 selectIds.clear();
249 checkBoxStatus.clear();
250 for (int i = 0; i < itemCount; i++) {
251 View view = listView.getChildAt(i);
252 Map<String, Object> data = (Map<String, Object>) listView
253 .getItemAtPosition(i);
254 String number = data.get(TableContanst.NumberColumns.NUMBER)
255 .toString();
256 if (view != null) {
257 CheckBox cb = (CheckBox) view.findViewById(R.id.cb_item_delete);
258 cb.setChecked(checked);
259 }
260 checkBoxStatus.put(number, checked);
261 if (checked) {
262 selectIds.add(number);
263 }
264 }
265 }
266
267 /**
268 * 自定义SimpleAdapter显示ListView数据
269 */
270 private class TelphoneAdpter extends SimpleAdapter {
271 public TelphoneAdpter(Context context,
272 List<? extends Map<String, ?>> data, int resource,
273 String[] from, int[] to) {
274 super(context, data, resource, from, to);
275 selectIds = new ArrayList<String>();
276 checkBoxStatus = new HashMap<String, Boolean>();
277 }
278
279 @Override
280 public View getView(int position, View convertView, ViewGroup parent) {
281 View view = super.getView(position, convertView, parent);
282 CheckBox box = (CheckBox) view.findViewById(R.id.cb_item_delete);
283 TextView idView = (TextView) view.findViewById(R.id.tv_item_number);
284 String number = idView.getText().toString();
285 if (checkBoxStatus.containsKey(number)) {
286 box.setChecked(checkBoxStatus.get(number));
287 } else {
288 box.setChecked(selectAllCheckBox.isChecked());
289 }
290 return view;
291 }
292 }
293 }
以上就把主界面显示出来,运行效果如下:
<二>由于要对黑名单进行增删查操作,多归属地要进行查操作,所以我们需要创建一个数据库帮助类,还有就是要将数据库拷到应用文件目录下。下面就将实现代码附在下面,大家自己琢磨吧。
TelphoneMangerDBHelper:
- package
- import
- import
- import
- import
- import
- import
- /**
- *
- *创建一个数据库帮助类
- *
- */
- public class TelphoneMangerDBHelper extends
- private static final
- public static final
- public static final int
- public
- int
- super(context, name, factory, version);
- }
- public
- this(context, DB_NAME, null, VERSION);
- }
- /**
- * 创建数据库
- */
- public void
- Log.v(TAG, "onCreate");
- db.execSQL("create table "
- + TableContanst.BLACK_NUMBER_TABLE
- + "(_id Integer primary key AUTOINCREMENT,"
- + "number char,"
- + "modify_time DATETIME)");
- }
- @Override
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int
- Log.v(TAG, "onUpgrade");
- }
- }
TelphoneDao:
1 package cn.yj3g.dao;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6 import java.util.Map;
7
8 import android.content.ContentValues;
9 import android.database.Cursor;
10 import cn.yj3g.TelPhoneMangerDb.TelphoneMangerDBHelper;
11 import cn.yj3g.entity.TableContanst;
12 import cn.yj3g.entity.Telphone;
13
14 public class TelphoneDao {
15 private TelphoneMangerDBHelper dbHelper;
16
17 public TelphoneDao(TelphoneMangerDBHelper dbHelper) {
18 this.dbHelper = dbHelper;
19 }
20
21 /**
22 * 添加一个Telphone对象数据到数据库表
23 */
24 public long addTelphone(Telphone phone) {
25
26 ContentValues values = new ContentValues();
27 values.put(TableContanst.NumberColumns.NUMBER, phone.getNumber());
28 return dbHelper.getWritableDatabase().insert(
29 TableContanst.BLACK_NUMBER_TABLE, null, values);
30
31 }
32
33 /**
34 * 删除一个number所对应的数据库表Telphone的记录
35 */
36 public int deleteTelphoneById(String number) {
37 return dbHelper.getWritableDatabase().delete(
38 TableContanst.BLACK_NUMBER_TABLE,
39 TableContanst.NumberColumns.NUMBER + "=?",
40 new String[] { number + "" });
41 }
42
43 /**
44 * 查询所有的记录
45 */
46 public List<Map<String, Object>> getAllTelphone() {
47 List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
48 Cursor cursor = dbHelper.getWritableDatabase().query(
49 TableContanst.BLACK_NUMBER_TABLE, null, null, null, null, null,
50 "_id desc");
51 while (cursor.moveToNext()) {
52 Map<String, Object> map = new HashMap<String, Object>(8);
53 String number = cursor.getString(cursor
54 .getColumnIndex(TableContanst.NumberColumns.NUMBER));
55 map.put(TableContanst.NumberColumns.NUMBER, number);
56 data.add(map);
57 }
58 cursor.close();
59 return data;
60 }
61 /**
62 * 黑名单号码查询
63 */
64 public Cursor findTelphone(String number) {
65 Cursor cursor = dbHelper.getWritableDatabase().query(
66 TableContanst.BLACK_NUMBER_TABLE, null, "number=?",
67 new String[] { number }, null, null, null, null);
68 return cursor;
69 }
70
71 public void closeDB() {
72 dbHelper.close();
73 }
74 }
AddressService:
- package
- import
- import
- import
- import
- import
- import
- import
- import
- /**
- * 定义一个归属地服务的类,为以后的归属地查询等提供方法。
- */
- public class
- private
- public
- this.context = context;
- }
- /**
- * 判断当前databases目录下有无phoneAddres.db
- */
- public boolean
- return
- }
- /**
- * 将phoneAddres.db拷贝到datebases目录下
- */
- public void copyDB() throws
- new
- // 找到data目录下的databases文件夹
- if
- databases.mkdirs();
- }
- new
- new
- this.getClass().getClassLoader()
- // 得到phoneAddress.db
- byte[] bs = new byte[1024];
- int
- while
- fos.write(bs, 0, length);
- }
- fos.flush();
- is.close();
- }
- /**
- * 获得来电的归属地 手机的正则表达式为:^1[358]\d{9}$
- */
- public
- null;
- File file = context.getDatabasePath(TableContanst.ADDRESS_DB_NAME);
- SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getAbsolutePath(),
- null, SQLiteDatabase.OPEN_READONLY);
- if
- if (Pattern.compile("^1[358]\\d{9}$").matcher(number).matches()) {// 手机来电匹配
- Cursor cursor = db
- .rawQuery(
- "select p.name as province,c.name as city from address as a "
- + "inner join city as c on a.cityid=c._id "
- + "inner join province as p on c.provinceid=p._id "
- + "where a.mobileprefix=?",
- new
- address = getAddressInfo(cursor);
- else {// 座机电话匹配
- Cursor cursor = null;
- null;
- null;
- switch
- case 12: // 4位区号+8位电话号码
- cursor = db
- .rawQuery(
- "select p.name as province,c.name as city from city c "
- + "inner join province p on c.provinceid=p._id "
- + "where c.areacode=? "
- + "order by c._id asc limit 1",
- new
- address = getAddressInfo(cursor);
- break;
- case 11:// 4位区号+8位电话号码 或者 3位区号+8位电话号码
- subNumber3 = number.substring(0, 3);
- cursor = db
- .rawQuery(
- "select p.name as province,c.name as city from city c "
- + "inner join province p on c.provinceid=p._id "
- + "where c.areacode in(?,?) "
- + "order by c._id asc limit 1",
- new
- address = getAddressInfo(cursor);
- break;
- case 10:// 3位区号+7位电话号码
- cursor = db
- .rawQuery(
- "select p.name as province,c.name as city from city c "
- + "inner join province p on c.provinceid=p._id "
- + "where c.areacode=? "
- + "order by c._id asc limit 1",
- new
- address = getAddressInfo(cursor);
- break;
- case
- case 7:// 本地号码
- break;
- case
- if
- address = "模拟器";
- else
- cursor = db
- .rawQuery(
- "select p.name as province,c.name as city from city c "
- + "inner join province p on c.provinceid=p._id "
- + "where c.areacode=? "
- + "order by c._id asc limit 1",
- new
- address = getAddressInfo(cursor);
- }
- break;
- case
- cursor = db
- .rawQuery(
- "select p.name as province,c.name as city from city c "
- + "inner join province p on c.provinceid=p._id "
- + "where c.areacode=? "
- + "order by c._id asc limit 1",
- new
- address = getAddressInfo(cursor);
- break;
- default:
- break;
- }
- }
- db.close();
- }
- return
- }
- /**
- * 根据查询所得游标得到来电的具体归属地并返回
- */
- private
- if
- String province = cursor.getString(0);
- String city = cursor.getString(1);
- if
- return
- else
- return
- }
- cursor.close();
- return
- }
- /**
- * 得到来电的类型
- */
- public
- if
- return
- else if
- .matches()) {
- return
- else if
- .matches()) {
- return
- else if
- return
- else if
- return
- else
- return
- }
- /**
- * 根据查询输入框输入的号码找到响应的归属地区号
- */
- public
- null;
- File file = context.getDatabasePath(TableContanst.ADDRESS_DB_NAME);
- SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getAbsolutePath(),
- null, SQLiteDatabase.OPEN_READONLY);
- if
- if (Pattern.compile("^1[358]\\d{9}$").matcher(number).matches()) {// 手机来电匹配
- Cursor cursor = db
- .rawQuery(
- "select c.areacode as areacode from city as c "
- + "inner join address a on a.cityid=c._id "
- + "where a.mobileprefix=? order by c._id asc limit 1",
- new
- areacode = getAreacodeInfo(cursor);
- else
- if
- Cursor cursor = db
- .rawQuery(
- "select c.name as name from city as c "
- + "where c.areacode =? order by c._id asc limit 1",
- new
- areacode = getAreacodeInfo2(cursor, number);
- else if
- String subNumber4 = number.substring(0, 4);
- Cursor cursor = db
- .rawQuery(
- "select c.name as name from city as c "
- + "where c.areacode =? order by c._id asc limit 1",
- new
- areacode = getAreacodeInfo2(cursor, subNumber4);
- }
- }
- }
- db.close();
- return
- }
- /**
- * 根据查询所得游标得到查询手机号码的归属地
- */
- private
- if
- return
- }
- cursor.close();
- return
- }
- /**
- * 根据查询所得游标得到查询固话号码的归属地
- */
- private
- if
- return
- else
- cursor.close();
- return
- }
- }
<三>设置黑名单拦截和短信拦截以及归属地查询功能。具体代码如下:
TelphoneMangerListenterService:
1 package cn.yj3g.TelphonemangerService;
2
3 import java.lang.reflect.Method;
4 import android.app.Service;
5 import android.content.Context;
6 import android.content.Intent;
7 import android.database.Cursor;
8 import android.graphics.PixelFormat;
9 import android.net.Uri;
10 import android.os.IBinder;
11 import android.provider.ContactsContract.Contacts;
12 import android.telephony.PhoneStateListener;
13 import android.telephony.TelephonyManager;
14 import android.util.Log;
15 import android.view.LayoutInflater;
16 import android.view.View;
17 import android.view.WindowManager;
18 import android.widget.TextView;
19 import cn.yj3g.TelPhoneMangerActivity.R;
20 import cn.yj3g.TelPhoneMangerDb.TelphoneMangerDBHelper;
21 import cn.yj3g.dao.TelphoneDao;
22
23 import com.android.internal.telephony.ITelephony;
24
25 /**
26 * 实现来电拦截和归属地显示
27 */
28 public class TelphoneMangerListenterService extends Service {
29 private TelphoneDao dao;
30 private AddressService addressService;
31 private WindowManager windowManager;
32 private LayoutInflater inflater;
33 private View addressView;
34
35 @Override
36 public IBinder onBind(Intent intent) {
37 Log.v("TAG", "onBind");
38 return null;
39 }
40
41 @Override
42 public void onCreate() {
43 Log.v("TAG", "service onCreate()");
44 super.onCreate();
45 dao = new TelphoneDao(new TelphoneMangerDBHelper(this));
46 addressService = new AddressService(this);
47 // 窗口界面管理
48 windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
49 // View加载器
50 inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
51 // 电话服务管理
52 TelephonyManager manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
53 // 监听电话状态
54 manager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
55 }
56
57 private PhoneStateListener listener = new PhoneStateListener() {
58 @Override
59 public void onCallStateChanged(int state, String incomingNumber) {
60 super.onCallStateChanged(state, incomingNumber);
61 // 打印电话状态改变信息
62 Log.v("TAG", "onCallStateChanged state=" + state);
63 switch (state) {
64 case TelephonyManager.CALL_STATE_RINGING: // 响铃时
65 Cursor cursor = dao.findTelphone(incomingNumber);
66 //
67 if (cursor != null && cursor.getCount() != 0) {
68 stop(incomingNumber);
69 } else {
70 String number = getContactsName(incomingNumber);
71 String address = addressService.getAddress(incomingNumber)
72 +" "+addressService.getType(incomingNumber);
73 showAddress(address, number);
74 }
75 cursor.close();
76 break;
77 case TelephonyManager.CALL_STATE_IDLE:// 挂断或者无电话时
78 removeAddressView();
79 break;
80 case TelephonyManager.CALL_STATE_OFFHOOK:// 接起电话
81 break;
82 default:
83 break;
84 }
85 }
86
87 /**
88 * 来电号码和电话本里的号码进行匹配
89 */
90 private String getContactsName(String incomingNumber) {
91 String number = incomingNumber;
92 Uri uri = Uri
93 .parse("content://com.android.contacts/data/phones/filter/"
94 + incomingNumber);
95 Cursor cursor = getContentResolver().query(uri,
96 new String[] { Contacts.DISPLAY_NAME }, null, null, null);
97 if (cursor.moveToFirst()) {
98 number = cursor.getString(0);
99 }
100 cursor.close();
101 return number;
102 }
103
104 /**
105 * 显示来电归属地窗口
106 */
107 private void showAddress(String address, String incomingNumber) {
108 WindowManager.LayoutParams params = new WindowManager.LayoutParams();
109 params.height = WindowManager.LayoutParams.WRAP_CONTENT;
110 params.width = WindowManager.LayoutParams.WRAP_CONTENT;
111 params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
112 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
113 params.format = PixelFormat.TRANSLUCENT;
114 params.y += 24;
115 params.type = WindowManager.LayoutParams.TYPE_TOAST;
116 addressView = inflater.inflate(R.layout.address, null);
117 TextView shownumber = (TextView) addressView
118 .findViewById(R.id.shownumber);
119 TextView showaddress = (TextView) addressView
120 .findViewById(R.id.showaddress);
121 shownumber.setText(incomingNumber);
122 showaddress.setText(address);
123 windowManager.addView(addressView, params);
124 }
125 };
126
127 /**
128 * 去除添加的来电显示界面
129 */
130 private void removeAddressView() {
131 if (addressView != null) {
132 windowManager.removeView(addressView);
133 addressView = null;
134 }
135 }
136
137 /**
138 * 电话拦截
139 */
140 public void stop(String s) {
141 Log.e("TAG", "来电" + s + "为黑名单号码,已拦截!");
142 // 调用ITelephony.endCall()结束通话
143 try {
144 Method method = Class.forName("android.os.ServiceManager")
145 .getMethod("getService", String.class);
146 IBinder binder = (IBinder) method.invoke(null,
147 new Object[] { TELEPHONY_SERVICE });
148 ITelephony telephony = ITelephony.Stub.asInterface(binder);
149 telephony.endCall();
150 } catch (Exception e) {
151 e.printStackTrace();
152 }
153 }
154 }
BootCompleteReceiver:
1. package
2.
3. import
4. import
5. import
6. import
7. import
8. import
9. import
10. import
11. import
12. import
13. import
14. import
15. import
16.
17. /**
18. *
19. * 定义一个广播接受者实现短信拦截
20. *
21. */
22. public class BootCompleteReceiver extends
23. private
24.
25. public
26. Log.v("TAG", "开机了!");
27. }
28.
29. @Override
30. public void
31. /**
32. * 运用广播开启监听这个服务
33. */
34. new TelphoneDao(new
35. Object[] pdus = (Object[]) intent.getExtras().get("pdus");
36. if (pdus != null
37. new
38. for (int
39. byte[] pdu = (byte[]) pdus[i];
40. messages[i] = SmsMessage.createFromPdu(pdu);
41. }
42. for
43. // 得到发信息的号码
44. String content = message.getMessageBody();// 得到短信内容
45.
46. if (cursor != null
47. // 中止发送
48. //实例化通知
49. Notification n = new
50. System.currentTimeMillis());
51. new
52. i.setAction(Intent.ACTION_DIAL);
53. i.setData(Uri.parse("tel:"+sender));
54. //创建延期意图
55.
56. //设置通知的最新事件信息
57.
58. //获得通知管理器系统服务
59.
60. nm.notify(1, n);
61. Toast.makeText(context, "通知发布完成", 1).show();
62. Log.e("TAG", "号码" + sender + "为黑名单号码,已拦截!");
63. cursor.close();
64. }
65. }
66. }
67. }
68. }
运行效果如下:
黑名单短信通知:
显示归属地的运行效果如下:
<四>实现归属地查询功能
SearchActivity:
1 package cn.yj3g.TelPhoneMangerActivity;
2
3 import cn.yj3g.TelphonemangerService.AddressService;
4 import android.app.Activity;
5 import android.os.Bundle;
6 import android.view.View;
7 import android.view.View.OnClickListener;
8 import android.widget.Button;
9 import android.widget.EditText;
10 import android.widget.TextView;
11 import android.widget.Toast;
12
13 /**
14 * 实现归属地查询功能
15 */
16 public class SearchActivity extends Activity implements OnClickListener {
17 private AddressService addressService;
18 private EditText numberEdit;
19 private Button sureButton;
20 private TextView numberText;
21 private TextView addressText;
22 private TextView typeText;
23 private String address;
24 private static final int COLOR = android.graphics.Color.RED;
25
26 @Override
27 protected void onCreate(Bundle savedInstanceState) {
28 super.onCreate(savedInstanceState);
29 setContentView(R.layout.search);
30 addressService = new AddressService(this);
31 numberEdit = (EditText) findViewById(R.id.et_search);
32 sureButton = (Button) findViewById(R.id.btn_sure);
33 numberText = (TextView) findViewById(R.id.tv_number);
34 addressText = (TextView) findViewById(R.id.tv_address);
35 typeText = (TextView) findViewById(R.id.tv_type);
36 // 设置监听
37 sureButton.setOnClickListener(this);
38 }
39
40 @Override
41 public void onClick(View v) {
42 String number = numberEdit.getText().toString();
43 String areacode = addressService.getAreacode(number);
44 if (areacode.length() == 0) {
45 address = addressService.getAddress(number);
46 } else
47 address = addressService.getAddress(number) + "(" + areacode + ")";
48 String type = "中国-" + addressService.getType(number);
49 if (number.trim().length() <= 2 || address.length() == 0) {
50 addressText.setText("未知地区");
51 typeText.setText("未知");
52 typeText.setTextColor(COLOR);
53 addressText.setTextColor(COLOR);
54 numberText.setText(number);
55 numberText.setTextColor(COLOR);
56 Toast.makeText(this, "请输入正确格式的电话号码", 0).show();
57 numberEdit.setText(null);
58 } else {
59 numberText.setText(number);
60 numberText.setTextColor(COLOR);
61 addressText.setText(address);
62 addressText.setTextColor(COLOR);
63 typeText.setText(type);
64 typeText.setTextColor(COLOR);
65 numberEdit.setText(null);
66 }
67 }
68 }
归属地查询运行效果如下:
以上就把这个功能基本上就实现了,下来我将一些相关的常量定义,布局设计,权限等代码附在下面,供大家参考。
TableContanst:
- package
- public final class
- /**
- * 自定义的一些常量
- */
- public static final
- public static final
- public static final class
- public static final
- public static final
- }
- }
Telphone:
1 package cn.yj3g.entity;
2
3 import java.io.Serializable;
4 /**
5 *
6 * 自定义一个Telphone类
7 *
8 */
9 public class Telphone implements Serializable {
10
11 private long _id;
12 private String number;
13 private String modifyDateTime;
14 public Telphone(String number) {
15 this.number = number;
16 }
17
18 public Telphone(long _id, String number) {
19 super();
20 this._id = _id;
21 this.number = number;
22 }
23
24 public Telphone(long _id, String number, String modifyDateTime) {
25 super();
26 this._id = _id;
27 this.number = number;
28 this.modifyDateTime = modifyDateTime;
29 }
30
31 public Telphone() {
32 }
33 public long get_id() {
34 return _id;
35 }
36 public void set_id(long _id) {
37 this._id = _id;
38 }
39 public String getNumber() {
40 return number;
41 }
42 public void setNumber(String number) {
43 this.number = number;
44 }
45 public String getModifyDateTime() {
46 return modifyDateTime;
47 }
48 public void setModifyDateTime(String modifyDateTime) {
49 this.modifyDateTime = modifyDateTime;
50 }
51 @Override
52 public int hashCode() {
53 final int prime = 31;
54 int result = 1;
55 result = prime * result + (int) (_id ^ (_id >>> 32));
56 result = prime * result
57 + ((modifyDateTime == null) ? 0 : modifyDateTime.hashCode());
58 result = prime * result + ((number == null) ? 0 : number.hashCode());
59 return result;
60 }
61 @Override
62 public boolean equals(Object obj) {
63 if (this == obj)
64 return true;
65 if (obj == null)
66 return false;
67 if (getClass() != obj.getClass())
68 return false;
69 Telphone other = (Telphone) obj;
70 if (_id != other._id)
71 return false;
72 if (modifyDateTime == null) {
73 if (other.modifyDateTime != null)
74 return false;
75 } else if (!modifyDateTime.equals(other.modifyDateTime))
76 return false;
77 if (number == null) {
78 if (other.number != null)
79 return false;
80 } else if (!number.equals(other.number))
81 return false;
82 return true;
83 }
84 @Override
85 public String toString() {
86 return "Telphone [_id=" + _id + ", number=" + number + "]";
87 }
88 }
view.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_marginRight="10dp" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:textColor="#000" />
</LinearLayout>
search.xml:
1. <?xml version="1.0" encoding="utf-8"?>
2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="horizontal"
4. android:layout_width="fill_parent"
5. android:background="#8A2BE2"
6. android:layout_height="fill_parent">
7. <Button
8. android:id="@+id/btn_sure"
9. android:layout_width="wrap_content"
10. android:layout_height="wrap_content"
11. android:layout_weight="5"
12. android:text="查询"
13. android:layout_alignParentRight="true"
14. android:layout_marginLeft="2dip"/>
15. <EditText android:layout_height="wrap_content"
16. android:hint="可输入号码/区号"
17. android:id="@+id/et_search"
18. android:layout_width="wrap_content"
19. android:padding="5dip"
20. android:textSize="15sp"
21. android:inputType="phone"
22. android:maxLength="11"
23. android:layout_alignParentTop="true"
24. android:layout_alignParentLeft="true"
25. android:layout_toLeftOf="@+id/btn_sure"/>
26. <TextView android:layout_height="wrap_content"
27. android:text="号码:"
28. android:id="@+id/tv1"
29. android:layout_width="wrap_content"
30. android:layout_below="@+id/et_search"
31. android:layout_marginRight="15dip"
32. android:layout_alignParentLeft="true"
33. android:layout_marginTop="16dp"/>
34. <TextView
35. android:id="@+id/tv_number"
36. android:layout_height="wrap_content"
37. android:layout_width="fill_parent"
38. android:layout_toRightOf="@+id/tv1"
39. android:layout_below="@+id/et_search"
40. android:layout_alignBottom="@+id/tv1"
41. android:layout_marginTop="16dp"/>
42. <TextView android:layout_height="wrap_content"
43. android:text="归属:"
44. android:id="@+id/tv2"
45. android:layout_width="wrap_content"
46. android:layout_below="@+id/tv1"
47. android:layout_marginRight="15dip"
48. android:layout_alignParentLeft="true"
49. android:layout_marginTop="20dp"/>
50. <TextView
51. android:id="@+id/tv_address"
52. android:layout_height="wrap_content"
53. android:layout_width="fill_parent"
54. android:layout_toRightOf="@+id/tv2"
55. android:layout_below="@+id/tv_number"
56. android:layout_alignBottom="@+id/tv2"
57. android:layout_marginTop="20dp"/>
58. <TextView android:layout_height="wrap_content"
59. android:text="类型:"
60. android:id="@+id/tv3"
61. android:layout_width="wrap_content"
62. android:layout_below="@+id/tv2"
63. android:layout_marginRight="15dip"
64. android:layout_alignParentLeft="true"
65. android:layout_marginTop="25dp"/>
66. <TextView
67. android:id="@+id/tv_type"
68. android:layout_height="wrap_content"
69. android:layout_width="fill_parent"
70. android:layout_toRightOf="@+id/tv3"
71. android:layout_below="@+id/tv_address"
72. android:layout_alignBottom="@+id/tv3"
73. android:layout_marginTop="25dp"/>
74. </RelativeLayout>
dialog.xml:
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout
3 xmlns:Android="http://schemas.android.com/apk/res/android"
4 Android:layout_width="fill_parent"
5 Android:layout_height="fill_parent"
6 Android:orientation="vertical">
7 <EditText
8 Android:layout_width="fill_parent"
9 Android:layout_height="wrap_content"
10 Android:id="@+id/et_number"
11 Android:inputType="phone"
12 Android:hint="请输入电话号码"
13 Android:maxLength="11"
14 />
15 </LinearLayout>
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout
3 xmlns:Android="http://schemas.android.com/apk/res/android"
4 Android:layout_width="fill_parent"
5 Android:layout_height="fill_parent"
6 Android:orientation="vertical">
7 <EditText
8 Android:layout_width="fill_parent"
9 Android:layout_height="wrap_content"
10 Android:id="@+id/et_number"
11 Android:inputType="phone"
12 Android:hint="请输入电话号码"
13 Android:maxLength="11"
14 />
15 </LinearLayout>
address.xml:
1. <?xml version="1.0" encoding="utf-8"?>
2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3. android:orientation="vertical"
4. android:layout_width="wrap_content"
5. android:background="@drawable/addressbackground"
6. android:layout_height="wrap_content">
7. <LinearLayout
8. android:orientation="horizontal"
9. android:layout_width="wrap_content"
10. android:layout_height="wrap_content">
11. <ImageButton android:id="@+id/showimage"
12. android:layout_width="wrap_content"
13. android:layout_height="wrap_content"
14. android:background="@drawable/ic_launcher_vcard"
15. android:scaleType="center"/>
16. <TextView
17. android:id="@+id/showaddress"
18. android:layout_width="wrap_content"
19. android:layout_height="wrap_content"
20. android:gravity="center"
21. android:textSize="20sp"
22. android:textColor="#eee"/>
23. </LinearLayout>
24. <TextView
25. android:id="@+id/shownumber"
26. android:layout_width="fill_parent"
27. android:layout_height="wrap_content"
28. android:gravity="center"
29. android:textSize="20sp"
30. android:textColor="#eee"/>
31. </LinearLayout>
AndroidManifest.xml:
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="cn.yj3g.TelPhoneMangerActivity"
4 android:versionCode="1"
5 android:versionName="1.0">
6 <uses-sdk android:minSdkVersion="8" />
7
8 <application android:icon="@drawable/phone" android:label="@string/app_name">
9 <activity android:name=".TelPhoneMangerActivity"
10 android:label="@string/app_name">
11 <intent-filter>
12 <action android:name="android.intent.action.MAIN" />
13 <category android:name="android.intent.category.LAUNCHER" />
14 </intent-filter>
15 </activity>
16 <activity android:name=".SearchActivity"
17 android:label="归属地查询">
18 </activity>
19 <activity android:name=".ShowAvtivity"></activity>
20 <service android:name="cn.yj3g.TelphonemangerService.TelphoneMangerListenterService">
21 <intent-filter>
22 <action android:name="cn.yj3g.TelphonemangerService.TelphoneMangerListenterService" ></action>
23 </intent-filter>
24 </service>
25 <receiver android:name=".BootCompleteReceiver">
26 <intent-filter android:priority="1000">
27 <action android:name="android.provider.Telephony.SMS_RECEIVED" />
28 </intent-filter>
29 </receiver>
30 </application>
31 <!-- 读取电话状态权限-->
32 <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
33 <!-- 开机启动广播的权限 -->
34 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
35 <!-- 挂断电话时需要的权限 -->
36 <uses-permission android:name="android.permission.CALL_PHONE" />
37 <!-- 接收短信权限 -->
38 <uses-permission android:name="android.permission.RECEIVE_SMS"/>
39 <!-- 发送短信权限 -->
40 <uses-permission android:name="android.permission.SEND_SMS"/>
41 <!-- 读取联系人信息权限 -->
42 <uses-permission android:name="android.permission.READ_CONTACTS"/>
43 </manifest>
以上就是来电知了的全部代码和功能了,在做的过程中用到了许多的知识,比如数据库的增删查以及拷贝,线程的知识,广播机制,服务等知识。在做的过程中这些知识也就算是复习了一遍。如有有错误的地方,希望大家不吝指教。