Android embedded solution

Keywords: Mobile Android

I. event realization principle:
① View set AccessibilityDelegate

② when the View generates click, long click and other events, it will respond to the original Listener method

③ after the response of the original Listener method is completed, forward the message to the AccessibilityDelegate in the sendAccessibilityEvent method

④ handle the event in sendAccessibilityEvent of AccessibilityDelegate

⑤ do not call the method at the beginning of the call, such as callOnClick, because the event cannot be sent to sendAccessibilityEvent

The following methods can be used

    public boolean performClick() {
        final boolean result;
        final ListenerInfo li = mListenerInfo;
        if (li != null && li.mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            li.mOnClickListener.onClick(this);
            result = true;
        } else {
            result = false;
        }

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

        notifyEnterOrExitForAutoFillIfNeeded(true);

        return result;
    }

⑥. sendAccessibilityEvent generates the key and value of the event

 public void sendAccessibilityEvent(View host, int eventType) {
            host.sendAccessibilityEventInternal(eventType);
        }

II. Embedded point of Android component life cycle

① Activity life cycle

We can monitor Activity through Application.ActivityLifecycleCallbacks

② Service & broadcastreceiver life cycle

At present, it can only be implemented manually. As for the implementation method, you can modify the following code

public class ActivityStatusManager implements Application.ActivityLifecycleCallbacks{

    public final Integer STATUS_CREATED = 0x0001;
    public final Integer STATUS_RESUMED = 0x0002;
    public final Integer STATUS_PAUSED = 0x0003;
    public final Integer STATUS_STARTED = 0x0004;
    public final Integer STATUS_STOPED = 0x0005;
    public final Integer STATUS_DESTROYED = -1;

    private Map<Activity,Integer> activityStack;

    public void registerActivityLifecycleCallbacks(Application application) {
            application.registerActivityLifecycleCallbacks(this);
    }

    public void unregisterActivityLifecycleCallbacks(Application application){
        application.unregisterActivityLifecycleCallbacks(this);
    }

    private static class Holder{
        public final static ActivityStatusManager instance = new ActivityStatusManager();
    }

    public static ActivityStatusManager shareInstance(){
        return Holder.instance;
    }

    private ActivityStatusManager(){
        activityStack = new ArrayMap<Activity,Integer>();
    }

    public Integer getActivityStatus(Activity activity) {
        final Integer status = activityStack.get(activity);
        if(status==null){
             return  STATUS_DESTROYED;
         }
        return status;
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        if(activity!=null){
            activityStack.put(activity,STATUS_CREATED);
        }
    }

    @Override
    public void onActivityStarted(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_STARTED);
        }
    }

    @Override
    public void onActivityResumed(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_RESUMED);
        }
    }

    @Override
    public void onActivityPaused(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_PAUSED);
        }
    }

    @Override
    public void onActivityStopped(Activity activity) {
        if(activity!=null){
            activityStack.put(activity,STATUS_STOPED);
        }
        synchronized (Holder.instance){
            int counter = 0;
            for (Map.Entry<Activity,Integer> entry : activityStack.entrySet()){
                if(entry.getValue()==STATUS_STOPED){
                    counter++;
                }
            }
            if(counter>0 && activityStack.size()==counter){
                BaseApplication.setInForeground(false);
            }else{
                BaseApplication.setInForeground(true);
            }
        }
    }

    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }

    @Override
    public void onActivityDestroyed(Activity activity) {
        Application application = activity.getApplication();
        activityStack.remove(activity);
        clearInvalidActivity();
        if(activityStack.isEmpty() && application!=null){
            unregisterActivityLifecycleCallbacks(application);
        }
    }

    public void clearInvalidActivity(){
        Iterator<Map.Entry<Activity,Integer>> iterator = activityStack.entrySet().iterator();
        do{
            if(!iterator.hasNext()) return;
            Map.Entry<Activity, Integer> entry = iterator.next();
            if(entry!=null && activityIsDestroyed(entry.getKey()) ){
                iterator.remove();
            }
        }while(iterator.hasNext());

    }

    public void finishAll(){
        if(activityStack.isEmpty()) return;
        Activity activity = null;
        Iterator<Map.Entry<Activity,Integer>> iterator = activityStack.entrySet().iterator();
        do{
            if(!iterator.hasNext()) return;
            Map.Entry<Activity, Integer> entry = iterator.next();
            if(entry!=null ){
                activity = entry.getKey();
                if(activity!=null && !activityIsDestroyed(activity))
                {
                    activity.finish();
                }
                iterator.remove();
            }
        }while(iterator.hasNext());

    }

    /**
     * Whether the program runs in the foreground
     *
     * @return
     */
    public  boolean isForegroundProcess(Context context) {
        // Returns a list of application processes that are running on the
        // device

        ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(Context.ACTIVITY_SERVICE);
        String packageName = context.getApplicationContext().getPackageName();

        List<ActivityManager.RunningAppProcessInfo> appProcesses = activityManager
                .getRunningAppProcesses();
        if (appProcesses == null)
            return false;

        for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
            // The name of the process that this object is associated with.
            if (appProcess.processName.equals(packageName)
                    && appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                return true;
            }
        }
        return false;
    }

    private boolean activityIsDestroyed(Activity thatActivity){
        if(thatActivity==null) return  true;

        if(Build.VERSION.SDK_INT>=17){
            return thatActivity.isDestroyed() ||  thatActivity.isFinishing();
        }else{
            return  thatActivity.isFinishing();
        }
    }
}

 

III. environmental burying points

Register ComponentCallbacks2 in Application

Posted by niall_buckley on Thu, 05 Dec 2019 12:02:07 -0800