com.willowtreeapps.respeeker.ResPeeker.java Source code

Java tutorial

Introduction

Here is the source code for com.willowtreeapps.respeeker.ResPeeker.java

Source

/*
* Copyright (c) 2014. WillowTree Apps
*
* 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.willowtreeapps.respeeker;

import android.app.Activity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

import java.io.IOException;
import java.io.StringWriter;
import java.util.Properties;

@Aspect
public class ResPeeker {
    @Pointcut("target(android.app.Activity) && call(void setContentView(int))")
    public void setContentView() {
    }

    @Pointcut("target(android.view.View) && call(void setOnTouchListener(android.view.View$OnTouchListener))")
    public void setOnTouchListener() {
    }

    @Pointcut("target(android.view.LayoutInflater) && call(android.view.View inflate(int, android.view.ViewGroup, boolean))")
    public void inflate() {
    }

    @Around("setContentView()")
    public Object aroundSetContentView(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();

        Activity context = (Activity) joinPoint.getThis();
        int layoutRes = (Integer) joinPoint.getArgs()[0];
        View view = context.findViewById(android.R.id.content);

        attachTouchListener(view);

        ViewPeeker.put(view, layoutRes);

        Configurator configurator = new Configurator(context);
        Properties properties = configurator.getProperties();
        Log.v("__ResPeeker__", "config <<" + propertiesToString(properties) + ">>");

        return result;
    }

    @Around("inflate()")
    public Object aroundInflate(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();

        int layoutRes = (Integer) joinPoint.getArgs()[0];
        View layoutView = (View) joinPoint.getArgs()[1];
        View view = (View) result;

        attachTouchListener(view);

        ViewPeeker.put(layoutView, layoutRes);

        return result;
    }

    @Around("setOnTouchListener()")
    public Object aroundSetOnTouchListener(ProceedingJoinPoint joinPoint) throws Throwable {
        final View.OnTouchListener originalTouchListener = (View.OnTouchListener) joinPoint.getArgs()[0];
        final View.OnTouchListener interceptTouchListener = getTouchListener();

        View.OnTouchListener delegateTouchListener = new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                interceptTouchListener.onTouch(v, event);
                return originalTouchListener != null && originalTouchListener.onTouch(v, event);
            }
        };

        return joinPoint.proceed(new Object[] { delegateTouchListener });
    }

    public void attachTouchListener(View view) {
        view.setOnTouchListener(null);

        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                attachTouchListener(viewGroup.getChildAt(i));
            }
        }
    }

    public View.OnTouchListener getTouchListener() {
        return new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    int layoutRes = ViewPeeker.getLayout(v);
                    if (layoutRes > 0) {
                        String layoutName = v.getContext().getResources().getResourceName(layoutRes);
                        Log.v("__ResPeeker__", "layout <<" + layoutName + ">>");
                    }
                }
                return false;
            }
        };
    }

    public String propertiesToString(Properties properties) {
        StringWriter writer = new StringWriter();
        try {
            properties.store(writer, null);
        } catch (IOException e) {
            // Should never happen since StringWriter doesn't do IO.
            throw new RuntimeException(e);
        }
        return writer.toString();
    }

    // This shouldn't be required?
    public static ResPeeker aspectOf() {
        return new ResPeeker();
    }
}