AOP的简单应用

来源:互联网 发布:淘宝上的内存条能买吗 编辑:程序博客网 时间:2024/06/11 05:24

需求场景:无埋点实现监控到应用中所有的Button和Edittext。要求获取Button点击时压力和输入框每次输入字符时陀螺仪的值。
一开始思路是想办法获取要监控的控件对象,于是用到了registerActivityLifecycleCallbacks,代码如下:

public class MyApplication extends Application {    @Override    public void onCreate() {        super.onCreate();        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {            @Override            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {            }            @Override            public void onActivityStarted(Activity activity) {            }            @Override            public void onActivityResumed(Activity activity) {            }            @Override            public void onActivityPaused(Activity activity) {            }            @Override            public void onActivityStopped(Activity activity) {            }            @Override            public void onActivitySaveInstanceState(Activity activity, Bundle outState) {            }            @Override            public void onActivityDestroyed(Activity activity) {            }        });    }}

这样可以获取到Activity对象,然后遍历Activity对象中所有的控件,遍历方法:
先获取view树:

View rootView = ((ViewGroup) activity.findViewById(android.R.id.content)).getChildAt(0);

然后调用:

private void traversalView(View view) {        if (view instanceof ViewGroup) {            ViewGroup viewGroup = (ViewGroup) view;            for (int i = 0; i < viewGroup.getChildCount(); i++) {                View child = viewGroup.getChildAt(i);                traversalView(child);            }        } else if (view instanceof EditText) {            //当是edittext时加入自己的操作            onFindEditText((EditText) view);        } else if (view instanceof Button) {            //当是button时加入自己的操作            onFindButton((Button) view);        }    }    private void onFindButton(final Button view) {        view.setOnTouchListener(new View.OnTouchListener() {            @Override            public boolean onTouch(View v, MotionEvent event) {                switch (event.getAction()) {                    case MotionEvent.ACTION_DOWN:                        Log.i("AA", view.getText().toString() + ":jar:down:" + event.getPressure() + ":" + event.getPressure(0));                        break;                    case MotionEvent.ACTION_MOVE:                        Log.i("AA", "jar:move:" + ":jar:down:" + event.getPressure() + ":" + event.getPressure(0));                        break;                    case MotionEvent.ACTION_UP:                        Log.i("AA", "jar:up:" + ":jar:down:" + event.getPressure() + ":" + event.getPressure(0));                        break;                }                return false;            }        });    }    private void onFindEditText(EditText view) {        EditText et = view;        TextWatcher watcher = new TextWatcher() {            @Override            public void beforeTextChanged(CharSequence s, int start, int count, int after) {            }            @Override            public void onTextChanged(CharSequence s, int start, int before, int count) {            }            @Override            public void afterTextChanged(Editable editable) {                Toast.makeText(application, "陀螺仪:" + "\nX:" + SensorUtils2.getInstence().X + "\nY:" + SensorUtils2.getInstence().Y + "\nZ:" + SensorUtils2.getInstence().Z                        + "\n传感加速器:" + "\nX:" + SensorUtils.getInstence().X + "\nY:" + SensorUtils.getInstence().Y + "\nZ:" + SensorUtils.getInstence().Z, Toast.LENGTH_LONG).show();            }        };        et.addTextChangedListener(watcher);        mEditTextMap.put(et, watcher);    }

这样就实现了给遍历到的控件添加的监听,但是这样却不能拿到popupwindow和fragment里的控件。
于是转换思路,用到了面向切面编程的思想(AOP),其中一种就是AspectJ 参考http://blog.csdn.net/eclipsexys/article/details/54425414

完整代码:

package com.example.nieyuqi959.mylibrary;import android.text.Editable;import android.text.TextWatcher;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.Button;import android.widget.EditText;import com.example.nieyuqi959.mylibrary.bean.Press;import com.example.nieyuqi959.mylibrary.bean.SensorValue;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;@Aspectpublic class AspectTest {    private static final String TAG = "AA";    private String editable;    @AfterReturning(value = "call(* android.view.View.findViewById(..))", returning = "returnvalue")    public void onFindViewMethodAfter(Object returnvalue, JoinPoint joinPoint) throws Throwable {        //次方法可以劫持到findviewbyid方法以及用butternife注解获取控件对象的方法        if (returnvalue instanceof Button) {            ((Button) returnvalue).setOnTouchListener(new View.OnTouchListener() {                @Override                public boolean onTouch(View v, MotionEvent event) {                    return false;                }            });        } else if (returnvalue instanceof EditText) {            ((EditText) returnvalue).addTextChangedListener(new TextWatcher() {                @Override                public void beforeTextChanged(CharSequence s, int start, int count, int after) {                }                @Override                public void onTextChanged(CharSequence s, int start, int before, int count) {                }                @Override                public void afterTextChanged(Editable s) {                }            });        }        Log.e("AA", "find控件" + (returnvalue instanceof Button) + (returnvalue instanceof EditText));    }    @AfterReturning(value = "call(* android.support.v7.app.AppCompatActivity.findViewById(..))", returning = "returnvalue")    public void onActivityFindViewMethodAfter(Object returnvalue, JoinPoint joinPoint) throws Throwable {        //次方法是劫持Activity中findviewbyid方法        if (returnvalue instanceof Button) {            ((Button) returnvalue).setOnTouchListener(new View.OnTouchListener() {                @Override                public boolean onTouch(View v, MotionEvent event) {                    return false;                }            });        } else if (returnvalue instanceof EditText) {            ((EditText) returnvalue).addTextChangedListener(new TextWatcher() {                @Override                public void beforeTextChanged(CharSequence s, int start, int count, int after) {                }                @Override                public void onTextChanged(CharSequence s, int start, int before, int count) {                }                @Override                public void afterTextChanged(Editable s) {                }            });        }        Log.e("AA", "find控件" + (returnvalue instanceof Button) + (returnvalue instanceof EditText));    }    @Before("execution(* android.text.TextWatcher.beforeTextChanged(..))")    public void onBeforeTextChangedMethodBefore(JoinPoint joinPoint) throws Throwable {        editable = "";    }    @Before("execution(* android.view.View.OnTouchListener.onTouch(..))")    public void onOntouchMethodBefore(JoinPoint joinPoint) throws Throwable {        Object[] args = joinPoint.getArgs();        MotionEvent motionEvent = (MotionEvent) args[1];        String eventTitle = null;        switch (motionEvent.getAction()) {            case 0:                eventTitle = "down:";                break;            case 2:                eventTitle = "move:";                break;            case 1:                eventTitle = "up:";                break;        }        Button button = (Button) joinPoint.getArgs()[0];//        WriteReadFile.getInstance().writeTxtToFile(eventTitle.equals("down") ? button.getText().toString() + "按钮压力值:" : "" + "\r\n" + eventTitle + ":" + motionEvent.getPressure(), null,"press.txt");//        WriteReadFile.getInstance().save(eventTitle.equals("down") ? button.getText().toString() + "按钮传感加速器值:" : "" + "\r\n" + eventTitle + ":" + "\r\n" + "X:" + SensorAccelerometer.getInstence().X +//                "\r\n" + "Y:" + SensorAccelerometer.getInstence().Y + "\r\n" + "Z:" + SensorAccelerometer.getInstence().Z, "accelerometer.txt");//        WriteReadFile.getInstance().save(eventTitle.equals("down") ? button.getText().toString() + "按钮陀螺仪值:" : "" + "\r\nX:" + SensorGyroscope.getInstence().X+"\r\nY:"+SensorGyroscope.getInstence().Y+//                "\r\nZ:"+SensorGyroscope.getInstence().Z, "gyroscope.txt");        ListValue.listPress.add(new Press(eventTitle, String.valueOf(motionEvent.getPressure()), button.getText().toString()));        ListValue.listAccelerometer.add(new SensorValue(eventTitle, String.valueOf(SensorAccelerometer.getInstence().X), String.valueOf(SensorAccelerometer.getInstence().Y), String.valueOf(SensorAccelerometer.getInstence().Z), button.getText().toString()));        ListValue.listGyroscope.add(new SensorValue(eventTitle, String.valueOf(SensorGyroscope.getInstence().X), String.valueOf(SensorGyroscope.getInstence().Y), String.valueOf(SensorGyroscope.getInstence().Z), button.getText().toString()));        Log.e("AA", eventTitle + ":" + motionEvent.getPressure());    }    @Before("execution(* android.text.TextWatcher.afterTextChanged(..))")    public void onTextAfterChangedMethodBefore(JoinPoint joinPoint) throws Throwable {        String s = joinPoint.getArgs()[0].toString();        if (!s.equals(editable)) {            editable = s;//            SensorAccelerometer.getInstence().registAccelerometer();            ListValue.listAccelerometer.add(new SensorValue(s, String.valueOf(SensorAccelerometer.getInstence().X), String.valueOf(SensorAccelerometer.getInstence().Y), String.valueOf(SensorAccelerometer.getInstence().Z), "输入框"));            ListValue.listGyroscope.add(new SensorValue(s, String.valueOf(SensorGyroscope.getInstence().X), String.valueOf(SensorGyroscope.getInstence().Y), String.valueOf(SensorGyroscope.getInstence().Z), "输入框"));            Log.e("AA", "获取陀螺仪:" + "\nX:" + SensorGyroscope.getInstence().X + "\nY:" + SensorGyroscope.getInstence().Y + "\nZ:" + SensorGyroscope.getInstence().Z);            Log.e("AA", "传感加速器:" + "\nX:" + SensorAccelerometer.getInstence().X + "\nY:" + SensorAccelerometer.getInstence().Y + "\nZ:" + SensorAccelerometer.getInstence().Z);        }    }}

这样就是不需要动原来的项目就能实现需求。

原创粉丝点击