- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
经过论坛的大量研究,现在我知道没有办法找到双卡手机中两张SIM卡的IMSI或SIM序列号(除了联系制造商)。现在我改变的问题是,我们能否检测到手机有两个 SIM 卡?我相信它可以通过一些情报来检测。我能想到的几种方法是:
调用 USSD 代码并跟踪日志中的 IMEI 号码(我在印度使用 *139# 进行了尝试。它成功了。)这将为我提供我调用 USSD 代码的 SIM 卡的 IMEI 号码。 (推测手机遵循安卓规范,有两个IMEI号码。)
存储 SIM 的序列号和/或 SIM 的 IMSI。并且在检测到任何其他 IMSI/序列号后,即使手机没有重新启动(即 SIM 已切换),也可以通过跟踪一些日志或一些广播事件处理。
调用*06#你会看到两个IMEI号码。通过某种方式,得到这两个数字。 (例如屏幕捕获和文本图像解析。)
如果有人能想到一些其他的方法,他们是最受欢迎的。我真的很感激任何关于这方面的帮助。此外,如果有人有任何有关任何制造商 API 的信息或联系他们的链接,请与社区人员分享。
最佳答案
2015 年 3 月 23 日更新:
Official multiple SIM API is available now from Android 5.1 onwards
其他可能的选择:
您可以使用 Java 反射 来获取两个 IMEI 号码。
使用这些 IMEI 号码,您可以检查手机是否为双 SIM 卡。
尝试以下 Activity :
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TelephonyInfo telephonyInfo = TelephonyInfo.getInstance(this);
String imeiSIM1 = telephonyInfo.getImsiSIM1();
String imeiSIM2 = telephonyInfo.getImsiSIM2();
boolean isSIM1Ready = telephonyInfo.isSIM1Ready();
boolean isSIM2Ready = telephonyInfo.isSIM2Ready();
boolean isDualSIM = telephonyInfo.isDualSIM();
TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(" IME1 : " + imeiSIM1 + "\n" +
" IME2 : " + imeiSIM2 + "\n" +
" IS DUAL SIM : " + isDualSIM + "\n" +
" IS SIM1 READY : " + isSIM1Ready + "\n" +
" IS SIM2 READY : " + isSIM2Ready + "\n");
}
}
这里是 TelephonyInfo.java
:
import java.lang.reflect.Method;
import android.content.Context;
import android.telephony.TelephonyManager;
public final class TelephonyInfo {
private static TelephonyInfo telephonyInfo;
private String imeiSIM1;
private String imeiSIM2;
private boolean isSIM1Ready;
private boolean isSIM2Ready;
public String getImsiSIM1() {
return imeiSIM1;
}
/*public static void setImsiSIM1(String imeiSIM1) {
TelephonyInfo.imeiSIM1 = imeiSIM1;
}*/
public String getImsiSIM2() {
return imeiSIM2;
}
/*public static void setImsiSIM2(String imeiSIM2) {
TelephonyInfo.imeiSIM2 = imeiSIM2;
}*/
public boolean isSIM1Ready() {
return isSIM1Ready;
}
/*public static void setSIM1Ready(boolean isSIM1Ready) {
TelephonyInfo.isSIM1Ready = isSIM1Ready;
}*/
public boolean isSIM2Ready() {
return isSIM2Ready;
}
/*public static void setSIM2Ready(boolean isSIM2Ready) {
TelephonyInfo.isSIM2Ready = isSIM2Ready;
}*/
public boolean isDualSIM() {
return imeiSIM2 != null;
}
private TelephonyInfo() {
}
public static TelephonyInfo getInstance(Context context){
if(telephonyInfo == null) {
telephonyInfo = new TelephonyInfo();
TelephonyManager telephonyManager = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
telephonyInfo.imeiSIM1 = telephonyManager.getDeviceId();;
telephonyInfo.imeiSIM2 = null;
try {
telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getDeviceIdGemini", 0);
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getDeviceIdGemini", 1);
} catch (GeminiMethodNotFoundException e) {
e.printStackTrace();
try {
telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getDeviceId", 0);
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getDeviceId", 1);
} catch (GeminiMethodNotFoundException e1) {
//Call here for next manufacturer's predicted method name if you wish
e1.printStackTrace();
}
}
telephonyInfo.isSIM1Ready = telephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY;
telephonyInfo.isSIM2Ready = false;
try {
telephonyInfo.isSIM1Ready = getSIMStateBySlot(context, "getSimStateGemini", 0);
telephonyInfo.isSIM2Ready = getSIMStateBySlot(context, "getSimStateGemini", 1);
} catch (GeminiMethodNotFoundException e) {
e.printStackTrace();
try {
telephonyInfo.isSIM1Ready = getSIMStateBySlot(context, "getSimState", 0);
telephonyInfo.isSIM2Ready = getSIMStateBySlot(context, "getSimState", 1);
} catch (GeminiMethodNotFoundException e1) {
//Call here for next manufacturer's predicted method name if you wish
e1.printStackTrace();
}
}
}
return telephonyInfo;
}
private static String getDeviceIdBySlot(Context context, String predictedMethodName, int slotID) throws GeminiMethodNotFoundException {
String imei = null;
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
try{
Class<?> telephonyClass = Class.forName(telephony.getClass().getName());
Class<?>[] parameter = new Class[1];
parameter[0] = int.class;
Method getSimID = telephonyClass.getMethod(predictedMethodName, parameter);
Object[] obParameter = new Object[1];
obParameter[0] = slotID;
Object ob_phone = getSimID.invoke(telephony, obParameter);
if(ob_phone != null){
imei = ob_phone.toString();
}
} catch (Exception e) {
e.printStackTrace();
throw new GeminiMethodNotFoundException(predictedMethodName);
}
return imei;
}
private static boolean getSIMStateBySlot(Context context, String predictedMethodName, int slotID) throws GeminiMethodNotFoundException {
boolean isReady = false;
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
try{
Class<?> telephonyClass = Class.forName(telephony.getClass().getName());
Class<?>[] parameter = new Class[1];
parameter[0] = int.class;
Method getSimStateGemini = telephonyClass.getMethod(predictedMethodName, parameter);
Object[] obParameter = new Object[1];
obParameter[0] = slotID;
Object ob_phone = getSimStateGemini.invoke(telephony, obParameter);
if(ob_phone != null){
int simState = Integer.parseInt(ob_phone.toString());
if(simState == TelephonyManager.SIM_STATE_READY){
isReady = true;
}
}
} catch (Exception e) {
e.printStackTrace();
throw new GeminiMethodNotFoundException(predictedMethodName);
}
return isReady;
}
private static class GeminiMethodNotFoundException extends Exception {
private static final long serialVersionUID = -996812356902545308L;
public GeminiMethodNotFoundException(String info) {
super(info);
}
}
}
编辑:
获取其他 SIM 插槽详细信息的“getDeviceIdGemini”等方法可以预测该方法存在。
如果该方法的名称与设备制造商提供的名称不匹配,它将无法工作。您必须为这些设备找到相应的方法名称。
可以使用 Java 反射来查找其他制造商的方法名称,如下所示:
public static void printTelephonyManagerMethodNamesForThisDevice(Context context) {
TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> telephonyClass;
try {
telephonyClass = Class.forName(telephony.getClass().getName());
Method[] methods = telephonyClass.getMethods();
for (int idx = 0; idx < methods.length; idx++) {
System.out.println("\n" + methods[idx] + " declared by " + methods[idx].getDeclaringClass());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
编辑:
作为 Seetha在她的评论中指出:
telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getDeviceIdDs", 0);
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getDeviceIdDs", 1);
这对她有用。她成功地为三星 Duos 设备中的 SIM 卡获取了两个 IMEI 号码。
添加 <uses-permission android:name="android.permission.READ_PHONE_STATE" />
编辑 2:
联想A319和该厂商其他手机的数据检索方法(图片来源Maher Abuthraa):
telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 0);
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 1);
关于安卓 : Check whether the phone is dual SIM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14517338/
为什么下面的查询给出值 2 而不是我期望的 1? SELECT SUM(1) FROM ( SELECT '0' as R FROM dual UNION SELECT '1' as R FROM
我使用的是 Oracle 11g,并且我确实了解第 3 方授权的问题。 但是,假设 user1 创建了一个 View “view1”作为 Select 'foo' from Dual。 然后我将 vi
正常情况下(不使用SYS或可能使用它)- SQL> select * from dual; D - X 在不太正常的情况下(作为 SYS 连接)- SQL> alter database close;
如果表肯定是空的,我将使用此代码插入默认行。我试图扩展它以插入多行,但无法弄清楚语法: INSERT INTO myTable(`myCol`) SELECT 'myVal' FROM DUAL WH
当对 LE 设备使用 ScanCallback 时,我得到以下条件为真: bluetoothDevice.getType() == BluetoothDevice.DEVICE_TYPE_DUAL 设
zoom允许我们在实际定义了更多变量的上下文中使用仅使用某些状态变量的状态操作。 {-# LANGUAGE TemplateHaskell #-} import Control.Lens import
我需要加入从我的程序中动态检索的动态数字列表。行数不是固定的,使用的数字也不是固定的。 我没有找到比以下更好的方法来实现这一点(就我而言,临时表没有帮助): select 111 as col1, 3
我试图获取从上周到当前的日期,但似乎 或 >= 在这里不起作用。 WITH curr_cyc_dt AS ( SELECT BETWEEN TO_DATE ('20181228', 'yyyy
我想向数据库中插入一些数据。在插入的时候,我想先做一个判断:如果table1和table2中不存在title,则插入。这个双关语怎么写?这是正确的吗?或者……谢谢。 mysql_query(" INS
我有一个像这样的嵌套数组(只有一层深): $a = array( array( 1, 2, 3 ), array( 2, 4, 6 ), array( 5, 10, 15 ) ); 我
我们有三个redis服务器设置如下: Node1: Default Redis Master & Running Redis Sentinel Software Node2: Redis Slave
因此,A* 指针可以指向任何具有基 A 的对象,而 B* 指针可以指向任何具有基 B*。有没有办法创建一个只能指向以 A 和 B 为基础的对象的指针? 我还希望它是我可以存储为类成员的东西(也许是智能
双表用于选择伪列。 它有一行和一列 DUMMY,其值为 X。 我有两个问题 伪代码实际上做了什么 列是什么意思? 双重身份如何给予 值例如: select sysdate from dual 将导致当
我很惊讶这个问题还没有被问到。我一定错过了一些非常明显的东西,我已经准备好接受所有的反对票和 3 秒的回答。 在 MSSQL 中,您可以调用 GETDATE() 而不必依赖于数据库表,但在 Oracl
什么是“双生命”模块? perldelta for Perl 5.14 中有提到. 最佳答案 Dual Life 模块是存在于两个断开连接的源存储库中的模块,通常意味着在 Perl 核心(与 perl
不久前,我在使用jdbc插入/更新数百万条记录时遇到了数据库性能问题。为了提高性能,我更改了代码以使用batch。然后我决定使用 jprofiler 监控代码以了解性能提高了多少......但同时监控
我有一个插入和更新表的函数。调用它的来源: select AGENTS_REGISTRATION() from dual; 或者: declare x NUMBER; begin select
能给我一些类似的东西吗 SELECT (1, 2, 4542, 342) FROM DUAL; 然后像这样得到它? | 1 | | 2 | | 4542 | | 3
有没有办法在 Oracle 中创建/重新创建双表?它不小心掉了下来。 最佳答案 您可能应该联系 Oracle 支持。 你有备份吗?如果是这样,请从备份中恢复该表。否则(如果您不适合联系 Oracle)
Dual 是一个 newtype-wrapper,只是颠倒了 mappend 的顺序对于包裹类型的 Monoid实例: >>> "hello" <> " " <> "world" "hello wor
我是一名优秀的程序员,十分优秀!