MTK-Android13-定制Dialer-拨打固定电话显示动画效果

MTK-Android13-定制Dialer-拨打固定电话显示动画效果

文章目录


前言-基本需求

基本需求就是:MTK-Android13-定制Dialer-拨打固定电话显示动画效果

如下:拨打指定号码播放动画、当然界面其它按钮位置、显示与不显示都是定制过了的。

一、参考资料

之前有Dialer 定制相关,可以借鉴下相关思路:

  • 修改哪一部分内容、相关部分模块在哪里
  • 如果要添加动画,理论上添加位置在哪里添加比较好

MTK-Android13-Dialer 通话界面定制修改

MTK-Android13-Dialer 通话界面定制修改(二)

Camera2和Camera1实现打开USB相机-实现Dialer 调用USB实现预览等视频通话

MTK-Android13-实现Dialer 调用USB实现预览等视频通话

二、修改文件

java 复制代码
/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/incall/impl/res/raw/
/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml
/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/DialpadFragment.java
/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/InCallActivity.java
/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/incall/impl/InCallFragment.java

初步了解:

  • raw 存放播放的动画 比如.gif 文件
  • dialpad_view_unthemed.xml 按键框框去掉白色背景改为透明
  • DialpadFragment.java 数字按键框 在Java中的硬编码中把白色背景改为透明
  • InCallActivity.java 实现指定的电话判断,来默认弹出数据键盘布局
  • InCallFragment.java、frag_incall_voice.xml 各种UI的显示与影藏、根据指定号码是否播放动画

三、实现方案

准备需要播放的动画资源

路径:/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/incall/impl/res/raw/

去掉数字键盘弹框的背景-透明化

路径:/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml /vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/DialpadFragment.java

根据电话号码来判断是否弹框数字按键键盘

在onResume 方法中添加逻辑:

