Android 实现电话拦截及拦截提示音功能的开发

本文所讲的内容是在Android系统中如何写程序进行电话拦截,并发出拦截提示音提醒用户,可以说此功能还是比较实用的。

       1、电话拦截

这个功能大家可能都知道了,就是利用反射原理调用ITelephony的隐藏方法来实现。

       2、拦截后提示忙音/空号/已关机/已停机

这个功能其实是要用到MMI指令,具体如何设置呼叫转移的指定可以参考这里 http://baike.baidu.com/view/206402.html?fromTaglist。

在本文中我们会用到“遇忙转移”的功能。中国移动的设置方式是 **67#电话号码#,取消方式为 ##67#。”无条件转移“用21代替67即可。这两个指令可以直接在手机的拨号界面输入并拨号测试。ITelephony的endcall方法挂断电话后,会提示电话忙。如果事前设置好了忙时转移到一个空号/已关机/已停机的电话号码,就会提示您拨的电话号码是空号/已关机/已停机。

其实大家可以下载 xxx卫士看下,它设置来电拒接模式后,都是会启动设置MMI指令的界面。然后再去“设置->通话设置->来电转接”,看看 “占线时转接” 设置好的电话号码,就可以知道空号/已关机/已停机对应的电话号码是什么了。

  1、修改一下BLOCKED_NUMBER这个变量值,把它设置为你要测试拦截的电话号码。

  2、全部功能是在一个Activity里实现的,所以大家要先运行这个Activity,然后点击“设置呼叫转移”,设置好呼叫转移后,不要关闭这个Activity,关了就拦截不了电话了。有心的朋友可以自己去写一个Service在后台运行拦截功能。

实现方式1:

代码如下:

package net.toeach.android.callforwarding;   

import java.lang.reflect.Method;   

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;   

import com.android.internal.telephony.ITelephony;   

/**
 * 演示如何设置呼叫转移,拦截电话(拦截后提示为空号)的例子
 * @author Tony from ToEach.
 * @email wan1976@21cn.com
 */
public class MainActivity extends Activity {
 private static final String TAG = MainActivity.class.getSimpleName();   

 private final static int OP_REGISTER = 100;
 private final static int OP_CANCEL = 200;   

 private final static String BLOCKED_NUMBER = "1892501xxxx";//要拦截的号码
 //占线时转移,这里13800000000是空号,所以会提示所拨的号码为空号
  private final String ENABLE_SERVICE = "tel:**67*13800000000%23";
  //占线时转移
  private final String DISABLE_SERVICE = "tel:%23%2367%23";   

 private IncomingCallReceiver mReceiver;
  private ITelephony iTelephony;
  private AudioManager mAudioManager;   

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);   

    findViewById(R.id.btnEnable).setOnClickListener(new OnClickListener(){
  public void onClick(View v) {
     //设置呼叫转移
     Message message = mHandler.obtainMessage();
  message.what = OP_REGISTER;
  mHandler.dispatchMessage(message);
  }
    });   

    findViewById(R.id.btnDisable).setOnClickListener(new OnClickListener(){
  public void onClick(View v) {
  //取消呼叫转移
       Message message = mHandler.obtainMessage();
    message.what = OP_CANCEL;
    mHandler.dispatchMessage(message);
  }
    });   

    mReceiver = new IncomingCallReceiver();
 IntentFilter filter = new IntentFilter("android.intent.action.PHONE_STATE");
    registerReceiver(mReceiver, filter);// 注册BroadcastReceiver   

    mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);   

    //利用反射获取隐藏的endcall方法
    TelephonyManager telephonyMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
 try {
  Method getITelephonyMethod = TelephonyManager.class.getDeclaredMethod("getITelephony", (Class[]) null);
  getITelephonyMethod.setAccessible(true);
  iTelephony = (ITelephony) getITelephonyMethod.invoke(telephonyMgr, (Object[]) null);
   } catch (Exception e) {
   e.printStackTrace();
   }
  }   

  private Handler mHandler = new Handler() {
 public void handleMessage(Message response) {
   int what = response.what;
   switch(what) {
    case OP_REGISTER:{
    Intent i = new Intent(Intent.ACTION_CALL);
       i.setData(Uri.parse(ENABLE_SERVICE));
       startActivity(i);
    break;
    }
    case OP_CANCEL:{
    Intent i = new Intent(Intent.ACTION_CALL);
       i.setData(Uri.parse(DISABLE_SERVICE));
       startActivity(i);
    break;
    }
   }
 }
 };   

 private class IncomingCallReceiver extends BroadcastReceiver{
 @Override
 public void onReceive(Context context, Intent intent) {
  String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
     Log.i(TAG, "State: "+ state);   

  String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
     Log.d(TAG, "Incomng Number: " + number);   

     if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING)){//电话正在响铃
     if(number.equals(BLOCKED_NUMBER)){//拦截指定的电话号码
      //先静音处理
      mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
      Log.d(TAG, "Turn ringtone silent");   

      try {
      //挂断电话
   iTelephony.endCall();
   } catch (RemoteException e) {
   e.printStackTrace();
   }   

   //再恢复正常铃声
         mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
     }
     }
 }
 }
}  

