首页 > 代码库 > 仿手机卫士打电话弹出归属地

仿手机卫士打电话弹出归属地

所要实现的功能如下图

 

no tu no bb

实现此功能需要解决一下问题

1,来电号码所在地址怎么解决?
答:从数据库里面获取,数据库从哪来?从百度,google。soga!

2,怎么知道什么时候来电or去电?
答:监听系统广播

3,怎么知道来电or去电人的姓名和号码归属地
答:通过内容提供者来获取!

4,弹出的窗口怎么来做?
答:用popupwindow ? 否 我们经常在service 或者 BroadcastReceiver里面弹出Toast,
我们这里就用Toast做,通过WindowManager来实现

 

我们先来实现第1个问题加载数据库

先从网上下个数据库contactAddress.db,把此文件放在assets文件夹中,我们要想使用该数据库就要把contactAddress.db放在files文件中

下面是实现代码

 1   /** 2      * 加载数据库 3      */ 4     private void loadDb() { 5         try { 6             File file = new File(getFilesDir(), "contactAddress.db"); 7             // 判断contactAddress.db是否存在,不存在复制数据库到app 8             if (file.exists() && file.length() > 0) { 9                 return;10             } else {11                 // 找到assets,打开contactAddress.db,得到输入流12                 InputStream is = getAssets().open("contactAddress.db");13                 FileOutputStream fos = new FileOutputStream(file);14                 byte []buffer = new byte[1024];15                 int length = 0;16                 while((length = is.read(buffer)) != -1){17                     fos.write(buffer, 0, length);18                 }19                 fos.flush();20                 is.close();21                 fos.close();22             }23         } catch (IOException e) {24             e.printStackTrace();25         }26     }

 

  

第1个问题以解决,下面我们来实现第2个问题:怎么知道什么时候来电or去电?

这个问题我们换个方法来实现我们用service来实现,通常情况下都是用BroadcastReceiver来实现,这个地方有个问题BroadcastReceiver生命周期限制,有可能会因为通话时间过长
导致BroadcastReceiver生命周期结束,这样弹出的窗口就不显示了。

我们想要开启service时,我们要考虑一个问题,如果这个service已开启,我们就不用再次开启,那么,问题来了怎么检测服务是否开启!

直接上代码:

 1 /** 2  * service 工具类 3  * @author Administrator 4  * 5  */ 6 public class ServiceUtil { 7      8     /** 9      * 根据service名称查看是否死掉10      * service名称 = 需要加上包名+service类名称11      * @param context12      * @param serviceName13      * @return14      */15     public static boolean isRun(Context context,String serviceName){16         ActivityManager activityManager = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);17         List<RunningServiceInfo> list = activityManager.getRunningServices(200);18         for(RunningServiceInfo info : list){19             if(info.service.getClassName().equals(serviceName)){20                 return true;21             }22         }23         return false;        24     }25     26 }

 

 

下面我们来看看这个service怎么来写

新建一个PhoneService,在onCreate()方法里面先实现来电监听

 1 mTeleManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); 2 myListener = new MyPhoneStateListener(); 3 mTeleManager.listen(myListener, PhoneStateListener.LISTEN_CALL_STATE); 4  5    /** 6      * 电话进来,监听 7      * @author Administrator 8      * 9      */10     class MyPhoneStateListener extends PhoneStateListener{11 12         @Override13         public void onCallStateChanged(int state, String incomingNumber) {14             super.onCallStateChanged(state, incomingNumber);15             switch (state) {16             case TelephonyManager.CALL_STATE_RINGING://电话铃声响起17                //to do21                 break;22 23             case TelephonyManager.CALL_STATE_IDLE: //电话空闲了24                //to do27                 break;28             }29         }30         31     }

这样来电监听就可以实现了,下面实现去电监听

 1     /** 2      * 打电话广播接收者 3      */ 4     class OutCallReceiver extends BroadcastReceiver{ 5  6         @Override 7         public void onReceive(Context context, Intent intent) { 8             //获取拨打出去的电话 9             String phone = getResultData();  
//to do
14         }
15 16 }

我们需要在PhoneService 的onCreate动态注册一下

1 //注册广播2 receiver = new OutCallReceiver();3 IntentFilter filter = new IntentFilter();4 filter.addAction("android.intent.action.NEW_OUTGOING_CALL");5 registerReceiver(receiver, filter );

ok 电话去电和来电的监听已解决.

 

下面来看第3个问题: 怎么知道来电or去电人的姓名和号码归属地

通过问题2可以获取到来电or去电的电话号码 解决姓名和归属地也就是分分钟钟的事了

我们先看如何获取姓名,这里我写了一个工具类方法:

 1    public static String getContactName(Context context,String phone) { 2         String name = "陌生人"; 3         // 内容解析器     4         ContentResolver resolver = context.getContentResolver(); 5         // 获取手机联系人 6         String[] PHONES_PROJECTION = new String[] { Phone.DISPLAY_NAME,Phone.NUMBER};         7         Cursor phoneCursor = resolver.query(Phone.CONTENT_URI, 8                 PHONES_PROJECTION, Phone.NUMBER+" =? ", new String[]{phone}, null); 9         if (phoneCursor != null && phoneCursor.getCount() > 0) {10             while (phoneCursor.moveToNext()) {11                  name = phoneCursor.getString(0);    12             }13         }14         phoneCursor.close();15         return name;16     }

搜噶!调用这个方法就可以获取到姓名了!

来看一下获取归属地我们的数据库要登场了,封装一下吧!

 1     public static String getAddress(String phone) { 2         String dbAddress = "data/data/com.example.demo/files/contactAddress.db"; 3         String address = phone; 4         SQLiteDatabase database = SQLiteDatabase.openDatabase(dbAddress, null, 5                 SQLiteDatabase.OPEN_READONLY); 6         // 判断是否为手机号 7         if (phone.matches("^1[34568]\\d{9}$")) { 8             String sql = "select d2.location from data1 as d1 left join data2 as d2 on d1.outkey = d2.id where d1.id = ?"; 9             Cursor cursor = database.rawQuery(sql,10                     new String[] { (String) phone.subSequence(0, 7) });11             if (cursor != null && cursor.getCount() > 0) {12                 while (cursor.moveToNext()) {13                     address = cursor.getString(0);14                 }15             }16         } else {17             switch (phone.length()) {18             case 3:19                 address = "求救电话";20                 break;21             default:22                 // 固话23                 if (phone.length() > 0 && phone.startsWith("0")) {24                     String sql = "select location from data2 where area = ? or area = ?";25                     Cursor cursor = database.rawQuery(sql,26                             new String[] { (String) phone.subSequence(1, 3),27                                     (String) phone.subSequence(1, 4) });28                     if (cursor != null && cursor.getCount() > 0) {29                         while (cursor.moveToNext()) {30                             address = cursor.getString(0);31                             address = address32                                     .substring(0, address.length() - 2);33                         }34                     }35                 }36                 break;37             }38         }39         return address;40 41     }

这样我们就可以获取到归属地和姓名了

我们监听的时候调用这两个方法就可以了 在 //to do 下面调用就可以了

 

我们来解决第4个问题:弹出的窗口怎么来?

我们需要在PhoneService 的onCreate 实例化一个WindowManager

1 mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

窗口管理类 有两个方法addView()和 removeView(),如果来电话或者去电我们调用一下 addview 就可以弹出一个窗口了 挂断时调用removeView()。

下面我们调用addview显示弹出窗口,so 封装一个方法

 1   /** 2      * 弹出来电号码地址 3      */ 4     public void showWindow(String address){ 5         view = View.inflate(PhoneService.this, R.layout.address_show, null); 6         TextView tv_address = (TextView) view.findViewById(R.id.tv_address); 7         tv_address.setText(address); 8      9         params = new WindowManager.LayoutParams();10         params.height = WindowManager.LayoutParams.WRAP_CONTENT;11         params.width = WindowManager.LayoutParams.WRAP_CONTENT;12         params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE              13                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;14         params.format = PixelFormat.TRANSLUCENT;15         params.type = WindowManager.LayoutParams.TYPE_TOAST;16 17         params.gravity = Gravity.CENTER_VERTICAL|Gravity.CENTER_HORIZONTAL;18         mWindowManager.addView(view, params );19     }

好了,这样就可以打电话时弹出电话归属地了!!!!!尼玛,等等!腾讯的手机管家弹出的归属地还可以移动,我的也必须动起,

给view 添加一个触摸事件就ok了

 1 view.setOnTouchListener(new OnTouchListener() { 2             int startX ,startY; 3             @Override 4             public boolean onTouch(View v, MotionEvent event) { 5                 switch (event.getAction()) { 6                 case MotionEvent.ACTION_DOWN: 7                      startX = (int) event.getRawX(); 8                      startY = (int) event.getRawY(); 9                     break;10                 case MotionEvent.ACTION_MOVE:11                     int newX = (int) event.getRawX();12                     int newY= (int) event.getRawY();13                     int dx = newX - startX;14                     int dy = newY - startY;15                     params.x += dx;16                     params.y += dy;17                     mWindowManager.updateViewLayout(view, params);18                     // 重新初始化手指的开始结束位置。19                     startX = (int) event.getRawX();20                     startY = (int) event.getRawY();21                     break;22                 case MotionEvent.ACTION_UP:23                     break;24                 }25                 return false;26             }27         });

这个触摸事件用 GestureDetector 更容易实现。

当service 死掉后 我们把该回收的要回收一下!扫扫地

 1     @Override 2     public void onDestroy() { 3         // TODO Auto-generated method stub 4         super.onDestroy(); 5         mTeleManager.listen(myListener,PhoneStateListener.LISTEN_NONE); 6         myListener = null; 7          8         unregisterReceiver(receiver); 9         receiver = null;10     }

主要的代码就这么多

最后我们给客户要看到的界面是什么样的!让用户可操作是否开启归属地显示!直接给用户一个Button 自己玩吧

我们看一下activity 怎么写的

1 isRunPhoneService = ServiceUtil.isRun(this, "com.example.demo.PhoneService");2 mButton = (Button) findViewById(R.id.button);3         4 if(isRunPhoneService){5    mButton.setText("service 服务已开启");6 }else{7    mButton.setText("service 服务已关闭");8 }

button的点击事件

 1   /** 2      * 点击开启服务,如果服务已开启,就不用开启 3      *  4      * @param view 5      */ 6     public void click(View view) { 7         isRunPhoneService = !isRunPhoneService; 8         Intent service = new Intent(MainActivity.this, PhoneService.class); 9         if(isRunPhoneService){10             mButton.setText("service 服务已开启");11             startService(service );12         }else{13             mButton.setText("service 服务已关闭");14             stopService(service);15         }16     }

结束

 

仿手机卫士打电话弹出归属地