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>