Android开源代码解读の使用TelephonyManager获取移动网络信息

本文介绍了如何利用Android系统中的TelephonyManager类来监听并获取手机SIM卡的状态以及移动网络的相关信息,通过注册PhoneStateListener接口来实时更新SIM卡状态和网络类型,并展示了具体实现代码及布局文件。

本文介绍使用TelephonyManager来获取手机SIM卡的状态和移动网络的相关信息,主要使用了TelephonyManager.listen函数,这个函数源码如下:

public void listen(PhoneStateListener listener, int events) {
    String pkgForDebug = mContext != null ? mContext.getPackageName() : "<unknown>";
    try {
        Boolean notifyNow = (getITelephony() != null);
        mRegistry.listen(pkgForDebug, listener.callback, events, notifyNow);
    } catch (RemoteException ex) {
        // system process dead
    } catch (NullPointerException ex) {
        // system process dead
    }
}

具体的实现不是本文的重点,这里只来了解函数的两个参数:

1)PhoneStateListener listener

一般根据events的值,来实现相应的回调函数接口,在回调函数里面执行我们的处理,这些接口包括:

public void onServiceStateChanged(ServiceState serviceState)
public void onMessageWaitingIndicatorChanged(boolean mwi) 
public void onCallForwardingIndicatorChanged(boolean cfi)
public void onCellLocationChanged(CellLocation location) 
public void onCallStateChanged(int state, String incomingNumber) 
public void onDataConnectionStateChanged(int state) 
public void onDataConnectionStateChanged(int state, int networkType) 
public void onDataActivity(int direction) 
public void onSignalStrengthsChanged(SignalStrength signalStrength) 

2)int events

Events取值如下:

public static final int LISTEN_NONE = 0; //停止监听
public static final int LISTEN_SERVICE_STATE = 0x00000001;
public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 0x00000004;
public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008;
public static final int LISTEN_CELL_LOCATION = 0x00000010;
public static final int LISTEN_CALL_STATE = 0x00000020;
public static final int LISTEN_DATA_CONNECTION_STATE = 0x00000040;
public static final int LISTEN_DATA_ACTIVITY = 0x00000080;
public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100;

下面就是使用了上面知识点的代码了,先看布局文件network_detector.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <TextView android:id="@+id/phone_type"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <TextView android:id="@+id/network_name"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <TextView android:id="@+id/sim_state"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
    <TextView android:id="@+id/network_type"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

完整Java代码如下(对APIDemos的解析,有删改):

package hust.iprai.asce1885;

import android.app.Activity;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.widget.TextView;

public class NetworkDetector extends Activity {
	
	//SIM卡状态常量
	private static final String SIM_ABSENT = "Absent"; //手机内无SIM卡
	private static final String SIM_READY = "Ready"; //SIM卡已准备好
	private static final String SIM_PIN_REQUIRED = "PIN required"; //需要SIM卡的PIN解锁
	private static final String SIM_PUK_REQUIRED = "PUK required"; //需要SIM卡的PUK解锁 
	private static final String SIM_NETWORK_LOCKED = "Network locked"; //需要Network PIN解锁
	private static final String SIM_UNKNOWN = "Unknown"; //状态未知
    
    //网络类型常量
	private static final String NETWORK_CDMA = "CDMA: Either IS95A or IS95B (2G)";
	private static final String NETWORK_EDGE = "EDGE (2.75G)";
	private static final String NETWORK_GPRS = "GPRS (2.5G)";
	private static final String NETWORK_UMTS = "UMTS (3G)";
    private static final String NETWORK_EVDO_0 = "EVDO revision 0 (3G)";
    private static final String NETWORK_EVDO_A = "EVDO revision A (3G - Transitional)";
    private static final String NETWORK_EVDO_B = "EVDO revision B (3G - Transitional)";
    private static final String NETWORK_1X_RTT = "1xRTT  (2G - Transitional)";
    private static final String NETWORK_HSDPA = "HSDPA (3G - Transitional)";
    private static final String NETWORK_HSUPA = "HSUPA (3G - Transitional)";
    private static final String NETWORK_HSPA = "HSPA (3G - Transitional)";
    private static final String NETWORK_IDEN = "iDen (2G)";
    private static final String NETWORK_UNKOWN = "Unknown";
    
