如何在Android 4.1中以编程方式接听/结束电话?

53

我正在编写一个Android应用程序,在其中需要接听来电,执行一些操作,然后结束通话。 在进行了所有搜索之后,我找到了两种不同的方法来实现这一点,但它们都无法在较新版本的Android中使用,特别是在4.1(Jelly Bean)之后。

I.) 使用Java Reflection访问“com.android.internal.telephony.ITelephony”,在“android.intent.action.PHONE_STATE”广播接收器中实现。以下示例代码可以在数百个相关帖子中找到:

public class PhoneCallReceiver extends BroadcastReceiver {
 Context context = null;
 private static final String TAG = "Phone call";
 private ITelephony telephonyService;

@Override
 public void onReceive(Context context, Intent intent) {
  if (!intent.getAction().equals("android.intent.action.PHONE_STATE")) 
    return;

  Log.v(TAG, "Receving....");
  TelephonyManager telephony = (TelephonyManager) 
  context.getSystemService(Context.TELEPHONY_SERVICE);  
  try {
      Log.v(TAG, "Get getTeleService...");
      Class c = Class.forName(telephony.getClass().getName());
      Method m = c.getDeclaredMethod("getITelephony");
      m.setAccessible(true);
      telephonyService = (ITelephony) m.invoke(telephony);
      telephonyService.silenceRinger();
      Log.v(TAG, "Answering Call now...");
      telephonyService.answerRingingCall();
      Log.v(TAG, "Call answered...");
      //telephonyService.endCall();
  } catch (Exception e) {
   e.printStackTrace();
   Log.e(TAG,
           "FATAL ERROR: could not connect to telephony subsystem");
   Log.e(TAG, "Exception object: " + e);
  }
 }
}

这段代码的问题在于

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

在 Android v2.3 中,这种方法需要“仅限系统应用”的权限才能工作。简而言之,普通用户应用程序现在不能再在清单文件中定义此权限。

II.) 另一种方法是模拟按下耳机钩子使Android接听电话。这可以通过广播“Intent.ACTION_MEDIA_BUTTON”来实现,如下面的代码所示。

public class PhoneCallReceiver extends BroadcastReceiver {
 Context context = null;
 private static final String TAG = "Phone call";

 @Override
 public void onReceive(Context context, Intent intent) {
     if (!intent.getAction().equals("android.intent.action.PHONE_STATE")) 
         return;

     String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
     if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
         String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);

         Intent answer = new Intent(Intent.ACTION_MEDIA_BUTTON);
         answer.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
         context.sendOrderedBroadcast(answer, null);
         Log.d(TAG, "Answered incoming call from: " + number);
     }   
     return;
 } 
}

这种方法适用于Android 4.1之前的版本,此后安卓限制了用户应用程序广播"Intent.ACTION_MEDIA_BUTTON"的功能。

因此,我的结论是在Android 4.1或更高版本中当前没有办法实现这一点。

还有其他人发现任何其他解决方案或解决此问题的方法吗?


3
答案是谷歌不希望你这样做。这就是为什么他们会阻止所有已知的方法。即使你找到了第三种方式,我也预计它在下一个操作系统版本上将无法运行。 - Gabe Sechan
7
显然,为了安全起见,谷歌限制了这些功能。我理解禁止从用户应用程序发起新呼叫,但为什么要限制应用程序接听来电呢?因此,用户可能会错过来电限制或本地电话答录机在安卓系统中无法使用,是吗? - Piyush
@Gabe Sechan,你在哪里找到谷歌阻止这些活动的信息?我很想读一下官方声明。 - WonderWorker
2
每种人们使用的方法都在下一个版本中被关闭了这一事实。 - Gabe Sechan
9个回答

17

这个工作适用于Android 2.2到4.0版本,现在添加了try catch到最后一行后,它能够在4.1.2和4.2版本上运行。坦白地说,我不知道它是如何工作的,但对我来说它可以工作。

Log.d(tag, "InSecond Method Ans Call");
// froyo and beyond trigger on buttonUp instead of buttonDown
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");

Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG);
headSetUnPluggedintent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
headSetUnPluggedintent.putExtra("state", 0);
headSetUnPluggedintent.putExtra("name", "Headset");
try {
    sendOrderedBroadcast(headSetUnPluggedintent, null);
} catch (Exception e) { 
    e.printStackTrace();
}

在Android 4.1.2上,这对我有用,并且我已经在4.2上进行了测试。这仍然会出现异常,但已被处理。