AndroidManifest.xml 如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android "
   package="net.toeach.android.callforwarding"
   android:versionCode="1"
   android:versionName="1.0">
  <application android:icon="@drawable/icon" 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>  

  </application>
  <uses-sdk android:minSdkVersion="8" />  

  <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
  <uses-permission android:name="android.permission.CALL_PHONE"/>  

</manifest>   

  实现方式2:

1、建立包android.refuseCalling。

refuseCalling.java代码如下:

package android.refuseCalling;   

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;   

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;   

import android.content.Context;
import android.content.Intent;
import android.os.RemoteException;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.TextView;
import com.android.internal.telephony.ITelephony;   

public class refuseCalling extends Activity {   

  private static final String TAG = "Telephony";
  private TextView view = null;
  private TelephonyManager tManager = null;
  private ITelephony iTelephony = null;   

   //占线时转移,提示所拨的号码为空号
  private final String ENABLE_SERVICE = "tel:**67*13800000000%23";
   //占线时转移,提示所拨的号码为关机
  private final String ENABLE_POWEROFF_SERVICE = "tel:**67*13810538911%23";
  //占线时转移,提示所拨的号码为停机
  private final String ENABLE_STOP_SERVICE = "tel:**21*13701110216%23";   

  //占线时转移
  private final String DISABLE_SERVICE = "tel:%23%2321%23";   

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);   

    //打开监听电话功能
    TelephonyManager mTelephonyMgr = (TelephonyManager) this
        .getSystemService(Context.TELEPHONY_SERVICE);
    mTelephonyMgr.listen(new TeleListener(),
        PhoneStateListener.LISTEN_CALL_STATE);   

    //gui
    view = new TextView(this);
    view.setText("listen the state of phone\n");
    setContentView(view);   

    tManager = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
    //初始化iTelephony
    Class <TelephonyManager> c = TelephonyManager.class;
    Method getITelephonyMethod = null;
    try {
    getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[])null);
    getITelephonyMethod.setAccessible(true);
    } catch (SecurityException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (NoSuchMethodException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }   

    try {
    iTelephony = (ITelephony) getITelephonyMethod.invoke(tManager, (Object[])null);
    } catch (IllegalArgumentException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } catch (InvocationTargetException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }   

    //启用空号提示
    Intent i = new Intent(Intent.ACTION_CALL);
    i.setData(Uri.parse(ENABLE_STOP_SERVICE));
    startActivity(i);
    Log.v(TAG, "启用空号提示");
  }   

  class TeleListener extends PhoneStateListener {   

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {
      super.onCallStateChanged(state, incomingNumber);
      switch (state) {
      case TelephonyManager.CALL_STATE_IDLE: {
        Log.e(TAG, "CALL_STATE_IDLE");
        view.append("CALL_STATE_IDLE " + "\n");
        break;
      }
      case TelephonyManager.CALL_STATE_OFFHOOK: {
        Log.e(TAG, "CALL_STATE_OFFHOOK");
        view.append("CALL_STATE_OFFHOOK" + "\n");
        break;
      }
      case TelephonyManager.CALL_STATE_RINGING: {
        Log.e(TAG, "CALL_STATE_RINGING");
        view.append("CALL_STATE_RINGING" + "\n");
        try {
          iTelephony.endCall();
        } catch (RemoteException e1) {
          // TODO Auto-generated catch block
          e1.printStackTrace();
        }
        break;
      }
      default:
        break;
      }
    }
  }
  protected void onStop() {
    super.onStop();
    }
  protected void onDestroy() {
    super.onDestroy();
    finish();
    Intent i = new Intent(Intent.ACTION_CALL);
    i.setData(Uri.parse(DISABLE_SERVICE));
    startActivity(i);
    }
}  

