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

所要实现的功能如下图

 

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 context
12      * @param serviceName
13      * @return
14      */
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         @Override
13         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 = address
32                                     .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     }

结束

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。