我正在创建简单的呼叫过滤器应用程序,以限制不必要的呼叫我使用以下代码限制调用,但我无法在下面的代码“ com.android.internal.telephony.ITelephony telephonyService =(ITelephony)m.invoke(tm); ”中解决此行的问题它显示错误消息com.android.internal.telephony无法解析为android中的类型如何解决此错误。
public class CallBlockReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
}
private void getTeleService(Context context) {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
try {
// Java reflection to gain access to TelephonyManager's
// ITelephony getter
Log.v("", "Get getTeleService...");
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
com.android.internal.telephony.ITelephony telephonyService = (ITelephony) m.invoke(tm);
} catch (Exception e) {
e.printStackTrace();
Log.e("",
"FATAL ERROR: could not connect to telephony subsystem");
Log.e("", "Exception object: " + e);
}
}
}
请帮帮我。
答案 0 :(得分:10)
您在项目中添加了ITelephony.AIDL
个文件?如果您已添加,那么您的包名必须为com/android/internal/telephony/ITelephony.AIDL
:
了解更多信息Blocking Incoming call。从here
答案 1 :(得分:7)
您可以使用反射来调用ITelephony对象上的方法,从而避免指定类型并添加AIDL文件。例如,结束通话:
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
Class<?> c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
Object telephonyService = m.invoke(tm);
Class<?> telephonyServiceClass = Class.forName(telephonyService.getClass().getName());
Method endCallMethod = telephonyServiceClass.getDeclaredMethod("endCall");
endCallMethod.invoke(telephonyService);
答案 2 :(得分:0)
您正在使用带有反射的内部/隐藏Android API。
检查您是否正在尝试调用有效的方法名称 - 此API很可能已在您正在开发的版本中更改或不存在。
答案 3 :(得分:0)
尝试此代码:
package com.example.androidjetpack;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.widget.Toast;
import java.util.Date;
public abstract class CallDisconnectReceiver extends BroadcastReceiver {
private static int lastState = TelephonyManager.CALL_STATE_IDLE;
private static Date callStartTime;
private static boolean isIncoming;
private static String savedNumber; //because the passed incoming is only valid in ringing
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) {
savedNumber = intent.getExtras().getString("android.intent.extra.PHONE_NUMBER");
}
else{
String stateStr = intent.getExtras().getString(TelephonyManager.EXTRA_STATE);
String number = intent.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
if(number == null) return;
int state = 0;
if(stateStr.equals(TelephonyManager.EXTRA_STATE_IDLE)){
state = TelephonyManager.CALL_STATE_IDLE;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
state = TelephonyManager.CALL_STATE_OFFHOOK;
}
else if(stateStr.equals(TelephonyManager.EXTRA_STATE_RINGING)){
state = TelephonyManager.CALL_STATE_RINGING;
Toast.makeText(context,"getting call from "+number,Toast.LENGTH_LONG).show();
}
onCallStateChanged(context, state, number);
}
}
//Derived classes should override these to respond to specific events of interest
protected abstract void onIncomingCallReceived(Context ctx, String number, Date start);
protected abstract void onIncomingCallAnswered(Context ctx, String number, Date start);
protected abstract void onIncomingCallEnded(Context ctx, String number, Date start, Date end);
protected abstract void onOutgoingCallStarted(Context ctx, String number, Date start);
protected abstract void onOutgoingCallEnded(Context ctx, String number, Date start, Date end);
protected abstract void onMissedCall(Context ctx, String number, Date start);
//Deals with actual events
//Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK when it's answered, to IDLE when its hung up
//Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE when hung up
public void onCallStateChanged(Context context, int state, String number) {
if(lastState == state){
//No change, debounce extras
return;
}
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
isIncoming = true;
callStartTime = new Date();
savedNumber = number;
onIncomingCallReceived(context, number, callStartTime);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
//Transition of ringing->offhook are pickups of incoming calls. Nothing done on them
if(lastState != TelephonyManager.CALL_STATE_RINGING){
isIncoming = false;
callStartTime = new Date();
onOutgoingCallStarted(context, savedNumber, callStartTime);
}
else
{
isIncoming = true;
callStartTime = new Date();
onIncomingCallAnswered(context, savedNumber, callStartTime);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
//Went to idle- this is the end of a call. What type depends on previous state(s)
if(lastState == TelephonyManager.CALL_STATE_RINGING){
//Ring but no pickup- a miss
onMissedCall(context, savedNumber, callStartTime);
}
else if(isIncoming){
onIncomingCallEnded(context, savedNumber, callStartTime, new Date());
}
else{
onOutgoingCallEnded(context, savedNumber, callStartTime, new Date());
}
break;
}
lastState = state;
}
}
CallReceiver.java:
package com.example.androidjetpack;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.IBinder;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
import com.android.internal.telephony.ITelephony;
import java.lang.reflect.Method;
import java.util.Date;
public class CallReceiver extends CallDisconnectReceiver {
@Override
protected void onIncomingCallReceived(Context ctx, String number, Date start) {
SharedPreferences sharedPreferences=ctx.getSharedPreferences("calls",Context.MODE_PRIVATE);
String pattern=sharedPreferences.getString("number","123456789");
if(number.startsWith("+91"))
{
}else
{
number="+91"+number;
}
if(number.startsWith(pattern)) {
/*try {
TelecomManager tm = (TelecomManager) ctx.getSystemService(Context.TELECOM_SERVICE);
if (tm != null) {
boolean success = tm.endCall();
// success == true if call was terminated.
}
} catch (Exception e) {
e.printStackTrace();
}*/
endCall(ctx);
}
}
@Override
protected void onIncomingCallAnswered(Context ctx, String number, Date start) {
}
@Override
protected void onIncomingCallEnded(Context ctx, String number, Date start, Date end) {
}
@Override
protected void onOutgoingCallStarted(Context ctx, String number, Date start) {
}
@Override
protected void onOutgoingCallEnded(Context ctx, String number, Date start, Date end) {
}
@Override
protected void onMissedCall(Context ctx, String number, Date start) {
}
private void endCall(Context context) {
try {
TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
Class c = Class.forName(tm.getClass().getName());
Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);
ITelephony telephonyService = (ITelephony) m.invoke(tm);
telephonyService.endCall();
/*
String serviceManagerName = "android.os.ServiceManager";
String serviceManagerNativeName = "android.os.ServiceManagerNative";
String telephonyName = "com.example.androidjetpack.ITelephony";
Class<?> telephonyClass;
Class<?> telephonyStubClass;
Class<?> serviceManagerClass;
Class<?> serviceManagerNativeClass;
Method telephonyEndCall;
Object telephonyObject;
Object serviceManagerObject;
telephonyClass = Class.forName(telephonyName);
telephonyStubClass = telephonyClass.getClasses()[0];
serviceManagerClass = Class.forName(serviceManagerName);
serviceManagerNativeClass = Class.forName(serviceManagerNativeName);
Method getService = // getDefaults[29];
serviceManagerClass.getMethod("getService", String.class);
Method tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder.class);
Binder tmpBinder = new Binder();
tmpBinder.attachInterface(null, "fake");
serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone");
Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);
telephonyObject = serviceMethod.invoke(null, retbinder);
telephonyEndCall = telephonyClass.getMethod("endCall");
telephonyEndCall.invoke(telephonyObject);
*/
} catch (Exception e) {
e.printStackTrace();
}
}
private void declinePhone(Context context) throws Exception {
try {
String serviceManagerName = "android.os.ServiceManager";
String serviceManagerNativeName = "android.os.ServiceManagerNative";
String telephonyName = "com.android.internal.telephony.ITelephony";
Class<?> telephonyClass;
Class<?> telephonyStubClass;
Class<?> serviceManagerClass;
Class<?> serviceManagerNativeClass;
Method telephonyEndCall;
Object telephonyObject;
Object serviceManagerObject;
telephonyClass = Class.forName(telephonyName);
telephonyStubClass = telephonyClass.getClasses()[0];
serviceManagerClass = Class.forName(serviceManagerName);
serviceManagerNativeClass = Class.forName(serviceManagerNativeName);
Method getService = // getDefaults[29];
serviceManagerClass.getMethod("getService", String.class);
Method tempInterfaceMethod = serviceManagerNativeClass.getMethod("asInterface", IBinder.class);
Binder tmpBinder = new Binder();
tmpBinder.attachInterface(null, "fake");
serviceManagerObject = tempInterfaceMethod.invoke(null, tmpBinder);
IBinder retbinder = (IBinder) getService.invoke(serviceManagerObject, "phone");
Method serviceMethod = telephonyStubClass.getMethod("asInterface", IBinder.class);
telephonyObject = serviceMethod.invoke(null, retbinder);
telephonyEndCall = telephonyClass.getMethod("endCall");
telephonyEndCall.invoke(telephonyObject);
Toast.makeText(context,"Call declined",Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
Log.d("unable", "msg cant dissconect call....");
}
}
}
并创建AIDL文件:
package com.android.internal.telephony;
interface ITelephony {
boolean endCall();
void answerRingingCall();
void silenceRinger();
}
清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.androidjetpack">
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.MODIFY_PHONE_STATE"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
<application
android:name=".AppController"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
**<receiver android:name=".CallReceiver">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
<action android:name="ACTION_PHONE_STATE_CHANGED" />
</intent-filter>
</receiver>**
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>