1

I have a working code that disconnects the calls on Android 4.4 (KitKat). I use the technique of "service call phone 5" that was described at
How to programmatically answer/end a call in Android 4.1? and How can incoming calls be answered programmatically in Android 5.0 (Lollipop)?

But that code failed to disconnect the incoming call on 6.0. I have a background service that runs continously in the background and monitors a list of phone numbers and chose to automatically disconnect these numbers.

How can I programmatically disconnect the incoming calls on Nexus5 and Android version 6.0

Edit1

Complete code snippet is as follows

       Executor eS = Executors.newSingleThreadExecutor();
       eS.execute(new Runnable() {
           @Override
           public void run() {               
               Runtime runtime = Runtime.getRuntime();
               try {
                   runtime.exec("service call phone 5 \n");
               } catch (Exception exc) {
                   Log.e("XX", exc.getMessage());
               }
           }
       });

Following permissions are defined in Android.xml

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.PROCESS_INCOMING_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />

EDIT2

I added one more permission

 <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />

The class to detect incoming call extends from PhoneStateListener and I override the method

    @Override
    public void onCallStateChanged(int state, String incomingNumber) {

        Log.e("XX","*************IncomingPhoneStateListener........"+state+"   incoming no:"+incomingNumber);             
       Executor eS = Executors.newSingleThreadExecutor();
       eS.execute(new Runnable() {
           @Override
           public void run() {

               Runtime runtime = Runtime.getRuntime();
               try {
                   Log.e("XX", "*DISCONNECTING THE CALL* \n" );
                   runtime.exec("service call phone 5 \n");
               } catch (Exception exc) {
                   Log.e("XX", exc.getMessage());
               }
           }
       });


        }

From logcat, I notice output statements that I am printing from my above code (hence service is getting called), but my call never gets disconnected. I tested it on marshmallow (nexus 5).

EDIT3

I am targeting API 19 in AndroidManifest.xml.

<uses-sdk
    android:minSdkVersion="19"
    android:targetSdkVersion="19" />

EDIT4

Here is my current code base (modified sdkversion for now to get this whole thing working. I still didnt make any progress (same old problems)

Build.gradle

apply plugin: 'com.android.application'

 android {
   compileSdkVersion 23
   buildToolsVersion "23.0.3"

defaultConfig {
    applicationId "com.XX.disconnectcall"
    minSdkVersion 19
    targetSdkVersion 23
    versionCode 1
    versionName "1.0"
}
buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  testCompile 'junit:junit:4.12'
  compile 'com.android.support:appcompat-v7:23.4.0'
 }

MainActivity.java

  public class MainActivity extends AppCompatActivity {

private IncomingPhoneStateListener phoneStateListener;
public static final int PERMISSION_REQUEST_CODE = 1001;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.e("TAG ","onCreate");
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        Log.e("TAG ","VERSION_CODES.M");
       /* if (ContextCompat.checkSelfPermission(MainActivity.this,
                Manifest.permission.READ_PHONE_STATE)
                != PackageManager.PERMISSION_GRANTED) {

             */
            ActivityCompat.requestPermissions(MainActivity.this,
                    new String[]{Manifest.permission.READ_PHONE_STATE,Manifest.permission.MODIFY_PHONE_STATE,Manifest
                            .permission.CALL_PHONE,Manifest.permission.PROCESS_OUTGOING_CALLS},
                    PERMISSION_REQUEST_CODE);

      //  }
    } else {
        phoneStateListener = new IncomingPhoneStateListener();
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

}

@Override
public void onResume() {
    super.onResume();

}

@Override
public void onDestroy() {
    super.onDestroy();
    TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
    telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    Log.e("TAG ","onRequestPermissionsResult");
    boolean permissionBoolean = true;

    if (requestCode == PERMISSION_REQUEST_CODE) {
        for (int i = 0; i < permissions.length; i++) {
            if (grantResults[i] != PackageManager.PERMISSION_GRANTED) {
                permissionBoolean = false;
            }
        }
        if (permissionBoolean) {
            phoneStateListener = new IncomingPhoneStateListener();

        }
    }
}

}

IncomingPhoneStateListener

