android 上层电话状态的监听

1,概述

做开发时,有时完全不利用Dialer.apk来开发拨号等功能,如何拨打/接听/挂断电话呢?电话来了又怎么知道呢?现在分为2个部分一一到来。首先是拨打/接听/挂断等电话操作,然后监听电话的状态,并进行相应的处理,本文基于Android 5.1.

 2, 电话操作

2.1 拨号

拨号最简单了,直接发个广播就可以了

private String callnumber = “10086”; // 比如 给移动客服打电话
   Uri uri = getCallUri(callnumber); // 将所拨号码进行格式化
   Intent intentd = new Intent();
   intentd.setAction(Intent.ACTION_CALL);
	 intentd.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
	 intentd.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION);
	 intentd.setData(uri);
	 startActivity(intentd);

public static Uri getCallUri(String number) {
        if (number != null && (number.contains("@") || number.contains("%40"))) {
             return Uri.fromParts("sip", number, null);
        }
        return Uri.fromParts("tel", number, null);
     }


2.2 挂断

利用反射机制调用telephonyManager的endCall方法进行挂断。

private Object telephonyObject = null;
TelephonyManager telephonyManager = 
        (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		
		Class telManager = telephonyManager.getClass();
		Method getITelephony = null;
		try {
			try {
				getITelephony = telManager
						.getDeclaredMethod("getITelephony");
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			getITelephony.setAccessible(true);
			telephonyObject = getITelephony.invoke(telephonyManager);
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			if (null != telephonyObject) {
				Class telephonyClass = telephonyObject.getClass();
                 Method endCallMethod = telephonyClass.getMethod("endCall");
				endCallMethod.setAccessible(true); 
				endCallMethod.invoke(telephonyObject);
			}
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}


 

2.3 接听

实现接听有多种方法,和上小节的挂断操作一样,可以直接利用反射机制来进行接听;还有一种方法利用按键事件这个接口,通过发送广播的形式,实现接听。

try {
			Runtime.getRuntime().exec("input keyevent " + Integer
					.toString(KeyEvent.KEYCODE_HEADSETHOOK));
		} catch (IOException e) {
			String enforcedPerm = "android.permission.CALL_PRIVILEGED";
			Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON)
					.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(
							KeyEvent.ACTION_DOWN,
							KeyEvent.KEYCODE_HEADSETHOOK));
			Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON)
					.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(
							KeyEvent.ACTION_UP,
							KeyEvent.KEYCODE_HEADSETHOOK));

			sendOrderedBroadcast(btnDown, enforcedPerm);
			sendOrderedBroadcast(btnUp, enforcedPerm);
		}


 

3, 电话状态的监听

import java.lang.reflect.Method;

import android.app.Activity;
import android.app.Dialog;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.TextView;

public class PhoneBroadcastReceiver extends BroadcastReceiver   {

	private static final String TAG = "message";
    private static boolean mIncomingFlag = false;
    private static String mIncomingNumber = null;
    private static boolean callover = false;
    
    @Override
    public void onReceive(Context context, Intent intent) {
       if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {// 如果是拨打电话
            mIncomingFlag = false;
            String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
        } else {
            TelephonyManager tManager = (TelephonyManager) 
                  context.getSystemService(Service.TELEPHONY_SERVICE);
            switch (tManager.getCallState()) {
            case TelephonyManager.CALL_STATE_RINGING:  //来电状态
                mIncomingNumber = intent.getStringExtra("incoming_number");
                •••                }
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK: //摘机状态(接听)
            	 mIncomingNumber = intent.getStringExtra("incoming_number");
                   callover = true;
                  •••
                break;
            case TelephonyManager.CALL_STATE_IDLE:// 空闲状态,没有任何活动。(挂断)
            	android.util.Log.d("fangc", " mIncomingNumber " + "guaduan");
                if (mIncomingFlag||callover) {
                  mIncomingFlag = false;
                	callover = false;
                  •••                
                }
                break;
            }
        }
        
    }
	
}


在这四个状态中,可以分别添加一些boolean值来确定是拨号/来电还是挂断,接听等状态,然后在里面分别进行不同的处理。

 

4, 结尾

最后不要忘记了在AdnroidManifest.xml 文件中添加相关权限

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


PhoneBroadcastReceiver类一定要注册静态广播,而不是动态广播。

<receiver android:name=".PhoneBroadcastReceiver">
            <intent-filter android:priority="1000">
                <action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
                <action android:name="android.intent.action.PHONE_STATE"/>   
            </intent-filter>
        </receiver>


 

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值