java 如何接听电话并挂断电话?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5320046/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 10:37:24  来源:igfitidea点击:

How can I answer a phone call and hang it up?

javaandroid

提问by Christian

I have code which is supposed to answer the phone and hang up right away when someone calls the phone. I get no errors and no force close when the call comes in from a different phone. The problem is that it doesn't do what it is supposed to do.

我有代码,当有人打电话时,它应该接听电话并立即挂断。当呼叫从另一部电话打进来时,我没有收到任何错误,也没有强制关闭。问题是它没有做它应该做的。

This is the broadcaster:

这是主播:

package com.QuickCallBlocking;

import java.lang.reflect.Method;


import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.TelephonyManager;

import com.android.internal.telephony.ITelephony;

public abstract class CallBlock extends BroadcastReceiver {
    private Context context;
    private ITelephony telephonyService;

    /** Called when the activity is first created. */
    public void getTeleService() {
        TelephonyManager tm = (TelephonyManager) context
        getSystemService(Context.TELEPHONY_SERVICE);

        try {
            // Java reflection to gain access to TelephonyManager's
            // ITelephony getter

            Class c = Class.forName(tm.getClass().getName());
            Method m = c.getDeclaredMethod("getITelephony");
            m.setAccessible(true);
            com.android.internal.telephony.ITelephony telephonyService = (ITelephony) m.invoke(tm);
        } catch (Exception e) {
            e.printStackTrace();
        }

        telephonyService.endCall();
    }

    String[] blockedNumbers = {"+911234567")};
    String incommingNumber;

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle b = intent.getExtras();
        incommingNumber = b.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
        // Additional Step
        // Check whether this number matches with your defined Block List
        // If yes, Reject the Call
    }    
}

This is the com.android.internal.telephony.ITelephony

这是 com.android.internal.telephony.ITelephony

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.telephony;

import android.os.Bundle;
import java.util.List;
//import android.telephony.NeighboringCellInfo;

/**
 * Interface used to interact with the phone.  Mostly this is used by the
 * TelephonyManager class.  A few places are still using this directly.
 * Please clean them up if possible and use TelephonyManager insteadl.
 *
 * {@hide}
 */
public interface ITelephony {

    /**
     * Dial a number. This doesn't place the call. It displays
     * the Dialer screen.
     * @param number the number to be dialed. If null, this
     * would display the Dialer screen with no number pre-filled.
     */
    void dial(String number);

    /**
     * Place a call to the specified number.
     * @param number the number to be called.
     */
    void call(String number);

    /**
     * If there is currently a call in progress, show the call screen.
     * The DTMF dialpad may or may not be visible initially, depending on
     * whether it was up when the user last exited the InCallScreen.
     *
     * @return true if the call screen was shown.
     */
    boolean showCallScreen();

    /**
     * Variation of showCallScreen() that also specifies whether the
     * DTMF dialpad should be initially visible when the InCallScreen
     * comes up.
     *
     * @param showDialpad if true, make the dialpad visible initially,
     *                    otherwise hide the dialpad initially.
     * @return true if the call screen was shown.
     *
     * @see showCallScreen
     */
    boolean showCallScreenWithDialpad(boolean showDialpad);

    /**
     * End call or go to the Home screen
     *
     * @return whether it hung up
     */
    boolean endCall();

    /**
     * Answer the currently-ringing call.
     *
     * If there's already a current active call, that call will be
     * automatically put on hold.  If both lines are currently in use, the
     * current active call will be ended.
     *
     * TODO: provide a flag to let the caller specify what policy to use
     * if both lines are in use.  (The current behavior is hardwired to
     * "answer incoming, end ongoing", which is how the CALL button
     * is specced to behave.)
     *
     * TODO: this should be a oneway call (especially since it's called
     * directly from the key queue thread).
     */
    void answerRingingCall();

    /**
     * Silence the ringer if an incoming call is currently ringing.
     * (If vibrating, stop the vibrator also.)
     *
     * It's safe to call this if the ringer has already been silenced, or
     * even if there's no incoming call.  (If so, this method will do nothing.)
     *
     * TODO: this should be a oneway call too (see above).
     *       (Actually *all* the methods here that return void can
     *       probably be oneway.)
     */
    void silenceRinger();

