Android: Перевірте, чи телефон подвійний SIM


113

Після безлічі досліджень на форумах, тепер я знаю, що немає можливості знайти серійний номер IMSI або SIM для обох SIM-карт у подвійному телефоні SIM (за винятком звернення до виробника). Тепер моє змінене питання: чи можна взагалі виявити, що в телефоні є дві SIM-карти? Я вважаю, що це можна виявити за допомогою певного інтелекту. Я думаю про декілька способів:

  1. Набір коду USSD і відстеження журналів для номера IMEI (я пробував це з * 139 # в Індії. Це спрацювало.) Це дасть мені номер IMEI для SIM-карти, з якої я набрав код USSD. (Припускається, що телефон дотримується інструкцій для android та має два номери IMEI.)

  2. Збереження серійного номера SIM-карти та / або IMSI для SIM-карти. І після виявлення будь-якого іншого IMSI / Серійного номера, навіть якщо телефон не був перезавантажений (тобто SIM була перемкнена) шляхом відстеження деяких журналів або обробки деяких трансляцій подій.

  3. Набравши * 06 #, ви побачите обидва номери IMEI. Якимось чином отримайте ці два числа. (Щось на зразок захоплення екрана та розбору зображення для тексту.)

Якщо хтось може придумати якісь інші способи, вони дуже вітаються. Я дуже вдячний за будь-яку допомогу щодо цього. Крім того, якщо хтось має будь-яку інформацію про будь-які API виробників або посилання на них, зв'яжіться з ними.


Привіт, Раджкіран, нарешті, я отримав рішення, воно добре працює для мене. Сподіваємось, це може бути корисним для всіх, хто хоче працювати з Duel SIM в мобільних додатках. API дуелі SIM-ручки не документально підтверджено. Будь ласка, перевірте мою відповідь. stackoverflow.com/questions/17618651 / ...
Jebasuthan

1
Дякую .. але ваша відповідь не відповідає на моє запитання. Я хочу всі деталі щодо другої SIM-карти та IMEI. Відповідь @Pied Piper допомагає мені все отримати.
Раджкіран

@Rajkiran Pied Piper відповідь вам справді допомогла? Я перевірив його код у m Samsung samsung galaxy y duos, але він не працює. Ви допомогли мені знайти IMEI номери подвійного сим-телефону?
Nitish Patel

@nitishpatel: Так, безумовно, це допомогло. На жаль, у мене немає Y Duos для перевірки. Але я вважаю, що Samsung використовує інший механізм для подвійної обробки SIM на Android версії 4.0 і далі. Відповідь Pied Pipers допомагає на пристроях 4.0 далі. Для решти, вам потрібно буде копати трохи більше, використовуючи роздуми.
Раджкіран

Привіт, я знаходжу рішення ... будь ласка, перевірте код stackoverflow.com/a/32304799/3131373 Це тестування на різних телефонах
user3131373

Відповіді:


184

Оновлення 23 березня'15:

Офіційний кілька SIM-інтерфейсів доступний зараз з Android 5.1

Інший можливий варіант:

Ви можете використовувати відображення Java, щоб отримати обидва номери IMEI.

Використовуючи ці номери IMEI, ви можете перевірити, чи є телефон ДВОЙНОЮ SIM-карткою чи ні.

Спробуйте виконати наступну діяльність:

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);
        }
    }
}

Редагувати:

Отримання доступу до таких методів, як "getDeviceIdGemini" для деталей іншого слота SIM, передбачає, що метод існує.

Якщо ім'я цього методу не відповідає тому, яке вказано виробником пристрою, воно не працюватиме. Ви повинні знайти відповідну назву методу для цих пристроїв.

Пошук назв методів для інших виробників можна виконати за допомогою відображення 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();
    }
} 

Редагувати:

Як вказував Сетя у своєму коментарі:

telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getDeviceIdDs", 0);
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getDeviceIdDs", 1); 

Це працює для неї. Вона отримала два номери IMEI для SIM-карти на пристрої Samsung Duos.

Додайте <uses-permission android:name="android.permission.READ_PHONE_STATE" />

EDIT 2:

Метод, який використовується для отримання даних, призначений для Lenovo A319 та інших телефонів цього виробництва (Credit Maher Abuthraa ):

telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 0); 
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 1); 

4
Класно! Це працювало для мене з "getDeviceId" на Karbonn. Буде шукати методи Samsung і оновлюватиметься тут, коли я матиме його. Спасибі людина. Кудос.
Раджкіран