java 复制代码
  @Override
  protected void onResume() {
    Trace.beginSection("InCallActivity.onResume");
    super.onResume();

    if (!InCallPresenter.getInstance().isReadyForTearDown()) {
      /// M: Update theme colors according to primary call. @{
      InCallPresenter.getInstance().setThemeColors();
      /// @}
      updateTaskDescription();
    }
	// modify by fangchen start

    DialerCall currentCall = CallList.getInstance().getFirstCall();
    if (currentCall != null 
            && "61520".equals(currentCall.getNumber())
            && !isDialpadVisible()
            && showDialpadRequest == DIALPAD_REQUEST_NONE) {
        LogUtil.i("InCallActivity.onResume", "special number, request show dialpad");
        showDialpadRequest = DIALPAD_REQUEST_SHOW;
        animateDialpadOnShow = true;
    }
	
	// modify by fangchen end 

.......原有逻辑.......

指定电话号码动画-UI显示与隐藏逻辑判断

动画业务逻辑

定义常量
java 复制代码
     // modify by fangchen start 
    private static final String SPECIAL_NUMBER = "61520";

    // ★ GIF View
    private ImageView specialCallGif;

    
    private boolean specialGifLoaded = false;
    private boolean specialGifPlaying = false;
   // modify by fangchen end  
初始化动画view
java 复制代码
  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle bundle) {
    LogUtil.i("InCallFragment.onViewCreated", null);
    super.onViewCreated(view, bundle);
	
	// modify by fangcehen start 
	specialCallGif = view.findViewById(R.id.special_call_gif);
	// modify by fangcehen end  

......原有逻辑.......
判断-是否播放动画-判断时机-方法业务

路径:/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/incall/impl/InCallFragment.java

java 复制代码
  @Override
  public void setPrimary(@NonNull PrimaryInfo primaryInfo) {
    LogUtil.d("InCallFragment.setPrimary", primaryInfo.toString());
    setAdapterMedia(primaryInfo.multimediaData(), primaryInfo.showInCallButtonGrid());
    contactGridManager.setPrimary(primaryInfo);

	// modify by fangchen start
    checkAndPlaySpecialGif(primaryInfo);	
	// modify by fangchen end 
	
   .........原有逻辑.......
  }




// modify by fangchen start
 
private void checkAndPlaySpecialGif(PrimaryInfo primaryInfo) {
    if (specialCallGif == null) {
        return;
    }

    String number = primaryInfo.number();
    LogUtil.d("InCallFragment.checkAndPlaySpecialGif", "number = " + number);

    if (number == null) {
		
		LogUtil.i("InCallFragment.checkAndPlaySpecialGif", "number == null return  ");

        return;
    }

     String normalized = number.replace(" ", "").replace("-", "");
    if (normalized.startsWith("+86")) {
        normalized = normalized.substring(3);
    }

    if (!SPECIAL_NUMBER.equals(normalized)) {
		LogUtil.i("InCallFragment.checkAndPlaySpecialGif", "!SPECIAL_NUMBER.equals(normalized) return  ");
         stopSpecialGif();
        return;
    }

     if (specialGifLoaded) {
		 LogUtil.i("InCallFragment.checkAndPlaySpecialGif", "specialGifLoaded is true  so --> return  ");
        return;
    }
    specialGifLoaded = true;

	/*if (getActivity() instanceof InCallActivity) {
        ((InCallActivity) getActivity()).showDialpadFragment(true, true);
    }*/
     playSpecialGif();
}

 
private void playSpecialGif() {
	LogUtil.i("InCallFragment.playSpecialGif", "==========playSpecialGif  ");
    specialCallGif.setVisibility(View.VISIBLE);
    specialGifPlaying = true;
   
    Glide.with(this)
            .asGif()                                   
            .load(R.raw.xiaoxing)                      
           // .diskCacheStrategy(DiskCacheStrategy.NONE)  
            .into(specialCallGif);
}

 
private void stopSpecialGif() {
    if (specialCallGif == null) {
        return;
    }

    
    if (specialGifPlaying) {
        Glide.with(this).clear(specialCallGif);
        specialGifPlaying = false;
    }

    specialCallGif.setVisibility(View.GONE);
    specialGifLoaded = false;
}  
  // modify by fangchen end 

部分按键显示与隐藏

路径:java/com/android/incallui/incall/impl/res/layout/frag_incall_voice.xml、/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/incall/impl/InCallFragment.java

这里需要对照业务、定制化UI的需求来实现,对部分图表隐藏、更改位置等客制化需求,当然也有部分代码、布局文件在其它地方,可以参考之前笔记。 这里仅仅将源码罗列出来,自己对比看看。

java 复制代码
/*
 * Copyright (C) 2016 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.incallui.incall.impl;

import android.Manifest.permission;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.telecom.CallAudioState;
import android.telephony.TelephonyManager;
import android.transition.TransitionManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.accessibility.AccessibilityEvent;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.android.dialer.common.Assert;
import com.android.dialer.common.FragmentUtils;
import com.android.dialer.common.LogUtil;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.multimedia.MultimediaData;
import com.android.dialer.strictmode.StrictModeUtils;
import com.android.dialer.widget.LockableViewPager;
import com.android.incallui.audioroute.AudioRouteSelectorDialogFragment;
import com.android.incallui.audioroute.AudioRouteSelectorDialogFragment.AudioRouteSelectorPresenter;
import com.android.incallui.call.CallList;
import com.android.incallui.call.DialerCall;
import com.android.incallui.call.state.DialerCallState;
import com.android.incallui.contactgrid.ContactGridManager;
import com.android.incallui.hold.OnHoldFragment;
import com.android.incallui.incall.impl.ButtonController.SpeakerButtonController;
import com.android.incallui.incall.impl.ButtonController.UpgradeToRttButtonController;
import com.android.incallui.incall.impl.InCallButtonGridFragment.OnButtonGridCreatedListener;
import com.android.incallui.incall.protocol.InCallButtonIds;
import com.android.incallui.incall.protocol.InCallButtonIdsExtension;
import com.android.incallui.incall.protocol.InCallButtonUi;
import com.android.incallui.incall.protocol.InCallButtonUiDelegate;
import com.android.incallui.incall.protocol.InCallButtonUiDelegateFactory;
import com.android.incallui.incall.protocol.InCallScreen;
import com.android.incallui.incall.protocol.InCallScreenDelegate;
import com.android.incallui.incall.protocol.InCallScreenDelegateFactory;
import com.android.incallui.incall.protocol.PrimaryCallState;
import com.android.incallui.incall.protocol.PrimaryCallState.ButtonState;
import com.android.incallui.incall.protocol.PrimaryInfo;
import com.android.incallui.incall.protocol.SecondaryInfo;
import java.util.ArrayList;
import java.util.List;
// modify by fangchen start 
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.gif.GifDrawable;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.android.incallui.InCallActivity;


// modify by fangchen end 



/** Fragment that shows UI for an ongoing voice call. */
public class InCallFragment extends Fragment
        implements InCallScreen,
        InCallButtonUi,
        OnClickListener,
        AudioRouteSelectorPresenter,
        OnButtonGridCreatedListener {

  private List<ButtonController> buttonControllers = new ArrayList<>();
  private View endCallButton;
  private InCallPaginator paginator;
  private LockableViewPager pager;
  private InCallPagerAdapter adapter;
  private ContactGridManager contactGridManager;
  private InCallScreenDelegate inCallScreenDelegate;
  private InCallButtonUiDelegate inCallButtonUiDelegate;
  private InCallButtonGridFragment inCallButtonGridFragment;
  @Nullable private ButtonChooser buttonChooser;
  private SecondaryInfo savedSecondaryInfo;
  private int voiceNetworkType;
  private int phoneType;
  private boolean stateRestored;
  
  
     // modify by fangchen start 
    private static final String SPECIAL_NUMBER = "61520";

    // ★ GIF View
    private ImageView specialCallGif;

    
    private boolean specialGifLoaded = false;
    private boolean specialGifPlaying = false;
   // modify by fangchen end  
  
  /// M: ALPS05941240 AudioRouteSelectorDialogFragment would not dismiss when call
  /// audio state changed. @{
  private static final String TAG_AUDIOROUTE_SELECTOR_FRAGMENT = "tag_audioroute_selector_fragment";
  /// @}

  // Add animation to educate users. If a call has enriched calling attachments then we'll
  // initially show the attachment page. After a delay seconds we'll animate to the button grid.
  private final Handler handler = new Handler();
  private final Runnable pagerRunnable =
          new Runnable() {
            @Override
            public void run() {
              pager.setCurrentItem(adapter.getButtonGridPosition());
            }
          };

  private static boolean isSupportedButton(@InCallButtonIds int id) {


    return
            id == InCallButtonIds.BUTTON_AUDIO
			//|| id == InCallButtonIds.BUTTON_DIALPAD
                    || id == InCallButtonIds.BUTTON_MUTE;
                    //|| id == InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO;
    /*return
	// modify by fangchen start
           id == InCallButtonIds.BUTTON_AUDIO
          || id == InCallButtonIds.BUTTON_MUTE
    //    || id == InCallButtonIds.BUTTON_DIALPAD
    //    ||
   // id == InCallButtonIds.BUTTON_HOLD
        || id == InCallButtonIds.BUTTON_SWAP
         || id == InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO
   //     || id == InCallButtonIds.BUTTON_ADD_CALL
        || id == InCallButtonIds.BUTTON_MERGE
        || id == InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE
        //|| id == InCallButtonIds.BUTTON_SWAP_SIM
        || id == InCallButtonIds.BUTTON_UPGRADE_TO_RTT
        /// M: [Voice Record]
    //    || id == InCallButtonIds.BUTTON_SWITCH_VOICE_RECORD

	// modify by fangchen end
        /// M: [Hang Up]
        || id == InCallButtonIds.BUTTON_HANG_UP_ALL
        || id == InCallButtonIds.BUTTON_HANG_UP_HOLD
        /// M: [ECT(blind)]
        || id == InCallButtonIds.BUTTON_ECT
        || id == InCallButtonIds.BUTTON_BLIND_ECT
        /// M: [One way video]
        || id == InCallButtonIds.BUTTON_ONE_WAY_VIDEO
        /// M: ALPS03949921, add switch_to_secondary to enable and disable.
        || id == InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY;*/
  }

  @Override
  public void onAttach(Context context) {
    super.onAttach(context);
    if (savedSecondaryInfo != null) {
      setSecondary(savedSecondaryInfo);
    }
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    inCallButtonUiDelegate =
            FragmentUtils.getParent(this, InCallButtonUiDelegateFactory.class)
                    .newInCallButtonUiDelegate();
    if (savedInstanceState != null) {
      inCallButtonUiDelegate.onRestoreInstanceState(savedInstanceState);
      stateRestored = true;
    }
  }

  @Nullable
  @Override
  @SuppressLint("MissingPermission")
  public View onCreateView(
          @NonNull LayoutInflater layoutInflater,
          @Nullable ViewGroup viewGroup,
          @Nullable Bundle bundle) {
    LogUtil.i("InCallFragment.onCreateView", null);
    getActivity().setTheme(R.style.Theme_InCallScreen);
    // Bypass to avoid StrictModeResourceMismatchViolation
    final View view =
            StrictModeUtils.bypass(
                    () -> layoutInflater.inflate(R.layout.frag_incall_voice, viewGroup, false));
    contactGridManager =
            new ContactGridManager(
                    view,
                    (ImageView) view.findViewById(R.id.contactgrid_avatar),
                    getResources().getDimensionPixelSize(R.dimen.incall_avatar_size),
                    true /* showAnonymousAvatar */);
    contactGridManager.onMultiWindowModeChanged(getActivity().isInMultiWindowMode());

    paginator = (InCallPaginator) view.findViewById(R.id.incall_paginator);
    pager = (LockableViewPager) view.findViewById(R.id.incall_pager);
    pager.setOnTouchListener(
            (v, event) -> {
              handler.removeCallbacks(pagerRunnable);
              return false;
            });

    endCallButton = view.findViewById(R.id.incall_end_call);
    endCallButton.setOnClickListener(this);
    
	//endCallButton.setVisibility(View.GONE);       // modify by fangchen 
 
    if (ContextCompat.checkSelfPermission(getContext(), permission.READ_PHONE_STATE)
            != PackageManager.PERMISSION_GRANTED) {
      voiceNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
    } else {
      LogUtil.d("InCallFragment.onCreateView", "getVoiceNetworkType");
      voiceNetworkType =
              getContext().getSystemService(TelephonyManager.class).getVoiceNetworkType();
    }
    // TODO(a bug): Change to use corresponding phone type used for current call.
    /// M: Performance. @{
    /// Google code:
    /// phoneType = getContext().getSystemService(TelephonyManager.class).getPhoneType();
    phoneType = TelephonyManager.getPhoneType(voiceNetworkType);
    /// @}

    // Workaround to adjust padding for status bar and navigation bar since fitsSystemWindows
    // doesn't work well when switching with other fragments.
    view.addOnAttachStateChangeListener(
            new OnAttachStateChangeListener() {
              @Override
              public void onViewAttachedToWindow(View v) {
                View container = v.findViewById(R.id.incall_ui_container);
                int topInset = v.getRootWindowInsets().getSystemWindowInsetTop();
                int bottomInset = v.getRootWindowInsets().getSystemWindowInsetBottom();
                if (topInset != container.getPaddingTop()) {
                  TransitionManager.beginDelayedTransition(((ViewGroup) container.getParent()));
                  container.setPadding(0, topInset, 0, bottomInset);
                }
              }

              @Override
              public void onViewDetachedFromWindow(View v) {}
            });
    return view;
  }

  @Override
  public void onResume() {
    super.onResume();
    inCallScreenDelegate.onInCallScreenResumed();
  }

  @Override
  public void onViewCreated(@NonNull View view, @Nullable Bundle bundle) {
    LogUtil.i("InCallFragment.onViewCreated", null);
    super.onViewCreated(view, bundle);
	
	// modify by fangcehen start 
	specialCallGif = view.findViewById(R.id.special_call_gif);
	// modify by fangcehen end  
	
	
    /// M: [Voice Record] Add for recording. @{
    initVoiceRecorderIcon(view);
    /// @}
    inCallScreenDelegate =
            FragmentUtils.getParent(this, InCallScreenDelegateFactory.class).newInCallScreenDelegate();
    Assert.isNotNull(inCallScreenDelegate);

    // modify by fangchen start
    buttonControllers.add(new ButtonController.MuteButtonController(inCallButtonUiDelegate));
    buttonControllers.add(new ButtonController.SpeakerButtonController(inCallButtonUiDelegate));
    buttonControllers.add(new ButtonController.DialpadButtonController(inCallButtonUiDelegate));
    //  buttonControllers.add(new ButtonController.HoldButtonController(inCallButtonUiDelegate));
    //    buttonControllers.add(new ButtonController.AddCallButtonController(inCallButtonUiDelegate));
    // modify by fangchen end
    buttonControllers.add(new ButtonController.SwapButtonController(inCallButtonUiDelegate));
    buttonControllers.add(new ButtonController.MergeButtonController(inCallButtonUiDelegate));
    //buttonControllers.add(new ButtonController.SwapSimButtonController(inCallButtonUiDelegate));
    // modify by fangchen start
   /* buttonControllers.add(
            new ButtonController.UpgradeToVideoButtonController(inCallButtonUiDelegate));*/
    // modify by fangchen end
    buttonControllers.add(new UpgradeToRttButtonController(inCallButtonUiDelegate));
    buttonControllers.add(
            new ButtonController.ManageConferenceButtonController(inCallScreenDelegate));
    buttonControllers.add(
            new ButtonController.SwitchToSecondaryButtonController(inCallScreenDelegate));
    /// M: [Voice Record] @{
    // modify by fangchen start
  /*  buttonControllers.add(
        new ButtonController.SwitchVoiceRecordButtonController(inCallButtonUiDelegate));*/
    // modify by fangchen end
    /// @}
    /// M: [Hang Up] @{
    buttonControllers.add(
            new ButtonController.HangupAllButtonController(inCallScreenDelegate));
    buttonControllers.add(
            new ButtonController.HangupHoldButtonController(inCallScreenDelegate));
    /// @}
    /// M: [ECT(blind)] @{
    buttonControllers.add(
            new ButtonController.ECTButtonController(inCallButtonUiDelegate));
    buttonControllers.add(
            new ButtonController.BlindECTButtonController(inCallButtonUiDelegate));
    /// @}

    /// M: [One way video] @{
    /*buttonControllers.add(
            new ButtonController.UpgradeToOneWayVideoButtonController(inCallButtonUiDelegate));
    */
    /// @}

    inCallScreenDelegate.onInCallScreenDelegateInit(this);
    inCallScreenDelegate.onInCallScreenReady();
  }

  @Override
  public void onPause() {
    super.onPause();
    inCallScreenDelegate.onInCallScreenPaused();
  }

  @Override
  public void onDestroyView() {
    super.onDestroyView();
    inCallScreenDelegate.onInCallScreenUnready();
  }

  @Override
  public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    inCallButtonUiDelegate.onSaveInstanceState(outState);
  }

  @Override
  public void onClick(View view) {
    if (view == endCallButton) {
      LogUtil.i("InCallFragment.onClick", "end call button clicked");
      Logger.get(getContext())
              .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_HANG_UP_BUTTON_PRESSED);
      inCallScreenDelegate.onEndCallClicked();
    } else {
      LogUtil.e("InCallFragment.onClick", "unknown view: " + view);
      Assert.fail();
    }
  }

  @Override
  public void setPrimary(@NonNull PrimaryInfo primaryInfo) {
    LogUtil.d("InCallFragment.setPrimary", primaryInfo.toString());
    setAdapterMedia(primaryInfo.multimediaData(), primaryInfo.showInCallButtonGrid());
    contactGridManager.setPrimary(primaryInfo);

	// modify by fangchen start
    checkAndPlaySpecialGif(primaryInfo);	
	// modify by fangchen end 
	
    if (primaryInfo.shouldShowLocation()) {
      // Hide the avatar to make room for location
      contactGridManager.setAvatarHidden(true);

      // Need to let the dialpad move up a little further when location info is being shown
      View dialpadView = getView().findViewById(R.id.incall_dialpad_container);
      ViewGroup.LayoutParams params = dialpadView.getLayoutParams();
      if (params instanceof RelativeLayout.LayoutParams) {
        ((RelativeLayout.LayoutParams) params).removeRule(RelativeLayout.BELOW);
      }
      dialpadView.setLayoutParams(params);
    }
  }

  private void setAdapterMedia(MultimediaData multimediaData, boolean showInCallButtonGrid) {
    if (adapter == null) {
      adapter =
              new InCallPagerAdapter(getChildFragmentManager(), multimediaData, showInCallButtonGrid);
      pager.setAdapter(adapter);
    } else {
      adapter.setAttachments(multimediaData);
    }

    if (adapter.getCount() > 1 && getResources().getInteger(R.integer.incall_num_rows) > 1) {
      paginator.setVisibility(View.VISIBLE);
      paginator.setupWithViewPager(pager);
      pager.setSwipingLocked(false);
      if (!stateRestored) {
        handler.postDelayed(pagerRunnable, 4_000);
      } else {
        pager.setCurrentItem(adapter.getButtonGridPosition(), false /* animateScroll */);
      }
    } else {
      paginator.setVisibility(View.GONE);
    }
  }

  @Override
  public void setSecondary(@NonNull SecondaryInfo secondaryInfo) {
    LogUtil.d("InCallFragment.setSecondary", secondaryInfo.toString());

    /// M: Need inset secondary view after sim account dialog show @{
    if (needInsetSecondaryView) {
      getActivity().getWindow().getDecorView().requestApplyInsets();
      needInsetSecondaryView = false;
      LogUtil.i("InCallFragment.setSecondary", "requestApplyInsets");
    }
    /// @}

    /// M: [Performance] Do not update button state every time. @{
    /// Google code: updateButtonStates();
    if (secondaryInfo.shouldShow()) {
      updateButtonStates();
    }
    /// @}

    if (!isAdded()) {
      savedSecondaryInfo = secondaryInfo;
      return;
    }
    savedSecondaryInfo = null;
    FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
    Fragment oldBanner = getChildFragmentManager().findFragmentById(R.id.incall_on_hold_banner);
    if (secondaryInfo.shouldShow()) {
      transaction.replace(R.id.incall_on_hold_banner, OnHoldFragment.newInstance(secondaryInfo));
    } else {
      if (oldBanner != null) {
        transaction.remove(oldBanner);
      }
    }
    transaction.setCustomAnimations(R.anim.abc_slide_in_top, R.anim.abc_slide_out_top);
    transaction.commitNowAllowingStateLoss();
  }

  @Override
  public void setCallState(@NonNull PrimaryCallState primaryCallState) {
    LogUtil.i("InCallFragment.setCallState", primaryCallState.toString() +
            ", Phonetype:" + phoneType);
    contactGridManager.setCallState(primaryCallState);
    getButtonController(InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY)
            .setAllowed(primaryCallState.swapToSecondaryButtonState() != ButtonState.NOT_SUPPORT);
    getButtonController(InCallButtonIds.BUTTON_SWITCH_TO_SECONDARY)
            .setEnabled(primaryCallState.swapToSecondaryButtonState() == ButtonState.ENABLED);
    /// M: Get voice network type and phone type according to call account @{
    updateInfoForButtonChooser(primaryCallState.state());
    /// @}
    buttonChooser =
            ButtonChooserFactory.newButtonChooser(
                    voiceNetworkType, primaryCallState.isWifi(), phoneType);
    updateButtonStates();
	
	// modify by fangchen start 
	LogUtil.i("InCallFragment.setCallState", "to check call state ");

	int state = primaryCallState.state();
    if (state == DialerCallState.DISCONNECTED
            || state == DialerCallState.DISCONNECTING
            || state == DialerCallState.IDLE) {
		LogUtil.i("InCallFragment.setCallState", "=======stopSpecialGif===");
        stopSpecialGif();
    }
	// modify by fangchen start 

  }

  @Override
  public void setEndCallButtonEnabled(boolean enabled, boolean animate) {
    if (endCallButton != null) {
      endCallButton.setEnabled(enabled);
    }
  }

  @Override
  public void showManageConferenceCallButton(boolean visible) {
    /// M: [Performance] Improve volte mo call performance. @{
    LogUtil.d("InCallFragment.showManageConferenceCallButton", "visible = " + visible);
    if (isManageConferenceVisible() != visible) {
      getButtonController(InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE).setAllowed(visible);
      getButtonController(InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE).setEnabled(visible);
      updateButtonStates();
    }
    /// @}
  }

  @Override
  public boolean isManageConferenceVisible() {
    return getButtonController(InCallButtonIds.BUTTON_MANAGE_VOICE_CONFERENCE).isAllowed();
  }

  @Override
  public void dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
    contactGridManager.dispatchPopulateAccessibilityEvent(event);
  }

  @Override
  public void showNoteSentToast() {
    LogUtil.i("InCallFragment.showNoteSentToast", null);
    Toast.makeText(getContext(), R.string.incall_note_sent, Toast.LENGTH_LONG).show();
  }

  @Override
  public void updateInCallScreenColors() {}

  @Override
  public void onInCallScreenDialpadVisibilityChange(boolean isShowing) {
    LogUtil.i("InCallFragment.onInCallScreenDialpadVisibilityChange", "isShowing: " + isShowing);
    // Take note that the dialpad button isShowing
    // modify by fangchen start
    getButtonController(InCallButtonIds.BUTTON_DIALPAD).setChecked(isShowing);
    // modify by fangchen end

    // This check is needed because there is a race condition where we attempt to update
    // ButtonGridFragment before it is ready, so we check whether it is ready first and once it is
    // ready, #onButtonGridCreated will mark the dialpad button as isShowing.
    if (inCallButtonGridFragment != null) {
      // Update the Android Button's state to isShowing.
      inCallButtonGridFragment.onInCallScreenDialpadVisibilityChange(isShowing);
    }
    Activity activity = getActivity();
    Window window = activity.getWindow();
    window.setNavigationBarColor(
            activity.getColor(
                    isShowing ? android.R.color.background_dark : android.R.color.transparent));
  }

  @Override
  public int getAnswerAndDialpadContainerResourceId() {
    return R.id.incall_dialpad_container;
  }

  @Override
  public Fragment getInCallScreenFragment() {
    return this;
  }

  @Override
  public void showButton(@InCallButtonIds int buttonId, boolean show) {
    LogUtil.v(
            "InCallFragment.showButton",
            "buttionId: %s, show: %b",
            InCallButtonIdsExtension.toString(buttonId),
            show);
    if (isSupportedButton(buttonId)) {
      getButtonController(buttonId).setAllowed(show);
      // modify by fangchen start
      /*if (buttonId == InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO && show) {
        Logger.get(getContext())
                .logImpression(DialerImpression.Type.UPGRADE_TO_VIDEO_CALL_BUTTON_SHOWN);
      }*/
      // modify by fangchen end
    }
  }

  @Override
  public void enableButton(@InCallButtonIds int buttonId, boolean enable) {
    LogUtil.v(
            "InCallFragment.enableButton",
            "buttonId: %s, enable: %b",
            InCallButtonIdsExtension.toString(buttonId),
            enable);
    if (isSupportedButton(buttonId)) {
      getButtonController(buttonId).setEnabled(enable);
    }
  }

  @Override
  public void setEnabled(boolean enabled) {
    LogUtil.v("InCallFragment.setEnabled", "enabled: " + enabled);
    for (ButtonController buttonController : buttonControllers) {
      buttonController.setEnabled(enabled);
    }
  }

  @Override
  public void setHold(boolean value) {
    // modify by fangchen start
    // getButtonController(InCallButtonIds.BUTTON_HOLD).setChecked(value);
    // modify by fangchen end
  }

  @Override
  public void setCameraSwitched(boolean isBackFacingCamera) {}

  @Override
  public void setVideoPaused(boolean isPaused) {}

  @Override
  public void setAudioState(CallAudioState audioState) {
    /// M: do not show bluetooth device information. @{
    /// Google code: LogUtil.i("InCallFragment.setAudioState", "audioState: " + audioState);
    LogUtil.i("InCallFragment.setAudioState", "isMuted: " + audioState.isMuted() + ", route: "
            + CallAudioState.audioRouteToString(audioState.getRoute()) + ", supportMask: "
            + CallAudioState.audioRouteToString(audioState.getSupportedRouteMask()));
    /// @}

    /// M: ALPS05941240 AudioRouteSelectorDialogFragment would not dismiss when call
    /// audio state changed. @{
    AudioRouteSelectorDialogFragment audioRouteSelectorDialog =
            (AudioRouteSelectorDialogFragment) this.getChildFragmentManager().
                    findFragmentByTag(TAG_AUDIOROUTE_SELECTOR_FRAGMENT);
    if (audioRouteSelectorDialog != null) {
      audioRouteSelectorDialog.dismissAllowingStateLoss();
      audioRouteSelectorDialog = null;
    }
    /// @}

// modify by fangchen start
    ((SpeakerButtonController) getButtonController(InCallButtonIds.BUTTON_AUDIO))
            .setAudioState(audioState);
    getButtonController(InCallButtonIds.BUTTON_MUTE).setChecked(audioState.isMuted());
    // modify by fangchen end
  }

  @Override
  public void updateButtonStates() {
    // When the incall screen is ready, this method is called from #setSecondary, even though the
    // incall button ui is not ready yet. This method is called again once the incall button ui is
    // ready though, so this operation is safe and will be executed asap.
    if (inCallButtonGridFragment == null) {
      return;
    }
    int numVisibleButtons =
            inCallButtonGridFragment.updateButtonStates(
                    buttonControllers, buttonChooser, voiceNetworkType, phoneType);

    int visibility = numVisibleButtons == 0 ? View.GONE : View.VISIBLE;
    pager.setVisibility(visibility);
    if (adapter != null
            && adapter.getCount() > 1
            && getResources().getInteger(R.integer.incall_num_rows) > 1) {
      paginator.setVisibility(View.VISIBLE);
      pager.setSwipingLocked(false);
    } else {
      paginator.setVisibility(View.GONE);
      if (adapter != null) {
        pager.setSwipingLocked(true);
        pager.setCurrentItem(adapter.getButtonGridPosition());
      }
    }
  }

  @Override
  public void updateInCallButtonUiColors(@ColorInt int color) {
    inCallButtonGridFragment.updateButtonColor(color);
  }

  @Override
  public Fragment getInCallButtonUiFragment() {
    return this;
  }

  @Override
  public void showAudioRouteSelector() {
    /// M: ALPS05941240 AudioRouteSelectorDialogFragment would not dismiss when call
    /// audio state changed. @{
    AudioRouteSelectorDialogFragment.newInstance(inCallButtonUiDelegate.getCurrentAudioState())
            .show(getChildFragmentManager(), TAG_AUDIOROUTE_SELECTOR_FRAGMENT);
    /// @}
  }

  @Override
  public void onAudioRouteSelected(int audioRoute) {
    /// M: Add debug info
    LogUtil.d("InCallFragment.onAudioRouteSelected", "audioRoute: " + audioRoute);
    inCallButtonUiDelegate.setAudioRoute(audioRoute);
  }

  @Override
  public void onAudioRouteSelectorDismiss() {}

  @NonNull
  @Override
  public ButtonController getButtonController(@InCallButtonIds int id) {
    for (ButtonController buttonController : buttonControllers) {
      if (buttonController.getInCallButtonId() == id) {
        return buttonController;
      }
    }
    Assert.fail();
    return null;
  }

  @Override
  public void onButtonGridCreated(InCallButtonGridFragment inCallButtonGridFragment) {
    LogUtil.i("InCallFragment.onButtonGridCreated", "InCallUiReady");
    this.inCallButtonGridFragment = inCallButtonGridFragment;
    inCallButtonUiDelegate.onInCallButtonUiReady(this);
    
     // modify by fangchen start
      try {
        getButtonController(InCallButtonIds.BUTTON_DIALPAD).setAllowed(false);   
    } catch (Exception e) {
        LogUtil.e("InCallFragment", "hide dialpad button failed", e);
    } 
	// modify by fangchen end 	

    updateButtonStates();
	
	
	
	
  }

  @Override
  public void onButtonGridDestroyed() {
    LogUtil.i("InCallFragment.onButtonGridCreated", "InCallUiUnready");
    inCallButtonUiDelegate.onInCallButtonUiUnready();
    this.inCallButtonGridFragment = null;
  }

  @Override
  public boolean isShowingLocationUi() {
    Fragment fragment = getLocationFragment();
    return fragment != null && fragment.isVisible();
  }

  @Override
  public void showLocationUi(@Nullable Fragment locationUi) {
    boolean isVisible = isShowingLocationUi();
    if (locationUi != null && !isVisible) {
      // Show the location fragment.
      getChildFragmentManager()
              .beginTransaction()
              .replace(R.id.incall_location_holder, locationUi)
              .commitAllowingStateLoss();
    } else if (locationUi == null && isVisible) {
      // Hide the location fragment
      getChildFragmentManager()
              .beginTransaction()
              .remove(getLocationFragment())
              .commitAllowingStateLoss();
    }
  }

  @Override
  public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
    super.onMultiWindowModeChanged(isInMultiWindowMode);
    if (isInMultiWindowMode == isShowingLocationUi()) {
      LogUtil.i("InCallFragment.onMultiWindowModeChanged", "hide = " + isInMultiWindowMode);
      // Need to show or hide location
      showLocationUi(isInMultiWindowMode ? null : getLocationFragment());
    }
    contactGridManager.onMultiWindowModeChanged(isInMultiWindowMode);
  }

  private Fragment getLocationFragment() {
    return getChildFragmentManager().findFragmentById(R.id.incall_location_holder);
  }

  /// M: ----------------------------MediaTek feature --------------------------
  private boolean needInsetSecondaryView = true;

  private void updateInfoForButtonChooser(int state) {
    DialerCall call = CallList.getInstance().getFirstCallWithState(state);
    if (call == null) {
      LogUtil.i("InCallFragment.updateInfoForButtonChooser", "no call, state: " + state);
      return;
    }
    if (call.getDetails() == null) {
      LogUtil.i("InCallFragment.updateInfoForButtonChooser", "no call details, state: " + state);
      return;
    }
    LogUtil.d("InCallFragment.updateInfoForButtonChooser", String.valueOf(call));
    /// M: ALPS03567937. Do not get network type and phone type in connecting status
    // dut to performance. @{
    if (call != null && !DialerCallState.isConnecting(state)) {
      voiceNetworkType = call.getVoiceNetworkTypeForCall();
      phoneType = call.getPhoneTypeByNetworkType(voiceNetworkType);
    }
    /// @}
  }

  /**
   * M: [Voice Record] updateRecordStateUi
   * @param isRecording
   */
  @Override
  public void updateRecordStateUi(boolean isRecording) {
    LogUtil.d("InCallFragment.updateRecordStateUi", "[updateRecordStateUi]... " + isRecording);

    DialerCall ringCall = CallList.getInstance().getIncomingCall();
    if (isRecording && (ringCall == null)) {
      updateVoiceRecordIcon(true);
    } else {
      updateVoiceRecordIcon(false);
    }
    // modify by fangchen start
    //   getButtonController(InCallButtonIds.BUTTON_SWITCH_VOICE_RECORD).setChecked(isRecording);
    // modify by fangchen end
  }

  /// M: [Voice Record] recording indication icon
  private ImageView voiceRecorderIcon;

  /**
   * M: [Voice Record] initVoiceRecorderIcon
   * @param view
   */
  private void initVoiceRecorderIcon(View view) {
    voiceRecorderIcon = (ImageView) view.findViewById(R.id.voiceRecorderIcon);
    voiceRecorderIcon.setImageResource(R.drawable.voice_record_indicator);
    voiceRecorderIcon.setVisibility(View.INVISIBLE);
  }

  /**
   * M: [Voice Record] updateVoiceRecordIcon
   * @param show need to show
   */
  public void updateVoiceRecordIcon(boolean show) {
    voiceRecorderIcon.setVisibility(show ? View.VISIBLE : View.INVISIBLE);
    AnimationDrawable ad = (AnimationDrawable) voiceRecorderIcon.getDrawable();
    if (ad != null) {
      if (show && !ad.isRunning()) {
        ad.start();
      } else if (!show && ad.isRunning()) {
        ad.stop();
      }
    }
  }

  @Override
  public void updateDeclineTimer() {
  }

  /// M: Video early ringtone for MT. @{
  @Override
  public void updateMediaActionUI(boolean hasFirstFrame, int[] buttonState) {
  }
  /// @}
  
  
  // modify by fangchen start
 
