2014-04-16 4 views
24

일부 크랭크 호출을 차단하여 프로그래밍 방식으로 안드로이드에 전화를 끊어야합니다.Android에서 프로그래밍 방식으로 전화를 끊을 수 있습니까?

다음 조각은 다음과 같습니다. How to hang up outgoing call in Android?
전화 끊기 기술은 향후 Android 버전에서 언제든지 차단 될 예정입니까?
전화를 끊을 앱을 쓸 수 없다는 뜻입니까?

지금까지 만난 전화를 끊는 유일한 방법은 Java Reflection을 사용하는 것입니다. 공개 API의 일부가 아니기 때문에이를 사용하고 사용하지 않도록주의해야합니다. Android의 내부 구성이 변경되면 애플리케이션이 효과적으로 중단됩니다.

답변

62

먼저 사전 킷캣에서 일 듯, 당신이 그런 AndroidManifest.xml

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

에이 권한을 선언 할 필요가 당신 설치 android.intent.action.PHONE_STATE (수신 통화)에 대한 BroadcastReceiver 서비스 및 android.intent.action.NEW_OUTGOING_CALL (발신 전화)에 다음을 추가하여 AndroidManifest.xml

AndroidManifest.xml에 안드로이드 팀 everyt을 설정 할 가능성이있다

<receiver android:name=".PhoneStateReceiver"> 
    <intent-filter android:priority="0"> 
     <action android:name="android.intent.action.PHONE_STATE" /> 
     <action android:name="android.intent.action.NEW_OUTGOING_CALL" /> 
    </intent-filter> 
</receiver> 

PhoneStateReceiver.JAVA

import java.lang.reflect.Method; 
import android.content.BroadcastReceiver; 
import android.content.Context; 
import android.content.Intent; 
import android.telephony.TelephonyManager; 
import android.util.Log; 

public class PhoneStateReceiver extends BroadcastReceiver { 

    public static String TAG="PhoneStateReceiver"; 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     if (intent.getAction().equals("android.intent.action.PHONE_STATE")) { 
      String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 
      Log.d(TAG,"PhoneStateReceiver**Call State=" + state); 

      if (state.equals(TelephonyManager.EXTRA_STATE_IDLE)) { 
       Log.d(TAG,"PhoneStateReceiver**Idle"); 
      } else if (state.equals(TelephonyManager.EXTRA_STATE_RINGING)) { 
       // Incoming call 
       String incomingNumber = 
         intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); 
       Log.d(TAG,"PhoneStateReceiver**Incoming call " + incomingNumber); 

       if (!killCall(context)) { // Using the method defined earlier 
        Log.d(TAG,"PhoneStateReceiver **Unable to kill incoming call"); 
       } 

      } else if (state.equals(TelephonyManager.EXTRA_STATE_OFFHOOK)) { 
       Log.d(TAG,"PhoneStateReceiver **Offhook"); 
      } 
     } else if (intent.getAction().equals("android.intent.action.NEW_OUTGOING_CALL")) { 
      // Outgoing call 
      String outgoingNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER); 
      Log.d(TAG,"PhoneStateReceiver **Outgoing call " + outgoingNumber); 

      setResultData(null); // Kills the outgoing call 

     } else { 
      Log.d(TAG,"PhoneStateReceiver **unexpected intent.action=" + intent.getAction()); 
     } 
    } 

    public boolean killCall(Context context) { 
     try { 
      // Get the boring old TelephonyManager 
      TelephonyManager telephonyManager = 
        (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 

      // Get the getITelephony() method 
      Class classTelephony = Class.forName(telephonyManager.getClass().getName()); 
      Method methodGetITelephony = classTelephony.getDeclaredMethod("getITelephony"); 

      // Ignore that the method is supposed to be private 
      methodGetITelephony.setAccessible(true); 

      // Invoke getITelephony() to get the ITelephony interface 
      Object telephonyInterface = methodGetITelephony.invoke(telephonyManager); 

      // Get the endCall method from ITelephony 
      Class telephonyInterfaceClass = 
        Class.forName(telephonyInterface.getClass().getName()); 
      Method methodEndCall = telephonyInterfaceClass.getDeclaredMethod("endCall"); 

      // Invoke endCall() 
      methodEndCall.invoke(telephonyInterface); 

     } catch (Exception ex) { // Many things can go wrong with reflection calls 
      Log.d(TAG,"PhoneStateReceiver **" + ex.toString()); 
      return false; 
     } 
     return true; 
    } 

} 