1
Так. Навіть я це зробив. Встановлено, що Samsung використовує com.android.internal.telephony.RILConstants$SimCardIDвнутрішньо. Навіть намагався створити цей клас з однаковою підписом методів та однаковими іменами змінних. Але не пощастило. Спробуємо отримати вихідний код і спробуємо перевірити. Дякую.
Раджкіран

4
Я використовую telephonyInfo.imeiSIM1 = getDeviceIdBySlot (контекст, "getDeviceIdDs", 0); telephonyInfo.imeiSIM2 = getDeviceIdBySlot (контекст, "getDeviceIdDs", 1); Це працює для мене. Мені вдалося отримати два номери IMEI для обох SIM-карт.
Сета

1
Як я можу отримати номер телефону SIM2? Я отримую номер SIM1 методом telephony.getLine1Number (), у списку методу я не можу знайти такий метод, як getLine2Number () або getLine1Number (int)
DCoder

4
deviceId - це IMEI не IMSI, чи не так?
falko

5

У мене є пристрій Samsung Duos з Android 4.4.4, і метод, запропонований Seetha у прийнятій відповіді (тобто виклик getDeviceIdDs), для мене не працює, оскільки метод не існує. Мені вдалося відновити всю необхідну інформацію, викликавши метод "getDefault (int slotID)", як показано нижче:

public static void samsungTwoSims(Context context) {
    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 getFirstMethod = telephonyClass.getMethod("getDefault", parameter);

        Log.d(TAG, getFirstMethod.toString());

        Object[] obParameter = new Object[1];
        obParameter[0] = 0;
        TelephonyManager first = (TelephonyManager) getFirstMethod.invoke(null, obParameter);

        Log.d(TAG, "Device Id: " + first.getDeviceId() + ", device status: " + first.getSimState() + ", operator: " + first.getNetworkOperator() + "/" + first.getNetworkOperatorName());

        obParameter[0] = 1;
        TelephonyManager second = (TelephonyManager) getFirstMethod.invoke(null, obParameter);

        Log.d(TAG, "Device Id: " + second.getDeviceId() + ", device status: " + second.getSimState()+ ", operator: " + second.getNetworkOperator() + "/" + second.getNetworkOperatorName());
    } catch (Exception e) {
        e.printStackTrace();
    }   
}

Також я переписав код, який ітераційно перевіряє методи відновлення цієї інформації, щоб він використовував масив назв методів замість послідовності спроб / лову. Наприклад, щоб визначити, чи є у нас два активних SIM-карти:

private static String[] simStatusMethodNames = {"getSimStateGemini", "getSimState"};


public static boolean hasTwoActiveSims(Context context) {
    boolean first = false, second = false;

    for (String methodName: simStatusMethodNames) {
        // try with sim 0 first
        try {
            first = getSIMStateBySlot(context, methodName, 0);
            // no exception thrown, means method exists
            second = getSIMStateBySlot(context, methodName, 1);
           return first && second;
        } catch (GeminiMethodNotFoundException e) {
            // method does not exist, nothing to do but test the next
        }
    }
    return false;
}

Таким чином, якщо для деяких пристроїв запропоновано нове ім'я методу, ви можете просто додати його до масиву, і він повинен працювати.


4

Під час пошуку способу перевірки мережевого оператора я знайшов кілька нативних рішень.

Для API> = 17:

TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

// Get information about all radio modules on device board
// and check what you need by calling #getCellIdentity.

final List<CellInfo> allCellInfo = manager.getAllCellInfo();
for (CellInfo cellInfo : allCellInfo) {
    if (cellInfo instanceof CellInfoGsm) {
        CellIdentityGsm cellIdentity = ((CellInfoGsm) cellInfo).getCellIdentity();
        //TODO Use cellIdentity to check MCC/MNC code, for instance.
    } else if (cellInfo instanceof CellInfoWcdma) {
        CellIdentityWcdma cellIdentity = ((CellInfoWcdma) cellInfo).getCellIdentity();
    } else if (cellInfo instanceof CellInfoLte) {
        CellIdentityLte cellIdentity = ((CellInfoLte) cellInfo).getCellIdentity();
    } else if (cellInfo instanceof CellInfoCdma) {
        CellIdentityCdma cellIdentity = ((CellInfoCdma) cellInfo).getCellIdentity();
    } 
}

Додайте дозвіл в AndroidManifest:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>

Щоб отримати оператора мережі, ви можете перевірити коди mcc та mnc:

Для API> = 22:

final SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
final List<SubscriptionInfo> activeSubscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfoList) {
    final CharSequence carrierName = subscriptionInfo.getCarrierName();
    final CharSequence displayName = subscriptionInfo.getDisplayName();
    final int mcc = subscriptionInfo.getMcc();
    final int mnc = subscriptionInfo.getMnc();
    final String subscriptionInfoNumber = subscriptionInfo.getNumber();
}

