程序员人生 网站导航

Android提供的系统服务之--TelephonyManager(电话管理器)

栏目:互联网时间:2014-11-15 02:33:34

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

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐

1.cyou 非常适合 Z 世代企业家的三大理由 2阿里、京东类ChatGPT产品正在内测 未来或将融入产品 3公会积极复工复产,2023直播行业有哪些新机遇? 4第三届OpenHarmony技术大会展区亮点纷呈,全方位洞见智慧互联未来 5第三届OpenHarmony技术大会应用生态实践分论坛成功举办 6第三届OpenHarmony技术大会OS安全分论坛圆满举办 7第三届 OpenHarmony 技术大会:创新成果丰硕,共筑开源生态新未来

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