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.定义了1个存储状态名称的array.xml的数组资源文件;
2.布局定义了1个简单的listview,列表项是两个水平方向的textview
3.Activity界面中调用相干方法取得对应参数的值,再把数据绑定到listview上!
详细代码以下:
array.xml:
<?xml version="1.0" encoding="utf⑻"?>
<resources>
<!-- 声明1个名为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>
<!-- 声明1个名为simState的字符串数组 -->
<string-array name="simState">
<item>状态未知</item>
<item>无SIM卡</item>
<item>被PIN加锁</item>
<item>被PUK加锁</item>
<item>被NetWork PIN加锁</item>
<item>已准备好</item>
</string-array>
<!-- 声明1个名为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⑻"?>
<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 {
//定义1个ListView对象,1个代表状态名称的数组,和手机状态的集合
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.监听手机的所有来电:
对监听到的通话记录结果,你可以采取不同的方式获得到,这里用到的是把通话记录写入到文件中,
而你也能够以短信的情势发送给你,或是上传到某个平台,固然如果通讯记录不多的话还可以用短信
多了的话就很容易给人发现的了!
另外,这里用的是Activity而非Service,就是说要打开这个Activity,才可以进行监听,通常我们的需求都是
要偷偷滴在后台跑的,由于时间关系就不写Service的了,大家自己写写吧,让Service随开机1起启动便可!
代码解析:
很简单,其实就是重写TelephonyManager的1个通话状态监听器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);
// 创建1个通话状态监听器
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.黑名单来电自动挂断:
所谓的黑名单就是将1些电话号码添加到1个集合中,当手机接收到这些电话的时候就直接挂断!
但是Android并没有给我们提供挂断电话的API,因而乎我们需要通过AIDL来调用服务中的API来
实现挂断电话!
因而乎第1步要做的就是把android源码中的下面两个文件复制到src下的相应位置,他们分别是:
com.android.internal.telephony包下的ITelephony.aidl;
android.telephony包下的NeighboringCellInfo.aidl;
要创建对应的包哦!就是要把aidl文件放到上面的包下!!!
接着只需要调用ITelephony的endCall便可挂断电话!
这里给出的是简单的单个号码的拦截,输入号码,点击屏蔽按钮后,如果此时屏蔽的电话呼入的话;
直接会挂断,代码还是比较简单的,下面粘1下,由于用的摹拟器是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" />
固然,更多的时候我们屏蔽的不会只是1个号码,这个时候可使用集合,把多个要屏蔽的号码添加到
集合中,或是文件中,这里就直接给出李刚老师的demo,他提供的是1个带复选框的列表供用户
勾选黑名单,这里就不解析了,直接给出代码下载吧!
单个号码拦截的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
|
------分隔线----------------------------
------分隔线----------------------------