    /**
     * Check if we are in either an active or holding call
     * @return true if the phone state is OFFHOOK.
     */
    boolean isOffhook();

    /**
     * Check if an incoming phone call is ringing or call waiting.
     * @return true if the phone state is RINGING.
     */
    boolean isRinging();

    /**
     * Check if the phone is idle.
     * @return true if the phone state is IDLE.
     */
    boolean isIdle();

    /**
     * Check to see if the radio is on or not.
     * @return returns true if the radio is on.
     */
    boolean isRadioOn();

    /**
     * Check if the SIM pin lock is enabled.
     * @return true if the SIM pin lock is enabled.
     */
    boolean isSimPinEnabled();

    /**
     * Check if the SIM FDN lock is enabled.
     * @return true if the SIM FDN lock is enabled.
     */
    boolean isSimFDNEnabled();

    /**
     * Cancels the missed calls notification.
     */
    void cancelMissedCallsNotification();

    /**
     * Supply a pin to unlock the SIM.  Blocks until a result is determined.
     * @param pin The pin to check.
     * @return whether the operation was a success.
     */
    boolean supplyPin(String pin);

    /**
     * Supply a pin to unlock the SIM.  Blocks until a result is determined.
     * @param pin The pin to check.
     * @return whether the operation was a success.
     */
    boolean supplyPuk(String pin, String newPin);

    /**
     * Supply a pin2 to unlock the SIM.  Blocks until a result is determined.
     * @param pin The pin2 to check.
     * @return whether the operation was a success.
     */
    boolean supplyPin2(String pin2);

    /**
     * Check MS-ISDN field in SIM.
     * @param 
     * @return whether there is MS-ISDN field in SIM.
     */

    boolean getMsisdnavailable();
    /**
     * Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
     * without SEND (so <code>dial</code> is not appropriate).
     *
     * @param dialString the MMI command to be executed.
     * @return true if MMI command is executed.
     */
    boolean handlePinMmi(String dialString);

    /**
     * Toggles the radio on or off.
     */
    void toggleRadioOnOff();

    /**
     * Set the radio to on or off
     */
    boolean setRadio(boolean turnOn);

    /**
     * Request to update location information in service state
     */
    void updateServiceLocation();

    /**
     * Enable location update notifications.
     */
    void enableLocationUpdates();

    /**
     * Disable location update notifications.
     */
    void disableLocationUpdates();

    /**
     * Enable a specific APN type.
     */
    int enableApnType(String type);

    /**
     * Disable a specific APN type.
     */
    int disableApnType(String type);

    /**
     * Allow mobile data connections.
     */
    boolean enableDataConnectivity();

    /**
     * Disallow mobile data connections.
     */
    boolean disableDataConnectivity();

    /**
     * Report whether data connectivity is possible.
     */
    boolean isDataConnectivityPossible();

    Bundle getCellLocation();

    /**
     * Returns the neighboring cell information of the device.
     */
    //List<NeighboringCellInfo> getNeighboringCellInfo();

     int getCallState();
     int getDataActivity();
     int getDataState();

    /**
     * Returns the current active phone type as integer.
     * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
     * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
     */
    int getActivePhoneType();

    /**
     * Returns the CDMA ERI icon index to display
     */
    int getCdmaEriIconIndex();

    /**
     * Returns the CDMA ERI icon mode,
     * 0 - ON
     * 1 - FLASHING
     */
    int getCdmaEriIconMode();

    /**
     * Returns the CDMA ERI text,
     */
    String getCdmaEriText();

    /**
     * Returns true if CDMA provisioning needs to run.
     */
    boolean getCdmaNeedsProvisioning();

    /**
      * Returns the unread count of voicemails
      */
    int getVoiceMessageCount();

    /**
      * Returns the network type
      */
    int getNetworkType();

    /**
     * Return true if an ICC card is present
     */
    boolean hasIccCard();

    //[ TelephonyFeature.CONFIG_FAKECALL_FEATURE
    void initiateFakecall();
    //]

    /**
     * Returns the Value of PIN remain retry number.
     */
    int getSimPinRetry();

    /**
     * Returns the Value of PUK remain retry number.
     */
    int getSimPukRetry();

    /**
     * Switch Holding and Active
     */
    void switchHoldingAndActive();