    //手机制式类型常量
    private static final String PHONE_CDMA = "CDMA";
    private static final String PHONE_GSM = "GSM";
    private static final String PHONE_NONE = "No radio";
    	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.network_detector);
        
        //获取telephony系统服务,用于取得SIM卡和网络相关信息
        final TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        
        //更新界面上相关网络信息
        updateViews(tm);
        
        //由于SIM卡状态和网络信息随时都可能发生变化,因此需要注册PhoneStateListener
        //来实时更新界面显示的信息。这里监听两个事件:LISTEN_SERVICE_STATE和LISTEN_DATA_CONNECTION_STATE
        //它们分别对应回调函数onServiceStateChanged和onDataConnectionStateChanged
        tm.listen(new PhoneStateListener() {

			@Override
			public void onDataConnectionStateChanged(int state, int networkType) {
				//数据连接状态改变可能导致网络类型的改变
				updateViews(tm);
			}

			@Override
			public void onServiceStateChanged(ServiceState serviceState) {
				updateViews(tm);
			}
        	
        }, PhoneStateListener.LISTEN_SERVICE_STATE 
        		| PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
    }
    
	@Override
	protected void onResume() {
		super.onResume();
		final TelephonyManager tm = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
		updateViews(tm);
	}
    
    /**
     * 更新SIM卡状态和网络信息
     * @param tm
     */
    private final void updateViews(TelephonyManager tm) {
    	TextView view = null;
    	
    	view = (TextView) findViewById(R.id.sim_state);
    	view.setText("SIM State : " + mapSimStateToName(tm.getSimState()));
    	
    	view = (TextView) findViewById(R.id.network_type);
    	view.setText("Network Type : " + mapNetworkTypeToName(tm.getNetworkType()));
    	
    	view = (TextView) findViewById(R.id.network_name);
    	view.setText("Network Operator : " + tm.getNetworkOperatorName());
    	
    	view = (TextView) findViewById(R.id.phone_type);
    	view.setText("Phone Type : " + mapDeviceTypeToName(tm.getPhoneType()));
    	
    }

    /**
     * 将手机制式值以字符串形式返回
     * @param phoneType
     * @return
     */
	private String mapDeviceTypeToName(int phoneType) {
        switch (phoneType) {
        case TelephonyManager.PHONE_TYPE_CDMA:
            return PHONE_CDMA;
        case TelephonyManager.PHONE_TYPE_GSM:
            return PHONE_GSM;
        case TelephonyManager.PHONE_TYPE_NONE:
            return PHONE_NONE;
        default:
        	//不应该走到这个分支
            return null;
        }
	}

	/**
	 * 将网络类型值以字符串形式返回
	 * @param networkType
	 * @return
	 */
	private String mapNetworkTypeToName(int networkType) {
        switch (networkType) {
        case TelephonyManager.NETWORK_TYPE_CDMA:
            return NETWORK_CDMA;
        case TelephonyManager.NETWORK_TYPE_EDGE:
            return NETWORK_EDGE;
        case TelephonyManager.NETWORK_TYPE_GPRS:
            return NETWORK_GPRS;
        case TelephonyManager.NETWORK_TYPE_UMTS:
            return NETWORK_UMTS;
        case TelephonyManager.NETWORK_TYPE_EVDO_0:
            return NETWORK_EVDO_0;
        case TelephonyManager.NETWORK_TYPE_EVDO_A:
            return NETWORK_EVDO_A;
        case TelephonyManager.NETWORK_TYPE_EVDO_B:
            return NETWORK_EVDO_B;
        case TelephonyManager.NETWORK_TYPE_1xRTT:
            return NETWORK_1X_RTT;
        case TelephonyManager.NETWORK_TYPE_HSDPA:
            return NETWORK_HSDPA;
        case TelephonyManager.NETWORK_TYPE_HSPA:
            return NETWORK_HSPA;
        case TelephonyManager.NETWORK_TYPE_HSUPA:
            return NETWORK_HSUPA;
        case TelephonyManager.NETWORK_TYPE_IDEN:
            return NETWORK_IDEN;
        case TelephonyManager.NETWORK_TYPE_UNKNOWN:
        default:
            return NETWORK_UNKOWN;
        }
	}

	/**
	 * 将SIM卡状态值以字符串形式返回
	 * @param simState
	 * @return
	 */
	private static String mapSimStateToName(int simState) {
        switch (simState) {
        case TelephonyManager.SIM_STATE_ABSENT:
            return SIM_ABSENT;
        case TelephonyManager.SIM_STATE_READY:
            return SIM_READY;
        case TelephonyManager.SIM_STATE_PIN_REQUIRED:
            return SIM_PIN_REQUIRED;
        case TelephonyManager.SIM_STATE_PUK_REQUIRED:
            return SIM_PUK_REQUIRED;
        case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
            return SIM_NETWORK_LOCKED;
        case TelephonyManager.SIM_STATE_UNKNOWN:
            return SIM_UNKNOWN;
        default:
            //不应该走到这个分支
            return null;
        }
	}
	
}