MainActivity.JAVA

import android.Manifest; 
import android.content.pm.PackageManager; 
import android.support.v4.app.ActivityCompat; 
import android.support.v4.content.ContextCompat; 
import android.support.v7.app.AppCompatActivity; 
import android.os.Bundle; 

public class MainActivity extends AppCompatActivity { 

public static final int MY_PERMISSIONS_REQUEST_READ_PHONE_STATE = 101; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    if (ContextCompat.checkSelfPermission(this, 
      Manifest.permission.READ_PHONE_STATE) 
      != PackageManager.PERMISSION_GRANTED) { 

     // Should we show an explanation? 
     if (ActivityCompat.shouldShowRequestPermissionRationale(this, 
       Manifest.permission.READ_PHONE_STATE)) { 

      // Show an explanation to the user *asynchronously* -- don't block 
      // this thread waiting for the user's response! After the user 
      // sees the explanation, try again to request the permission. 

     } else { 

      // No explanation needed, we can request the permission. 

      ActivityCompat.requestPermissions(this, 
        new String[]{Manifest.permission.READ_PHONE_STATE}, 
        MY_PERMISSIONS_REQUEST_READ_PHONE_STATE); 

      // MY_PERMISSIONS_REQUEST_READ_PHONE_STATE is an 
      // app-defined int constant. The callback method gets the 
      // result of the request. 
     } 
    } 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, 
             String permissions[], int[] grantResults) { 
    switch (requestCode) { 
     case MY_PERMISSIONS_REQUEST_READ_PHONE_STATE: { 
      // If request is cancelled, the result arrays are empty. 
      if (grantResults.length > 0 
        && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 

       // permission was granted, yay! 

      } else { 

       // permission denied, boo! Disable the 
       // functionality that depends on this permission. 
      } 
      return; 
     } 

     // other 'case' lines to check for other 
     // permissions this app might request 
    } 
} 
} 
+0

감사! 코드가 잘 작동합니다! 유일한 문제가 있습니다. 일반적으로 통화를 놓친 경우 알림 표시 줄에 "부재중 전화"라는 경고 정보가 표시됩니다. killCall (컨텍스트 컨텍스트) 함수를 호출 할 때 "부재 중 전화"경고 정보가 표시되지 않습니다. killCall (컨텍스트 컨텍스트) 함수를 호출하더라도 정보가 표시되도록하려면 어떻게해야합니까? – HelloCW

+0

@HelloCW 위와 같은 경우 수동으로 통화 로그 앱의 DB 제공을 포함하여 작성해야합니다. – dhams

+0

이 문제를 해결할 수 있습니까? 휴대 전화를 차단 모드로 설정해 보셨습니까? 링크 http://www.techrepublic.com/article/get-the-most-out-of-samsungs-blocking-mode/#. 또는 프로그래밍 방식으로 설정하십시오 – izbrannick

2

Does it mean the technique of hang up call will be block at any time in further Android version?

이 구체적인 서비스를 위해 뒤집어 놓습니다. 나에 관해서는, 나는 그러한 가능성이 꽤 무시할 만하다고 생각한다.

Does it mean I can't write an app to hang up a call?

제안 된 접근 방식이 작동하는 경우, 왜? 먼 미래의 어딘가에서 뭔가 복잡해질 수 있다는 것을 염두에 두십시오 (예 : 마음의 배경 어딘가에 :).) 그러면 녹슬지 않는 API를 통해 또 다른 더러운 해킹을 찾아야합니다. 전화를 걸 수 있습니다.

0

만약 당신이 JUnit 테스트에 있다면, 이것은 방법입니다;

테스트 외부에서도 작동 할 수 있지만 시도하지는 않았습니다.

관련 문제