为结束通话而编辑

希望这能帮助所有寻找完整的答案和结束通话解决方案的人。

/**
 * Reject button click listener will reject the incoming call.
 */
private class RejectCallOnClickListener implements OnClickListener {
    @Override
    public void onClick(View v) {
        Log.d(tag, "OnRejectButton: " + "Reject OnClick");
        ignoreCall();
        exitCleanly();
    }
}

/**
 * ignore incoming calls
 */
private void ignoreCall() {
    if (USE_ITELEPHONY)
        ignoreCallAidl();
    else
        ignoreCallPackageRestart();
}
/**
 * AIDL/ITelephony technique for ignoring calls
 */
private void ignoreCallAidl() {
    try {
        // telephonyService.silenceRinger();

        telephonyService.endCall();
    } catch (RemoteException e) {
        e.printStackTrace();
        Log.d(tag, "ignoreCall: " + "Error: " + e.getMessage());

    } catch (Exception e) {
        e.printStackTrace();
        Log.d(tag, "ignoreCall" + "Error: " + e.getMessage());

    }
}
/**
 * package restart technique for ignoring calls
 */
private void ignoreCallPackageRestart() {
    ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    am.restartPackage("com.android.providers.telephony");
    am.restartPackage("com.android.phone");
}
/**
 * cleanup and exit routine
 */
private void exitCleanly() {
    unHookReceiver();
    this.finish();

}

1
@PravinDodia 有人能帮我吗?我需要一种通过任何技术结束特定号码的通话的工作版本。我需要在2.3.3+设备上的工作版本,你能帮我吗? - Pro_Zeck
@PravinDodia:你好,是否可以通过编程方式结束通话? - Mehul Joisar
@PravinDodia:我应该在什么情况下使用ignoreCallAidl()和什么情况下使用ignoreCallPackageRestart() - Mehul Joisar
@MehulJoisar 这取决于情况,我在我的情况下使用了if else语句,但是对于你的情况,你可以尝试使用try 1方法,如果失败了,你可以保留其他方法,以确保结束通话。虽然ignoreCallAidl来自电话方法,而ignorecallpackageRestart则是重新启动整个电话包。 - PravinDodia
1
am.restartPackage()已经被弃用 - 它是killBackgroundProcess(String)的包装器,系统会适当地重新启动服务。因此,在ignoreCallPackageRestart()中的代码应该是am.killBackgroundProcesses("com.android.providers.telephony"); am.killBackgroundProcesses("com.android.phone"); - DritanX
显示剩余11条评论

8

我的应用程序已经使用以下代码接听电话约6个月:

Intent i = new Intent(Intent.ACTION_MEDIA_BUTTON);
i.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
            KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(i, null);

我已经在Android 2.2到4.2.2版本上进行了测试。在我的4.2.2设备上,我没有看到SecurityException广播“Intent.ACTION_MEDIA_BUTTON”的情况,也没有从Play Store收到崩溃报告表明这样的异常正在发生。
我想说的是,这并不总是有效。它在HTC设备上无法工作,因为HTC设备有一个HeadsetObeserver来监听有线耳机的插入事件。如果没有这个事件(目前第三方应用程序广播此事件会引发SecurityException),HeadsetHook KeyEvent将被忽略。
之前的答案是误导性的。以下代码块什么也不做:
Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG);
headSetUnPluggedintent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
headSetUnPluggedintent.putExtra("state", 0);
headSetUnPluggedintent.putExtra("name", "Headset");
try {
    sendOrderedBroadcast(headSetUnPluggedintent, null);
} catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

除了生成SecurityException并捕获它之外。

在其他代码能够正常工作的答案中,这是因为KeyEvent.KEYCODE_HEADSETHOOK被广播了。


8
尝试这个: 使用编程方式结束通话的答案。对我而言,它运行良好。
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 serviceManagerStubClass;
    Class serviceManagerNativeClass;
    Class serviceManagerNativeStubClass;

    Method telephonyCall;
    Method telephonyEndCall;
    Method telephonyAnswerCall;
    Method getDefault;

    Method[] temps;
    Constructor[] serviceManagerConstructor;

    // Method getService;
    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);
    //telephonyCall = telephonyClass.getMethod("call", String.class);
    telephonyEndCall = telephonyClass.getMethod("endCall");
    //telephonyAnswerCall = telephonyClass.getMethod("answerRingingCall");

    telephonyEndCall.invoke(telephonyObject);

} catch (Exception e) {
    e.printStackTrace();
    Log.error(DialerActivity.this,
            "FATAL ERROR: could not connect to telephony subsystem");
    Log.error(DialerActivity.this, "Exception object: " + e);
}

