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

所要实现的功能如下图

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     }

结束

时间: 2024-11-08 04:55:04

仿手机卫士打电话弹出归属地的相关文章

iOS开发实用技巧—在手机浏览器头部弹出app应用下载提示

iOS开发实用技巧—在手机浏览器头部弹出app应用下载提示 本文介绍其简单使用: 第一步:在本地建立一个访问的服务端.  打开本地终端,在本地新建一个文件夹,在该文件夹中存放测试的html页面.   在终端输入一行代码:python -m SimpleHTTPServer ---第二步:配置环境  打开safari,偏好设置->勾选 "在菜单栏中显示开发菜单",如下图所示. 第三步:编写html文件 在测试文件appdown.html中编写的测试代码如下:   `说明`44493

手机客户端阻止手机软键盘弹出

手机网页怎么禁止缩放和拖动 禁止缩放 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" />user-scalable=no    yes 设置用户缩放 禁止拖动document.ontouchmove = function(e){ e.preventDefault(

仿IPhone从底部弹出选项菜单

项目中开发需要,就是在点击某个控件(如头像ImageView)时要求弹出一个操作的选项菜单(对话框),效果就是像IPhone的一样,从手机屏幕底部往上弹出的,做了个简单的效果工具类,写下来方便下次使用. 首先我们要定义弹出的对话框样式: public static Dialog createShowAlert(final Context context, int layoutId) {/**方法中要传入建立对话框的Layout*/ LayoutInflater inflater = (Layou

小技巧|H5禁止手机虚拟键盘弹出

本文首发于我的博客:http://dunizb.com原文地址:http://dunizb.com/2017/09/24/disable-the-phone-virtual-keyboard-up/ 工作中遇到如下需求,点击输入框弹出自定义弹窗,输入框是input标签:但是在移动端,input会默认触发手机的虚拟键盘,如何阻止手机虚拟键盘弹起呢?目前我试过有两个方案,一个是给input添加readonly属性,另一个就是在input事件处理方法前面添加一句document.activeEleme

转:仿QQ长按弹出功能菜单

android app普遍常用的弹出上下文菜单是列表式的.QQ列表,在上方弹出冒泡效果菜单,如图 这里讲解一下如何写出这个效果: 图片资源:两张图片,可以拼接成如上效果. 首先,我们需要写布局文件: layout_pop.xml (mipmap是android studio 的引用图片的写法,以前常用@drawable/xxx) <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns

仿QQ邮箱的弹出层,弹出确认框

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><HTML> <HEAD> <TITLE>QQ邮箱的弹出层</TITLE> <meta http-equiv="Content-Type" c

react native仿微信性别选择-自定义弹出框

简述 要实现微信性别选择需要使用两部分的技术: 第一.是自定义弹出框: 第二.单选框控件使用: 效果 实现 一.配置弹出框 弹出框用的是:react-native-popup-dialog(Git地址:https://github.com/jacklam718/react-native-popup-dialog) 具体配置见Git文档~ 二.配置单选框 用的是:react-native-elements(Git地址:https://react-native-training.github.io/

[android] 手机卫士来电显示号码归属地

继续N天前的项目 开启服务监听手机来电,查询数据库,显示归属地 详细内容可以参考这篇博文:http://www.cnblogs.com/taoshihan/p/5331232.html AddressService.java package com.qingguow.mobilesafe.service; import com.qingguow.mobilesafe.utils.NumberQueryAddressUtil; import android.app.Service; import

Android开发之仿手机卫士悬浮窗效果

基本的实现原理,这种桌面悬浮窗的效果很类似与Widget,但是它比Widget要灵活的多.主要是通过WindowManager这个类来实现的,调用这个类的addView方法用于添加一个悬浮窗,updateViewLayout方法用于更新悬浮窗的参数,removeView用于移除悬浮窗.其中悬浮窗的参数这里有必要详细说明一下. WindowManager.LayoutParams这个类用于提供悬浮窗所需的参数,其中有几个经常会用到的变量: type值用于确定悬浮窗的类型,一般设为2002,表示在所