您的位置:首页 > 移动开发 > Android开发

android学习笔记---双卡双待

2014-04-22 18:16 363 查看
简介

Android双卡双待已经越来越普及了,解决双卡双待管理是广大手机开发人员必须得面对的问题,为实现Android平台的双卡双待操作,笔者研究了Android 应用层操作双卡双待的机制。

机制

获取基于ITelephony接口实现phone应用中的“phone服务”,通过TelephonyManager接口获取不同的卡(GSMPhone /CDMAPhone)进行不同的操作(拨号、接通、挂断、保持通话等)。

Android平台是一个多样型的平台,不同的手机获取ITelephony接口不同,用一种方法实现双卡双待管理是不可取的。那怎么办呢?只有针对不同的手机分析出一套管理的方案,该方案实现难度大,因为需要各个厂家的SDK的资料。为了实现该功能,笔者做了大量工作,整合各个厂家的SDK的资料。

实现

为了更好的管理双卡双待的问题,新建一个双卡双待模块静态库,其它项目引用便是,项目如图:



AbsSim是抽象类,负责实现手机操作的类。不同的厂家继承该类实现各自的接口。AbsSim信息如下:

[cpp] view
plaincopy





public abstract class AbsSim implements IDualDetector { //抽象基类

protected final String TAG = getClass().getSimpleName();

protected ArrayList<SimSlot> mSimSlots = new ArrayList<SimSlot>();

protec
4000
ted boolean mIsDualSimPhone = false;

protected String mCallLogExtraField = "";

public abstract String getSimPhoneNumber(int paramInt); // 返回手机号码

public abstract int getDataState(int paramInt);// 返回数据状态

public abstract String getIMSI(int paramInt);// 返回手机标识

public abstract String getIMSI(int paramInt, Context paramContext);// 返回手机标识

public abstract int getPhoneState(int paramInt);// 返回手机状态

public abstract boolean isServiceAvaliable(int paramInt);// 服务是否可用

public abstract boolean isSimStateIsReady(int paramInt);// 卡是否在使用

public abstract int getSimOperator(int paramInt);// 服务商(电信、移动、联通)

protected abstract Object getITelephonyMSim(int paramInt);// 获取操作接口

protected abstract Object getMSimTelephonyManager(int paramInt);// 获取操作接口

@Override

public AbsSim detect() { // 根据手机信息匹配

if ((getITelephonyMSim(0) != null) && (getITelephonyMSim(1) != null)

// && (getmMSimSmsManager(0) != null)

// && (getmMSimSmsManager(1) != null)

// && (detectSms(paramContext, paramBoolean))

// && (detectCallLog(paramContext, paramBoolean))

)

return this;

return null;

}

public boolean directCall(String paramString, int paramInt) { // 拨打电话(根据不同卡拨打电话)

Intent localIntent = new Intent("android.intent.action.CALL",

Uri.fromParts("tel", paramString, null));

localIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

try {

getContext().startActivity(localIntent);

return true;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

return false;

}

protected boolean detectCallLog() { // 通过通话记录信息匹配

return false;

}

protected boolean detectSms() {// 通过短信记录信息匹配

return false;

}

protected Context getContext() { // 返回句柄

return SimManager.getInstance().getContext();

}

protected int getSimSlotNum() { // 返回插槽个数(默认2)

return 2;

}

public void init() { // 初始化

for (int i = 0; i < getSimSlotNum(); i++) {

try {

String imsi = getIMSI(i);

boolean isUsing = isSimStateIsReady(i);

if (imsi != null || isUsing) {

if (imsi == null || hasSimSlotByIMSI(imsi))

continue;

SimSlot simSlot = new SimSlot();

mSimSlots.add(simSlot);

simSlot.setUsing(isUsing);

simSlot.setIMSI(imsi);

simSlot.setSimOperator(getSimOperator(i));

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

public boolean hasSimPhone() {// 是否有sd卡在使用

if (mSimSlots.isEmpty())

return false;

for (SimSlot simslot : mSimSlots) {

if (simslot.isUsing())

return true;

}

return false;

}

public boolean isDualSimPhone() {// 是否为双卡

if (getSimSlots().isEmpty() || getSimSlots().size() < 2)

return false;

for (SimSlot simSlot : getSimSlots()) {

if (!simSlot.isUsing())

return false;

}

return true;

}

public ArrayList<SimSlot> getSimSlots() { // 返回已确认的卡

return mSimSlots;

}

protected boolean delSimSlotByIMSI(String imsi) { // 删除相同的卡的信息

for (SimSlot simSlot : getSimSlots()) {

if (simSlot.getIMSI() != null && simSlot.getIMSI().equals(imsi)) {

getSimSlots().remove(simSlot);

}

}

return false;

}

protected boolean hasSimSlotByIMSI(String imsi) {

for (SimSlot simSlot : getSimSlots()) {

if (simSlot.getIMSI() != null && simSlot.getIMSI().equals(imsi)) {

return true;

}

}

return false;

}

}

现在列举一款实现MTK方案:

[cpp] view
plaincopy





public class MTKDualSim extends AbsSim {// 采用MTK方案的类(根据厂家SDK实现不同的接口)

private Object mMSimTelephonyManager = null;

private Object mTelephonyMSim = null;

public MTKDualSim() {

mCallLogExtraField = "simid";

String str1 = SimManager.getModel();

String str2 = SimManager.getManufaturer();

if ((str1 != null) && (str2 != null)) {

String str3 = str1.toLowerCase();

String str4 = str2.toLowerCase();

if ((str4.indexOf("huawei") > -1) && (str3.indexOf("h30-t00") > -1))

mCallLogExtraField = "subscription";

if ((str4.indexOf("hisense") > -1)

&& (str3.indexOf("hs-u970") > -1)) {

mCallLogExtraField = "subtype";

}

}

}

@Override

public boolean directCall(String paramString, int paramInt) {

if (SimManager.isSDKVersionMore4_1()) {

Intent localIntent1 = new Intent("android.intent.action.CALL",

Uri.fromParts("tel", paramString, null));

localIntent1.putExtra("simId", paramInt);

localIntent1.putExtra("com.android.phone.extra.slot", paramInt);

localIntent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

try {

getContext().startActivity(localIntent1);

return true;

} catch (Throwable localThrowable1) {

localThrowable1.printStackTrace();

}

} else if (SimManager.isSDKVersionMore4_0()) {

Intent localIntent2 = new Intent(

"com.android.phone.OutgoingCallReceiver");

localIntent2.putExtra("com.android.phone.extra.slot", paramInt);

localIntent2.putExtra("simId", paramInt);

localIntent2.putExtra("com.android.phone.force.slot", true);

localIntent2.setClassName("com.android.phone",

"com.android.phone.OutgoingCallReceiver");

localIntent2.setData(Uri.fromParts("tel", paramString, null));

try {

getContext().sendBroadcast(localIntent2);

return true;

} catch (Throwable localThrowable2) {

localThrowable2.printStackTrace();

}

}

try {

Intent localIntent3 = new Intent();

localIntent3.setAction("out_going_call_to_phone_app");

localIntent3.putExtra("number", paramString);

localIntent3.putExtra("simId", paramInt);

localIntent3.putExtra("com.android.phone.extra.slot", paramInt);

localIntent3.putExtra("launch_from_dialer", 1);

localIntent3.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

getContext().sendBroadcast(localIntent3);

return true;

} catch (Throwable localThrowable3) {

localThrowable3.printStackTrace();

}

return false;

}

@Override

public AbsSim detect() {

String imsi = getIMSI(0);

if (imsi != null && !TextUtils.isEmpty(imsi)) {

return this;

}

return super.detect();

}

@Override

public String getSimPhoneNumber(int paramInt) {

Object[] arrayOfObject2 = new Object[1];

try {

Object localObject = getMSimTelephonyManager(paramInt);

arrayOfObject2[0] = Integer.valueOf(paramInt);

String result = (String) ReflecterHelper.invokeMethod(localObject,

"getLine1NumberGemini", arrayOfObject2);

arrayOfObject2 = null;

return result;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

return "";

}

@Override

public int getDataState(int paramInt) {

Object[] arrayOfObject2 = new Object[1];

try {

Object localObject = getMSimTelephonyManager(paramInt);

arrayOfObject2[0] = Integer.valueOf(paramInt);

int result = ((Integer) ReflecterHelper.invokeMethod(localObject,

"getDataStateGemini", arrayOfObject2)).intValue();

arrayOfObject2 = null;

return result;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

arrayOfObject2 = null;

return -1;

}

@Override

public String getIMSI(int paramInt) {

return getIMSI(paramInt, null);

}

@Override

public String getIMSI(int paramInt, Context paramContext) {

Object localObject = getMSimTelephonyManager(paramInt);

Object[] arrayOfObject2 = new Object[1];

try {

arrayOfObject2[0] = Integer.valueOf(paramInt);

String result = (String) ReflecterHelper.invokeMethod(localObject,

"getSubscriberIdGemini", arrayOfObject2);

arrayOfObject2 = null;

return result;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

arrayOfObject2 = null;

return null;

}

@Override

public int getPhoneState(int paramInt) {

Object localObject = getMSimTelephonyManager(paramInt);

Object[] arrayOfObject2 = new Object[1];

try {

arrayOfObject2[0] = Integer.valueOf(paramInt);

int result = ((Integer) ReflecterHelper.invokeMethod(localObject,

"getCallStateGemini", arrayOfObject2)).intValue();

arrayOfObject2 = null;

return result;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

arrayOfObject2 = null;

return 0;

}

@Override

public boolean isServiceAvaliable(int paramInt) {

Object localObject = getITelephonyMSim(paramInt);

if (localObject == null)

return false;

Object[] arrayOfObject2 = new Object[1];

try {

arrayOfObject2[0] = Integer.valueOf(paramInt);

boolean result = ((Boolean) ReflecterHelper.invokeMethod(

localObject, "isRadioOnGemini", arrayOfObject2))

.booleanValue();

arrayOfObject2 = null;

return result;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

arrayOfObject2 = null;

return false;

}

@Override

public boolean isSimStateIsReady(int paramInt) {

Object localObject = getMSimTelephonyManager(paramInt);

if (localObject != null) {

Object[] arrayOfObject2 = new Object[1];

try {

arrayOfObject2[0] = Integer.valueOf(paramInt);

int result = ((Integer) ReflecterHelper.invokeMethod(

localObject, "getSimStateGemini", arrayOfObject2))

.intValue();

arrayOfObject2 = null;

return result == 5;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

arrayOfObject2 = null;

}

return false;

}

@Override

public int getSimOperator(int paramInt) { // 注意

Object localObject = getMSimTelephonyManager(paramInt);

Object[] arrayOfObject2 = new Object[1];

try {

arrayOfObject2[0] = Integer.valueOf(paramInt);

String result = ((String) ReflecterHelper.invokeMethod(localObject,

"getSimOperatorGemini", arrayOfObject2));

arrayOfObject2 = null;

return Integer.valueOf(result);

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

arrayOfObject2 = null;

return 0;

}

@Override

protected Object getITelephonyMSim(int paramInt) {

if (mTelephonyMSim == null)

mTelephonyMSim = ITelephony.Stub.asInterface(ServiceManager

.getService("phone"));

return mTelephonyMSim;

}

@Override

protected Object getMSimTelephonyManager(int paramInt) {

if (mMSimTelephonyManager != null)

return mMSimTelephonyManager;

Object[] arrayOfObject3 = new Object[1];

try {

mMSimTelephonyManager = SimManager.getInstance()

.getTelephonyManagerByPhone();

try {

Object localObject = mMSimTelephonyManager;

arrayOfObject3[0] = Integer.valueOf(0);

ReflecterHelper.invokeMethod(localObject,

"getSubscriberIdGemini", arrayOfObject3);

arrayOfObject3 = null;

return mMSimTelephonyManager;

} catch (Throwable localThrowable2) {

localThrowable2.printStackTrace();

}

} catch (Throwable localThrowable1) {

localThrowable1.printStackTrace();

}

arrayOfObject3 = null;

return null;

}

}

再列举一款单卡的方案:

[cpp] view
plaincopy





public class SingleSim extends AbsSim implements IDualDetector {// 单卡方案

private final String TAG = getClass().getSimpleName();

private HashMap<String, Byte> mCallLogExtraFields = new SingleSim$1(this);

@Override

public boolean hasSimPhone() {

return false;

}

@Override

public AbsSim detect() {// 根据某些字段判是否为双卡(有可能误判)

if (mIsDualSimPhone)

return null;

Cursor localSafeCursor = null;

String[] arrayOfString;

try {

localSafeCursor = SimManager

.getInstance()

.getContext()

.getContentResolver()

.query(CallLog.Calls.CONTENT_URI, null, null, null,

"_id limit 0,1");

if (localSafeCursor != null && localSafeCursor.moveToFirst()) {

arrayOfString = localSafeCursor.getColumnNames();

for (int i = 0; i < arrayOfString.length; i++) {

String str = arrayOfString[i];

if (mCallLogExtraFields.containsKey(str.toLowerCase())) {

mIsDualSimPhone = true;

mCallLogExtraField = str;

}

}

}

} catch (Exception e) {

e.printStackTrace();

}

return this;

}

@Override

public boolean isDualSimPhone() {

return mIsDualSimPhone;

}

@Override

public int getSimSlotNum() {

return 1;

}

@Override

public String getSimPhoneNumber(int paramInt) {

return ((TelephonyManager) getMSimTelephonyManager(0)).getLine1Number();

}

@Override

public int getDataState(int paramInt) {

return ((TelephonyManager) getMSimTelephonyManager(0)).getDataState();

}

@Override

public String getIMSI(int paramInt) {

return ((TelephonyManager) getMSimTelephonyManager(0)).getDeviceId();

}

@Override

public String getIMSI(int paramInt, Context paramContext) {

return ((TelephonyManager) getMSimTelephonyManager(0))

.getSubscriberId();

}

@Override

public int getPhoneState(int paramInt) {

return ((TelephonyManager) getMSimTelephonyManager(0)).getCallState();

}

@Override

public boolean isServiceAvaliable(int paramInt) {

ITelephony localITelephony = (ITelephony) getITelephonyMSim(0);

if (localITelephony == null)

return false;

try {

boolean bool = localITelephony.isRadioOn();

return bool;

} catch (Throwable localThrowable) {

localThrowable.printStackTrace();

}

return false;

}

@Override

public boolean isSimStateIsReady(int paramInt) {

return ((TelephonyManager) getMSimTelephonyManager(0)).getSimState() == 5;

}

@Override

public int getSimOperator(int paramInt) {

TelephonyManager localTelephonyManager = (TelephonyManager) getMSimTelephonyManager(paramInt);

return Integer.parseInt(localTelephonyManager.getSimOperator());

}

@Override

protected Object getITelephonyMSim(int paramInt) {

return SimManager.getInstance().getITelephonyByPhone();

}

@Override

protected Object getMSimTelephonyManager(int paramInt) {

return SimManager.getInstance().getTelephonyManagerByPhone();

}

}

总结

利用java 反射机制操作Android隐藏的类,很好的解决了双卡双待的问题。

Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和methods的所有信息,并可于运行时改变fields内容或唤起methods。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android