Android:スマートフォンがデュアルSIMかどうかを確認する


113

フォーラムで多くの調査を行った結果、デュアルSIM電話の両方のSIMカードのIMSIまたはSIMシリアル番号を見つける方法がないことがわかりました(製造元への連絡を除く)。私の変更された質問は、電話に2つのSIMが搭載されていることをまったく検出できるかどうかです。ある程度の知能で検出できると思います。私が考えることができるいくつかの方法は次のとおりです。

  1. USSDコードをダイヤルし、IMEI番号のログをトレースします(インドで* 139#を使用してこれを試しました。動作しました。)これにより、USSDコードをダイヤルしたSIMのIMEI番号がわかります。(スマートフォンはAndroidガイドラインに準拠しており、IMEI番号が2つあると想定されています。)

  2. SIMのSIMシリアル番号やIMSIを保存します。また、一部のログをトレースしたり、ブロードキャストイベントの処理を行ったりして電話を再起動しなかった(SIMを切り替えた)場合でも、他のIMSI /シリアル番号を検出した後。

  3. * 06#をダイヤルすると、両方のIMEI番号が表示されます。何らかの方法で、これらの2つの数値を取得します。(テキストの画面キャプチャや画像解析のようなもの。)

誰か他の方法を考えることができれば、彼らは大歓迎です。私はこれに関してどんな種類の助けにも本当に感謝します。また、製造元のAPIに関する情報や連絡先のリンクがある場合は、コミュニティの人々と共有してください。


こんにちはラジキラン、最後に私は解決策を私のためにうまく機能するようにしました モバイルアプリケーションでDuel SIMを処理したいすべての人に役立つことを願っています。決闘SIMハンドルAPIは文書化されていません。私の答えが私にとってうまく機能していることを確認してください。stackoverflow.com/questions/17618651/...
Jebasuthan

1
ありがとう..しかし、あなたの答えは私の質問に答えません。2番目のSIMとIMEIに関するすべての詳細が必要です。@Pied Piperの答えは私がすべてを得るのに役立ちます。
Rajkiran 14

@Rajkiran Pied Piperの回答は本当に役に立ちましたか?私はm samsung galaxy y duosで彼のコードを確認しましたが、機能しません。デュアルsim電話のIMEI noを見つけるのを手伝ってくれましたか?
Nitish Patel 14

@nitishpatel:はい、間違いなく役に立ちました。残念ながら、チェックするY Duosはありません。しかし、サムスンは、Androidバージョン4.0以降のデュアルSIM処理に異なるメカニズムを使用していると思います。Pied Pipersの回答は、4.0以降のデバイスで役立ちます。残りについては、リフレクションを使用してもう少し掘り下げる必要があります。
Rajkiran 14

こんにちは、私は解決策を見つけました...コードを確認してくださいstackoverflow.com/a/32304799/3131373 これはさまざまな電話でテストされています
user3131373

回答:


184

2015年3月23日更新:

公式の複数SIM APIがAndroid 5.1以降で利用可能になりました

その他の可能なオプション:

Javaリフレクションを使用て、両方のIMEI番号を取得できます。

これらのIMEI番号を使用して、電話がDUAL 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);
        }
    }
}

編集:

他の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();
    }
} 

編集:

以下のようシーサは彼女のコメントで指摘しました:

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

それは彼女のために働いています。彼女は、Samsung Duosデバイスの両方のSIMに対して2つのIMEI番号を取得することに成功しました。

追加 <uses-permission android:name="android.permission.READ_PHONE_STATE" />

編集2:

データを取得するために使用される方法は、その製造元(Credit Maher Abuthraa)によるLenovo A319およびその他の電話用です。

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

4
涼しい!Karbonnで「getDeviceId」を使用すると、うまくいきました。サムスンの方法を検索し、一緒に持っている場合はここで更新します。ありがとう。称賛。
Rajkiran 2013