    /**
     * Make call mute or unmute
     */
    void setMute(boolean flag);

    /**
     * Return mute state
     */
    boolean getMute();

    /**
     * Make speaker call on or off
     */
    void turnOnSpeaker(boolean flag);

    /**
     * Return Active calls count.
     */
    int getActiveCallsCount();

    /**
     * Return Hold calls count.
     */
    int getHoldCallsCount();

    /**
     * Return Caller name
     * First active call has priority
     */
    String getCallerName();

    /**
     * Return Call time
     * First active call has priority
     */
    long getCallTime();

    /**
     * Return Call base time
     * First active call has priority
     */
    long getCallBaseTime();

    /**
     * Return TRUE, if current call is video call
     * First active call has priority
     */
    boolean isVideoCall();

    // [TelephonyFeature.CONFIG_MULTIPLE_PDP_FEATURE
    boolean getDataStatebyApnType(String ApnType);
    // ]
   }

P.S This is some one else's work from this site: Prasanta's Blog

PS 这是来自该站点的其他人的作品:Prasanta 的博客

回答by Jason Plank

I don't think you want to do telephonyService.endCall()in getTeleService(). You probably want to call that within the onReceivemethod instead.

我认为你不想telephonyService.endCall()getTeleService(). 您可能想在onReceive方法中调用它。

I'm not sure whether you want to reject all calls or only ones from certain numbers. If you are trying to only reject certain numbers, it looks like you don't have any code to check the number of the incoming call against the blocked numbers after retrieving it here:

我不确定您是要拒绝所有电话还是只拒绝某些号码的电话。如果您试图仅拒绝某些号码,那么在此处检索后,您似乎没有任何代码来检查来电号码与阻止号码:

public void onReceive(Context context, Intent intent) {
    Bundle b = intent.getExtras();
    incommingNumber = b.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
--->// Additional Step                                                       <---
--->// Check whether this number matches with your defined Block List        <---
--->// If yes, Reject the Call                                               <---
}

You can try changing it to the following if you want to check the number and reject calls only from the blocked numbers:

如果您想检查号码并仅拒绝来自被阻止号码的呼叫,您可以尝试将其更改为以下内容:

public void onReceive(Context context, Intent intent) {
    Bundle b = intent.getExtras();
    incommingNumber = b.getString(TelephonyManager.EXTRA_INCOMING_NUMBER);

    // Additional Step
    // Check whether this number matches with your defined Block List
    // If yes, Reject the Call
    for (int i=0; i<blockedNumbers.length; i++) {
        if (incommingNumber.equals(blockedNumbers[i])) {
            telephonyService.endCall();
            break;
        }
    }
}

Or if you just want to reject all calls, it's even simpler:

或者,如果您只想拒绝所有来电,则更简单:

public void onReceive(Context context, Intent intent) {
    telephonyService.endCall();
}

回答by Shockzort

Yeah, one can't just use

是的,不能只是使用

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

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

because it is reserved by system, so for answering calls we use a bluetooth trick like hereand for rejecting calls we can still use TelephonyManager's endCall(); function. It actually works without such permission. Dont forget to add

因为它是系统保留的,所以为了接听电话,我们使用像这里这样的蓝牙技巧,对于拒绝电话,我们仍然可以使用 TelephonyManager 的 endCall();功能。它实际上无需此类许可即可工作。不要忘记添加

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

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

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

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

though! Cheers...

尽管!干杯...

回答by aha16

Add following code to AndroidManifest.xml

将以下代码添加到 AndroidManifest.xml

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.CALL_PHONE"/> (add it after READ_PHONE_STATE and before MODIFY_PHONE_STATE")
    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />

and use it for EndCall :

并将其用于 EndCall :

private void endCall() 
     { 
            Class<TelephonyManager> c = TelephonyManager.class;  
            Method getITelephonyMethod = null;  
            try {  

            getITelephonyMethod = c.getDeclaredMethod("getITelephony",(Class[]) null);  


            getITelephonyMethod.setAccessible(true);  
            ITelephony iTelephony = (ITelephony) getITelephonyMethod.invoke(tm, (Object[]) null);  
            iTelephony.endCall();  

        } catch (Exception e) {  

        }   
 }