2、建立包android.telephony。

NeighboringCellInfo.aidl代码如下:

package android.telephony;

3、建立包 com.android.internal.telephony。

ITelephony.aidl代码如下:

/*
 *
 * Licensed under the android License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */  

package com.android.internal.telephony;   

import android.os.Bundle;
import java.util.List;
import android.telephony.NeighboringCellInfo;
//import com.FrameSpeed.NeighboringCellInfo;   

/**
 * Interface used to interact with the phone. Mostly this is used by the
 * TelephonyManager class. A few places are still using this directly.
 * Please clean them up if possible and use TelephonyManager insteadl.
 *
 * {@hide}
 */
interface ITelephony {   

  /**
   * Dial a number. This doesn't place the call. It displays
   * the Dialer screen.
   * @param number the number to be dialed. If null, this
   * would display the Dialer screen with no number pre-filled.
   */
  void dial(String number);
/**
   * Place a call to the specified number.
   * @param number the number to be called.
   */
  void call(String number);   

  /**
   * If there is currently a call in progress, show the call screen.
   * The DTMF dialpad may or may not be visible initially, depending on
   * whether it was up when the user last exited the InCallScreen.
   *
   * @return true if the call screen was shown.
   */
  boolean showCallScreen();   

  /**
   * Variation of showCallScreen() that also specifies whether the
   * DTMF dialpad should be initially visible when the InCallScreen
   * comes up.
   *
   * @param showDialpad if true, make the dialpad visible initially,
   *          otherwise hide the dialpad initially.
   * @return true if the call screen was shown.
   *
   * @see showCallScreen
   */
  boolean showCallScreenWithDialpad(boolean showDialpad);   

  /**
   * End call if there is a call in progress, otherwise does nothing.
   *
   * @return whether it hung up
   */
  boolean endCall();   

  /**
   * Answer the currently-ringing call.
   *
   * If there's already a current active call, that call will be
   * automatically put on hold. If both lines are currently in use, the
   * current active call will be ended.
   *
   * TODO: provide a flag to let the caller specify what policy to use
   * if both lines are in use. (The current behavior is hardwired to
   * "answer incoming, end ongoing", which is how the CALL button
   * is specced to behave.)
   *
   * TODO: this should be a oneway call (especially since it's called
   * directly from the key queue thread).
   */
  void answerRingingCall();   

  /**
   * Silence the ringer if an incoming call is currently ringing.
   * (If vibrating, stop the vibrator also.)
   *
   * It's safe to call this if the ringer has already been silenced, or
   * even if there's no incoming call. (If so, this method will do nothing.)
   *
   * TODO: this should be a oneway call too (see above).
   *    (Actually *all* the methods here that return void can
   *    probably be oneway.)
   */
  void silenceRinger();   

  /**
   * Check if we are in either an active or holding call
   * @return true if the phone state is OFFHOOK.
   */
  boolean isOffhook();   

  /**
   * Check if an incoming phone call is ringing or call waiting.
   * @return true if the phone state is RINGING.
   */
  boolean isRinging();   

  /**
   * Check if the phone is idle.
   * @return true if the phone state is IDLE.
   */
  boolean isIdle();   

  /**
   * Check to see if the radio is on or not.
   * @return returns true if the radio is on.
   */
  boolean isRadioOn();   

  /**
   * Check if the SIM pin lock is enabled.
   * @return true if the SIM pin lock is enabled.
   */
  boolean isSimPinEnabled();   

  /**
   * Cancels the missed calls notification.
   */
  void cancelMissedCallsNotification();   

  /**
   * Supply a pin to unlock the SIM. Blocks until a result is determined.
   * @param pin The pin to check.
   * @return whether the operation was a success.
   */
  boolean supplyPin(String pin);   

