Android TelephonyManager (电话管理器)
TelephonyManager 用于管理手机通话状态,获取电话信息(设备信息、sim卡信息以及 网络信息),侦听电话状态(呼叫状态服务状态、信号强度状态等)以及可以调用电话拨号器拨打电话
获得 TelephonyManager 的服务对象
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
调用拨号器拨打电话号码
Uri uri=Uri.parse("tel:"+电话号码); Intent intent=new Intent(Intent.ACTION_DIAL,uri); startActivity(intent);
获取 Sim 卡信息与网络信息
-
创建一个 空的 Android 项目
cn.twle.android.PhoneInfo
-
创建包
cn.twle.android.common
并在包下创建权限管理帮助类PermHelper.java
package cn.twle.android.common; import android.content.Context; import android.content.pm.PackageManager; import android.support.v4.content.ContextCompat; public class PermHelper { private final Context mContext; public PermHelper(Context context) { mContext = context.getApplicationContext(); } // 判断权限集合 public boolean lacksPermissions(String... permissions) { for (String permission : permissions) { if (lacksPermission(permission)) { return true; } } return false; } // 判断是否缺少权限 private boolean lacksPermission(String permission) { return ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_DENIED; } }
-
添加授权页
授权页, 首先使用系统默认的授权页, 当用户拒绝时, 指导用户手动设置, 当用户再次操作失败后, 返回继续提示
用户手动退出授权页时, 给使用页发送授权失败的通知
我们可以保存这个授权页并将其在多个应用中复用
-
创建授权页
PermActivity.java
package cn.twle.android.phoneinfo; import android.app.Activity; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import cn.twle.android.common.PermHelper; public class PermActivity extends AppCompatActivity { public static final int PERMISSIONS_GRANTED = 0; // 权限授权 public static final int PERMISSIONS_DENIED = 1; // 权限拒绝 private static final int PERMISSION_REQUEST_CODE = 0; // 系统权限管理页面的参数 private static final String EXTRA_PERMISSIONS = "cn.twle.android.common.permission.extra_permission"; // 权限参数 private static final String PACKAGE_URL_SCHEME = "package:"; // 方案 private PermHelper permHelper; // 权限检测器 private boolean isRequireCheck; // 是否需要系统权限检测, 防止和系统提示框重叠 // 启动当前权限页面的公开接口 public static void startActivityForResult(Activity activity, int requestCode, String... permissions) { Intent intent = new Intent(activity, PermActivity.class); intent.putExtra(EXTRA_PERMISSIONS, permissions); ActivityCompat.startActivityForResult(activity, intent, requestCode, null); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getIntent() == null || !getIntent().hasExtra(EXTRA_PERMISSIONS)) { throw new RuntimeException("PermissionsActivity需要使用静态startActivityForResult方法启动!"); } //setContentView(R.layout.activity_perm); permHelper = new PermHelper(this); isRequireCheck = true; } @Override protected void onResume() { super.onResume(); if (isRequireCheck) { String[] permissions = getPermissions(); if (permHelper.lacksPermissions(permissions)) { requestPermissions(permissions); // 请求权限 } else { allPermissionsGranted(); // 全部权限都已获取 } } else { isRequireCheck = true; } } // 返回传递的权限参数 private String[] getPermissions() { return getIntent().getStringArrayExtra(EXTRA_PERMISSIONS); } // 请求权限兼容低版本 private void requestPermissions(String... permissions) { ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE); } // 全部权限均已获取 private void allPermissionsGranted() { setResult(PERMISSIONS_GRANTED); finish(); } /** * 用户权限处理, * 如果全部获取, 则直接过. * 如果权限缺失, 则提示Dialog. * * @param requestCode 请求码 * @param permissions 权限 * @param grantResults 结果 */ @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if (requestCode == PERMISSION_REQUEST_CODE && hasAllPermissionsGranted(grantResults)) { isRequireCheck = true; allPermissionsGranted(); } else { isRequireCheck = false; showMissingPermissionDialog(); } } // 含有全部的权限 private boolean hasAllPermissionsGranted(@NonNull int[] grantResults) { for (int grantResult : grantResults) { if (grantResult == PackageManager.PERMISSION_DENIED) { return false; } } return true; } // 显示缺失权限提示 private void showMissingPermissionDialog() { AlertDialog.Builder builder = new AlertDialog.Builder(PermActivity.this); builder.setTitle("帮助"); builder.setMessage("当前应用缺少必要权限。\n请点击\"设置\"-\"权限\" 打开所需权限。\n最后点击两次回退按钮,即可返回"); // 拒绝, 退出应用 builder.setNegativeButton("推出", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { setResult(PERMISSIONS_DENIED); finish(); } }); builder.setPositiveButton("设置", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { startAppSettings(); } }); builder.setCancelable(false); builder.show(); } // 启动应用的设置 private void startAppSettings() { Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.setData(Uri.parse(PACKAGE_URL_SCHEME + getPackageName())); startActivity(intent); } }
-
修改
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="5dp"> <TextView android:id="@+id/ms_phone1" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone2" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone3" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone4" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone5" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone6" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone7" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone8" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/ms_phone9" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
-
修改
AndroidManifest.xml
中加上权限<!-- 添加访问手机位置的权限 --> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> <!-- 添加访问手机状态的权限 --> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
-
修改
MainActivity.java
package cn.twle.android.phoneinfo; import android.Manifest; import android.content.Context; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.telephony.TelephonyManager; import android.widget.TextView; import cn.twle.android.common.PermHelper; public class MainActivity extends AppCompatActivity { final private static int REQUEST_CODE = 29; // 请求码 static final String[] PERMISSIONS = new String[]{ Manifest.permission.READ_PHONE_STATE, Manifest.permission.ACCESS_COARSE_LOCATION }; private PermHelper permHelper; private TextView ms_phone1; private TextView ms_phone2; private TextView ms_phone3; private TextView ms_phone4; private TextView ms_phone5; private TextView ms_phone6; private TextView ms_phone7; private TextView ms_phone8; private TextView ms_phone9; private TelephonyManager tm; private String[] phoneType = {"未知","2G","3G","4G"}; private String[] simState = {"状态未知","无SIM卡","被PIN加锁","被PUK加锁", "被NetWork PIN加锁","已准备好"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); permHelper = new PermHelper(this); if (permHelper.lacksPermissions(PERMISSIONS)) { startPermissionsActivity(); } // 获得系统提供的 TelphonyManager 对象的实例 tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); ms_phone1 = (TextView) findViewById(R.id.ms_phone1); ms_phone2 = (TextView) findViewById(R.id.ms_phone2); ms_phone3 = (TextView) findViewById(R.id.ms_phone3); ms_phone4 = (TextView) findViewById(R.id.ms_phone4); ms_phone5 = (TextView) findViewById(R.id.ms_phone5); ms_phone6 = (TextView) findViewById(R.id.ms_phone6); ms_phone7 = (TextView) findViewById(R.id.ms_phone7); ms_phone8 = (TextView) findViewById(R.id.ms_phone8); ms_phone9 = (TextView) findViewById(R.id.ms_phone9); ms_phone1.setText("设备编号:" + tm.getDeviceId()); ms_phone2.setText("软件版本:" + (tm.getDeviceSoftwareVersion()!= null? tm.getDeviceSoftwareVersion():"未知")); ms_phone3.setText("运营商代号:" + tm.getNetworkOperator()); ms_phone4.setText("运营商名称:" + tm.getNetworkOperatorName()); ms_phone5.setText("网络类型:" + phoneType[tm.getPhoneType()]); ms_phone6.setText("设备当前位置:" + (tm.getCellLocation() != null ? tm .getCellLocation().toString() : "未知位置")); ms_phone7.setText("SIM卡的国别:" + tm.getSimCountryIso()); ms_phone8.setText("SIM卡序列号:" + tm.getSimSerialNumber()); ms_phone9.setText("SIM卡状态:" + simState[tm.getSimState()]); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // 拒绝时, 关闭页面, 缺少主要权限, 无法运行 if (requestCode == REQUEST_CODE && resultCode == PermActivity.PERMISSIONS_DENIED) { finish(); } } @Override protected void onResume() { super.onResume(); if (permHelper.lacksPermissions(PERMISSIONS)) { startPermissionsActivity(); } } private void startPermissionsActivity() { PermActivity.startActivityForResult(this, REQUEST_CODE, PERMISSIONS); } }
其它信息
如果想获取网络制式,而非普通的 2G,3G,4G 这样,可以调用 getNetworkClass()
方法
/** * Return general class of network type, such as "3G" or "4G". In cases * where classification is contentious, this method is conservative. * * @hide */ public static int getNetworkClass(int networkType) { switch (networkType) { case NETWORK_TYPE_GPRS: case NETWORK_TYPE_GSM: case NETWORK_TYPE_EDGE: case NETWORK_TYPE_CDMA: case NETWORK_TYPE_1xRTT: case NETWORK_TYPE_IDEN: return NETWORK_CLASS_2_G; case NETWORK_TYPE_UMTS: case NETWORK_TYPE_EVDO_0: case NETWORK_TYPE_EVDO_A: case NETWORK_TYPE_HSDPA: case NETWORK_TYPE_HSUPA: case NETWORK_TYPE_HSPA: case NETWORK_TYPE_EVDO_B: case NETWORK_TYPE_EHRPD: case NETWORK_TYPE_HSPAP: case NETWORK_TYPE_TD_SCDMA: return NETWORK_CLASS_3_G; case NETWORK_TYPE_LTE: case NETWORK_TYPE_IWLAN: case NETWORK_TYPE_LTE_CA: return NETWORK_CLASS_4_G; default: return NETWORK_CLASS_UNKNOWN; } }
我们可以根据这个 networkType
的值,判断不同的网络制式,比如,如果 networkType == 1
那个是 GPRS 这种制式的,而这个networkType的值可以通过
/** * Returns a string representation of the radio technology (network type) * currently in use on the device. * @return the name of the radio technology * * @hide pending API council review */ public String getNetworkTypeName() { return getNetworkTypeName(getNetworkType()); } /** * Returns a string representation of the radio technology (network type) * currently in use on the device. * @param subId for which network type is returned * @return the name of the radio technology * */ /** {@hide} */ public static String getNetworkTypeName(int type) { switch (type) { case NETWORK_TYPE_GPRS: return "GPRS"; case NETWORK_TYPE_EDGE: return "EDGE"; case NETWORK_TYPE_UMTS: return "UMTS"; case NETWORK_TYPE_HSDPA: return "HSDPA"; case NETWORK_TYPE_HSUPA: return "HSUPA"; case NETWORK_TYPE_HSPA: return "HSPA"; case NETWORK_TYPE_CDMA: return "CDMA"; case NETWORK_TYPE_EVDO_0: return "CDMA - EvDo rev. 0"; case NETWORK_TYPE_EVDO_A: return "CDMA - EvDo rev. A"; case NETWORK_TYPE_EVDO_B: return "CDMA - EvDo rev. B"; case NETWORK_TYPE_1xRTT: return "CDMA - 1xRTT"; case NETWORK_TYPE_LTE: return "LTE"; case NETWORK_TYPE_EHRPD: return "CDMA - eHRPD"; case NETWORK_TYPE_IDEN: return "iDEN"; case NETWORK_TYPE_HSPAP: return "HSPA+"; case NETWORK_TYPE_GSM: return "GSM"; case NETWORK_TYPE_TD_SCDMA: return "TD_SCDMA"; case NETWORK_TYPE_IWLAN: return "IWLAN"; case NETWORK_TYPE_LTE_CA: return "LTE_CA"; default: return "UNKNOWN"; } }
即这个 getNetworkType()
方法获得!好了,就这么简单,可以像上面列好一个数组然后根据
不同的下标显示不同的值!
Sim 卡状态的,字符串数组中的值
/** * Returns a constant indicating the state of the default SIM card. * * @see #SIM_STATE_UNKNOWN * @see #SIM_STATE_ABSENT * @see #SIM_STATE_PIN_REQUIRED * @see #SIM_STATE_PUK_REQUIRED * @see #SIM_STATE_NETWORK_LOCKED * @see #SIM_STATE_READY * @see #SIM_STATE_NOT_READY * @see #SIM_STATE_PERM_DISABLED * @see #SIM_STATE_CARD_IO_ERROR * @see #SIM_STATE_CARD_RESTRICTED */ public int getSimState() { int slotIndex = getSlotIndex(); // slotIndex may be invalid due to sim being absent. In that case query all slots to get // sim state if (slotIndex < 0) { // query for all slots and return absent if all sim states are absent, otherwise // return unknown for (int i = 0; i < getPhoneCount(); i++) { int simState = getSimState(i); if (simState != SIM_STATE_ABSENT) { Rlog.d(TAG, "getSimState: default sim:" + slotIndex + ", sim state for " + "slotIndex=" + i + " is " + simState + ", return state as unknown"); return SIM_STATE_UNKNOWN; } } Rlog.d(TAG, "getSimState: default sim:" + slotIndex + ", all SIMs absent, return " + "state as absent"); return SIM_STATE_ABSENT; } return getSimState(slotIndex); }