请问您能否指导我如何在较高版本的Android #Marshmallow中断开电话连接? - AndroidHacker
@AndroidHacker,请参考答案https://dev59.com/sWEi5IYBdhLWcg3wweqq#21013894。 - Jebasuthan

7
作为本主题的结论,这是适用于Android 4.2.2的代码。
- 通过模拟耳机钩子的推送接听呼叫,并保持广播在try-catch中,如@PravinDodia在上面的主题中所提到的。(注意,异常被抛出并在catch中处理,但呼叫仍然被接听。因此我想我们可以忽略此异常并继续生活,好像什么都没有发生一样!) - 使用ITelephony断开电话连接。
public class PhoneCallReceiver extends BroadcastReceiver {
 Context context = null;
 private static final String TAG = "Phone call";

 @Override
 public void onReceive(Context context, Intent intent) {
     if (!intent.getAction().equals("android.intent.action.PHONE_STATE")) 
         return;
     else {
         String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);

         if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
             answerPhoneHeadsethook(context, intent);
             return;
         }
         else if(state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)){
             Log.d(TAG, "CALL ANSWERED NOW!!");
             try {
                    synchronized(this) {
                        Log.d(TAG, "Waiting for 10 sec ");
                        this.wait(10000);
                    }
                }
                catch(Exception e) {
                    Log.d(TAG, "Exception while waiting !!");
                    e.printStackTrace();
                }
             disconnectPhoneItelephony(context);
             return;
         }
         else {
             Log.d(TAG, "ALL DONE ...... !!");
         }
     }  
 }

 public void answerPhoneHeadsethook(Context context, Intent intent) {
     String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
     if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) {
         String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
         Log.d(TAG, "Incoming call from: " + number);
         Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);             
         buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
         try {
             context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");
             Log.d(TAG, "ACTION_MEDIA_BUTTON broadcasted...");
         }
         catch (Exception e) {
             Log.d(TAG, "Catch block of ACTION_MEDIA_BUTTON broadcast !");
         }

         Intent headSetUnPluggedintent = new Intent(Intent.ACTION_HEADSET_PLUG);
         headSetUnPluggedintent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         headSetUnPluggedintent.putExtra("state", 1); // 0 = unplugged  1 = Headset with microphone 2 = Headset without microphone
         headSetUnPluggedintent.putExtra("name", "Headset");
         // TODO: Should we require a permission?
         try {
             context.sendOrderedBroadcast(headSetUnPluggedintent, null);
             Log.d(TAG, "ACTION_HEADSET_PLUG broadcasted ...");
         }
         catch (Exception e) {
                // TODO Auto-generated catch block
                //e.printStackTrace();
                Log.d(TAG, "Catch block of ACTION_HEADSET_PLUG broadcast");
                Log.d(TAG, "Call Answered From Catch Block !!");
         }
         Log.d(TAG, "Answered incoming call from: " + number);  
    }
    Log.d(TAG, "Call Answered using headsethook");
 }

 public static void disconnectPhoneItelephony(Context context) {
     ITelephony telephonyService;
     Log.v(TAG, "Now disconnecting using ITelephony....");
      TelephonyManager telephony = (TelephonyManager) 
      context.getSystemService(Context.TELEPHONY_SERVICE);  
      try {
          Log.v(TAG, "Get getTeleService...");
          Class c = Class.forName(telephony.getClass().getName());
          Method m = c.getDeclaredMethod("getITelephony");
          m.setAccessible(true);
          telephonyService = (ITelephony) m.invoke(telephony);
          //telephonyService.silenceRinger();
          Log.v(TAG, "Disconnecting Call now...");
          //telephonyService.answerRingingCall();
          //telephonyService.endcall();
          Log.v(TAG, "Call disconnected...");
          telephonyService.endCall();
      } catch (Exception e) {
       e.printStackTrace();
       Log.e(TAG,
               "FATAL ERROR: could not connect to telephony subsystem");
       Log.e(TAG, "Exception object: " + e);
      }
 }
}

至少断开功能是可行的,我们知道它是如何工作的。因此,那些想要开发呼叫限制应用程序的人可以继续前进。对于像我这样想要接听电话的人,我想现在我们可以使用它,只希望它在下一个版本中不会停止工作。