   /**
   * [ASD2-ES1|Connice|2011.04.14]
   */
  boolean supplyPuk(String puk, String pin);   

  /**
   * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
   * without SEND (so <code>dial</code> is not appropriate).
   *
   * @param dialString the MMI command to be executed.
   * @return true if MMI command is executed.
   */
  boolean handlePinMmi(String dialString);
/**
   * Toggles the radio on or off.
   */
  void toggleRadioOnOff();   

  /**
   * Set the radio to on or off
   */
  boolean setRadio(boolean turnOn);   

  /**
   * Request to update location information in service state
   */
  void updateServiceLocation();   

  /**
   * Enable location update notifications.
   */
  void enableLocationUpdates();   

  /**
   * Disable location update notifications.
   */
  void disableLocationUpdates();   

  /**
   * Enable a specific APN type.
   */
  int enableApnType(String type);   

  /**
   * Disable a specific APN type.
   */
  int disableApnType(String type);   

  /**
   * Allow mobile data connections.
   */
  boolean enableDataConnectivity();   

  /**
   * Disallow mobile data connections.
   */
  boolean disableDataConnectivity();   

  /**
   * Report whether data connectivity is possible.
   */
  boolean isDataConnectivityPossible();   

  Bundle getCellLocation();   

  /**
   * Returns the neighboring cell information of the device.
   */
  List<NeighboringCellInfo> getNeighboringCellInfo();   

   int getCallState();
   int getDataActivity();
   int getDataState();   

  /**
   * Returns the current active phone type as integer.
   * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
   * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
   */
  int getActivePhoneType();   

  /**
   * Returns the CDMA ERI icon index to display
   */
  int getCdmaEriIconIndex();   

  /**
   * Returns the CDMA ERI icon mode,
   * 0 - ON
   * 1 - FLASHING
   */
  int getCdmaEriIconMode();   

  /**
   * Returns the CDMA ERI text,
   */
  String getCdmaEriText();   

  /**
   * Returns true if OTA service provisioning needs to run.
   * Only relevant on some technologies, others will always
   * return false.
   */
  boolean needsOtaServiceProvisioning();   

  /**
   * Returns the unread count of voicemails
   */
  int getVoiceMessageCount();   

  /**
   * Returns the network type
   */
  int getNetworkType();   

  /**
   * Return true if an ICC card is present
   */
  boolean hasIccCard();
}   

parcelable NeighboringCellInfo; 

4、AndroidManifest.xml代码如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="android.refuseCalling"
   android:versionCode="1"
   android:versionName="1.0">
   <uses-permission android:name="android.permission.READ_PHONE_STATE" />
   <uses-permission android:name="android.permission.CALL_PHONE" />
   <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />        

  <application android:icon="@drawable/icon" android:label="@string/app_name">
    <activity android:name=".refuseCalling"
         android:label="@string/app_name">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
    </activity>  

  </application>
</manifest>  

希望通过此文能对开发Android 开发电话应用的朋友提供帮助,谢谢大家对本站的支持!

(0)

