Skip to content

Instantly share code, notes, and snippets.

@falkolab
Last active September 11, 2017 12:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save falkolab/2eb217822a1b9931d34c to your computer and use it in GitHub Desktop.
Save falkolab/2eb217822a1b9931d34c to your computer and use it in GitHub Desktop.
Titanium android module proxy to check whether the phone is dual SIM
// http://stackoverflow.com/a/17499889/506724
package com.falkolab.drunkmode.platform;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.appcelerator.kroll.KrollProxy;
import org.appcelerator.kroll.annotations.Kroll;
import org.appcelerator.kroll.common.Log;
import org.appcelerator.titanium.TiApplication;
import android.content.Context;
import android.telephony.TelephonyManager;
@Kroll.proxy
public class TelephonyInfoProxy extends KrollProxy {
private static final String TAG = TelephonyInfoProxy.class.getSimpleName();
private static TelephonyInfoProxy info;
private String imeiSIM1;
private String imeiSIM2;
private String imsiSIM1;
private String imsiSIM2;
private boolean isSIM1Ready;
private boolean isSIM2Ready;
private String[] getDeviceIdMethods = { "getDeviceId", "getDeviceIdGemini",
"getDeviceIdDs" };
private String[] getSimStateBySlotMethods = { "getSimStateGemini",
"getSimState", "getSimStateDs" };
private String[] getSubscriberIdMethods = { "getSubscriberId",
"getSubscriberIdGemini" };
private String getDeviceIdMethodName = null;
private String getSimStateBySlotMethodName = null;
private String getSubscriberIdMethodName = null;
public TelephonyInfoProxy() {
super();
}
@Kroll.method
@Kroll.getProperty
public String getImeiSIM1() {
return imeiSIM1;
}
@Kroll.method
@Kroll.getProperty
public String getImeiSIM2() {
return imeiSIM2;
}
@Kroll.method
@Kroll.getProperty
public String getImsiSIM1() {
return imsiSIM1;
}
@Kroll.method
@Kroll.getProperty
public String getImsiSIM2() {
return imsiSIM2;
}
@Kroll.method
@Kroll.getProperty(name = "isSIM1Ready")
public boolean isSIM1Ready() {
return isSIM1Ready;
}
@Kroll.method
@Kroll.getProperty(name = "isSIM2Ready")
public boolean isSIM2Ready() {
return isSIM2Ready;
}
@Kroll.method
@Kroll.getProperty(name = "isDualSIM")
public boolean isDualSIM() {
return imeiSIM2 != null;
}
private void detectManufacturerMethods() {
TiApplication tiApp = TiApplication.getInstance();
if (getDeviceIdMethodName != null
&& getSimStateBySlotMethodName != null) {
return;
}
TelephonyManager telephony = (TelephonyManager) tiApp
.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> telephonyClass;
try {
telephonyClass = Class.forName(telephony.getClass().getName());
} catch (ClassNotFoundException e) {
return;
}
String currentMethodName = null;
try {
if (getDeviceIdMethodName == null) {
for (String methodName : getDeviceIdMethods) {
currentMethodName = methodName;
Class<?>[] parameter = new Class[1];
parameter[0] = int.class;
String dmsg = "Test for method:" + methodName + "(simId)";
try {
telephonyClass.getMethod(methodName, parameter);
Log.d(TAG, dmsg + "- ok");
getDeviceIdMethodName = methodName;
break;
} catch (NoSuchMethodException e) {
Log.d(TAG, dmsg + "- not found");
}
}
}
if (getSubscriberIdMethodName == null) {
for (String methodName : getSubscriberIdMethods) {
currentMethodName = methodName;
Class<?>[] parameter = new Class[1];
parameter[0] = int.class;
String dmsg = "Test for method:" + methodName + "(simId)";
try {
telephonyClass.getMethod(methodName, parameter);
Log.d(TAG, dmsg + "- ok");
getSubscriberIdMethodName = methodName;
break;
} catch (NoSuchMethodException e) {
Log.d(TAG, dmsg + "- not found");
}
}
}
if (getSimStateBySlotMethodName == null) {
for (String methodName : getSimStateBySlotMethods) {
currentMethodName = methodName;
Class<?>[] parameter = new Class[1];
parameter[0] = int.class;
String dmsg = "Test for method:" + methodName + "(simId)";
try {
telephonyClass.getMethod(methodName, parameter);
Log.d(TAG, dmsg + "- ok");
getSimStateBySlotMethodName = methodName;
break;
} catch (NoSuchMethodException e) {
Log.d(TAG, dmsg + "- not found");
}
}
}
} catch (SecurityException e) {
Log.e(TAG, "Can't get method '" + currentMethodName
+ "' accordance with security restriction");
}
}
public static TelephonyInfoProxy getInstance() {
if (info == null) {
TiApplication tiApp = TiApplication.getInstance();
Context context = (Context) tiApp;
info = new TelephonyInfoProxy();
info.detectManufacturerMethods();
TelephonyManager telephonyManager = ((TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE));
info.imeiSIM1 = telephonyManager.getDeviceId();
info.imeiSIM2 = null;
if (info.getDeviceIdMethodName != null) {
info.imeiSIM1 = getStringValueBySlot(context,
info.getDeviceIdMethodName, 0);
info.imeiSIM2 = getStringValueBySlot(context,
info.getDeviceIdMethodName, 1);
Log.d(TAG, "Was used method: " + info.getDeviceIdMethodName);
}
if (info.getSubscriberIdMethodName != null) {
info.imsiSIM1 = getStringValueBySlot(context,
info.getSubscriberIdMethodName, 0);
info.imsiSIM2 = getStringValueBySlot(context,
info.getSubscriberIdMethodName, 1);
Log.d(TAG, "Was used method: " + info.getSubscriberIdMethodName);
} else {
try {
// http://stackoverflow.com/a/30647918/2267723
String imsiParcel = runCommand("service call iphonesubinfo 3");
info.imsiSIM1 = getNumberFromParcel(imsiParcel);
imsiParcel = runCommand("service call iphonesubinfo2 3");
info.imsiSIM2 = getNumberFromParcel(imsiParcel);
Log.d(TAG, "Was used method: service call iphonesubinfo");
} catch (Exception e) {
Log.d(TAG, "Couldn't get multi SIM IMSI info");
}
}
info.isSIM1Ready = telephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY;
info.isSIM2Ready = false;
if (info.getSimStateBySlotMethodName != null) {
info.isSIM1Ready = getSIMStateBySlot(context,
info.getSimStateBySlotMethodName, 0);
info.isSIM2Ready = getSIMStateBySlot(context,
info.getSimStateBySlotMethodName, 1);
Log.d(TAG, "Was used method: "
+ info.getSimStateBySlotMethodName);
}
}
return info;
}
private static Object invokePredictedMethod(Context context,
String predictedMethodName, int slotID) throws SecurityException,
NoSuchMethodException {
TelephonyManager telephony = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> telephonyClass;
try {
telephonyClass = Class.forName(telephony.getClass().getName());
} catch (ClassNotFoundException e1) {
return null;
}
Class<?>[] parameter = new Class[1];
parameter[0] = int.class;
Method m = telephonyClass.getMethod(predictedMethodName, parameter);
Object[] obParameter = new Object[1];
obParameter[0] = slotID;
try {
return m.invoke(telephony, obParameter);
} catch (Exception e) {
Log.e(TAG, "Can't invokation to method: " + predictedMethodName);
return null;
}
}
private static String getStringValueBySlot(Context context,
String predictedMethodName, int slotID) {
Object ob;
try {
ob = invokePredictedMethod(context, predictedMethodName, slotID);
return ob != null ? ob.toString() : null;
} catch (SecurityException e) {
e.printStackTrace();
return null;
} catch (NoSuchMethodException e) {
e.printStackTrace();
return null;
}
}
private static boolean getSIMStateBySlot(Context context,
String predictedMethodName, int slotID) {
Object ob_phone;
try {
ob_phone = invokePredictedMethod(context, predictedMethodName,
slotID);
if (ob_phone != null
&& Integer.parseInt(ob_phone.toString()) == TelephonyManager.SIM_STATE_READY) {
return true;
} else {
return false;
}
} catch (SecurityException e) {
e.printStackTrace();
return false;
} catch (NoSuchMethodException e) {
e.printStackTrace();
return false;
}
}
public static String runCommand(String src) {
try {
Process process = Runtime.getRuntime().exec(src);
BufferedReader reader = new BufferedReader(new InputStreamReader(
process.getInputStream()));
int read;
char[] buffer = new char[2048];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
// Waits for the command to finish.
process.waitFor();
return output.toString();
} catch (IOException e) {
Log.e(TAG, "IOException:" + e.getMessage());
return null;
} catch (InterruptedException e) {
Log.e(TAG, "InterruptedException:" + e.getMessage());
return null;
}
}
public static String getNumberFromParcel(String str) {
String res = "";
if (str != null && str.length() > 0) {
String lines[] = str.split("\n");
for (String line : lines) {
if (line == null || line.length() == 0)
continue;
String content[] = line.split("'");
if (content.length > 1) {
res += content[1].replace(".", "");
}
}
} else
return "NA";
return res;
}
@Kroll.method
public String[] listAvailableMethods() {
TiApplication tiApp = TiApplication.getInstance();
TelephonyManager telephony = (TelephonyManager) tiApp
.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> telephonyClass;
ArrayList<String> methodsInfo = new ArrayList<String>();
try {
telephonyClass = Class.forName(telephony.getClass().getName());
Method[] methods = telephonyClass.getMethods();
for (int idx = 0; idx < methods.length; idx++) {
methodsInfo.add(methods[idx] + " declared by "
+ methods[idx].getDeclaringClass());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String[] result = new String[methodsInfo.size()];
return (String[]) methodsInfo.toArray(result);
}
}
@Kroll.module(name="Telephony", id="...")
public class TelephonyModule extends KrollModule
{
public TelephonyModule()
{
super();
}
@Kroll.method(name = "createTelephonyInfo")
public TelephonyInfoProxy createTelephonyInfoProxy()
{
return TelephonyInfoProxy.getInstance();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment