在以编程方式结束调用之前获取传入呼叫者的名称

时间:2014-10-04 11:20:59

标签: java android android-intent

我已成功编写代码以结束调用programaticaly。但在呼叫结束之前,我想检索呼叫者的姓名以记录它。我该如何检索来电者的姓名?请注意,调用者被假定在联系人列表中。

我已经遇到过如何从来电号码中检索联系人姓名?我没有找到满意的答案。它没有上下文,信息也很少。

1 个答案:

答案 0 :(得分:0)

您需要传入/传出的电话号码才能从设备的联系人列表中检索联系人姓名。 在应用清单中定义以下权限和接收者:

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

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

然后在CallReciever类中:

public class CallReceiver extends BroadcastReceiver {

    // The receiver will be recreated whenever android feels like it. We need a
    // static variable to remember data between instantiations
    static PhonecallStartEndDetector listener;
    string contactName;
    Context context;

    @Override
    public void onReceive(Context context, Intent intent) {
         this.context = context;
        if (listener == null) {
            listener = new PhonecallStartEndDetector();

        }

        // We listen to two intents. The new outgoing call only tells us of an
        // outgoing call. We use it to get the number.
        if (intent.getAction()
                .equals("android.intent.action.NEW_OUTGOING_CALL")) {
            listener.setOutgoingNumber(intent.getExtras().getString(
                    "android.intent.extra.PHONE_NUMBER"));
            return;
        }

        // The other intent tells us the phone state changed. Here we set a
        // listener to deal with it
        TelephonyManager telephony = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        telephony.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);

    }


    // Deals with actual events
    public class PhonecallStartEndDetector extends PhoneStateListener {
        int lastState = TelephonyManager.CALL_STATE_IDLE;
        boolean isIncoming;
        boolean isIncomingPicked;
        boolean isOutgoingStarted;
        String savedNumber; // because the passed incoming is only valid in ringing

        public PhonecallStartEndDetector() {

        }

        // The outgoing number is only sent via a separate intent, so we need to
        // store it out of band
        public void setOutgoingNumber(String number) {
            savedNumber = number;
        }

        // Incoming call- goes from IDLE to RINGING when it rings, to OFFHOOK
        // when it's answered, to IDLE when its hung up
        // Outgoing call- goes from IDLE to OFFHOOK when it dials out, to IDLE
        // when hung up
        @Override
        public void onCallStateChanged(int state, String incomingNumber) {
            super.onCallStateChanged(state, incomingNumber);
                                                // state is changed
            if (lastState == state) {
                return;
            }

            switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
            //an incoming call has been started

                isIncoming = true;
                savedNumber = incomingNumber;

            break;
            case TelephonyManager.CALL_STATE_OFFHOOK:

                // Transition of ringing->offhook are pickups of incoming calls.
                // Nothing down on them
                if (lastState != TelephonyManager.CALL_STATE_RINGING) { 
                                                                        //if pickup but device didn't ring..it means was an outgoing call
                    isIncoming = false;
                    isIncomingPicked = false;
                    isOutgoingStarted = true;

                } else if (lastState == TelephonyManager.CALL_STATE_RINGING) { 
                                                                                // if pickup and device rang..it means an incoming call has been picked

                    isIncoming = true;
                    isIncomingPicked = true;
                    isOutgoingStarted = false;

                break;
            case TelephonyManager.CALL_STATE_IDLE:

                // Went to idle- this is the end of a call. What type depends on
                // previous state(s)
                if (lastState == TelephonyManager.CALL_STATE_RINGING) {
                    // Ring but no pickup- a miss


                }else if (isOutgoingStarted) {
               //outgoing call ended
              contactName = getContactName(savedNumber, context);

                } else if (isIncoming || isIncomingPicked) {
                    //incoming call ended
             contactName = getContactName(savedNumber, context);

            }
                break;
            }

        }

        //method to retrieve contact name 

private String getContactName(String number, Context context) {
        String contactNumber = "";

        // // define the columns I want the query to return
        String[] projection = new String[] {
                ContactsContract.PhoneLookup.DISPLAY_NAME,
                ContactsContract.PhoneLookup.NUMBER,
                ContactsContract.PhoneLookup.HAS_PHONE_NUMBER };

        // encode the phone number and build the filter URI
        Uri contactUri = Uri.withAppendedPath(
                ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                Uri.encode(number));

        // query time
        Cursor cursor = context.getContentResolver().query(contactUri,
                projection, null, null, null);
        // querying all contacts = Cursor cursor =
        // context.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
        // projection, null, null, null);

        if (cursor.moveToFirst()) {
            contactName = cursor.getString(cursor
                    .getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
        }
        cursor.close();
        return contactNumber.equals("") ? number : contactName;

    }

}

由于您对在呼叫结束前检索呼叫者姓名感兴趣,因此在呼入/呼出结束时检索该名称。您可以在启动或接听来电或启动拨出电话时检索来电者的姓名。我添加了评论作为指南。希望它有所帮助:)