在这里,我将描述我尝试过的两种方法。
1.) 可以从您的应用程序中显示“附加呼叫设置”屏幕。虽然它看起来像是设置应用程序的一部分,但事实并非如此。该活动是原生电话应用程序的一部分,并且可以使用以下意图进行访问:
Intent additionalCallSettingsIntent = new Intent("android.intent.action.MAIN");
ComponentName distantActivity = new ComponentName("com.android.phone", "com.android.phone.GsmUmtsAdditionalCallOptions");
additionalCallSettingsIntent.setComponent(distantActivity);
startActivity(additionalCallSettingsIntent);
然后用户必须手动按下CallerID偏好设置,并获得带有3个选项的单选按钮。
这实际上不是我在提问时想要实现的。我想避免用户必须选择任何进一步的选项的步骤。
2.) 当在本机电话应用程序中执行1.)中描述的方法时,使用了com.android.internal.telephony.Phone
中的setOutgoingCallerIdDisplay()
函数。这是下一个方法的基础:在此类上使用Java反射,并尝试使用适当的参数调用该函数:
try
{
Class <?> phoneFactoryClass = Class.forName("com.android.internal.telephony.PhoneFactory");
try
{
Method getDefaultPhoneMethod = phoneFactoryClass.getDeclaredMethod("getDefaultPhone");
Method makeDefaultPhoneMethod = phoneFactoryClass.getMethod("makeDefaultPhone" , Context.class);
try
{
makeDefaultPhoneMethod.invoke(null, this);
Object defaultPhone = getDefaultPhoneMethod.invoke(null);
Class <?> phoneInterface = Class.forName("com.android.internal.telephony.Phone");
Method getPhoneServiceMethod = phoneInterface.getMethod("setOutgoingCallerIdDisplay", int.class, Message.class);
getPhoneServiceMethod.invoke(defaultPhone, 1, null);
}
catch (InvocationTargetException ex)
{
ex.printStackTrace();
}
catch (IllegalAccessException ex)
{
ex.printStackTrace();
}
}
catch (NoSuchMethodException ex)
{
ex.printStackTrace();
}
}
catch (ClassNotFoundException ex)
{
ex.printStackTrace();
}
首先,我尝试使用getDefaultPhone(),但是我得到了RuntimeException。
"PhoneFactory.getDefaultPhone必须从Looper线程中调用"
显然,问题在于我试图从不是本机电话应用程序的消息循环中调用此方法。
尝试通过创建自己的默认电话来避免这个问题,但这是一种安全违规:
ERROR/AndroidRuntime(2338): java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.provider.Telephony.SPN_STRINGS_UPDATED from pid=2338, uid=10048
克服这个问题的唯一方法(两个问题)是使用与核心系统应用程序相同的密钥签署您的应用程序,如下所述
我不确定这是否是全球性的功能,但澳大利亚手机可以通过在呼叫者号码前加上#31#或1831来隐藏其号码。这可能不是完美的解决方案,但像这样的前缀可能在编程期间适用于您的要求。