private void checkAndPlaySpecialGif(PrimaryInfo primaryInfo) {
    if (specialCallGif == null) {
        return;
    }

    String number = primaryInfo.number();
    LogUtil.d("InCallFragment.checkAndPlaySpecialGif", "number = " + number);

    if (number == null) {
		
		LogUtil.i("InCallFragment.checkAndPlaySpecialGif", "number == null return  ");

        return;
    }

     String normalized = number.replace(" ", "").replace("-", "");
    if (normalized.startsWith("+86")) {
        normalized = normalized.substring(3);
    }

    if (!SPECIAL_NUMBER.equals(normalized)) {
		LogUtil.i("InCallFragment.checkAndPlaySpecialGif", "!SPECIAL_NUMBER.equals(normalized) return  ");
         stopSpecialGif();
        return;
    }

     if (specialGifLoaded) {
		 LogUtil.i("InCallFragment.checkAndPlaySpecialGif", "specialGifLoaded is true  so --> return  ");
        return;
    }
    specialGifLoaded = true;

	/*if (getActivity() instanceof InCallActivity) {
        ((InCallActivity) getActivity()).showDialpadFragment(true, true);
    }*/
     playSpecialGif();
}

 
private void playSpecialGif() {
	LogUtil.i("InCallFragment.playSpecialGif", "==========playSpecialGif  ");
    specialCallGif.setVisibility(View.VISIBLE);
    specialGifPlaying = true;
   
    Glide.with(this)
            .asGif()                                   
            .load(R.raw.xiaoxing)                      
           // .diskCacheStrategy(DiskCacheStrategy.NONE)  
            .into(specialCallGif);
}

 
private void stopSpecialGif() {
    if (specialCallGif == null) {
        return;
    }

    
    if (specialGifPlaying) {
        Glide.with(this).clear(specialCallGif);
        specialGifPlaying = false;
    }

    specialCallGif.setVisibility(View.GONE);
    specialGifLoaded = false;
}  
  // modify by fangchen end 
  
  
  
}
java 复制代码
<?xml version="1.0" encoding="utf-8"?>
<!--
  ~ Copyright (C) 2017 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
  -->
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
	<ImageView
      android:id="@+id/special_call_gif"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:layout_gravity="center"
      android:scaleType="centerCrop"
      android:visibility="gone"
      android:contentDescription="@null" />  
	  
  <RelativeLayout
      android:id="@+id/incall_ui_container"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:clipChildren="false"
      android:clipToPadding="false"
      android:fitsSystemWindows="true">

    <LinearLayout
        android:id="@id/incall_contact_grid"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="12dp"
        android:gravity="center_horizontal"
        android:orientation="vertical">

      <ImageView
          android:id="@id/contactgrid_avatar"
          android:layout_width="@dimen/incall_avatar_size"
          android:layout_height="@dimen/incall_avatar_size"
          android:layout_marginBottom="8dp"
          android:elevation="2dp"/>

      <include
          layout="@layout/incall_contactgrid_top_row"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="@dimen/incall_window_margin_horizontal"
          android:layout_marginEnd="@dimen/incall_window_margin_horizontal"/>

      <!-- We have to keep deprecated singleLine to allow long text being truncated with ellipses.
                 a bug -->
      <!-- M:fix ALPS04221220,add 'gravity' as center to make sure the content is
          in middle of the AutoResizeTextView -->
      <com.android.incallui.autoresizetext.AutoResizeTextView
          android:id="@id/contactgrid_contact_name"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginBottom="4dp"
          android:layout_marginStart="@dimen/incall_window_margin_horizontal"
          android:layout_marginEnd="@dimen/incall_window_margin_horizontal"
          android:singleLine="true"
          android:gravity="center_horizontal"
          android:textAppearance="@style/Dialer.Incall.TextAppearance.Large"
          app:autoResizeText_minTextSize="28sp"
          tools:ignore="Deprecated"
          tools:text="Jake Peralta"/>

      <include
          layout="@layout/incall_contactgrid_bottom_row"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_marginStart="@dimen/incall_window_margin_horizontal"
          android:layout_marginEnd="@dimen/incall_window_margin_horizontal"/>

      <FrameLayout
          android:id="@+id/incall_location_holder"
          android:layout_width="match_parent"
          android:layout_height="match_parent"/>

      <include
          layout="@layout/device_number_row"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"/>

      <!-- M:[Voice Record]record icon -->
      <!-- M:fix ALPS02297097,recording icon still at the right
          side as Arabic,correct layout_gravity from right to end -->
      <ImageView android:id="@+id/voiceRecorderIcon"
          android:layout_width="@dimen/incall_record_icon_size"
          android:layout_height="@dimen/incall_record_icon_size"
          android:layout_gravity="end"
          android:layout_marginEnd="10dip"
          android:layout_marginBottom="10dip"
          android:visibility="gone" />
    </LinearLayout>


    <com.android.incallui.incall.impl.InCallPaginator
        android:id="@+id/incall_paginator"
        android:layout_width="@dimen/paginator_width"
        android:layout_height="@dimen/paginator_height"
        android:layout_above="@+id/incall_end_call"
        android:layout_centerHorizontal="true"
        android:visibility="gone"/>

    <FrameLayout
        android:id="@+id/incall_dialpad_container"
        style="@style/DialpadContainer"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:clipChildren="false"
        android:clipToPadding="false"
        tools:background="@android:color/transparent"
        tools:visibility="gone"/>
		
	

    <com.android.dialer.widget.LockableViewPager
        android:id="@+id/incall_pager"
        android:layout_width="match_parent"
        android:layout_height="70px"
        android:layout_centerHorizontal="true"
		android:layout_marginBottom="36dp"
        android:layout_alignParentBottom="true"
		 />	
		
		
    <ImageButton
        android:id="@+id/incall_end_call"
        style="@style/Incall.Button.End"
        android:layout_marginTop="16dp"
        android:layout_marginBottom="36dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:contentDescription="@string/incall_content_description_end_call"
		/>
		
		
		
  </RelativeLayout>
  


  <FrameLayout
      android:id="@id/incall_on_hold_banner"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_gravity="top"/>
	  

