編輯:Android開發實例
這周做了一個來電知了的項目,具體需求如下:
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:
1 package cn.yj3g.TelPhoneMangerDb;
2
3 import cn.yj3g.entity.TableContanst;
4 import android.content.Context;
5 import android.database.sqlite.SQLiteDatabase;
6 import android.database.sqlite.SQLiteDatabase.CursorFactory;
7 import android.database.sqlite.SQLiteOpenHelper;
8 import android.util.Log;
9 /**
10 *
11 *創建一個數據庫幫助類
12 *
13 */
14 public class TelphoneMangerDBHelper extends SQLiteOpenHelper {
15 private static final String TAG = "TelphoneMangerDBHelper";
16 public static final String DB_NAME = "telphone_black.db";
17 public static final int VERSION = 1;
18
19 public TelphoneMangerDBHelper(Context context, String name,
20 CursorFactory factory, int version) {
21 super(context, name, factory, version);
22 }
23
24 public TelphoneMangerDBHelper(Context context) {
25 this(context, DB_NAME, null, VERSION);
26 }
27
28 /**
29 * 創建數據庫
30 */
31 public void onCreate(SQLiteDatabase db) {
32 Log.v(TAG, "onCreate");
33 db.execSQL("create table "
34 + TableContanst.BLACK_NUMBER_TABLE
35 + "(_id Integer primary key AUTOINCREMENT,"
36 + "number char,"
37 + "modify_time DATETIME)");
38 }
39 @Override
40 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
41 Log.v(TAG, "onUpgrade");
42 }
43
44 }
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:
1 package cn.yj3g.TelphonemangerService;
2
3 import java.io.File;
4 import java.io.FileOutputStream;
5 import java.io.InputStream;
6 import java.util.regex.Pattern;
7
8 import cn.yj3g.entity.TableContanst;
9 import android.content.Context;
10 import android.database.Cursor;
11 import android.database.sqlite.SQLiteDatabase;
12
13 /**
14 * 定義一個歸屬地服務的類,為以後的歸屬地查詢等提供方法。
15 */
16 public class AddressService {
17 private Context context;
18
19 public AddressService(Context context) {
20 this.context = context;
21 }
22
23 /**
24 * 判斷當前databases目錄下有無phoneAddres.db
25 */
26 public boolean dbIsexit() {
27 return context.getDatabasePath(TableContanst.ADDRESS_DB_NAME).exists();
28 }
29
30 /**
31 * 將phoneAddres.db拷貝到datebases目錄下
32 */
33 public void copyDB() throws Exception {
34 File databases = new File(context.getFilesDir().getParentFile(),
35 "databases"); // 找到data目錄下的databases文件夾
36 if (!databases.exists()) {
37 databases.mkdirs();
38 }
39 File dbFile = new File(databases, TableContanst.ADDRESS_DB_NAME);
40 FileOutputStream fos = new FileOutputStream(dbFile);
41 InputStream is = this.getClass().getClassLoader()
42 .getResourceAsStream(TableContanst.ADDRESS_DB_NAME); // 得到phoneAddress.db
43 byte[] bs = new byte[1024];
44 int length = 0;
45 while ((length = is.read(bs)) != -1) {
46 fos.write(bs, 0, length);
47 }
48 fos.flush();
49 is.close();
50 }
51
52 /**
53 * 獲得來電的歸屬地 手機的正則表達式為:^1[358]\d{9}$
54 */
55 public String getAddress(String number) {
56 String address = null;
57 File file = context.getDatabasePath(TableContanst.ADDRESS_DB_NAME);
58 SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getAbsolutePath(),
59 null, SQLiteDatabase.OPEN_READONLY);
60 if (db.isOpen()) {
61 if (Pattern.compile("^1[358]\\d{9}$").matcher(number).matches()) {// 手機來電匹配
62 String subNumber7 = number.substring(0, 7);
63 Cursor cursor = db
64 .rawQuery(
65 "select p.name as province,c.name as city from address as a "
66 + "inner join city as c on a.cityid=c._id "
67 + "inner join province as p on c.provinceid=p._id "
68 + "where a.mobileprefix=?",
69 new String[] { subNumber7 });
70 address = getAddressInfo(cursor);
71 } else {// 座機電話匹配
72 Cursor cursor = null;
73 String subNumber4 = null;
74 String subNumber3 = null;
75 switch (number.length()) {
76 case 12: // 4位區號+8位電話號碼
77 subNumber4 = number.substring(0, 4);
78 cursor = db
79 .rawQuery(
80 "select p.name as province,c.name as city from city c "
81 + "inner join province p on c.provinceid=p._id "
82 + "where c.areacode=? "
83 + "order by c._id asc limit 1",
84 new String[] { subNumber4 });
85 address = getAddressInfo(cursor);
86 break;
87 case 11:// 4位區號+8位電話號碼 或者 3位區號+8位電話號碼
88 subNumber4 = number.substring(0, 4);
89 subNumber3 = number.substring(0, 3);
90 cursor = db
91 .rawQuery(
92 "select p.name as province,c.name as city from city c "
93 + "inner join province p on c.provinceid=p._id "
94 + "where c.areacode in(?,?) "
95 + "order by c._id asc limit 1",
96 new String[] { subNumber4, subNumber3 });
97 address = getAddressInfo(cursor);
98 break;
99 case 10:// 3位區號+7位電話號碼
100 subNumber3 = number.substring(0, 3);
101 cursor = db
102 .rawQuery(
103 "select p.name as province,c.name as city from city c "
104 + "inner join province p on c.provinceid=p._id "
105 + "where c.areacode=? "
106 + "order by c._id asc limit 1",
107 new String[] { subNumber3 });
108 address = getAddressInfo(cursor);
109 break;
110 case 8:
111 case 7:// 本地號碼
112 address = "本地號碼";
113 break;
114 case 4:
115 if (number.startsWith("555")) {
116 address = "模擬器";
117 } else {
118 cursor = db
119 .rawQuery(
120 "select p.name as province,c.name as city from city c "
121 + "inner join province p on c.provinceid=p._id "
122 + "where c.areacode=? "
123 + "order by c._id asc limit 1",
124 new String[] { number });
125 address = getAddressInfo(cursor);
126 }
127 break;
128 case 3:
129 cursor = db
130 .rawQuery(
131 "select p.name as province,c.name as city from city c "
132 + "inner join province p on c.provinceid=p._id "
133 + "where c.areacode=? "
134 + "order by c._id asc limit 1",
135 new String[] { number });
136 address = getAddressInfo(cursor);
137 break;
138 default:
139 break;
140 }
141 }
142 db.close();
143 }
144 return address;
145 }
146
147 /**
148 * 根據查詢所得游標得到來電的具體歸屬地並返回
149 */
150 private String getAddressInfo(Cursor cursor) {
151 if (cursor.moveToFirst()) {
152 String province = cursor.getString(0);
153 String city = cursor.getString(1);
154 if (province.equals(city)) {
155 return province;
156 } else
157 return province + "省" + city + "市";
158 }
159 cursor.close();
160 return "";
161 }
162
163 /**
164 * 得到來電的類型
165 */
166 public String getType(String number) {
167 if (Pattern.compile("^1[38][0126]\\d{8}$").matcher(number).matches()) {
168 return "聯通";
169 } else if (Pattern.compile("^1[358][1456789]\\d{8}$").matcher(number)
170 .matches()) {
171 return "移動";
172 } else if (Pattern.compile("^1[358][039]\\d{8}$").matcher(number)
173 .matches()) {
174 return "電信";
175 } else if (number.startsWith("555")) {
176 return "模擬器";
177 } else if (getAddress(number).length() == 0) {
178 return "未知";
179 } else
180 return "固話";
181 }
182
183 /**
184 * 根據查詢輸入框輸入的號碼找到響應的歸屬地區號
185 */
186 public String getAreacode(String number) {
187 String areacode = null;
188 File file = context.getDatabasePath(TableContanst.ADDRESS_DB_NAME);
189 SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getAbsolutePath(),
190 null, SQLiteDatabase.OPEN_READONLY);
191 if (db.isOpen()) {
192 if (Pattern.compile("^1[358]\\d{9}$").matcher(number).matches()) {// 手機來電匹配
193 String subNumber7 = number.substring(0, 7);
194 Cursor cursor = db
195 .rawQuery(
196 "select c.areacode as areacode from city as c "
197 + "inner join address a on a.cityid=c._id "
198 + "where a.mobileprefix=? order by c._id asc limit 1",
199 new String[] { subNumber7 });
200 areacode = getAreacodeInfo(cursor);
201 } else {
202 if (number.length() == 3) {
203 Cursor cursor = db
204 .rawQuery(
205 "select c.name as name from city as c "
206 + "where c.areacode =? order by c._id asc limit 1",
207 new String[] { number });
208 areacode = getAreacodeInfo2(cursor, number);
209
210 } else if (number.length() >= 4) {
211 String subNumber4 = number.substring(0, 4);
212 Cursor cursor = db
213 .rawQuery(
214 "select c.name as name from city as c "
215 + "where c.areacode =? order by c._id asc limit 1",
216 new String[] { subNumber4 });
217 areacode = getAreacodeInfo2(cursor, subNumber4);
218 }
219 }
220 }
221 db.close();
222 return areacode;
223 }
224
225 /**
226 * 根據查詢所得游標得到查詢手機號碼的歸屬地
227 */
228 private String getAreacodeInfo(Cursor cursor) {
229 if (cursor.moveToFirst()) {
230 return cursor.getString(0);
231 }
232 cursor.close();
233 return "";
234 }
235
236 /**
237 * 根據查詢所得游標得到查詢固話號碼的歸屬地
238 */
239 private String getAreacodeInfo2(Cursor cursor, String number) {
240 if (cursor.moveToFirst()) {
241 return number;
242 } else
243 cursor.close();
244 return "";
245
246 }
247 }
<三>設置黑名單攔截和短信攔截以及歸屬地查詢功能。具體代碼如下:
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 cn.yj3g.TelPhoneMangerActivity;
2
3 import cn.yj3g.TelPhoneMangerDb.TelphoneMangerDBHelper;
4 import cn.yj3g.dao.TelphoneDao;
5 import android.app.Notification;
6 import android.app.NotificationManager;
7 import android.app.PendingIntent;
8 import android.content.BroadcastReceiver;
9 import android.content.Context;
10 import android.content.Intent;
11 import android.database.Cursor;
12 import android.net.Uri;
13 import android.telephony.SmsMessage;
14 import android.util.Log;
15 import android.widget.Toast;
16
17 /**
18 *
19 * 定義一個廣播接受者實現短信攔截
20 *
21 */
22 public class BootCompleteReceiver extends BroadcastReceiver {
23 private String sender;
24
25 public BootCompleteReceiver() {
26 Log.v("TAG", "開機了!");
27 }
28
29 @Override
30 public void onReceive(Context context, Intent intent) {
31 /**
32 * 運用廣播開啟監聽這個服務
33 */
34 TelphoneDao dao = new TelphoneDao(new TelphoneMangerDBHelper(context));
35 Object[] pdus = (Object[]) intent.getExtras().get("pdus");
36 if (pdus != null && pdus.length > 0) {
37 SmsMessage[] messages = new SmsMessage[pdus.length];
38 for (int i = 0; i < pdus.length; i++) {
39 byte[] pdu = (byte[]) pdus[i];
40 messages[i] = SmsMessage.createFromPdu(pdu);
41 }
42 for (SmsMessage message : messages) {
43 sender = message.getOriginatingAddress();// 得到發信息的號碼
44 String content = message.getMessageBody();// 得到短信內容
45 Cursor cursor = dao.findTelphone(sender);
46 if (cursor != null && cursor.getCount() != 0) {
47 abortBroadcast();// 中止發送
48 //實例化通知
49 Notification n = new Notification(R.drawable.ic_email_pending,"黑名單短信",
50 System.currentTimeMillis());
51 Intent i = new Intent();
52 i.setAction(Intent.ACTION_DIAL);
53 i.setData(Uri.parse("tel:"+sender));
54 //創建延期意圖
55 PendingIntent pi = PendingIntent.getActivity(context, 1, i, PendingIntent.FLAG_ONE_SHOT);
56 //設置通知的最新事件信息
57 n.setLatestEventInfo(context, "黑名單短信",content, pi);
58 //獲得通知管理器系統服務
59 NotificationManager nm = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
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:
1 package cn.yj3g.entity;
2
3 public final class TableContanst {
4
5 /**
6 * 自定義的一些常量
7 */
8 public static final String BLACK_NUMBER_TABLE = "number";
9 public static final String ADDRESS_DB_NAME="phoneAddress.db";
10 public static final class NumberColumns {
11 public static final String ID = "_id";
12 public static final String NUMBER = "number";
13 }
14 }
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>
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>
以上就是來電知了的全部代碼和功能了,在做的過程中用到了許多的知識,比如數據庫的增刪查以及拷貝,線程的知識,廣播機制,服務等知識。在做的過程中這些知識也就算是復習了一遍。如有有錯誤的地方,希望大家不吝指教。
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩
繪制圓環其實很簡單,有大概以下三種思路. 這裡先說網上提到的一種方法。思路是先繪制內圓,然後繪制圓環(圓環的寬度就是paint設置的paint.setStroke
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