content: package com.lody.virtual.server.notification;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import com.lody.virtual.helper.utils.Reflect;
  import com.lody.virtual.helper.utils.VLog;
  
  import android.app.PendingIntent;
  import android.graphics.Rect;
  import android.util.Log;
  import android.view.View;
  import android.view.ViewGroup;
  import android.view.ViewParent;
  import android.widget.ImageView;
  import android.widget.RemoteViews;
  import android.widget.TextView;
  
  import static com.lody.virtual.server.notification.NotificationCompat.TAG;
  
  /***
   * Remoteviews's PendIntent
   *
   * @author 247321453
   */
  class PendIntentCompat {
      private RemoteViews mRemoteViews;
      private Map<Integer, PendingIntent> clickIntents;
  
      PendIntentCompat(RemoteViews mRemoteViews) {
          this.mRemoteViews = mRemoteViews;
      }
  
      public int findPendIntents() {
          if (clickIntents == null) {
              clickIntents = getClickIntents(mRemoteViews);
          }
          return clickIntents.size();
      }
  
      /**
       *
       * @param remoteViews notification's old remoteViews
       * @param remoteview notification's old remoteViews view
       * @param oldRemoteView notification's new remoteViews view
       */
      public void setPendIntent(RemoteViews remoteViews, View remoteview, View oldRemoteView) {
          if (findPendIntents() > 0) {
              Iterator<Map.Entry<Integer, PendingIntent>> set = clickIntents.entrySet().iterator();
              List<RectInfo> list = new ArrayList<>();
              int index = 0;
              VLog.v(TAG, "start find intent");
              while (set.hasNext()) {
                  Map.Entry<Integer, PendingIntent> e = set.next();
                  View view = oldRemoteView.findViewById(e.getKey());
                  if (view != null) {
                      Rect rect = getRect(view);
                      list.add(new RectInfo(rect, e.getValue(), index));
                      index++;
                  }
              }
              VLog.v(TAG, "find:" + list);
              if (remoteview instanceof ViewGroup) {
                  setIntentByViewGroup(remoteViews, (ViewGroup) remoteview, list);
              }
          }
      }
  
      private Rect getRect(View view) {
          Rect rect = new Rect();
          rect.top = view.getTop();
          rect.left = view.getLeft();
          rect.right = view.getRight();
          rect.bottom = view.getBottom();
  
          ViewParent viewParent = view.getParent();
          if (viewParent != null) {
              if (viewParent instanceof ViewGroup) {
                  Rect prect = getRect((ViewGroup) viewParent);
                  rect.top += prect.top;
                  rect.left += prect.left;
                  rect.right += prect.left;
                  rect.bottom += prect.top;
              }
          }
          return rect;
      }
  
      private void setIntentByViewGroup(RemoteViews remoteViews, ViewGroup viewGroup, List<RectInfo> list) {
          int count = viewGroup.getChildCount();
          Rect p = new Rect();
          viewGroup.getHitRect(p);
          for (int i = 0; i < count; i++) {
              View v = viewGroup.getChildAt(i);
              if (v instanceof ViewGroup) {
                  // linearlayout
                  setIntentByViewGroup(remoteViews, (ViewGroup) v, list);
              } else if (v instanceof TextView || v instanceof ImageView) {
                  // textview
                  Rect rect = getRect(v);
                  RectInfo next = findIntent(rect, list);
                  if (next != null) {
  //					VLog.d(TAG, next.rect+":setPendIntent:"+i);
  //                    remoteViews.setImageViewBitmap(v.getId(), next.testBg);
                      remoteViews.setOnClickPendingIntent(v.getId(), next.mPendingIntent);
                  }
              }
          }
      }
  
      private RectInfo findIntent(Rect rect, List<RectInfo> list) {
          int maxArea = 0;
          RectInfo next = null;
          for (RectInfo rectInfo : list) {
              int size = getOverlapArea(rect, rectInfo.rect);
              if (size > maxArea) {
                  if (size == 0) {
                      Log.w("PendingIntentCompat", "find two:" + rectInfo.rect);
                  }
                  maxArea = size;
                  next = rectInfo;
              }
          }
          return next;
      }
  
      private int getOverlapArea(Rect rect1, Rect rect2) {
          Rect rect = new Rect();
          rect.left = Math.max(rect1.left, rect2.left);
          rect.top = Math.max(rect1.top, rect2.top);
          rect.right = Math.min(rect1.right, rect2.right);
          rect.bottom = Math.min(rect1.bottom, rect2.bottom);
          if (rect.left < rect.right && rect.top < rect.bottom) {
              return (rect.right - rect.left) * (rect.bottom - rect.top);
          }
          return 0;
      }
  
      private Map<Integer, PendingIntent> getClickIntents(RemoteViews remoteViews) {
          Map<Integer, PendingIntent> map = new HashMap<>();
          if (remoteViews == null)
              return map;
          Object mActionsObj = null;
          try {
              mActionsObj = Reflect.on(remoteViews).get("mActions");
          } catch (Exception e) {
              e.printStackTrace();
          }
          if (mActionsObj == null) {
              return map;
          }
          if (mActionsObj instanceof Collection) {
              Collection mActions = (Collection) mActionsObj;
              for (Object one : mActions) {
                  if (one != null) {
                      String action;
                      try {
                          action = Reflect.on(one).call("getActionName").get();
                      } catch (Exception e) {
                          action = one.getClass().getSimpleName();
                      }
                      if ("SetOnClickPendingIntent".equalsIgnoreCase(action)) {
                          int id = Reflect.on(one).get("viewId");
                          PendingIntent intent = Reflect.on(one).get("pendingIntent");
                          map.put(id, intent);
                      }
                  }
              }
          }
          return map;
      }
  
      class RectInfo {
          Rect rect;
          PendingIntent mPendingIntent;
          int index;
  
          public RectInfo(Rect rect, PendingIntent pendingIntent, int index) {
              this.rect = rect;
              mPendingIntent = pendingIntent;
              this.index = index;
          }
  
          @Override
          public String toString() {
              return "RectInfo{" +
                      "rect=" + rect +
                      '}';
          }
      }
  }
  