Java ClassCastException:怎么会这样?
Java ClassCastException: How Come?
我正在尝试使用 Android 电话管理器结束通话(新的呼叫筛选 API 不适合我)。我在网上找到了很多例子,都和我下面的代码非常相似。它编译得很好,但我在行
上得到了一个运行时 ClassCastException
telephonyService = (ITelephony) m.invoke(tm);
例外是
java.lang.ClassCastException:
com.android.internal.telephony.ITelephony$Stub$Proxy
cannot be cast to com.ramrod.MyApp.IncomingCallReceiver$ITelephony
我的密码是
public class IncomingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ITelephony telephonyService;
try {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING)){
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
try {
Method m = tm.getClass().getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(tm);
if ((number != null)) {
telephonyService.endCall();
}
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(context, "Ring " + number, Toast.LENGTH_SHORT).show();
}
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_OFFHOOK)){
Toast.makeText(context, "Answered " + number, Toast.LENGTH_SHORT).show();
}
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context, "Idle "+ number, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
我找到的示例也直接包含 Java 接口,如下所示:
public static interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
是什么导致了这种异常?我该如何解决?
(我对添加的界面非常怀疑)。
我也试过导入 com.android.internal.telephony(包括 ITelephony),但不兼容。
编译成功是因为你使用了反射:Object Method.invoke()
.
反射在编译时通常很好,但在运行时可能不太好。
在这里,您尝试转换的实例在运行时 Proxy
,更准确地说是嵌套的 class:com.android.internal.telephony.ITelephony.Stub.Proxy
。
您定义为 MyApp.IncomingCallReceiver
的嵌套 class 的接口 ITelephony
不是 Proxy
class 的实例。这是肯定的,因为它没有扩展 :
public static interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
而 class 转换异常。
我想 Proxy
是 com.android.internal.telephony.ITelephony
的生成实现,所以您需要做的可能只是导入 class 并转换为 class :
import com.android.internal.telephony.ITelephony;
//..
telephonyService = (ITelephony) m.invoke(tm);
我正在尝试使用 Android 电话管理器结束通话(新的呼叫筛选 API 不适合我)。我在网上找到了很多例子,都和我下面的代码非常相似。它编译得很好,但我在行
上得到了一个运行时 ClassCastExceptiontelephonyService = (ITelephony) m.invoke(tm);
例外是
java.lang.ClassCastException:
com.android.internal.telephony.ITelephony$Stub$Proxy
cannot be cast to com.ramrod.MyApp.IncomingCallReceiver$ITelephony
我的密码是
public class IncomingCallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ITelephony telephonyService;
try {
String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_RINGING)){
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
try {
Method m = tm.getClass().getDeclaredMethod("getITelephony");
m.setAccessible(true);
telephonyService = (ITelephony) m.invoke(tm);
if ((number != null)) {
telephonyService.endCall();
}
} catch (Exception e) {
e.printStackTrace();
}
Toast.makeText(context, "Ring " + number, Toast.LENGTH_SHORT).show();
}
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_OFFHOOK)){
Toast.makeText(context, "Answered " + number, Toast.LENGTH_SHORT).show();
}
if(state.equalsIgnoreCase(TelephonyManager.EXTRA_STATE_IDLE)){
Toast.makeText(context, "Idle "+ number, Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
e.printStackTrace();
}
}
我找到的示例也直接包含 Java 接口,如下所示:
public static interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
是什么导致了这种异常?我该如何解决?
(我对添加的界面非常怀疑)。
我也试过导入 com.android.internal.telephony(包括 ITelephony),但不兼容。
编译成功是因为你使用了反射:Object Method.invoke()
.
反射在编译时通常很好,但在运行时可能不太好。
在这里,您尝试转换的实例在运行时 Proxy
,更准确地说是嵌套的 class:com.android.internal.telephony.ITelephony.Stub.Proxy
。
您定义为 MyApp.IncomingCallReceiver
的嵌套 class 的接口 ITelephony
不是 Proxy
class 的实例。这是肯定的,因为它没有扩展 :
public static interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
而 class 转换异常。
我想 Proxy
是 com.android.internal.telephony.ITelephony
的生成实现,所以您需要做的可能只是导入 class 并转换为 class :
import com.android.internal.telephony.ITelephony;
//..
telephonyService = (ITelephony) m.invoke(tm);