Android 代码实现来电拦截
为了更好地理解这个Demo,我先向大家介绍一下需求与功能。
需求:
每天都会有很多无聊的电话,比如推销商品等,占用我们大量时间不说,有时候还会打乱我们的思路,扰乱我们的正常生活。所以实现一个对某些号码(比如陌生号码,指定号码/黑名单等)进行拦截以避免受到骚扰,是很有现实用途的。
为了避免程序过分复杂,造成不易学习的麻烦我在这里只实现“如果来电号码没在联系人中,则进行挂断,并存入xml文件(SharedPreferences)中,并在首页显示”,以期达到抛砖引玉的效果。
其实在android在1.1版本后就已经把Phone类的相关API给隐藏起来了,想要用代码实现挂断电话的功能,就必须通过AIDL才行,然后利用反射来使用其方法。
第一步:在程序中新建一个包,包名必须为:com.android.internal.telephony,因为要使用aidl。
第二步:在这个包里面新建一个名为ITelephony.aidl的文件,然后在文件里面写入代码:
- package com.android.internal.telephony;
- interface ITelephony{
- boolean endCall();
- void answerRingingCall();
- }
然后是要监听电话状态,当来电时,检测来电号码是否符合拦截标准(这个拦截标准是我们自己定的,你可以拦截指定号码如实现一个黑名单的功能,我们在这里拦截所有不在联系人里的号码,并把此号码存入文件,以方便在首页显示),代码如下:
- import java.lang.reflect.Method;
- import java.util.ArrayList;
- import com.android.internal.telephony.ITelephony;
- import android.app.Service;
- import android.content.BroadcastReceiver;
- import android.content.ContentResolver;
- import android.content.Context;
- import android.content.Intent;
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.Editor;
- import android.database.Cursor;
- import android.provider.ContactsContract;
- import android.telephony.TelephonyManager;
- import android.util.Log;
- public class PhoneStatReceiver extends BroadcastReceiver{
- String TAG = "tag";
- TelephonyManager telMgr;
- @Override
- public void onReceive(Context context, Intent intent) {
- telMgr = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);
- switch (telMgr.getCallState()) {
- case TelephonyManager.CALL_STATE_RINGING:
- String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
- Log.v(TAG,"number:"+number);
- if (!getPhoneNum(context).contains(number)) {
- SharedPreferences phonenumSP = context.getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);
- Editor editor = phonenumSP.edit();
- editor.putString(number,number);
- editor.commit();
- endCall();
- }
- break;
- case TelephonyManager.CALL_STATE_OFFHOOK:
- break;
- case TelephonyManager.CALL_STATE_IDLE:
- break;
- }
- }
- /**
- * 挂断电话
- */
- private void endCall()
- {
- Class<TelephonyManager> c = TelephonyManager.class;
- try
- {
- Method getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[]) null);
- getITelephonyMethod.setAccessible(true);
- ITelephony iTelephony = null;
- Log.e(TAG, "End call.");
- iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[]) null);
- iTelephony.endCall();
- }
- catch (Exception e)
- {
- Log.e(TAG, "Fail to answer ring call.", e);
- }
- }
- private ArrayList<String> getPhoneNum(Context context) {
- ArrayList<String> numList = new ArrayList<String>();
- //得到ContentResolver对象
- ContentResolver cr = context.getContentResolver();
- //取得电话本中开始一项的光标
- Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
- while (cursor.moveToNext())
- {
- // 取得联系人ID
- String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
- Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
- ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null);
- // 取得电话号码(可能存在多个号码)
- while (phone.moveToNext())
- {
- String strPhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
- numList.add(strPhoneNumber);
- Log.v("tag","strPhoneNumber:"+strPhoneNumber);
- }
- phone.close();
- }
- cursor.close();
- return numList;
- }
- }
这里我们要注意以下几点:
1.PhoneStatReceiver一定要在清单文件(AndroidManifest.xml)中注册。
2.一定要添加权限
AndroidManifest文件如下:
- <?xml version="1.0" encoding="utf-8"?>
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.xxxx.xxxx"
- android:versionCode="1"
- android:versionName="1.0" >
- <uses-sdk android:minSdkVersion="8" />
- <!-- 挂断手机的权限 -->
- <uses-permission android:name="android.permission.CALL_PHONE"/>
- <!-- 读取手机状态的权限 -->
- <uses-permission android:name="android.permission.READ_PHONE_STATE" />
- <!-- 读content的权限 -->
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <application
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name" >
- <activity
- android:name=".MainActivity"
- android:label="@string/app_name" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.LAUNCHER" />
- </intent-filter>
- </activity>
- <!-- 注册监听手机状态 -->
- <receiver android:name=".PhoneStatReceiver">
- <intent-filter android:priority="1000" >
- <action android:name="android.intent.action.PHONE_STATE" />
- </intent-filter>
- </receiver>
- </application>
- </manifest>
其实最到这里,整个拦截功能就已经实现了,但是呢,我们的首页也不能让它光秃秃的显示个Hello World!吧。所以,在MainActivity中,再给大家加点料,就是在listView中显示所有已经被拦截的电话号码,代码如下:
- import java.util.Map;
- import android.app.ListActivity;
- import android.content.Context;
- import android.content.SharedPreferences;
- import android.os.Bundle;
- import android.util.Log;
- import android.widget.ArrayAdapter;
- public class MainActivity extends ListActivity {
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- SharedPreferences phonenumSP = getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);
- Map map = phonenumSP.getAll();
- Object[] array = map.keySet().toArray();
- Log.v("tag",map.toString()+map.size());
- ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,array);
- setListAdapter(adapter);
- }
- }
好了,整个项目就完成了,我们可以拦截骚扰电话了,这只是一个小例子,你可以添加一些控制功能以更加人性化,比如开启和关闭拦截,可选的拦截时间段,给ListView添加点击事件使用户可以把拦截到的电话添加到通讯录等功能。
不过,这里只是完成了对来电的拦截功能,未对外拨电话进行拦截,下篇博客再写吧!
参考:http://blog.163.com/wu_zefeng/blog/static/1826291752011312114420975/
http://www.cotrun.net/blog/1572.html
Android 代码实现来电拦截的更多相关文章
- Android实战_来电拦截专家
1 项目演示: 2 代码演示: 1)MainActivity类代码: MainActivity类代码: package com.example.phoneinteceptor_one;import j ...
- 实现android手机来电拦截系统页面弹出自定义页面特效
如何实现android手机来电拦截系统页面弹出自定义页面特效, 首先: 我们需要注册一个监听来电的广播PhoneStateReceiver 类:其次: 在onReceive里面我们获取an ...
- Android监听来电和去电
要监听android打电话和接电话,只需下面2步骤1.第一步,写一个Receiver继承自BroadcastReceiver import android.app.Service; import an ...
- 下载最新Android代码的方法
之前我是去Android官方网站下载最新Android代码,但是这种方法需要FQ,而且有时候FQ又不太方便,今天我发现一个不错的网站,是清华大学搞的,跟Android官方的代码基本保持同步,而且下载方 ...
- Android代码混淆官方实现方法
首先查看一下 “project.properties” 这个文件: # This file is automatically generated by Android Tools.# Do not m ...
- 编写高效的Android代码
编写高效的Android代码 毫无疑问,基于Android平台的设备一定是嵌入式设备.现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远远比不上一 ...
- Android代码内存优化建议-OnTrimMemory优化
原文 http://androidperformance.com/2015/07/20/Android代码内存优化建议-OnTrimMemory优化/ OnTrimMemory 回调是 Androi ...
- Android代码混淆和项目宣布步骤记录器
原本放在一起Android项目与发布的文件相混淆.我突然想到,为什么不写博客,分享.有这篇文章的情况下,. Android代码混淆及项目公布步骤记录 一.清理代码中的调试信息,如Log.System. ...
- Android 代码混淆 混淆方案
本篇文章:自己在混淆的时候整理出比较全面的混淆方法,比较实用,自己走过的坑,淌出来的路.请大家不要再走回头路,可能只要我们代码加混淆,一点不对就会导致项目运行崩溃等后果,有许多人发现没有打包运行好好地 ...
随机推荐
- PIPESTATUS(bash) + pipefail(ksh)
I have two processes foo and bar, connected with a pipe: $ foo | bar bar always exits 0; I'm interes ...
- iOS 9音频应用播放音频之iOS 9音频播放进度
iOS 9音频应用播放音频之iOS 9音频播放进度 iOS 9音频应用开发播放进度 音频文件在播放后经过了多久以及还有多久才可以播放完毕,想必是用户所关注的问题.为了解决这一问题,在很多的音乐播放器中 ...
- 管理lvm 卷 system-storage-manager
安装 sudo yum install system-storage-manager [root@si-test-blueking--4 ~]# ssm list 创建物理磁盘到物理卷,<poo ...
- Django Restframework 实践(一)
具备以下知识: django http://www.cnblogs.com/menkeyi/p/5882464.html http://www.cnblogs.com/menkeyi/p/588245 ...
- property staticmathod classmethod 反射
使用@property 在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合逻 ...
- 【UOJ #204】【APIO 2016】Boat
http://uoj.ac/problem/204 肯定要离散化的,先离散化出\(O(n)\)个取值区间. 设\(f(i,j)\)表示第\(i\)所学校派出的划艇数量在\(j\)区间中. \(f(i, ...
- [BZOJ4444][SCOI2015]国旗计划(倍增)
链上是经典贪心问题,将线段全按左端点排序后把点全撒在线段右端点上.这里放到环上,倍长即可. 题目保证不存在区间包含情况,于是有一种暴力做法,先将战士的管辖区间按左端点从小到大排序,对于询问x,从x战士 ...
- HDU 5295 Unstable 计算几何
Unstable 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5295 Description Rasen had lost in labyrint ...
- winform中让pictureBox 显示的图片旋转
img.RotateFlip(RotateFlipType.Rotate90FlipNone);顺时针旋转90度 RotateFlipType.Rotate90FlipNone 逆时针旋转90度 Ro ...
- Python中进程无法结束的处理办法
1.方法一 http://hi.baidu.com/javalang/item/72fabf2359a30b464799625e 也就是说当线程使用start方法运行起来后,只有当run方法运行 ...