转载请注明出处:
现在 Android 手机越来越多的使用双卡双待,对于安装双卡的手机,有时我们想要获取两张卡的IMSI、IMEI等信息。我们知道 Android 中提供了相关 api,通过类 TelephonyManager可以获取IMSI、IMEI等信息,注意:在Android M及以后,在使用类TelephoneManager之前,需要动态申请权限android.permission.READ_PHONE_STATE,否则获取到的信息可能为空。
但是TelephoneManager提供的public String getDeviceId(),public String getSubscriberId()等API,只能返回默认的一个IMEI、IMSI,并不能获取双卡的信息。在 Android 5.0 之后,系统加入了public String getDeviceId(int slotId),public String getSubscriberId(int subId)等方法,可以根据slotId、subId来获取不同卡槽的信息,但是这些方法是hide方法,被系统隐藏了。然而在 API 23及以后,系统开放了 public String getDeviceId(int slotId) 方法。至此,可以想到我们的实现思路是,在 Android 5.0 及之后,通过反射系统方法来获取双卡的IMEI和IMSI信息。
在这里解释一下上文提到的 slotId,subId。slotId为卡槽Id,它的值为 0、1;subId为卡Id,相当于在手机卡插到手机上时,系统为卡分配的一个标识Id,这个值通过ContentProvider来获取。
public static int getSubId(int slotId, Context context) {
Uri uri = Uri.parse("content://telephony/siminfo");
Cursor cursor = null;
ContentResolver contentResolver = context.getContentResolver();
try {
cursor = contentResolver.query(uri, new String[] {"_id", "sim_id"}, "sim_id = ?", new String[] {String.valueOf(slotId)}, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
return cursor.getInt(cursor.getColumnIndex("_id"));
}
}
} catch (Exception e) {
LogUtil.d("getSubId", e.toString());
} finally {
if (null != cursor) {
cursor.close();
}
}
return -1;
}
讲一下通过反射获取IMEI、IMSI的思路:
1、通过方法名来获取方法的参数列表
public static Class[] getMethodParamTypes(String methodName) {
Class[] params = null;
try {
Method[] methods = TelephonyManager.class.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (methodName.equals(methods[i].getName())) {
params = methods[i].getParameterTypes();
if (params.length >= 1) {
LogUtil.d("length:", "" + params.length);
break;
}
}
}
} catch (Exception e) {
LogUtil.d("", e.toString());
}
return params;
}
2、通过subId和方法名来获取该方法的返回值
public static Object getPhoneInfo(int subId, String methodName, Context context) {
Object value = null;
try {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (Build.VERSION.SDK_INT >= 21) {
Method method = tm.getClass().getMethod(methodName, getMethodParamTypes(methodName));
if (subId >= 0) {
value = method.invoke(tm, subId);
}
}
} catch (Exception e) {
LogUtil.d("", e.toString());
}
return value;
}
3、获取IMEI和IMSI的值
// imei
public static String getDeviced(Context context, int soltId) {
return (String) getPhoneInfo(soltId "getDeviceId", context);
}
// imsi
public static String getSubscriberId(int subId, Context context) {
String imsi = (String) getPhoneInfo(subId, "getSubscriberId", context);
return imsi;
}
通过以上方式,可以获取Android 5.0以后双卡手机的IMEI、IMSI信息。这里解释下步骤1为何通过通过反射来获取参数列表,因为发现在部分机型上获取到的参数类型有long类型,所以直接通过反射的方式来获取了。
以上方法,亲测一加3、华为Mate8、小米Note、VIVO X6PlusA、荣耀V9可用。

最后
以上就是搞怪斑马最近收集整理的关于获取双卡手机IMEI、IMSI的全部内容,更多相关获取双卡手机IMEI、IMSI内容请搜索靠谱客的其他文章。
发表评论 取消回复