0

我正在构建一个默认的来电显示和垃圾邮件发送者应用程序,它将检索一个号码的来电详细信息并拦截呼叫的详细信息。我在 Android 10.0 上,不知道这段代码将如何在其他版本的 Android 上运行。安装应用程序后,我无法拨打任何拨出号码。我收到此错误消息:

Call can't be placed by <appname>. Try using a different call redirecting app or contacting the developer for help.

谁能告诉我如何解决这个问题?

This is the manifest file:

<?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="xxxx.xxxxxxxx.xxxxxxxxxxx">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
    <uses-permission android:name="android.permission.READ_CALL_LOG" />
    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" tools:ignore="ProtectedPermissions"/>
    <uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
    <uses-feature
        android:name="android.hardware.telephony"
        android:required="true" />
    <uses-feature
        android:name="android.hardware.microphone"
        android:required="true" />

    <application
        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/Theme.GoDial">
        <activity android:name="xxxx.xxxx.xxxx.GetCallerInfoActivity" android:theme="@style/Theme.AppCompat.Transparent.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <action android:name="android.intent.action.DIAL" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="tel" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.DIAL" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
        <receiver android:name="xxxxxxxx.xxxxxxxx.xxxxxxxx.AnsCallBroadcastReceiver"
            android:permission="android.permission.BIND_SCREENING_SERVICE" >
            <intent-filter>
                <action android:name="android.telecom.CallScreeningService" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.PHONE_STATE" />
                <action android:name="android.intent.action.NEW_OUTGOING_CALL" />
            </intent-filter>
        </receiver>
        <service
            android:name="xxxxxxxx.xxxxxxxxx.xxxxxxx.CallMonitorService"
            android:permission="android.permission.BIND_CALL_REDIRECTION_SERVICE"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.telecom.CallRedirectionService"/>
            </intent-filter>
        </service>
    </application>
</manifest>

GetCallerInfoActivity.java

public class GetCallerInfoActivity extends Activity{
    private String number;
    public static int READ_PHONE_STATE=101;
    public static int REQUEST_CALL_LOG=102;
    public static int PERMISSION_DRAW_OVER_OTHER_APP=103;
    private RoleManager roleManager = null;
    private static final String[] PERMS = {Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_CALL_LOG};
    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        synchronized (this) {         
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(GetCallerInfoActivity.this)) {
                //If the draw over permission is not available open the settings screen to grant the permission.
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent, PERMISSION_DRAW_OVER_OTHER_APP);
            }else
                checkCallStates();
        }
        
        try {
            if (getApplicationContext().checkSelfPermission(Manifest.permission.READ_PHONE_STATE)
                    != PackageManager.PERMISSION_GRANTED) {
                //Permission has not been granted, therefore prompt the user to grant permission
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_PHONE_STATE,
                        Manifest.permission.READ_CALL_LOG}, READ_PHONE_STATE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }         
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == PERMISSION_DRAW_OVER_OTHER_APP) {
            //Check if the permission is granted or not.
                    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
                        roleManager = (RoleManager) getSystemService(Context.ROLE_SERVICE);
                        Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION);
                        startActivityForResult(intent, 1);
                    }
        } else if (requestCode == 1){
            finish();
        }else
            super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == READ_PHONE_STATE && grantResults.length > 0) {
            if (grantResults[0] != PackageManager.PERMISSION_GRANTED|| grantResults[1] != PackageManager.PERMISSION_GRANTED) {
                if (grantResults[0] != PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(getApplicationContext(), "Please grant permission to read contacts", Toast.LENGTH_SHORT).show();
                } else if (grantResults[1] != PackageManager.PERMISSION_GRANTED) {
                    Toast.makeText(getApplicationContext(), "Please grant permission to get your contact number", Toast.LENGTH_SHORT).show();
                }
            }
        }
        if (requestCode==PERMISSION_DRAW_OVER_OTHER_APP&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //If the draw over permission is not available open the settings screen to grant the permission.
            checkCallStates();
        }
    }

    private void checkCallStates(){
        PhoneCallListener phoneListener = new PhoneCallListener();
        TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
        telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    class PhoneCallListener extends PhoneStateListener {
        private boolean isPhoneCalling = false;

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            if (TelephonyManager.CALL_STATE_RINGING == state) {
                // phone ringing
                Log.i("LOG_TAG", "RINGING, number: " + incomingNumber);
            }

            if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
                // active
                Log.i("LOG_TAG", "OFFHOOK");
                isPhoneCalling = true;
            }

            if (TelephonyManager.CALL_STATE_IDLE == state) {
                // run when class initial and phone call ended, need detect flag
                // from CALL_STATE_OFFHOOK
                Log.i("LOG_TAG", "IDLE number");

                if (isPhoneCalling) {
                    Handler handler = new Handler();

                    //Put in delay because call log is not updated immediately when state changed
                    // The dialler takes a little bit of time to write to it 500ms seems to be enough
                    handler.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            // get start of cursor
                            Log.i("CallLogDetailsActivity", "Getting Log activity...");
                            String[] projection = new String[]{CallLog.Calls.NUMBER};
                            Cursor cur = getContentResolver().query(CallLog.Calls.CONTENT_URI, projection, null, null, CallLog.Calls.DATE + " desc");
                            cur.moveToFirst();
                            String lastCallnumber = cur.getString(0);
                        }
                    }, 500);

                    isPhoneCalling = false;
                }
            }
        }
    }
}

