以编程方式一个接一个地拨打多个号码 | Android

Dial multiple numbers one by one programmatically | Android

我正在尝试为一个应用程序开发一项功能,您可以在其中输入 "codes" 的列表,然后一个一个地拨打。我查看了 TelephonyManager 并遵循 tutorial 开发带有响应侦听器的广播接收器,但它并不总是按预期工作。 一个想法是将所有必要的数字存储在 SharedPref 中。如果 Activity(仅为拨号器的意图而创建)进入 onStop()(意味着在上面,拨号器屏幕打开)然后进入 onResume()(调用结束并 activity 恢复),我会从 SharedPref 中删除上次拨打的号码,然后,如果还有的话,再次打开拨号器。广播确保一旦 TelephonyManager 的状态流为 "OFFHOOK => IDLE",它将 return 用户转到 Activity 。简而言之,它并不总是发挥应有的作用。

我该如何解决这个问题?

编辑

我目前的解决方案是

  1. 创建一个 doPhoneCall() 函数来处理意图创建和部署本身。

    @Override
    protected void doPhoneCall(){
        super.onResume();
        wentIntoCall = false;
        /** More code here for dialing */ 
    }
    
  2. 将此函数放入 onResume()。即使 onResume 会被多次调用,wentIntoCall 布尔值也会确保该函数不会被多次调用。

    @Override
    protected void onResume() {
        super.onResume();
        if(wentIntoCall) 
        doPhoneCall();
    }
    
  3. 请记住,在调用之后,phone 应该 return 到它之前的状态,所以它会 return 到 Activity我们正在做的是调用,我们将向 activity 添加一个 CallListener,在 IDLE 的情况下,根据上面链接的教程,我们使 wentIntoCall 为真。 ( activity 将进入 onResume() 并且,在看到布尔值为真时,它将初始化下一个调用)。

    case TelephonyManager.CALL_STATE_IDLE:
    
                Log.e(TAG, "CALL_STATE_IDLE==>"+incoming_number);
    
                if((prev_state == TelephonyManager.CALL_STATE_OFFHOOK)){
                    prev_state=state;
                    wentIntoCall = true;
                    //Answered Call which is ended
    
                }
                if((prev_state == TelephonyManager.CALL_STATE_RINGING)){
                    prev_state=state;
                    wentIntoCall = true;
                    //Rejected or Missed call
                }
    

我的最后一个问题:这是处理此功能的正确方法吗,还是我应该尝试想出另一种实现方法?

编辑 2

看起来我的 "codes",是 USSD 代码,不像正常的 phone 呼叫那样工作。所以对于正常的 phone 呼叫,上面的代码似乎有效,但用于拨号代码,没那么多。我有 "downgraded" 我的简单 for 循环解决方案。现在似乎工作正常。

作为旁注,在 Android O 开发者预览版中有一个新的 API,它允许您 send a USSD request 并注册一个回调以接收其结果。对于 Android 的较新版本,这可能会更好地满足您的需求。

我不知道 android O,但 android 6.0 > 您无法直接检测答案。呼叫不存在的号码并查看 PhoneStateListener 在一种情况下会触发什么并跟踪成功的呼叫。

创建 public 静态数组,添加所有数字 intro 数组。 我发了服务。在清单中插入权限也可以让您自己执行操作(例如 NEXT_CALL)。

比 startServices 更容易制作意图:

SharedPreferences settings;
SharedPreferences.Editor SAVES;

Intent serviceIntent = new Intent(MainActivity.this, ServiceForCalls.class);
                    serviceIntent.setAction("xxx.xxx.NEXT_CALL");
                    startService(serviceIntent);
                    isCalling = true;

                    SAVES.putBoolean(   "isCalling" ,  isCalling  );
                    SAVES.commit();
                    SAVES.apply();

下次调用必须使用超时间隔约 10 秒。

这里有一点帮助 func - 结束呼叫和 phoneState 处理程序 :

  void END_CALL () throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {

    tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
      Class c = null;
      try {
          c = Class.forName(tm.getClass().getName());
      } catch (ClassNotFoundException e) {
          e.printStackTrace();
      }
      Method m = null;
      try {
          m = c.getDeclaredMethod("getITelephony");
      } catch (NoSuchMethodException e) {
          e.printStackTrace();
      }
      m.setAccessible(true);
    Object telephonyService = m.invoke(tm); // Get the internal ITelephony object
    c = Class.forName(telephonyService.getClass().getName()); // Get its class
    m = c.getDeclaredMethod("endCall"); // Get the "endCall()" method
    m.setAccessible(true); // Make it accessible
    m.invoke(telephonyService); // invoke endCall()

      if ( SIGNAL_STOP == false ) {
          timerHandlerServicesStartNewNumber.postDelayed(timerRunnableServicesStartNewNumber, 1000);
      }

}


  private class PhoneStateChangeListener extends PhoneStateListener {

        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            switch(state){
                case TelephonyManager.CALL_STATE_RINGING:
                    Log.println( Log.INFO , "RINGING" , "SERVICES%%%%%%%%%%%%%%%%RINGING%%%%%%%%%%%%%%%%%%");
                    wasRinging = true;
                    break;
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Log.println( Log.INFO , "OFFHOOK BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%%%%%%%%");

                    if (!wasRinging) {
                        // Start your new activity
                        Log.println( Log.INFO , "OFFHOOK BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%%%%%%%");

                      if (SIGNAL_STOP == false) {
                          timerHandlerServices.postDelayed(timerRunnableServices, 10000);

                      }


                    } else {
                        // Cancel your old activity
                        Log.println( Log.INFO , "OFFHOOK BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                    }

                    // this should be the last piece of code before the break
                    wasRinging = true;
                    break;
                case TelephonyManager.CALL_STATE_IDLE:
                    Log.println( Log.INFO , "IDLE BROADCAST" , "SERVICES%%%%%%%%%%%%%%%%%IDLE%%%%%%%%%%%%%%%%%%%");

                    // this should be the last piece of code before the break
                    wasRinging = false;
                    break;
            }
        }
    }

感谢:"meaning that above, the dialer screen was on" 不错。