Data is accumulated to a certain amount and user behavior data is sent to the backend server. BaseActivity base class designUsing the Android event distribution mechanism, our custom base class BaseActivity inherits from the Activity and overwrites the dispatchTouchEvent method of the Activity (why? For more information, see my previous blog) and rewrite all lifecycle methods of an Activity.
Rewrite Activity lifecycle and event Distribution Method
Rewrite the onStart () and onStop () {or onDestory of the Activity life cycle, which are determined based on your choice} to complete tracking record for enabling and disabling the interface. The event distribution method detects the ACTION_UP event (that is, the event that the touch screen is lifted by a finger). The two broadcast the onStart or onStop events locally and receive them for processing.
1 public class BaseActivity extends Activity {2 protected void onStart () {3 super. onStart (); 4 // use local broadcast for efficient and safer 5 LoacalBroadcastManager bcManager = LocalBroadcastManager. getInstance (this); 6 Intent intent = new Intent (ACTIVITY_START); // custom ACTIVITY_START 7 bcManager. sendBroadcast (intent); 8} 9 protected void onStop () {10 super. onStop (); 11 LoacalBroadcastManager bcManager = LocalBroadcastManager. getInstance (this); 12 Intent intent = new Intent (ACTIVITY_STOP); // custom ACTIVITY_STOP13 bcManager. sendBroadcast (intent); 14} 15 //....... 16 protected boolean dispatchTouchEvent (MotionEvent e) {17 if (e. getAction () = MotionEvent. ACTION_UP) {18 LocalBroadcastManager broadcastManager = LocalBroadcastManager. getInstance (this); 19 Intent intent = new Intent (VIEW_CLICK); 20 intent. putExtra (VIEW_CLICK, e); 21 broadcastManager. sendBroadcast (intent); 22} 23}
Broadcast event processing
In the broadcast Processing event class, we get the VIEW_CLICK Action and start to traverse all views in the current Activity. By comparing the coordinates of the View by clicking the event, to determine which View event is clicked.
1 public class BaseActivity extends Activity {2 //....... 3 public class MonitorUserReceiver extends BroadcastReceiver {4 public void onReceive (Context context, Intent intent) {5 String action = intent. getAction (); 6 switch (action) {7 case VIEW_CLICK: 8 MotionEvent event = intent. getParcelableExtra (VIEW_CLICK); 9 // recursively traverse all views in the Activity to find the clicked View10 View clickView = searchClickView (View, event); 1 1 // obtain the clickView path information 12 // generate a log record and write 13 logs. writeLog (); 14 break; 15 case ACTIVITY_START: 16 // you can know that an interface is opened, and then record the operation Action 17 Log. writeLog (); 18 break; 19 case ACTIVITY_STOP: 20 Log. writeLog (); 21 break; 22 // extensible... 23} 24} 25 private View searchClickView (View view, MotionEvent event) {26 View clickView = null; 27 if (isInView (view, event) & 28 view. getVisibility () = View. VISIBLE) {// The current View must be VISIBLE 29 if (view inst Anceof ViewGroup) {// if it is a ViewGroup similar to Layout, continue to traverse its sub-View30 ViewGroup group = (ViewGroup) view; 31 for (int I = group. getChildCount ()-1; I> = 0; I --) {32 View childView = group. getChildAt (I); 33 clickView = searchClickView (childView, event); 34 if (clickView! = Null) {35 return clickView; 36} 37} 38} 39 clickView = view; 40} 41 return clickView; 42} 43 public boolean isInView (View view, MotionEvent event) {44 int clickX = event. getRawX (); // obtain the X and Y coordinates of the Click event 45 int clickY = event. getRawY (); 46 // the following view indicates the child View in the Activity or the control 47 int [] location = new int [2]; 48 view. getLocationOnScreen (location); 49 int x = location [0]; 50 int y = location [1]; 51 int width = view. getWidth (); 52 int height = view. getHeight (); 53 if (clickX <x | clickX> (x + width) | 54 clickY <y | clickY> (y + height) {55 return true; // if this condition is true, the view is clicked 56} 57 return false; 58} 59}
Record View path
As mentioned in the code above, to record the View path, we can add a Tag to the space to give the view space displacement name or ID, but there are too many controls in an Android app, adding tags is too troublesome and risky.
The UI in the Activity is nested layer by layer, and the root layout is PhoneWindow $ DecorView. The following uses the hierarchyviewer tool to give an example.
There is a TextView. If I use the View control path to identify the method, it should be:
DecorView [0]> ActionBarOverlayLayout [0]> FrameLayout [0]> RelativeLayout [0]> TextView [0]: helloworld
Adding the Activity name before this path constitutes the unique property identifier of the control View. For example, we have a button in DemoActivity, whose name is hello:
DemoActivity: DecorView [0]> ActionBarOverlayLayout [0]> FrameLayout [0]> RelativeLayout [0]> Button [0]: hello
DecorView, which can be obtained through this. getWindow (). getDecorView. In fact, in the searchClickView method, we can add a path to find the View we need, so the current path will naturally know. This method produces the following problems:
DecorView> ActionBarOverlayLayout> FrameLayout> RelativeLayout> Button: helloworld
When there is a Button with a duplicate name, it is unclear which Button it is. If we can generate a path similar to DemoActivity: DecorView [0]> ActionBarOverlayLayout [0]> FrameLayout [0]> RelativeLayout [0]> Button [0]: hello, this problem can be solved perfectly. So you need to look at the source code of the hierarchyviewer tool and see how it works. If you have analyzed the source code of hierarchyviewer, you are welcome to discuss how to obtain this path.
Upload user behavior information to the backend server
You can use XML or JSON to format the log information you click and save it to the app directory. After a period of time (this custom), the new thread is enabled, send user behavior information to the backend server. This step is relatively simple and you will not be able to use the source code.
Weaknesses
- The current APP uses the DemoActivity: DecorView> ActionBarOverlayLayout> FrameLayout> RelativeLayout> Button: helloworld absolute path. Although the app is relatively simple in the early stage, if engineers do not pay attention to using the same name control, if the first one is found, the returned result will be returned. Later, we will continue to study the source code of hierarchyviewer and find the method to use the absolute path.
- The two buttons overlap. If you click this Button, you may not be able to find the correct one. You have not figured out how to solve this problem for the time being. You can only rely on engineers to be careful. Do not add overlapping buttons.
For more information, see my personal website:Http://stackvoid.com/