</FrameLayout>

四、遇到的困难、难点

遇到难点

实际调试了很久,有几个坑。

  • 如何保证动画效果,发现动画总是遮挡其它UI组件
  • 挂断电话按钮下面总是有一个白色的图标
  • 数字按键弹框显示逻辑梳理清楚,不然总是崩溃。目标是数字键盘功能按钮要隐藏,那么如何隐藏?
  • 数字弹框背景白色,需要透明状态

分析解决方案

动画总是遮挡布局

确认清楚动画UI 放到布局最底部,不然放到最顶部肯定遮挡存在的。

数字弹框需要透明-去掉白色

这个过程就是找源码的过程,需要自己找一找,最终找到布局和数字弹框的类。

路径:/vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/dialer/dialpadview/res/layout/dialpad_view_unthemed.xml /vendor/mediatek/proprietary/packages/apps/Dialer/java/com/android/incallui/DialpadFragment.java

数字弹框默认显示-崩溃问题-去掉数字键盘(挂断中的白色背景)

首先要搞清楚数字键盘显示逻辑:本身我们是定制的指定电话显示数字弹框。实测发现 哪个白色的背景就是数字键盘 而不是 背景。 沿着这个思路、实验分析问题。

  • 不能在InCallFragment.java 中去掉数字键盘控制逻辑,比如这行代码绝对不能屏蔽:buttonControllers.add(new ButtonController.DialpadButtonController(inCallButtonUiDelegate));
  • 如何去掉数字键盘,它只是被挂断按钮遮住了而已,要隐藏:getButtonController(InCallButtonIds.BUTTON_DIALPAD).setAllowed(false); ,如下:
java 复制代码
  public void onButtonGridCreated(InCallButtonGridFragment inCallButtonGridFragment) {
    LogUtil.i("InCallFragment.onButtonGridCreated", "InCallUiReady");
    this.inCallButtonGridFragment = inCallButtonGridFragment;
    inCallButtonUiDelegate.onInCallButtonUiReady(this);
    
     // modify by fangchen start
      try {
        getButtonController(InCallButtonIds.BUTTON_DIALPAD).setAllowed(false);   
    } catch (Exception e) {
        LogUtil.e("InCallFragment", "hide dialpad button failed", e);
    } 
	// modify by fangchen end 	

    updateButtonStates();
	
	
	
	
  }

总结

  • 合格需求其实不麻烦的,但是还是需要对Dialer 相关模块非常熟悉,然后对代码要跟一下,对控制逻辑也要分析一下,思路错了会耽搁很长时间。