相关推荐

  • Android仿微信新消息提示音

    怕有些人不知道怎么进入微信的新消息提示音功能,我这里说下操作步骤: 打开微信----我---设置---新消息提醒---新消息提示音. 经过以上的步骤就进入了这样的界面 具体实现的步骤. 难点之一:获取到手机系统的提示音,并将它们显示在一个listview里面. 参考如下代码: // 获得RingtoneManager对象 RingtoneManager manager = new RingtoneManager(this); // 设置RingtoneManager对象的类型为TYPE_NOTI

  • android开发之蜂鸣提示音和震动提示的实现原理与参考代码

    最近在读zxing项目,学到了不少东西.推荐大家也读读.里面有个BeepManager类,实现一个蜂鸣音和震动的实现.我们一起来看看他是怎么做的: 蜂鸣 1.准备一个 音频文件 比如:beep.ogg. ogg格式是声音压缩格式的一种,类似mp3这样.我们准备播放它,就产生了蜂鸣的效果. 2.为activity注册的默认 音频通道 . activity.setVolumeControlStream(AudioManager.STREAM_MUSIC); 这里声明为 STREAM_MUSIC的通道

  • Android震动与提示音实现代码

    本文实例为大家分享了android消息提示的具体代码,供大家参考,具体内容如下 protected AudioManager audioManager; protected Vibrator vibrator; audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE); //此方法是由Context调用的 vibrator = (Vibrator)getSystemService(Context.VIBRATOR_S

  • Android 实现电话拦截及拦截提示音功能的开发

    本文所讲的内容是在Android系统中如何写程序进行电话拦截,并发出拦截提示音提醒用户,可以说此功能还是比较实用的.        1.电话拦截 这个功能大家可能都知道了,就是利用反射原理调用ITelephony的隐藏方法来实现.        2.拦截后提示忙音/空号/已关机/已停机 这个功能其实是要用到MMI指令,具体如何设置呼叫转移的指定可以参考这里 http://baike.baidu.com/view/206402.html?fromTaglist. 在本文中我们会用到"遇忙转移&qu

  • Android开发实现的电话窃听和拦截应用

    本文实例讲述了Android开发实现的电话窃听和拦截应用.分享给大家供大家参考,具体如下: 今天学习了进程间Service的通信-->AIDL,基于前几天学习的广播机制,我做了一个简单的电话窃听和录音应用.现将具体实现方法附在下面,供大家参考,希望大家提供一些宝贵的意见. 业务需求分析: 1.当手机处于开机状态,监听服务就要启动,对来电进行监听录音. 2.设置电话黑名单,当来电是黑名单电话,则直接挂断. 实现步骤: 首先我们要定义一个电话监听的服务,对来电进行监听录音和拦截.具体代码如下: Ph

  • Android 实现手机接通电话后振动提示的功能

    有些手机在电话接通后会有振动提示,这有个好处就是可以等到接通后再放到耳边接听,减少辐射.本文就讲讲如何在Android手机中实现这种接通电话后的振动提示功能,这里主要针对拨出的电话.      Android SDK提供的通话状态 很明显,要在电话接通的时候产生振动提示,首先需要知道电话在何时被接通.而Android SDK并没有给出直接读取这种状态的方法.下面是Android SDK的电话服务类TelephonyManager提供的三种电话状态: CALL_STATE_IDLE        

  • android 震动和提示音的实现代码

    android的消息提示(震动和提示音),实现代码如下所示: public class VibratorUtil { protected AudioManager audioManager; protected Vibrator vibrator; private Ringtone ringtone; private static final int MIN_TIME_OUT = 4000; //时间间隔 long lastNotificationTime; public VibratorUti

  • Android实现WebView点击拦截跳转原生

    1. 首先设置Web视图 webview.setWebViewClient(new MyWebViewClient()); webview1.setWebViewClient(new MyWebViewClient()); 2. 拦截点击的链接,跳转到对应的页面 // 监听 所有点击的链接,如果拦截到我们需要的,就跳转到相对应的页面. private class MyWebViewClient extends WebViewClient { @Override public boolean sh

  • 在Android环境下WebView中拦截所有请求并替换URL示例详解

    需求背景 接到这样一个需求,需要在 WebView 的所有网络请求中,在请求的url中,加上一个xxx=1的标志位. 例如 http://www.baidu.com 加上标志位就变成了 http://www.baidu.com?xxx=1 寻找解决方案 从 Android API 11 (3.0) 开始,WebView 开始在 WebViewClient 内提供了这样一条 API ,如下: public WebResourceResponse shouldInterceptRequest(Web

  • AngularJS使用拦截器实现的loading功能完整实例

    本文实例讲述了AngularJS使用拦截器实现的loading功能.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html lang="zh-CN" ng-app="myApp"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge

  • IOS 播放系统提示音使用总结(AudioToolbox)

    IOS 播放系统提示音使用总结(AudioToolbox) 开发过程中需要用到苹果自带的系统提示音,下面我总结了一下关于系统提示音播放的方法 第一步首先得导入AudioToolbox框架 #import <AudioToolbox/AudioToolbox.h> 播放系统自带的提示声 播放系统自带的提示声很简单,只需要两行代码就能搞定了: //定义一个SystemSoundID SystemSoundID soundID = 1000;//具体参数详情下面贴出来 //播放声音 AudioSer

随机推荐