3

ITelephony方法在4.4上不起作用,我发现耳机/媒体按钮方法仍然允许相当长的铃声时间才能挂断。

这位先生的博客文章展示了一种新方法,我已经测试过在4.4.2 Galaxy s4和HTC one mini上可以快速挂断电话,并且你也不会错过未接来电记录。

http://aprogrammersday.blogspot.co.uk/2014/05/disconnect-block-drop-calls-android-4.html

该技术使用如下的运行时exec,显然你可能需要为某些设备使用不同的号码。

public class HangupPhoneCallReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        if (TelephonyManager.EXTRA_STATE_RINGING.equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE))) {

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

            return;
        }
    }
}

1
谢谢你的推荐,Chris。请随时通过我的博客或电子邮件(naeem.akram.malik@gmail.com)与我联系并讨论想法。 - Naeem A. Malik
它在Nexus4 / kitkat上运行正常,这救了我的一天。感谢Chris和Naeem。 - kashili kashili
这个解决方案在Android 4.X上完美运行,但在Android 5.0和5.1上无法工作。您有什么解决办法来应对这个问题吗? - user2659694

3

试试这个:

Intent buttonDown = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonDown.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonDown, "android.permission.CALL_PRIVILEGED");

// froyo and beyond trigger on buttonUp instead of buttonDown
Intent buttonUp = new Intent(Intent.ACTION_MEDIA_BUTTON);
buttonUp.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
context.sendOrderedBroadcast(buttonUp, "android.permission.CALL_PRIVILEGED");

在AndroidManifest.xml文件中添加权限,如下所示:
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>

1
有人能确认这些解决方案是否适用于4.4 KitKat吗? - Bachalo
1
权限 MODIFY_PHONE_STATE 在 Lollipop 上无法工作。 - zooter

2

使用IT电话拨打电话时,在某些设备上(如三星S Duos)无法正常断开通话。但您仍然可以将铃声静音 :)


S5 Duos/Lollipop:可以使用(呼出或呼入都可以结束)。仅测试了SIM2。 - chksr

1
在早于9.0版本的情况下结束通话,请使用以下内容:

TelephonyManager tm = (TelephonyManager)context.getSystemService(TELEPHONY_SERVICE);

Method m1 = null;
try {
    m1 = tm.getClass().getDeclaredMethod("getITelephony");
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}
m1.setAccessible(true);
Object iTelephony = null;
try {
    iTelephony = m1.invoke(tm);
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

Method m3 = null;
try {
    m3 = iTelephony.getClass().getDeclaredMethod("endCall");
} catch (NoSuchMethodException e) {
    e.printStackTrace();
}

try {
    m3.invoke(iTelephony);
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}
    

& for pie

TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
if (telecomManager != null) {
    return telecomManager.endCall();
}

Make sure your compile SDK version is 28

1
private void PhoneControl(int nControl) {
    if(nControl == PHONE_END_CALL) { // End call, all Android version
        try {
            TelecomManager telecomManager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
            if (telecomManager != null) {
                telecomManager.endCall();
            }
        }catch (Exception e) {}
        try {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if(tm == null)
                return;
            tm.getClass().getMethod("endCall").invoke(tm);
            bIsEnding = true;
        } catch (Exception e) {


            /* Do Nothing */ }
    }

    if(nControl == PHONE_ACCEPT_CALL) { // Accept phone call
//      if(!bCallAccepted) { // Call déjà accepté => pas d'action (évite double action)
            bCallAccepted = true;
            if(Build.VERSION.SDK_INT >= 26) { // Pris en charge Android >= 8.0
                if(context.checkSelfPermission("android.permission.ANSWER_PHONE_CALLS") == PackageManager.PERMISSION_GRANTED) {
                    TelecomManager tm = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
                    if(tm != null)
                        tm.acceptRingingCall();
                }
            }
            if(Build.VERSION.SDK_INT >= 23 && Build.VERSION.SDK_INT < 26) { // Hangup in Android 6.x and 7.x
                MediaSessionManager mediaSessionManager =  (MediaSessionManager) context.getSystemService(Context.MEDIA_SESSION_SERVICE);
                if(mediaSessionManager != null) {
                    try {
                        List<MediaController> mediaControllerList = mediaSessionManager.getActiveSessions
                                (new ComponentName(context, NotificationReceiverService.class));

                        for (MediaController m : mediaControllerList) {
                            if ("com.android.server.telecom".equals(m.getPackageName())) {
                                m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK));
                                m.dispatchMediaButtonEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK));
                                break;
                            }
                        }
                    } catch (Exception e) {
//                      Toast.makeText(instance, "sdfsdf123123"+e, Toast.LENGTH_LONG).show();
                        Intent answerCalintent = new Intent(context, AcceptCallActivity.class);
                        answerCalintent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
                                Intent.FLAG_ACTIVITY_CLEAR_TASK  |
                                Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
                        context.startActivity(answerCalintent);
                        /* Do Nothing */ }
                }


