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 + '}'; } } }