仿手机卫士打电话弹出归属地
所要實現的功能如下圖
?
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 }結束
?
轉載于:https://www.cnblogs.com/lihaolihao/p/4123492.html
總結
以上是生活随笔為你收集整理的仿手机卫士打电话弹出归属地的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 周子衡:我所理解的DT时代
- 下一篇: 中国线缆产业电商的拓荒者 专访缆360