source: trunk/autoquest-androidmonitor/src/de/ugoe/cs/autoquest/androidmonitor/Androidmonitor.java @ 1728

Last change on this file since 1728 was 1728, checked in by funger, 10 years ago

changed functionality, implement addComponent, addEvent, writeToFile

  • Property svn:mime-type set to text/plain
File size: 7.0 KB
Line 
1package de.ugoe.cs.autoquest.androidmonitor;
2
3import java.io.File;
4import java.io.FileOutputStream;
5import java.io.StringWriter;
6import java.lang.reflect.Field;
7
8import org.xmlpull.v1.XmlSerializer;
9
10import de.ugoe.cs.autoquest.androidmonitor.AndroidmonitorCompositeOnClickListener;
11import android.app.Activity;
12import android.content.Context;
13import android.content.pm.ApplicationInfo;
14import android.content.pm.PackageManager;
15import android.content.pm.PackageManager.NameNotFoundException;
16import android.os.Build;
17import android.util.Log;
18import android.util.Xml;
19import android.view.View;
20import android.view.ViewGroup;
21
22public class Androidmonitor {
23
24        String activityName; // name of the activity Class that starts a Tracker
25
26        // Log file
27        private AndroidmonitorLogFile logFile;
28
29        /**
30         * constructor method to get a monitor object
31         *
32         * @return monitor
33         */
34        public static Androidmonitor getInstanceOfAndroidmonitor() {
35                Androidmonitor monitor = new Androidmonitor();
36                return monitor;
37        }
38
39        /**
40         * starts tracking an activity
41         *
42         * @param activity
43         */
44        public void startMonitor(Activity activity) {
45                activityName = activity.getClass().getSimpleName();
46
47                logFile = new AndroidmonitorLogFile(getAppLable(activity),
48                                activity.getFilesDir());
49
50                addLogListenerToView(getRootView(activity));
51
52                // tbd
53                // listen to changes and update own listener
54                // find out if it is possible to directly call addLogListenerToView
55                // again
56                // activity.onContentChanged();
57
58                // write backPresss as event to xml file
59                // activity.onBackPressed();
60
61                // handle onStop() method of the activity
62                // add a function that end up tracking if onStop() is given otherwise
63                // create onStop()
64                // http://developer.android.com/training/basics/activity-lifecycle/stopping.html
65        }
66
67        /**
68         * get the root view of an activity
69         *
70         * @param activity
71         * @return
72         */
73        public View getRootView(Activity activity) {
74                // get root view of the activity as start point
75                View view = activity.getWindow().getDecorView().getRootView();
76                // try out if the given node is the upper one in the tree and return the
77                // first node of the tree
78                // The root of the decorView could be embedded into another layout
79                // element.
80                return findFirstView(view);
81        }
82
83        /**
84         * returns first view element of the tree
85         *
86         * @param view
87         * @return
88         */
89        private View findFirstView(View view) {
90                if (view.getParent() != null && (view.getParent() instanceof ViewGroup)) {
91                        return findFirstView((View) view.getParent());
92                } else {
93                        return view;
94                }
95        }
96
97        /**
98         * replace the listener of each view with a composite listener which
99         * collects several listeners for one view.
100         *
101         * @param view
102         */
103        public void addLogListenerToView(View view) {
104                // traverse all views of the activity
105                logFile.addComponent(view, activityName);
106                if (view instanceof ViewGroup) {
107                        ViewGroup group = (ViewGroup) view;
108                        for (int i = 0; i < group.getChildCount(); i++) {
109                                View child = group.getChildAt(i);
110                                addLogListenerToView(child);
111                        }
112                }
113
114                // save original listener to add it later on to the groupLisatener
115                View.OnClickListener listener = getOnClickListener(view);
116
117                if (listener != null) {
118                        // create new compositeOnClickListener to handle multiple listeners
119                        // for one view
120                        AndroidmonitorCompositeOnClickListener groupListener = new AndroidmonitorCompositeOnClickListener();
121                        // replace the original onClickListener with the
122                        // compositeOnClickListener
123                        view.setOnClickListener(groupListener);
124                        // add the tracking part as a several listener
125                        groupListener.addOnClickListener(new View.OnClickListener() {
126                                public void onClick(View v) {
127
128                                        logFile.addEvent(v);
129
130                                        // track information ...
131                                        // Log.d("MyLog",
132                                        // "activity:" + activityName + " id:" + v.getId()
133                                        // + " element:"
134                                        // + v.getClass().getSimpleName() + " x:" + v.getX() + " y:"
135                                        // + v.getY() + " time:"
136                                        // + System.currentTimeMillis());
137
138                                }
139                        });
140                        // add original onClick listener to groupListener of the view
141                        groupListener.addOnClickListener(listener);
142                }
143        }
144
145        /**
146         * finds out if a listener exists
147         *
148         * @param view
149         * @return the listener of the view or null if no listener exists
150         */
151        public View.OnClickListener getOnClickListener(View view) {
152                // http://stackoverflow.com/questions/11186960/getonclicklistener-in-android-views
153                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
154                        return getOnClickListenerV14(view);
155                } else {
156                        return getOnClickListenerV(view);
157                }
158        }
159
160        // Used for APIs lower than ICS (API 14)
161        private View.OnClickListener getOnClickListenerV(View view) {
162                View.OnClickListener retrievedListener = null;
163                String viewStr = "android.view.View";
164                Field field;
165
166                try {
167                        field = Class.forName(viewStr).getDeclaredField("mOnClickListener");
168                        retrievedListener = (View.OnClickListener) field.get(view);
169                } catch (NoSuchFieldException ex) {
170                        Log.e("Reflection", "No Such Field.");
171                } catch (IllegalAccessException ex) {
172                        Log.e("Reflection", "Illegal Access.");
173                } catch (ClassNotFoundException ex) {
174                        Log.e("Reflection", "Class Not Found.");
175                }
176
177                return retrievedListener;
178        }
179
180        // Used for new ListenerInfo class structure used beginning with API 14
181        // (ICS)
182        private View.OnClickListener getOnClickListenerV14(View view) {
183                View.OnClickListener retrievedListener = null;
184                String viewStr = "android.view.View";
185                String lInfoStr = "android.view.View$ListenerInfo";
186
187                try {
188                        Field listenerField = Class.forName(viewStr).getDeclaredField(
189                                        "mListenerInfo");
190                        Object listenerInfo = null;
191
192                        if (listenerField != null) {
193                                listenerField.setAccessible(true);
194                                listenerInfo = listenerField.get(view);
195                        }
196
197                        Field clickListenerField = Class.forName(lInfoStr)
198                                        .getDeclaredField("mOnClickListener");
199
200                        if (clickListenerField != null && listenerInfo != null) {
201                                retrievedListener = (View.OnClickListener) clickListenerField
202                                                .get(listenerInfo);
203                        }
204                } catch (NoSuchFieldException ex) {
205                        Log.e("Reflection", "No Such Field.");
206                } catch (IllegalAccessException ex) {
207                        Log.e("Reflection", "Illegal Access.");
208                } catch (ClassNotFoundException ex) {
209                        Log.e("Reflection", "Class Not Found.");
210                }
211
212                return retrievedListener;
213        }
214
215        /**
216         * get application name as defined in Package Name
217         *
218         * @param pContext
219         *            package context; could also be an activity
220         * @return app name
221         */
222        public String getAppLable(Context pContext) {
223                // source (2014-09-04):
224                // http://stackoverflow.com/questions/11229219/android-get-application-name-not-package-name
225                PackageManager lPackageManager = pContext.getPackageManager();
226                ApplicationInfo lApplicationInfo = null;
227                try {
228                        lApplicationInfo = lPackageManager.getApplicationInfo(
229                                        pContext.getApplicationInfo().packageName, 0);
230                } catch (final NameNotFoundException e) {
231                }
232                return (String) (lApplicationInfo != null ? lPackageManager
233                                .getApplicationLabel(lApplicationInfo) : "Unknown");
234        }
235
236}
Note: See TracBrowser for help on using the repository browser.