public class IncomingPhoneStateListener extends PhoneStateListener {

int callState;
String callNumber;


public IncomingPhoneStateListener() {
    super();

}


@Override
public void onCallStateChanged(int state, final String incomingNumber) {


    callState = state;
    callNumber = incomingNumber;

    Log.e("TAG", "callState  "+callState);
    Executor eS = Executors.newSingleThreadExecutor();
    eS.execute(new Runnable() {
        @Override
        public void run() {

            Runtime runtime = Runtime.getRuntime();
            try {
                Log.e("TAG", "DISCONNECTING THE CALL From Number "+incomingNumber);
                runtime.exec("service call phone 5 \n");
            } catch (Exception exc) {
                Log.e(" ", exc.getMessage());
            }
        }
    });


}
}
Community
  • 1
  • 1
mobileDev
  • 1,358
  • 2
  • 14
  • 34

1 Answers1

1

I have searched the documentation and found that MODIFY_PHONE_STATE is for system app only. Protected permissions .So atleast for detecting incoming call you dont need this. You should add all these permission in manifest.

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
<uses-permission android:name="android.permission.PROCESS_INCOMING_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE"/>

And if you are working on Marshmallow you have to give these permissions at runtime too. Like this. Put this in onCreate

///  granting permission  ////
    if(!checkPermission())
    {
        requestPermission();
    }
 /////////////////////////////

And in class add these

    ///////////////////////   permission for marshmallow  ///////////////////

private boolean checkPermission(){
    int result1 = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE);
    int result3 = ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_OUTGOING_CALLS);
    int result4 = ContextCompat.checkSelfPermission(this, Manifest.permission.PROCESS_INCOMING_CALLS);
    int result5   = ContextCompat.checkSelfPermission(this, Manifest.permission.CALL_PHONE);

    if (result1 == PackageManager.PERMISSION_GRANTED && result3 == PackageManager.PERMISSION_GRANTED && result4 == PackageManager.PERMISSION_GRANTED
            && result5 == PackageManager.PERMISSION_GRANTED){

        return true;

    } else {

        //Toast.makeText(this,"You don't have permission to use further features",Toast.LENGTH_LONG).show();
        return false;

    }
}

private void requestPermission(){

    if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE) &&
            ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.PROCESS_OUTGOING_CALLS)  &&
            ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.PROCESS_INCOMING_CALLS) &&
                    ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CALL_PHONE)){

        Toast.makeText(this,"Application needs permission to use your camera, calls, storage and location.",Toast.LENGTH_LONG).show();

    } else {

        ActivityCompat.requestPermissions(this,new String[{Manifest.permission.READ_PHONE_STATE,Manifest.permission.PROCESS_OUTGOING_CALLS,
                Manifest.permission.PROCESS_INCOMING_CALLS, Manifest.permission.CALL_PHONE},1);

    }
}


@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case 1:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[1] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[2] == PackageManager.PERMISSION_GRANTED &&
                    grantResults[3] == PackageManager.PERMISSION_GRANTED) {

                Toast.makeText(this,"Permission Granted.",Toast.LENGTH_LONG).show();

            } else {

                Toast.makeText(this,"Permission Denied.",Toast.LENGTH_LONG).show();

            }
            break;
    }
}

////////////////////////////////////////////////////////////////////////
Shahbaz Hashmi
  • 2,631
  • 2
  • 26
  • 49
  • Added the MODIFY_PHONE_STATE and still no progress (edited my question with EDIT2 content). Please elaborate your comment on" permissions at runtime"? – mobileDev Jul 05 '16 at 21:35
  • These permissions are considered as dangerous. So in marshmallow all dangerous permission must be requested at run time. Or say dynamically. And it will be asked only once after installation. There are many reference and codes on internet regarding this. Pls check it. – Shahbaz Hashmi Jul 05 '16 at 21:45
  • See http://www.journaldev.com/10409/android-handling-runtime-permissions-example check permissions in main activity. If the app has no permission request permission. – Shahbaz Hashmi Jul 06 '16 at 00:06
  • Good example article. When I modify the code to grant the permissions for "MODIFY_PHONE_STATE", I donot get the popup prompt box. How else can we grant permissions for "MODIFY_PHONE_STATE" at run time? – mobileDev Jul 06 '16 at 16:16
  • These permission are asked as groups. Not one for popup box for one permission. If you gave all permission in the code. Then check your code is working now or not. – Shahbaz Hashmi Jul 06 '16 at 16:22
  • No luck. I donot get pop up box asking for any permissions. I have added all my source code under "EDIT4" above – mobileDev Jul 06 '16 at 19:44
  • No, I get toast message "permission denied". May be we can take it offline. I will email you shortly – mobileDev Jul 06 '16 at 20:51