AnsCallBroadcastReceiver.java

public class AnsCallBroadcastReceiver extends BroadcastReceiver {
    private boolean isPhoneCalling = false;
    @Override
    public void onReceive(Context arg0, Intent arg1) {
        TelephonyManager telephony = (TelephonyManager)arg0.getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(new PhoneStateListener(){
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                super.onCallStateChanged(state, incomingNumber);
                System.out.println("incomingNumber : "+incomingNumber);

                if (TelephonyManager.CALL_STATE_RINGING == state) {
                    // phone ringing
                    Log.i("LOG_TAG", "RINGING, number: " + incomingNumber);
                    Toast.makeText(arg0,"CALL_STATE_RINGING: "+incomingNumber,Toast.LENGTH_LONG).show();

                    Intent intent = new Intent(arg0, PopUpDialog.class);
                    // To pass any data to next activity
                    intent.putExtra("message", incomingNumber);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    // start your next activity
                    arg0.startActivity(intent);
                }

                if (TelephonyManager.CALL_STATE_OFFHOOK == state) {
                    // active
                    Log.i("LOG_TAG", "OFFHOOK");
                    isPhoneCalling = true;
                    Toast.makeText(arg0,"CALL_STATE_OFFHOOK: " +incomingNumber,Toast.LENGTH_LONG).show();
                    Intent intent = new Intent(arg0, PopUpDialog.class);
                    // To pass any data to next activity
                    intent.putExtra("message", incomingNumber);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    // start your next activity
                    arg0.startActivity(intent);
                }

                if (TelephonyManager.CALL_STATE_IDLE == state) {
                    // run when class initial and phone call ended, need detect flag
                    // from CALL_STATE_OFFHOOK
                    Log.i("LOG_TAG", "IDLE number");

                    if (isPhoneCalling) {
                        Handler handler = new Handler();

                        //Put in delay because call log is not updated immediately when state changed
                        // The dialler takes a little bit of time to write to it 500ms seems to be enough
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                // get start of cursor
                                Log.i("CallLogDetailsActivity", "Getting Log activity...");
                                String[] projection = new String[]{CallLog.Calls.NUMBER};
                                Cursor cur = arg0.getContentResolver().query(CallLog.Calls.CONTENT_URI, projection, null, null, CallLog.Calls.DATE + " desc");
                                cur.moveToFirst();
                                String lastCallnumber = cur.getString(0);
                                Toast.makeText(arg0,"CALL_STATE_OFFHOOK: " +lastCallnumber,Toast.LENGTH_LONG).show();
                            }
                        }, 500);

                        isPhoneCalling = false;
                    }
                }
            }
        }, PhoneStateListener.LISTEN_CALL_STATE);
    }
}

CallMonitorService.java

public class CallMonitorService extends CallRedirectionService {
    private static final String TAG = "CallMonitorService";

    public CallMonitorService() {
    }

    @Override
    public void onPlaceCall(Uri uri, PhoneAccountHandle phoneAccountHandle, boolean b) {
        Log.e(TAG, "onPlaceCall:### ");
    }
}
4

0 回答 0