android之来电知了
这周做了一个来电知了的项目,具体需求如下:
1.可以设置黑名单号码,拒接电话和短信
2.来电归属地查询
在生活中我们用到这些东西的时候感觉挺简单,但是让我们实现这些功能时,还是非常麻烦的。下面是我在做这个项目时的实现过程。
<一>设计首页,显示黑名单号码,并能进行黑名单添加和删除及其归属地查询功能。具体代码如下:
main.xml:主界面的布局文件
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#8A2BE2">
- <TextView
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:text="黑名单号码"
- android:id="@+id/tv_blacknumber"
- android:gravity="center"
- android:textColor="#ff0000"
- android:textSize="25px"/>
- <ListView
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:id="@android:id/list"
- android:cacheColorHint="#00000000"
- android:layout_weight="1"/>
- <TextView
- android:id="@android:id/empty"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:text="无黑名单号码,请添加!"
- android:gravity="center"
- android:textColor="#00CD00"
- android:textSize="25px"
- android:layout_weight="1"/>
- <LinearLayout android:id="@+id/ll_bottom"
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="@drawable/buttonbackground">
- <Button android:id="@+id/btn_add"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:background="@drawable/button_selector"
- android:text="添 加"/>
- <Button android:id="@+id/btn_search"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:background="@drawable/button_selector"
- android:text="归属地查询"/>
- <Button android:id="@+id/btn_delete"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:background="@drawable/button_selector"
- android:text="删 除"/>
- <CheckBox android:id="@+id/cb_select_all"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:text="全 选"/>
- </LinearLayout>
- </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:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <TextView android:id="@+id/tv_item_number"
- android:layout_width="wrap_content"
- android:layout_height="40dip"
- android:gravity="center"
- android:textSize="20sp"
- android:textColor="@drawable/itemcolor"
- android:layout_weight="1"
- android:layout_marginRight="6dip" />
- <CheckBox
- android:id="@+id/cb_item_delete"
- android:layout_width="wrap_content"
- android:layout_height="40dip"
- android:layout_weight="1"
- android:focusable="false"
- android:checked="false"
- android:clickable="false"
- android:layout_alignParentRight="true"
- android:layout_marginLeft="2dip"/>
- </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 cn.yj3g.TelPhoneMangerDb;
- import cn.yj3g.entity.TableContanst;
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.database.sqlite.SQLiteOpenHelper;
- import android.util.Log;
- /**
- *
- *创建一个数据库帮助类
- *
- */
- public class TelphoneMangerDBHelper extends SQLiteOpenHelper {
- private static final String TAG = "TelphoneMangerDBHelper";
- public static final String DB_NAME = "telphone_black.db";
- public static final int VERSION = 1;
- public TelphoneMangerDBHelper(Context context, String name,
- CursorFactory factory, int version) {
- super(context, name, factory, version);
- }
- public TelphoneMangerDBHelper(Context context) {
- this(context, DB_NAME, null, VERSION);
- }
- /**
- * 创建数据库
- */
- public void onCreate(SQLiteDatabase db) {
- 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 newVersion) {
- 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 cn.yj3g.TelphonemangerService;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.util.regex.Pattern;
- import cn.yj3g.entity.TableContanst;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- /**
- * 定义一个归属地服务的类,为以后的归属地查询等提供方法。
- */
- public class AddressService {
- private Context context;
- public AddressService(Context context) {
- this.context = context;
- }
- /**
- * 判断当前databases目录下有无phoneAddres.db
- */
- public boolean dbIsexit() {
- return context.getDatabasePath(TableContanst.ADDRESS_DB_NAME).exists();
- }
- /**
- * 将phoneAddres.db拷贝到datebases目录下
- */
- public void copyDB() throws Exception {
- File databases = new File(context.getFilesDir().getParentFile(),
- "databases"); // 找到data目录下的databases文件夹
- if (!databases.exists()) {
- databases.mkdirs();
- }
- File dbFile = new File(databases, TableContanst.ADDRESS_DB_NAME);
- FileOutputStream fos = new FileOutputStream(dbFile);
- InputStream is = this.getClass().getClassLoader()
- .getResourceAsStream(TableContanst.ADDRESS_DB_NAME); // 得到phoneAddress.db
- byte[] bs = new byte[1024];
- int length = 0;
- while ((length = is.read(bs)) != -1) {
- fos.write(bs, 0, length);
- }
- fos.flush();
- is.close();
- }
- /**
- * 获得来电的归属地 手机的正则表达式为:^1[358]\d{9}$
- */
- public String getAddress(String number) {
- String address = null;
- File file = context.getDatabasePath(TableContanst.ADDRESS_DB_NAME);
- SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getAbsolutePath(),
- null, SQLiteDatabase.OPEN_READONLY);
- if (db.isOpen()) {
- if (Pattern.compile("^1[358]\\d{9}$").matcher(number).matches()) {// 手机来电匹配
- String subNumber7 = number.substring(0, 7);
- 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 String[] { subNumber7 });
- address = getAddressInfo(cursor);
- } else {// 座机电话匹配
- Cursor cursor = null;
- String subNumber4 = null;
- String subNumber3 = null;
- switch (number.length()) {
- case 12: // 4位区号+8位电话号码
- subNumber4 = number.substring(0, 4);
- 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 String[] { subNumber4 });
- address = getAddressInfo(cursor);
- break;
- case 11:// 4位区号+8位电话号码 或者 3位区号+8位电话号码
- subNumber4 = number.substring(0, 4);
- 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 String[] { subNumber4, subNumber3 });
- address = getAddressInfo(cursor);
- break;
- case 10:// 3位区号+7位电话号码
- 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=? "
- + "order by c._id asc limit 1",
- new String[] { subNumber3 });
- address = getAddressInfo(cursor);
- break;
- case 8:
- case 7:// 本地号码
- address = "本地号码";
- break;
- case 4:
- if (number.startsWith("555")) {
- 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 String[] { number });
- address = getAddressInfo(cursor);
- }
- break;
- case 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=? "
- + "order by c._id asc limit 1",
- new String[] { number });
- address = getAddressInfo(cursor);
- break;
- default:
- break;
- }
- }
- db.close();
- }
- return address;
- }
- /**
- * 根据查询所得游标得到来电的具体归属地并返回
- */
- private String getAddressInfo(Cursor cursor) {
- if (cursor.moveToFirst()) {
- String province = cursor.getString(0);
- String city = cursor.getString(1);
- if (province.equals(city)) {
- return province;
- } else
- return province + "省" + city + "市";
- }
- cursor.close();
- return "";
- }
- /**
- * 得到来电的类型
- */
- public String getType(String number) {
- if (Pattern.compile("^1[38][0126]\\d{8}$").matcher(number).matches()) {
- return "联通";
- } else if (Pattern.compile("^1[358][1456789]\\d{8}$").matcher(number)
- .matches()) {
- return "移动";
- } else if (Pattern.compile("^1[358][039]\\d{8}$").matcher(number)
- .matches()) {
- return "电信";
- } else if (number.startsWith("555")) {
- return "模拟器";
- } else if (getAddress(number).length() == 0) {
- return "未知";
- } else
- return "固话";
- }
- /**
- * 根据查询输入框输入的号码找到响应的归属地区号
- */
- public String getAreacode(String number) {
- String areacode = null;
- File file = context.getDatabasePath(TableContanst.ADDRESS_DB_NAME);
- SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getAbsolutePath(),
- null, SQLiteDatabase.OPEN_READONLY);
- if (db.isOpen()) {
- if (Pattern.compile("^1[358]\\d{9}$").matcher(number).matches()) {// 手机来电匹配
- String subNumber7 = number.substring(0, 7);
- 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 String[] { subNumber7 });
- areacode = getAreacodeInfo(cursor);
- } else {
- if (number.length() == 3) {
- Cursor cursor = db
- .rawQuery(
- "select c.name as name from city as c "
- + "where c.areacode =? order by c._id asc limit 1",
- new String[] { number });
- areacode = getAreacodeInfo2(cursor, number);
- } else if (number.length() >= 4) {
- 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 String[] { subNumber4 });
- areacode = getAreacodeInfo2(cursor, subNumber4);
- }
- }
- }
- db.close();
- return areacode;
- }
- /**
- * 根据查询所得游标得到查询手机号码的归属地
- */
- private String getAreacodeInfo(Cursor cursor) {
- if (cursor.moveToFirst()) {
- return cursor.getString(0);
- }
- cursor.close();
- return "";
- }
- /**
- * 根据查询所得游标得到查询固话号码的归属地
- */
- private String getAreacodeInfo2(Cursor cursor, String number) {
- if (cursor.moveToFirst()) {
- return number;
- } 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:
- package cn.yj3g.TelPhoneMangerActivity;
- import cn.yj3g.TelPhoneMangerDb.TelphoneMangerDBHelper;
- import cn.yj3g.dao.TelphoneDao;
- import android.app.Notification;
- import android.app.NotificationManager;
- import android.app.PendingIntent;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.Intent;
- import android.database.Cursor;
- import android.net.Uri;
- import android.telephony.SmsMessage;
- import android.util.Log;
- import android.widget.Toast;
- /**
- *
- * 定义一个广播接受者实现短信拦截
- *
- */
- public class BootCompleteReceiver extends BroadcastReceiver {
- private String sender;
- public BootCompleteReceiver() {
- Log.v("TAG", "开机了!");
- }
- @Override
- public void onReceive(Context context, Intent intent) {
- /**
- * 运用广播开启监听这个服务
- */
- TelphoneDao dao = new TelphoneDao(new TelphoneMangerDBHelper(context));
- Object[] pdus = (Object[]) intent.getExtras().get("pdus");
- if (pdus != null && pdus.length > 0) {
- SmsMessage[] messages = new SmsMessage[pdus.length];
- for (int i = 0; i < pdus.length; i++) {
- byte[] pdu = (byte[]) pdus[i];
- messages[i] = SmsMessage.createFromPdu(pdu);
- }
- for (SmsMessage message : messages) {
- sender = message.getOriginatingAddress();// 得到发信息的号码
- String content = message.getMessageBody();// 得到短信内容
- Cursor cursor = dao.findTelphone(sender);
- if (cursor != null && cursor.getCount() != 0) {
- abortBroadcast();// 中止发送
- //实例化通知
- Notification n = new Notification(R.drawable.ic_email_pending,"黑名单短信",
- System.currentTimeMillis());
- Intent i = new Intent();
- i.setAction(Intent.ACTION_DIAL);
- i.setData(Uri.parse("tel:"+sender));
- //创建延期意图
- PendingIntent pi = PendingIntent.getActivity(context, 1, i, PendingIntent.FLAG_ONE_SHOT);
- //设置通知的最新事件信息
- n.setLatestEventInfo(context, "黑名单短信",content, pi);
- //获得通知管理器系统服务
- NotificationManager nm = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
- nm.notify(1, n);
- Toast.makeText(context, "通知发布完成", 1).show();
- Log.e("TAG", "号码" + sender + "为黑名单号码,已拦截!");
- cursor.close();
- }
- }
- }
- }
- }
运行效果如下:
黑名单短信通知:
显示归属地的运行效果如下:
<四>实现归属地查询功能
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 cn.yj3g.entity;
- public final class TableContanst {
- /**
- * 自定义的一些常量
- */
- public static final String BLACK_NUMBER_TABLE = "number";
- public static final String ADDRESS_DB_NAME="phoneAddress.db";
- public static final class NumberColumns {
- public static final String ID = "_id";
- public static final String NUMBER = "number";
- }
- }
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:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:background="#8A2BE2"
- android:layout_height="fill_parent">
- <Button
- android:id="@+id/btn_sure"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="5"
- android:text="查询"
- android:layout_alignParentRight="true"
- android:layout_marginLeft="2dip"/>
- <EditText android:layout_height="wrap_content"
- android:hint="可输入号码/区号"
- android:id="@+id/et_search"
- android:layout_width="wrap_content"
- android:padding="5dip"
- android:textSize="15sp"
- android:inputType="phone"
- android:maxLength="11"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_toLeftOf="@+id/btn_sure"/>
- <TextView android:layout_height="wrap_content"
- android:text="号码:"
- android:id="@+id/tv1"
- android:layout_width="wrap_content"
- android:layout_below="@+id/et_search"
- android:layout_marginRight="15dip"
- android:layout_alignParentLeft="true"
- android:layout_marginTop="16dp"/>
- <TextView
- android:id="@+id/tv_number"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:layout_toRightOf="@+id/tv1"
- android:layout_below="@+id/et_search"
- android:layout_alignBottom="@+id/tv1"
- android:layout_marginTop="16dp"/>
- <TextView android:layout_height="wrap_content"
- android:text="归属:"
- android:id="@+id/tv2"
- android:layout_width="wrap_content"
- android:layout_below="@+id/tv1"
- android:layout_marginRight="15dip"
- android:layout_alignParentLeft="true"
- android:layout_marginTop="20dp"/>
- <TextView
- android:id="@+id/tv_address"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:layout_toRightOf="@+id/tv2"
- android:layout_below="@+id/tv_number"
- android:layout_alignBottom="@+id/tv2"
- android:layout_marginTop="20dp"/>
- <TextView android:layout_height="wrap_content"
- android:text="类型:"
- android:id="@+id/tv3"
- android:layout_width="wrap_content"
- android:layout_below="@+id/tv2"
- android:layout_marginRight="15dip"
- android:layout_alignParentLeft="true"
- android:layout_marginTop="25dp"/>
- <TextView
- android:id="@+id/tv_type"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:layout_toRightOf="@+id/tv3"
- android:layout_below="@+id/tv_address"
- android:layout_alignBottom="@+id/tv3"
- android:layout_marginTop="25dp"/>
- </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:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
- android:layout_width="wrap_content"
- android:background="@drawable/addressbackground"
- android:layout_height="wrap_content">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
- <ImageButton android:id="@+id/showimage"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/ic_launcher_vcard"
- android:scaleType="center"/>
- <TextView
- android:id="@+id/showaddress"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textSize="20sp"
- android:textColor="#eee"/>
- </LinearLayout>
- <TextView
- android:id="@+id/shownumber"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:textSize="20sp"
- android:textColor="#eee"/>
- </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>
以上就是来电知了的全部代码和功能了,在做的过程中用到了许多的知识,比如数据库的增删查以及拷贝,线程的知识,广播机制,服务等知识。在做的过程中这些知识也就算是复习了一遍。如有有错误的地方,希望大家不吝指教。
原文地址: http://www.cnblogs.com/zxl-jay/archive/2011/09/30/2196555.html#2300170
android之来电知了相关推荐
- Android 号码, 来电归属地 Jni 使用C++对二进制文件查询(一) 理论篇
1.效果图 左边的是应用程序界面,只是做个测试.右边的是应用程序信息,你会发现数据这块很小,只有420KB,要知道里面有近280,000记录. 2.尝试使用sqlite数据库, 用db格式文件. 随便 ...
- android 来电过滤,Android实现来电挂断
Android实现来电挂断要注意区分系统版本 Android 9.0 以后使用TelecomManager (需要权限Manifest.permission.ANSWER_PHONE_CALLS). ...
- Android实现来电和去电的监听
写个实例实现Android中来电和去电的监听,来电可以使用PhoneStateListener对电话状态的改变进行监听,去电需要动态或者静态去注册广播接收器,对去电进行监听: 来电: 来电所对应的三种 ...
- android监控来电显示
当电话来电的时候,我们要监控着电话号码的来电,哪我们是通过代码控制,下面我们看看利用吐丝显示来电显示 package com.smart; import android.app.Activity; ...
- android 模拟来电广播,在Android模拟器上模拟来电
最近项目要做一个控制来电显示的Android 应用 需要在Emulator上模拟来电 效果 方法如下: 1.单个电话 打开命令行cmd,输入telnet 回车. 然后输入 o localhost 55 ...
- Android设置来电号码归属地
FAQ Content [DESCRIPTION] 如何关闭MTK内置来电号码归属地? [SOLUTION] MTK平台号码归属地分为两种:1.手机号码归属地:2.固话号码归属地: 手机号码归 ...
- Android中来电号码归属地的显示
昨日实现了360手机卫士的来电显示归属地的功能,具体的功能就是当来电的时候,界面会弹出来一个自定义的土司,显示当前号码的归属地,学习之后发现操作非常的简单,总结下加强自己的回忆. 具体细节大概为:别人 ...
- android来电电话获取,Android获取来电号码代码
对于Android平台的整个来电软件制作十分简单,Android平台在各方面都比较智能,加上一个BOOT_COMPLETED获取,保证开机自动运行,一个来电通就很容易的制作完成了. Android来电 ...
- android 来电显示号码,android监控来电显示
原理:电话预订功能,需要显示来电者的电话号码,c#实现获取电话号码,并在应用程序中显示出来.将电话机通过支持来电显示的moderm或USB来电显示盒(来电宝)与电话线连接,即可实现来电显示功能. 为了 ...
最新文章
- this keyword details
- linux grep 基本正则表达式与扩展正则表达式使用解析
- mysql不同count的性能分析
- nginx配置thinkphp5
- 在c#中用mutex类实现线程的互斥_面试官经常问的synchronized实现原理和锁升级过程,你真的了解吗...
- android 通知传值,Android消息通知(notification)和PendingIntent传值
- 计算机辅助语言和语言学关系,西方语言学与多媒体计算机辅助语言学习_王艳萍...
- 2014-3-16 星期天 晴[改变生活规律,稳中求进]
- kali字典WiFi
- VSCode 设置为 Monaco字体
- gwipr70驱动天空_gwi驱动
- STM8L HALT与IWDG同时使用问题
- web 打开pdf文件
- CVPR2021 多目标跟踪(MOT)汇总
- 跨境电商如何通过WhatsApp Business进行客户服务?
- 计算机组成原理八位全加器,8位全加器-课程设计
- 边打游戏边学编程,是一种怎样的体验?
- 虚拟机硬盘格式vdi、vhd、vmdk进行互相转换
- openGauss 极简版安装
- eclipse突然打不开,双击没反应
热门文章
- 美团二面:说说单点登录吧
- 手撸SSO单点登录(三):统一跳转至SSO登录页
- 【C语言学习笔记】int和long的范围
- python中import语句的作用是什么_什么是Pythonimport语句?在Python中的import语句作用有哪些?...
- 安卓开启子线程常用的方法
- AI正在让很多行业的红利消失
- c枚举类型enum例题_c枚举类型enum用法 枚举类型enum用法 怎么去取所有
- 可爱的皮卡丘print代码
- 《Automatic Image-Based WasteClassification》论文笔记
- 给vue的页面添加背景图片