Android提供的系统服务之--TelephonyManager(电话管理器)
Android提供的系统服务之--TelephonyManager(电话管理器)
转载请注明出处——coder-pig
TelephonyManager的作用:
用于管理手机通话状态,获取电话信息(设备信息、sim卡信息以及网络信息),
侦听电话状态(呼叫状态服务状态、信号强度状态等)以及能够调用电话拨号器拨打电话!
怎样获得TelephonyManager的服务对象:
TelephonyManager tManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
TelephonyManager的相关使用方法实例:
1.调用拨号器拨打电话号码:
Uri uri=Uri.parse("tel:"+电话号码); Intent intent=new Intent(Intent.ACTION_DIAL,uri); startActivity(intent);
ps:调用的是系统的拨号界面哦!
2.获取Sim卡信息与网络信息
执行效果图:(模拟器下获取不了相关信息的哦,这里用的是真机哈!)
代码实现流程:
1.定义了一个存储状态名称的array.xml的数组资源文件。
2.布局定义了一个简单的listview,列表项是两个水平方向的textview
3.Activity界面中调用相关方法获得相应參数的值,再把数据绑定到listview上!
具体代码例如以下:
array.xml:
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- 声明一个名为statusNames的字符串数组 --> <string-array name="statusNames"> <item>设备编号</item> <item>软件版本号</item> <item>网络运营商代号</item> <item>网络运营商名称</item> <item>手机制式</item> <item>设备当前位置</item> <item>SIM卡的国别</item> <item>SIM卡序列号</item> <item>SIM卡状态</item> </string-array> <!-- 声明一个名为simState的字符串数组 --> <string-array name="simState"> <item>状态未知</item> <item>无SIM卡</item> <item>被PIN加锁</item> <item>被PUK加锁</item> <item>被NetWork PIN加锁</item> <item>已准备好</item> </string-array> <!-- 声明一个名为phoneType的字符串数组 --> <string-array name="phoneType"> <item>未知</item> <item>GSM</item> <item>CDMA</item> </string-array> </resources>
activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/LinearLayout1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.jay.example.getphonestatus.MainActivity" > <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/statuslist" /> </LinearLayout>
line.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:width="230px" android:textSize="16dp" /> <TextView android:id="@+id/value" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="8px" android:textSize="16dp" /> </LinearLayout>
MainActivity.java
package com.jay.example.getphonestatus; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.telephony.TelephonyManager; import android.widget.ListView; import android.widget.SimpleAdapter; public class MainActivity extends Activity { //定义一个ListView对象,一个代表状态名称的数组,以及手机状态的集合 private ListView showlist; private String[] statusNames; private ArrayList<String> statusValues = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); showlist = (ListView) findViewById(R.id.statuslist); //①获得系统提供的TelphonyManager对象的实例 TelephonyManager tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); //②获得状态名词的数组,Sim卡状态的数组,电话网络类型的数组 //就是获得array.xml中的相应数组名的值 statusNames = getResources().getStringArray(R.array.statusNames); String[] simState = getResources().getStringArray(R.array.simState); String[] phoneType = getResources().getStringArray(R.array.phoneType); //③依照array.xml中的顺序,调用相应的方法,将相应的值保存到集合里 statusValues.add(tManager.getDeviceId()); //获得设备编号 //获取系统平台的版本号 statusValues.add(tManager.getDeviceSoftwareVersion() != null? tManager.getDeviceSoftwareVersion():"未知"); statusValues.add(tManager.getNetworkOperator()); //获得网络运营商代号 statusValues.add(tManager.getNetworkOperatorName()); //获得网络运营商的名称 statusValues.add(phoneType[tManager.getPhoneType()]); //获得手机的网络类型 // 获取设备所在位置 statusValues.add(tManager.getCellLocation() != null ? tManager .getCellLocation().toString() : "未知位置"); statusValues.add(tManager.getSimCountryIso()); // 获取SIM卡的国别 statusValues.add(tManager.getSimSerialNumber()); // 获取SIM卡序列号 statusValues.add(simState[tManager.getSimState()]); // 获取SIM卡状态 //④遍历状态的集合,把状态名与相应的状态加入到集合中 ArrayList<Map<String, String>> status = new ArrayList<Map<String, String>>(); for (int i = 0; i < statusValues.size(); i++) { HashMap<String, String> map = new HashMap<String, String>(); map.put("name", statusNames[i]); map.put("value", statusValues.get(i)); status.add(map); } //⑤使用SimpleAdapter封装List数据 SimpleAdapter adapter = new SimpleAdapter(this, status, R.layout.line, new String[] { "name", "value" } , new int[] { R.id.name, R.id.value }); // 为ListView设置Adapter showlist.setAdapter(adapter); } }
最后别忘了,往AndroidManifest.xml文件里加入下述权限哦!
<!-- 加入訪问手机位置的权限 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <!-- 加入訪问手机状态的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
3.监听手机的全部来电:
对于监听到的通话记录结果,你能够採取不同的方式获取到,这里用到的是把通话记录写入到文件里,
而你也能够以短信的形式发送给你,或者是上传到某个平台,当然假设通信记录不多的话还能够用短信
多了的话就非常easy给人发现的了。
另外,这里用的是Activity而非Service,就是说要打开这个Activity,才干够进行监听,通常我们的需求都是
要偷偷滴在后台跑的,由于时间关系就不写Service的了,大家自己写写吧,让Service随开机一起启动就可以!
代码解析:
非常easy,事实上就是重写TelephonyManager的一个通话状态监听器PhoneStateListener
然后调用TelephonyManager.listen()的方法进行监听,当来电的时候,
程序就会将来电号码记录到文件里
MainActivity.java:
package com.jay.PhoneMonitor; import java.io.FileNotFoundException; import java.io.OutputStream; import java.io.PrintStream; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import java.util.Date; public class MainActivity extends Activity { TelephonyManager tManager; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // 取得TelephonyManager对象 tManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); // 创建一个通话状态监听器 PhoneStateListener listener = new PhoneStateListener() { @Override public void onCallStateChanged(int state, String number) { switch (state) { // 无不论什么状态 case TelephonyManager.CALL_STATE_IDLE: break; case TelephonyManager.CALL_STATE_OFFHOOK: break; // 来电铃响时 case TelephonyManager.CALL_STATE_RINGING: OutputStream os = null; try { os = openFileOutput("phoneList", MODE_APPEND); } catch (FileNotFoundException e) { e.printStackTrace(); } PrintStream ps = new PrintStream(os); // 将来电号码记录到文件里 ps.println(new Date() + " 来电:" + number); ps.close(); break; default: break; } super.onCallStateChanged(state, number); } }; // 监听电话通话状态的改变 tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE); } }
当然还须要在AndroidManifest.xml中加入以下的权限:
<!-- 授予该应用读取通话状态的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
执行效果:
注意!要让这个程序位于前台哦!用还有一个电话拨打该电话,接着就能够在DDMS的file Explorer的应用
相应包名的files文件夹下看到phoneList的文件了,我们能够将他导出到电脑中打开,文件的大概内容例如以下:
THR Oct 30 12:05:48 GMT 2014 来电: 137xxxxxxx
4.黑名单来电自己主动挂断:
所谓的黑名单就是将一些电话号码加入到一个集合中,当手机接收到这些电话的时候就直接挂断!
可是Android并没有给我们提供挂断电话的API,于是乎我们须要通过AIDL来调用服务中的API来
实现挂断电话!
于是乎第一步要做的就是把android源代码中的以下两个文件拷贝到src下的对应位置,他们各自是:
com.android.internal.telephony包下的ITelephony.aidl;
android.telephony包下的NeighboringCellInfo.aidl;
要创建相应的包哦!就是要把aidl文件放到上面的包下!!!
接着仅仅须要调用ITelephony的endCall就可以挂断电话!
这里给出的是简单的单个号码的拦截,输入号码,点击屏蔽button后,假设此时屏蔽的电话呼入的话;
直接会挂断,代码还是比較简单的,以下粘一下,由于用的模拟器是Genymotion,所以就不演示
程序执行后的截图了!
MainActivity.java:
package com.jay.example.locklist; import java.lang.reflect.Method; import com.android.internal.telephony.ITelephony; import android.app.Activity; import android.os.Bundle; import android.os.IBinder; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; public class MainActivity extends Activity { private TelephonyManager tManager; private PhoneStateListener pListener; private String number; private EditText locknum; private Button btnlock; public class PhonecallListener extends PhoneStateListener { @Override public void onCallStateChanged(int state, String incomingNumber) { switch(state) { case TelephonyManager.CALL_STATE_IDLE:break; case TelephonyManager.CALL_STATE_OFFHOOK:break; //当有电话拨入时 case TelephonyManager.CALL_STATE_RINGING: if(isBlock(incomingNumber)) { try { Method method = Class.forName("android.os.ServiceManager") .getMethod("getService", String.class); // 获取远程TELEPHONY_SERVICE的IBinder对象的代理 IBinder binder = (IBinder) method.invoke(null, new Object[] { TELEPHONY_SERVICE }); // 将IBinder对象的代理转换为ITelephony对象 ITelephony telephony = ITelephony.Stub.asInterface(binder); // 挂断电话 telephony.endCall(); }catch(Exception e){e.printStackTrace();} } break; } super.onCallStateChanged(state, incomingNumber); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); locknum = (EditText) findViewById(R.id.locknum); btnlock = (Button) findViewById(R.id.btnlock); //获取系统的TelephonyManager管理器 tManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); pListener = new PhoneStateListener(); tManager.listen(pListener, PhoneStateListener.LISTEN_CALL_STATE); btnlock.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { number = locknum.getText().toString(); } }); } public boolean isBlock(String phone) { if(phone.equals(number))return true; return false; } }
另外还须要加入下述的权限:
<!-- 授予该应用控制通话的权限 --> <uses-permission android:name="android.permission.CALL_PHONE" /> <!-- 授予该应用读取通话状态的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
当然,很多其它的时候我们屏蔽的不会仅仅是一个号码,这个时候能够使用集合,把多个要屏蔽的号码加入到
集合中,或者是文件里,这里就直接给出李刚老师的demo,他提供的是一个带复选框的列表供用户
勾选黑名单,这里就不解析了,直接给出代码下载吧!
单个号码拦截的demo:点击下载
李刚老师的列表黑名单拦截demo:点击下载
TelephonyManager的相关属性与方法:
Constants
String |
ACTION_PHONE_ STATE_CHANGED |
Broadcast intent action indicating that the call state (cellular) on the device has changed. |
int |
CALL_STATE_IDLE |
Device call state: No activity. 空暇(无呼入或已挂机) |
int |
CALL_STATE_OFFHOOK |
Device call state: Off-hook. 摘机(有呼入) |
int |
CALL_STATE_RINGING |
Device call state: Ringing. 响铃(接听中) |
int |
DATA_ACTIVITY_DORMANT |
Data connection is active, but physical link is down 电话数据活动状态类型:睡眠模式(3.1版本号) |
int |
DATA_ACTIVITY_IN |
Data connection activity: Currently receiving IP PPP traffic. 电话数据活动状态类型:数据流入 |
int |
DATA_ACTIVITY_INOUT |
Data connection activity: Currently both sending and receiving IP PPP traffic.电话数据活动状态类型:数据交互 |
int |
DATA_ACTIVITY_NONE |
Data connection activity: No traffic. 电话数据活动状态类型:无数据流动 |
int |
DATA_ACTIVITY_OUT |
Data connection activity: Currently sending IP PPP traffic. 电话数据活动状态类型:数据流出 |
int |
DATA_CONNECTED |
Data connection state: Connected. 数据连接状态类型:已连接 |
int |
DATA_CONNECTING |
Data connection state: Currently setting up a data connection. 数据连接状态类型:正在连接 |
int |
DATA_DISCONNECTED |
Data connection state: Disconnected. 数据连接状态类型:断开 |
int |
DATA_SUSPENDED |
Data connection state: Suspended. 数据连接状态类型:已暂停 |
String |
EXTRA_INCOMING_NUMBER |
The lookup key used with the ACTION_PHONE_STATE_CHANGED broadcast for a String containing the incoming phone number. |
String |
EXTRA_STATE |
The lookup key used with the ACTION_PHONE_STATE_CHANGED broadcast for a String containing the new call state. |
int |
NETWORK_TYPE_1xRTT |
Current network is 1xRTT |
int |
NETWORK_TYPE_CDMA |
Current network is CDMA: Either IS95A or IS95B |
int |
NETWORK_TYPE_EDGE |
Current network is EDGE |
int |
NETWORK_TYPE_EHRPD |
Current network is eHRPD |
int |
NETWORK_TYPE_EVDO_0 |
Current network is EVDO revision 0 |
int |
NETWORK_TYPE_EVDO_A |
Current network is EVDO revision A |
int |
NETWORK_TYPE_EVDO_B |
Current network is EVDO revision B |
int |
NETWORK_TYPE_GPRS |
Current network is GPRS |
int |
NETWORK_TYPE_HSDPA |
Current network is HSDPA |
int |
NETWORK_TYPE_HSPA |
Current network is HSPA |
int |
NETWORK_TYPE_HSPAP |
Current network is HSPA+ |
int |
NETWORK_TYPE_HSUPA |
Current network is HSUPA |
int |
NETWORK_TYPE_IDEN |
Current network is iDen |
int |
NETWORK_TYPE_LTE |
Current network is LTE |
int |
NETWORK_TYPE_UMTS |
Current network is UMTS |
int |
NETWORK_TYPE_UNKNOWN |
Network type is unknown |
int |
PHONE_TYPE_CDMA |
Phone radio is CDMA. |
int |
PHONE_TYPE_GSM |
Phone radio is GSM. |
int |
PHONE_TYPE_NONE |
No phone radio. |
int |
PHONE_TYPE_SIP |
Phone is via SIP. |
int |
SIM_STATE_ABSENT |
SIM card state: no SIM card is available in the device |
int |
SIM_STATE_NETWORK_LOCKED |
SIM card state: Locked: requries a network PIN to unlock |
int |
SIM_STATE_PIN_REQUIRED |
SIM card state: Locked: requires the user's SIM PIN to unlock |
int |
SIM_STATE_PUK_REQUIRED |
SIM card state: Locked: requires the user's SIM PUK to unlock |
int |
SIM_STATE_READY |
SIM card state: Ready |
int |
SIM_STATE_UNKNOWN |
SIM card state: Unknown. |
F ields
public static final String |
EXTRA_STATE_IDLE |
Value used with EXTRA_STATE corresponding to CALL_STATE_IDLE. |
public static final String |
EXTRA_STATE_OFFHOOK |
Value used with EXTRA_STATE corresponding to CALL_STATE_OFFHOOK. |
public static final String |
EXTRA_STATE_RINGING |
Value used with EXTRA_STATE corresponding to CALL_STATE_RINGING. |
Public Methods
int |
getCallState() |
Returns a constant indicating the call state (cellular) on the device. |
CellLocation |
getCellLocation() |
Returns the current location of the device. |
int |
getDataActivity() |
Returns a constant indicating the type of activity on a data connection (cellular). 处理侦測到的数据活动的改变事件。通过该函数,能够获取数据活动状态信息。 电话数据活动状态类型定义在TelephoneyManager类中。 DATA_ACTIVITY_NONE 无数据流动 |
int |
getDataState() |
Returns a constant indicating the current data connection state (cellular). |
String |
getDeviceId() |
Returns the unique device ID, for example, the IMEI for GSM and the MEID or ESN for C DMA phones.获取设备标识(IMEI) |
String |
getDeviceSoftwareVersion() |
Returns the software version number for the device, for example, the IMEI/SV for GSM p hones.获得软件版本号 |
String |
getLine1Number() |
Returns the phone number string for line 1, for example, the MSISDN for a GSM phone. 线路1的电话号码 |
List<NeighboringCel lInfo> |
getNeighboringCellInfo() |
Returns the neighboring cell information of the device. |
String |
getNetworkCountryIso() |
Returns the ISO country code equivalent of the current registered operator's MCC (Mobile Country Code).获取网络的国家ISO代码 |
String |
getNetworkOperator() |
Returns the numeric name (MCC+MNC) of current registered operator. 获取SIM移动国家代码(MCC)和移动网络代码(MNC) |
String |
getNetworkOperatorName() |
Returns the alphabetic name of current registered operator. 获取服务提供商姓名(中国移动、中国联通等) |
int |
getNetworkType() |
Returns a constant indicating the radio technology (network type) currently in use on the device for data transmission. 获取网络类型 NETWORK_TYPE_UNKNOWN 未知网络 |
int |
getPhoneType() |
Returns a constant indicating the device phone type. 电话类型 PHONE_TYPE_NONE 未知 |
String |
getSimCountryIso() |
Returns the ISO country code equivalent for the SIM provider's country code. 获取SIM卡中国家ISO代码 |
String |
getSimOperator() |
Returns the MCC+MNC (mobile country code + mobile network code) of the provider of the SIM.获 得SIM卡中移动国家代码(MCC)和移动网络代码(MNC) |
String |
getSimOperatorName() |
Returns the Service Provider Name (SPN). 获取服务提供商姓名(中国移动、中国联通等) |
String |
getSimSerialNumber() |
Returns the serial number of the SIM, if applicable. SIM卡序列号 |
int |
getSimState() |
Returns a constant indicating the state of the device SIM card. SIM卡状态 SIM_STATE_UNKNOWN 未知状态 当中:PIN个人识别码 PUK个人解锁码 |
String |
getSubscriberId() |
Returns the unique subscriber ID, for example, the IMSI for a GSM phone. 获得客户标识(IMSI) |
String |
getVoiceMailAlphaTag() |
Retrieves the alphabetic identifier associated with the voice mail number. |
String |
getVoiceMailNumber() |
Returns the voice mail number. |
boolean |
hasIccCard() |
|
boolean |
isNetworkRoaming() |
Returns true if the device is considered roaming on the current network, for GSM purposes. |
void |
listen(PhoneStateListener listener, int events) |
Registers a listener object to receive notification of changes in specified telephony states. 侦听电话的呼叫状态。电话管理服务接口支持的侦听类型在PhoneStateListener类中定义。 |
PhoneStateListener类
Constants
int |
LISTEN_CALL_FORWARDING_INDICATOR |
Listen for changes to the call-forwarding indicator. 侦听呼叫转移指示器改变事件 |
int |
LISTEN_CALL_STATE |
Listen for changes to the device call state. 侦听呼叫状态改变事件 |
int |
LISTEN_CELL_LOCATION |
Listen for changes to the device's cell location. Note that this will result in frequent callbacks to the listener.侦听设备位置改变事件 |
int |
LISTEN_DATA_ACTIVITY |
Listen for changes to the direction of data traffic on the data connection (cellular).侦听数据连接的流向改变事件 |
int |
LISTEN_DATA_CONNECTION_STATE |
Listen for changes to the data connection state (cellular). 侦听数据连接状态改变事件 |
int |
LISTEN_MESSAGE_WAITING_INDICATOR |
Listen for changes to the message-waiting indicator. 侦听消息等待指示器改变事件 |
int |
LISTEN_NONE |
Stop listening for updates. 停止侦听 |
int |
LISTEN_SERVICE_STATE |
Listen for changes to the network service state (cellular). 侦听网络服务状态 |
int |
LISTEN_SIGNAL_STRENGTH |
This constant is deprecated. by LISTEN_SIGNAL_STRENGTHS 侦听网络信号强度 |
int |
LISTEN_SIGNAL_STRENGTHS |
Listen for changes to the network signal strengths (cellular). |
Public Constructors
PhoneStateListener()
Public Methods
void |
onCallForwardingIndicatorChanged(boolean cfi) |
Callback invoked when the call-forwarding indicator changes. |
void |
onCallStateChanged(int state, String incomingNumber) |
Callback invoked when device call state changes. 处理侦測到的电话呼叫状态的改变事件。通过该回调事件。能够获取来电号码。 并且能够获取电话呼叫状态。 即用switch(state){case TelephoneManager.CALL_STATE_……}来推断 |
void |
onCellLocationChanged(CellLocation location) |
Callback invoked when device cell location changes. |
void |
onDataActivity(int direction) |
Callback invoked when data activity state changes. |
void |
onDataConnectionStateChanged(int state) |
Callback invoked when connection state changes. |
void |
onDataConnectionStateChanged(int state, int networkType) |
same as above, but with the network type. 处理侦測到的数据连接状态的改变状态。通过该回调函数。 能够获取数据连接状态信息。 数据连接类型 DATA_DISCONNECTED 断开 |
void |
onMessageWaitingIndicatorChanged(boolean mwi) |
Callback invoked when the message-waiting indicator changes. |
void |
onServiceStateChanged(ServiceState serviceState) |
Callback invoked when device service state changes. 处理侦測到的服务状态的改变事件。通过该回调函数能够获取服务状态信息。 电话服务状态类型定义在ServiceState类中。 |
void |
onSignalStrengthChanged(int asu) |
This method is deprecated. Use onSignalStrengthsChanged(SignalStrength) 处理侦測到的信号强度的改变事件。通过该回调函数,能够获取信号强度类型。 |
void |
onSignalStrengthsChanged(SignalStrength signalStrength) |
Callback invoked when network signal strengths changes. |
參考文献:
1.李刚老师的Android疯狂讲义
2.相关属性与方法摘自:http://www.linuxidc.com/Linux/2011-10/45049.htm