//                new Thread(new Runnable() {
//
//                    @Override
//                    public void run() {
//                        try {
//                            Runtime.getRuntime().exec("input keyevent " +
//                                     Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
//                        } catch (IOException e) {
//                             // Runtime.exec(String) had an I/O problem, try to fall back
//                             String enforcedPerm = "android.permission.CALL_PRIVILEGED";
//                             Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
//                             Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
//                                      KeyEvent.KEYCODE_HEADSETHOOK));
//                             Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
//                                        Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
//                                        KeyEvent.KEYCODE_HEADSETHOOK));
//
//                             context.sendOrderedBroadcast(btnDown, enforcedPerm);
//                             context.sendOrderedBroadcast(btnUp, enforcedPerm);
//                         }
//                     }
//
//                  }).start();
            }
            if(Build.VERSION.SDK_INT < 23) { // Prend en charge jusqu'à Android 5.1
                try {
                    if(Build.MANUFACTURER.equalsIgnoreCase("HTC")) { // Uniquement pour HTC
                        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
                        if(audioManager!=null && !audioManager.isWiredHeadsetOn()) {
                            Intent i = new Intent(Intent.ACTION_HEADSET_PLUG);
                            i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                            i.putExtra("state", 0);
                            i.putExtra("name", "Orasi");
                            try {
                                context.sendOrderedBroadcast(i, null);
                            } catch (Exception e) { /* Do Nothing */ }
                        }
                    }
                    Runtime.getRuntime().exec("input keyevent " +
                            Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
                } catch (Exception e) {
                    // Runtime.exec(String) had an I/O problem, try to fall back
                    String enforcedPerm = "android.permission.CALL_PRIVILEGED";
                    Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                            Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_DOWN,
                                    KeyEvent.KEYCODE_HEADSETHOOK));
                    Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON).putExtra(
                            Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP,
                                    KeyEvent.KEYCODE_HEADSETHOOK));

                    context.sendOrderedBroadcast(btnDown, enforcedPerm);
                    context.sendOrderedBroadcast(btnUp, enforcedPerm);
                }
            }
//       }
    }
}
    
<!--Incoming call state Listen-->
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    <!--    Store Data in Device/Shared pref-->
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <!--Get Incoming Number-->
    <uses-permission android:name="android.permission.READ_CALL_LOG" />

    <!--Answer call-->
    <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission
        android:name="android.permission.MODIFY_PHONE_STATE"
        tools:ignore="ProtectedPermissions" />


    <!--End Calll-->
    <uses-permission android:name="android.permission.CALL_PHONE" />

    public class NotificationReceiverService extends NotificationListenerService {
        public NotificationReceiverService() {
        }
    }

<service
    android:name=".notifications.NotificationReceiverService"
    android:enabled="true"
    android:exported="true"
    android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">

    <intent-filter>
        <action android:name="android.service.notification.NotificationListenerService" />
    </intent-filter>
</service>


if(Build.VERSION.SDK_INT >= 26) { // Permission necessaire
    if(checkSelfPermission("android.permission.ANSWER_PHONE_CALLS") != PackageManager.PERMISSION_GRANTED) {
        String szPermissions[] = {"android.permission.ANSWER_PHONE_CALLS"};
        requestPermissions(szPermissions, 0);
    }
}
if(Build.VERSION.SDK_INT < 26 && Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1 )
{ // Permission pour Android 6.x et 7.x
    ContentResolver contentResolver = getContentResolver();
    String enabledNotificationListeners = Settings.Secure.getString(contentResolver, "enabled_notification_listeners");
    String packageName = getPackageName();
    if (enabledNotificationListeners == null || !enabledNotificationListeners.contains(packageName)) {
        Intent intent2 = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1) {
            intent2 = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS);
        }
        startActivity(intent2);


        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //Do something after 100ms
                Intent intent=new Intent(MainActivity.this, Main2Activity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);

            }
        }, 1000);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接