Для API> = 23. Щоб просто перевірити, чи телефон подвійний / потрійний / багато сим:

TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (manager.getPhoneCount() == 2) {
    // Dual sim
}

4

Я в змозі прочитати обидва IMEI з OnePlus 2 Phone

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                TelephonyManager manager = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
                Log.i(TAG, "Single or Dual Sim " + manager.getPhoneCount());
                Log.i(TAG, "Default device ID " + manager.getDeviceId());
                Log.i(TAG, "Single 1 " + manager.getDeviceId(0));
                Log.i(TAG, "Single 2 " + manager.getDeviceId(1));
            }

Добре, що це працює на One Plus. Але просимо вас опублікувати відповіді, які працюють для всіх телефонів та всіх версій Android (можливо)
Rajkiran

1
Це офіційний SDK. Має працювати на весь телефон. Я перевірив його на OnePlus 2
Swapnil Godambe

Тож прийнята відповідь від @Swapnil говорить те саме, що правда?
Раджкіран

2

Я переглядав журнали викликів, і помітив, що крім звичайних полів у вмісті керованого Курсора, у телефонах подвійної SIM-карти є колонка "simid" (я перевірив Xolo A500s Lite), щоб позначити кожен виклик в журналі викликів за допомогою SIM-карти. Це значення або 1, або 2, найімовірніше, позначає SIM1 / SIM2.

managedCursor = context.getContentResolver().query(contacts, null, null, null, null);
managedCursor.moveToNext();        
for(int i=0;i<managedCursor.getColumnCount();i++)
{//for dual sim phones
    if(managedCursor.getColumnName(i).toLowerCase().equals("simid"))
        indexSIMID=i;
}

Я не знайшов цю колонку в одному SIM-телефоні (я перевірив на Xperia L).

Тож хоча я не думаю, що це дурний спосіб перевірити наявність подвійної SIM-карти, я розміщую це тут, оскільки це може бути корисним комусь.


Ви читаєте БД, яка? Поясніть, будь ласка, що ви тут робите. (Де зберігаються "контакти" db?
not2qubit

1

Поради:

Можна спробувати використовувати

ctx.getSystemService("phone_msim")

замість

ctx.getSystemService(Context.TELEPHONY_SERVICE)

Якщо ви вже спробували відповідь Вайбхава і telephony.getClass().getMethod()не вдається, вище це те, що працює для мого мобільного телефону Qualcomm .


Поки відповідь повна, ви можете розміщувати посилання на веб-сторінки іншими мовами для отримання додаткової інформації. meta.stackoverflow.com/questions/271060/…
мач

Це насправді було корисним посиланням , не потрібно його видаляти.
not2qubit

0

Я знайшов ці властивості системи на Samsung S8

SystemProperties.getInt("ro.multisim.simslotcount", 1) > 1

Також за даними джерела: https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/com/android/internal/telephony/TelephonyProperties.java

getprop persist.radio.multisim.configповертає " dsds" або " dsda" на мульти sim.

Я протестував це на Samsung S8, і він працює


Не звертай уваги. Android вже має API для подвійної SIM-карти. developer.android.com/about/versions/android-5.1.html#multisim Для всього іншого ви можете звернутися до вищезгаданої відповіді від @vaibhav
Rajkiran

-1

3
Так, людина. Я це знаю. Але саме тому я намагаюся знайти вирішення. І мають бути якісь. Спробуйте додаток USSDDualWidget від Play Store. Він може фактично перемикатися між двома SIM-картами. Навіть намагався змінити інженерний код, але не пощастило.
Раджкіран

Чи працює він на всіх пристроях або лише у обмеженій підмножині, яка розкриває якийсь фірмовий інтерфейс?
gonzobrains

2
Чому ця відповідь спростовується? Це правильна відповідь. ^
N Sharma

24
Багато разів публічне програмне забезпечення заявило, що це неможливо, що стало можливим іншими розробниками. Отже, це не так, як сказано в загальному випадку, завжди правильно :-)
Лаліт Поптані

1
Ви можете бути прав, але я думаю, що він є досить надійним ресурсом для всіх речей Android. Що стосується цього конкретного питання, я впевнений, що я зробив те саме, що використовував роздуми, щоб отримати дані подвійної сими, але це було для мого конкретного пристрою. До сьогоднішнього дня я все ще не вірю, що існує якийсь загальний спосіб зробити це. Також зауважте, що я цитував розробника Google, а не лише Commonsware.
gonzobrains
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.