1
はい。私もそうしました。Samsungがcom.android.internal.telephony.RILConstants$SimCardID社内で使用していることがわかりました。メソッドの同じシグネチャと変数の同じ名前でそのクラスを作成してみました。しかし、運はありません。ソースコードの取得を試み、チェックを試みます。ありがとう。
Rajkiran 2013

4
私はtelephonyInfo.imeiSIM1 = getDeviceIdBySlot(context、 "getDeviceIdDs"、0); telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context、 "getDeviceIdDs"、1);を使用しています。それは私のために働いています。両方のSIMに対して2つのIMEI番号を取得することに成功しました。
Seetha

1
SIM2の電話番号を取得するにはどうすればよいですか?telephony.getLine1Number()メソッドを使用してSIM1番号を取得していますが、メソッドのリストでgetLine2Number()やgetLine1Number(int)などのメソッドが見つかりません
DCoder

4
deviceIdはIMSIではなくIMEIですよね?
ファルコ2015

5

Android 4.4.4を搭載したSamsung Duosデバイスを使用していて、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();
    }   
}

また、この情報を回復するためにメソッドを繰り返しテストするコードを書き直して、try / catchのシーケンスではなくメソッド名の配列を使用するようにしました。たとえば、2つのアクティブな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

OnePlus 2 Phoneから両方のIMEIを読むことができます

 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から受け入れられた答えは同じことを正しいと言いますか?
Rajkiran

2

私は通話ログを見ていたところ、managedCursorのコンテンツの通常のフィールドとは別に、デュアルSIM電話(「Xolo A500s Lite」で確認した)に「simid」という列があり、各通話にタグを付けることがわかりました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)

Vaibhavの答えをすでに試し、telephony.getClass().getMethod()失敗した場合、上記は私のQualcommモバイルで機能します。


回答が完全である限り、補足情報として他の言語のWebページへのリンクを投稿できます。meta.stackoverflow.com/questions/271060/...
マッハ

これは実際には便利なリンクであり、削除する必要はありません。
not2qubit 2017

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」を返します。

私はサムスンS8でこれをテストしましたが、動作します


気にしないで。AndroidにはすでにデュアルSIM用のAPIがすでにあります。developer.android.com/about/versions/android-5.1.html#multisim その他については、@ vaibhavによる上記の回答を参照できます
Rajkiran

-1

Commonswareは、これは不可能だと言っています。以下をご覧ください。

Android SDKを使用してデュアルSIMを検出することはできません。

これは主題に関するさらなる対話です:

Google開発チームの担当者は、Android SDKを使用してデュアルSIMを検出することは不可能だと述べています。


3
はい男。そんなこと知ってる。しかし、それが私が回避策を見つけようとしている理由です。そして、いくつかある必要があります。PlayストアからUSSDDualWidgetアプリをお試しください。2つのSIMを実際に切り替えることができます。コードをリバースエンジニアリングしようとしても、運はありませんでした。
Rajkiran 2013

それはすべてのデバイスで動作しますか、それとも何らかの独自のインターフェースを公開する限られたサブセットで動作しますか?
ゴンゾブレーン

2
なぜこの回答は反対投票されたのですか?これが正解です。^
Nシャルマ

24
多くの場合、コモンズウェアは言っています 、他の開発者によって可能にされた不可能をています。したがって、コモンズウェアが言うことは常に正しいというわけではありません:-)
Lalit Poptani 14年

1
あなたは正しいかもしれませんが、私は彼がAndroidのすべてのものについてかなり信頼できるリソースだと思います。この特定の問題については、確かに同じことを行い、リフレクションを使用してデュアルsimデータを取得しましたが、それは私の特定のデバイス用でした。今日に至るまで、これを行う一般的な方法があるとはまだ信じていません。また、Commonswareだけでなく、Google開発者も引用していることに注意してください。
ゴンゾブレーン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.