程序执行结果如图所示:




### 获取当前网络信息的方法 在 Android 应用开发中,可以通过 `TelephonyManager` 类获取设备的当前网络信息。`TelephonyManager` 提供了一系列用于访问与手机通讯相关的状态和信息的 `get` 方法,包括电信网络的状态、SIM 卡信息以及用户信息等[^1]。通过这些方法,开发者可以轻松获取设备的网络运营商名称、网络类型、信号强度等关键数据。 #### 获取网络运营商信息 可以通过 `getNetworkOperatorName()` 方法获取当前设备连接的网络运营商名称。该方法返回一个字符串,表示当前设备所连接的运营商名称。 ```java TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); String carrierName = telephonyManager.getNetworkOperatorName(); ``` 此外,如果需要获取网络运营商的代码,可以使用 `getNetworkOperator()` 方法,它返回一个字符串,表示当前网络运营商的 MCC(移动国家代码)和 MNC(移动网络代码)组合[^1]。 #### 获取网络类型信息 为了获取当前设备所使用网络类型(例如 4G、5G 等),可以使用 `getNetworkType()` 方法。该方法返回一个整数值,表示当前的网络类型。常见的网络类型值包括: - `TelephonyManager.NETWORK_TYPE_GPRS`:GPRS - `TelephonyManager.NETWORK_TYPE_EDGE`:EDGE - `TelephonyManager.NETWORK_TYPE_UMTS`:UMTS - `TelephonyManager.NETWORK_TYPE_LTE`:LTE - `TelephonyManager.NETWORK_TYPE_NR`:NR(5G) 可以通过以下方式获取当前网络类型并将其转换为可读字符串: ```java int networkType = telephonyManager.getNetworkType(); String networkTypeName = "Unknown"; switch (networkType) { case TelephonyManager.NETWORK_TYPE_GPRS: networkTypeName = "GPRS"; break; case TelephonyManager.NETWORK_TYPE_EDGE: networkTypeName = "EDGE"; break; case TelephonyManager.NETWORK_TYPE_UMTS: networkTypeName = "UMTS"; break; case TelephonyManager.NETWORK_TYPE_LTE: networkTypeName = "LTE"; break; case TelephonyManager.NETWORK_TYPE_NR: networkTypeName = "NR (5G)"; break; default: networkTypeName = "Unknown"; break; } ``` #### 获取信号强度信息获取当前设备的信号强度,可以通过 `getSignalStrength()` 方法。该方法返回一个 `SignalStrength` 对象,包含有关信号强度的详细信息。例如,对于 LTE 网络,可以通过 `getLteRsrp()` 方法获取 RSRP(参考信号接收功率)值,用于衡量信号质量[^1]。 ```java SignalStrength signalStrength = telephonyManager.getSignalStrength(); int rsrp = signalStrength.getLteRsrp(); // 适用于 LTE 网络 ``` 需要注意的是,不同网络类型的信号强度指标不同,开发者需要根据当前网络类型选择合适的获取方式。 #### 权限要求 为了使用 `TelephonyManager` 获取网络信息,应用必须在 `AndroidManifest.xml` 文件中声明相应的权限。特别是需要访问手机状态的权限: ```xml <uses-permission android:name="android.permission.READ_PHONE_STATE"/> ``` 在 Android 6.0 及以上版本中,还需要在运行时请求该权限,以确保应用能够在不同版本的系统上正常运行[^2]。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值