技术要点大概如下
- 对最新号码归属地数据的压缩与解压
- sqlite3数据库的基本 *** 作
- 监听手机来电
- 自定义Toast
准备 *** 作
最新号码归属地数据库,这里有一份但不是最新的https://pan.baidu.com/s/1bpKSghT,这是压缩过的2兆多,解压后40多兆,本来更大,这里将一个表拆成多表,减少数据冗余,其实里面的表还可以拆分,更大程度的减少数据冗余,只是查询上会造成单表查询变成多表查询,不过这种拆分应该是值得的。
1.解压
前面准备的数据库其实已经压缩过了,是用下面的工具类ZipUtil实现的,用360压缩也是ok的,亲测一样。压缩过的(链接中下载到的)放到assets目录下,启动应用程序的时候解压缩,或者用到的时候再解压,暂称为懒解压。工具类ZipUtil如下:
/** * 压缩 * @param filePath * @param savePath * @throws Exception */ public static voID compress(String filePath,String savePath) throws Exception{ ZipOutputStream out = new ZipOutputStream(new fileOutputStream( savePath)); bufferedoutputstream bos = new bufferedoutputstream(out); file file = new file(filePath); zip(out,file,file.getname(),bos); if(bos != null){ bos.close(); } if(out != null){ out.close(); } } private static int k = 0; private static voID zip(ZipOutputStream out,file f,String base,bufferedoutputstream bo) throws Exception { // 方法重载 if (f.isDirectory()) { file[] fl = f.Listfiles(); if (fl.length == 0) { out.putNextEntry(new ZipEntry(base + "/")); // 创建zip压缩进入点base System.out.println(base + "/"); } for (int i = 0; i < fl.length; i++) { zip(out,fl[i],base + "/" + fl[i].getname(),bo); // 递归遍历子文件夹 } System.out.println("第" + k + "次递归"); k++; } else { out.putNextEntry(new ZipEntry(base)); // 创建zip压缩进入点base System.out.println(base); fileinputStream in = new fileinputStream(f); BufferedinputStream bi = new BufferedinputStream(in); int b; while ((b = bi.read()) != -1) { bo.write(b); // 将字节流写入当前zip目录 } bi.close(); in.close(); // 输入流关闭 } } /** * 解压缩 * @param filePath 源文件路径 * @param rootPath 要解压到哪个文件夹下 * @throws Exception */ public static voID uncompress(String filePath,String rootPath) throws Exception{ ZipinputStream zis=new ZipinputStream(new fileinputStream( filePath));//输入源zip路径 BufferedinputStream bis=new BufferedinputStream(zis); file fOut=null; ZipEntry entry; while((entry = zis.getNextEntry())!=null){ if(entry.isDirectory()){ continue; } fOut=new file(rootPath,entry.getname()); if(!fOut.exists()){ (new file(fOut.getParent())).mkdirs(); } fileOutputStream out=new fileOutputStream(fOut); bufferedoutputstream Bout=new bufferedoutputstream(out); int b; while((b=bis.read())!=-1){ Bout.write(b); } Bout.flush(); Bout.close(); out.close(); } bis.close(); zis.close(); }
ok,解压完成,40多兆的东西进了手机,流汗!
2.监听来电,自定义toast
用后台开启服务的方式监听手机来电
public class MonitorPhoneservice extends Service { private static final String TAG = "MonitorPhoneservice"; private WindowManager windowManager; private TelephonyManager manager; private MyListener Listener; private VIEw vIEw; @Nullable @OverrIDe public IBinder onBind(Intent intent) { return null; } @OverrIDe public voID onCreate() { super.onCreate(); windowManager = (WindowManager) getSystemService(WINDOW_SERVICE); manager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); Listener = new MyListener(); manager.Listen(Listener,PhonestateListener.ListEN_CALL_STATE); } private class MyListener extends PhonestateListener { @OverrIDe public voID onCallStateChanged(int state,String incomingNumber) { super.onCallStateChanged(state,incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_IDLE: //处于静止状态,没有呼叫 if (vIEw != null) { //这里及时移除vIEw(自定义toast) windowManager.removeVIEw(vIEw); vIEw = null; } break; case TelephonyManager.CALL_STATE_OFFHOOK: //接通状态 if (vIEw != null) { //同上 windowManager.removeVIEw(vIEw); vIEw = null; } break; case TelephonyManager.CALL_STATE_RINGING: //铃响状态 showAddress(incomingNumber); break; } } } //显示归属地,自定义Toast private voID showAddress(String incomingNumber) { WindowManager.LayoutParams params = new WindowManager.LayoutParams(); params.height = WindowManager.LayoutParams.WRAP_CONTENT; params.wIDth = WindowManager.LayoutParams.WRAP_CONTENT; params.format = PixelFormat.TRANSLUCENT; params.type = WindowManager.LayoutParams.TYPE_TOAST; params.setTitle("Toast"); params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_touchABLE; vIEw = LayoutInflater.from(getApplicationContext()).inflate(R.layout.toast_query_address,null); TextVIEw tv = (TextVIEw) vIEw.findVIEwByID(R.ID.tv_toast_query_address); //这里 *** 作数据库查询号码归属地 tv.setText(new queryAddressEngine(getApplicationContext()).queryAddress(incomingNumber)); tv.setTextSize(20); windowManager.addVIEw(vIEw,params); } @OverrIDe public voID onDestroy() { super.onDestroy(); manager.Listen(Listener,PhonestateListener.ListEN_NONE); Listener = null; }}
只需启动服务监听就行了,还要添加权限
<uses-permission androID:name="androID.permission.CALL_PHONE" /> <uses-permission androID:name="androID.permission.READ_PHONE_STATE" /> <uses-permission androID:name="androID.permission.READ_EXTERNAL_STORAGE" /> <uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission androID:name="androID.permission.SYstem_ALERT_WINDOW"/> <uses-permission androID:name="androID.permission.MODIFY_PHONE_STATE" />
3.查询号码归属地
这里只用对数据库进行查-DQL
public class queryAddressEngine { private Context mContext; public queryAddressEngine(Context mContext) { this.mContext = mContext; } public String queryAddress(String number) { //匹配手机号可以写成工具类 String pattern = "^1[3458]\d{9}$"; String result = number; int type = -1; String city = ""; String province = ""; if(number.matches(pattern)){ //手机号码 sqliteDatabase database = DbDao.getDatabase(mContext); if(database.isopen()){ Cursor cursor = database.rawquery( "select province,city,type from phone where mobilepre = ? limit 1",new String[]{number.substring(0,7)}); if(cursor.movetoNext()){ city = cursor.getString(cursor.getColumnIndex("city")); type = cursor.getInt(cursor.getColumnIndex("type")); province = cursor.getString(cursor.getColumnIndex("province")); } result = province + " " + city + " " + getoperatorByType(type); cursor.close(); database.close(); } } else { //固定电话 int len = number.length(); sqliteDatabase db; switch (len){ case 4: //模拟器 result = "模拟器"; break; case 7: //本地号码 case 8: //本地号码 result = "本地号码"; break; case 10: //3位区号 + 7位号码 db = DbDao.getDatabase(mContext); if(db.isopen()){ Cursor cursor = db.rawquery( "select province,type from phone where areacode = ? limit 1",3)}); if(cursor.movetoNext()){ city = cursor.getString(cursor.getColumnIndex("city")); type = cursor.getInt(cursor.getColumnIndex("type")); province = cursor.getString(cursor.getColumnIndex("province")); } result = province + " " + city + " " + getoperatorByType(type); cursor.close(); db.close(); } break; case 11: //3位区号 + 8位号码 4位区号 + 7位号码 sqliteDatabase db2 = DbDao.getDatabase(mContext); if(db2.isopen()){ Cursor cursor = db2.rawquery( "select province,3)}); if(cursor.movetoNext()){ city = cursor.getString(cursor.getColumnIndex("city")); type = cursor.getInt(cursor.getColumnIndex("type")); province = cursor.getString(cursor.getColumnIndex("province")); } else { Cursor cursor2 = db2.rawquery( "select province,4)}); if(cursor.movetoNext()){ city = cursor.getString(cursor.getColumnIndex("city")); type = cursor.getInt(cursor.getColumnIndex("type")); province = cursor.getString(cursor.getColumnIndex("province")); } cursor2.close(); } result = province + " " + city + " " + getoperatorByType(type); cursor.close(); db2.close(); } break; case 12: //4位区号 +8位号码 db = DbDao.getDatabase(mContext); if (db.isopen()) { Cursor cursor = db.rawquery( "select province,new String[] { number.substring(0,4) }); if(cursor.movetoNext()){ city = cursor.getString(cursor.getColumnIndex("city")); type = cursor.getInt(cursor.getColumnIndex("type")); province = cursor.getString(cursor.getColumnIndex("province")); } result = province + " " + city + " " + getoperatorByType(type); cursor.close(); db.close(); } break; } } return result; } public String getoperatorByType(int type){ String operator = "未知"; switch (type){ case 1: operator = "移动"; break; case 2: operator = "联通"; break; case 3: operator = "电信"; break; case 4: operator = "虚拟运营商"; break; } return operator; }}public class DbDao { public static sqliteDatabase getDatabase(Context mContext){ return new DbHelper(mContext).getWritableDatabase(); }}public class DbHelper extends sqliteOpenHelper { public DbHelper(Context context){ this(context,Db.name,null,Db.VERSION); } public DbHelper(Context context,String name,sqliteDatabase.CursorFactory factory,int version) { super(context,name,factory,version); } @OverrIDe public voID onCreate(sqliteDatabase db) { } @OverrIDe public voID onUpgrade(sqliteDatabase db,int oldVersion,int newVersion) { }}
好了,写完收工领盒饭
总结以上是内存溢出为你收集整理的仿360手机卫士之查询号码归属地全部内容,希望文章能够帮你解决仿360手机卫士之查询号码归属地所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)