11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # HyperLog Android
2 |
3 | [](https://opensource.org/licenses/MIT) [](https://opensource.org/licenses/MIT)
4 | [  ](https://bintray.com/piyushgupta27/maven/hyperlog/_latestVersion)
5 |
6 | * [Overview](#overview)
7 | * [Log format](#log-format)
8 | * [Download](#download)
9 | * [Initialize](#initialize)
10 | * [Usage](#usage)
11 | * [Get Logs in a File](#get-logs-in-a-file)
12 | * [Push Logs Files to Remote Server](#push-logs-files-to-remote-server)
13 | * [Sample Testing Endpoint using RequestBin](#follow-steps-to-setup-testing-endpoint-at-requestbin)
14 | * [Example Testing Endpoint inside Django](#setup-example-endpoint-inside-django)
15 | * [Custom Log Message Format](#custom-log-message-format)
16 | * [Additional Methods](#additional-methods)
17 | * [Documentation(Kotlin/Android)](#documentation-for-android-using-kotlin)
18 | * [Contribute](#contribute)
19 | * [About HyperTrack](#about-hypertrack)
20 | * [License](#license)
21 |
22 | ## Overview
23 | A utility logger library for Android on top of standard Android `Log` class for debugging purpose. This is a simple library that will allow Android apps or library to store `log` into `database` so that developer can pull the logs from the database into `File` or push the logs to your `remote server` for `debugging` purpose. Want to know more on this and wondering why you should prefer using this library over doing it yourself. Check out the [blog post](https://www.hypertrack.com/blog/2017/12/19/hyperlog-library/) or [sample apk](hyperlog-demo-debug.apk).
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | ## Log Format
32 | ```
33 | timeStamp + " | " + appVersion + " : " + osVersion + " | " + deviceUUID + " | [" + logLevelName + "]: " + message
34 | ```
35 | ```
36 | 2017-10-05T14:46:36.541Z 1.0 | 0.0.1 : Android-7.1.1 | 62bb1162466c3eed | [INFO]: Log has been pushed
37 | ```
38 | ## Download
39 | Download the latest version or grab via Gradle.
40 |
41 | The library is available on [`mavenCentral()`](https://dl.bintray.com/piyushgupta27/maven/com/hypertrack/hyperlog/) and [`jcenter()`](http://jcenter.bintray.com/com/hypertrack/hyperlog/). In your module's `build.gradle`, add the following code snippet and run the `gradle-sync`.
42 | from rest_framework import views
43 |
44 | class SDKLogFileAPIView(views.APIView):
45 | '''
46 | SDK Log endpoint for file uploads
47 |
48 | Example curl call:
49 | curl -i -X POST
50 | -H "Content-Type: multipart/form-data"
51 | -H "Authorization: token pk_e6c9cf663714fb4b96c12d265df554349e0db79b"
52 | -H "Content-Disposition: attachment; filename=upload.txt"
53 | -F "data=@/Users/Arjun/Desktop/filename.txt"
54 | localhost:8000/api/v1/logs/
55 | '''
56 | parser_classes = (
57 | parsers.FileUploadParser,
58 | )
59 |
60 | def post(self, request):
61 |
62 |
63 | ```
64 | dependencies {
65 | ...
66 | compile 'com.hypertrack:hyperlog:0.0.10'
67 | ...
68 | }
69 | ```
70 |
71 | Don't forget to add also the following dependencies
72 |
73 | ```
74 |
75 | compile 'com.android.volley:volley:1.0.0'
76 | compile 'com.google.code.gson:gson:2.8.1'
77 |
78 | ```
79 | and the following permession to AndroidManifest.xml
80 |
81 | ```
82 |
83 |
84 |
85 | ```
86 |
87 |
88 |
89 | ## Initialize
90 | Inside `onCreate` of Application class or Launcher Activity.
91 | ```
92 | HyperLog.initialize(this);
93 | HyperLog.setLogLevel(Log.VERBOSE);
94 | ```
95 |
96 | ## Usage
97 | ```
98 | HyperLog.d(TAG,"Debug Log");
99 | ```
100 |
101 | ## Get Logs in a File
102 | ```
103 | File file = HyperLog.getDeviceLogsInFile(this);
104 | ```
105 |
106 | ## Push Logs Files to Remote Server
107 | Logs file can be pushed to your remote server or `RequestBin`(for testing) or to [`Logstash`](https://www.elastic.co/products/logstash).
108 |
109 | **Steps:**
110 |
111 | 1. Set the API Endpoint URL `HyperLog.setURL` before calling `HyperLog.pushLogs` method otherwise `exception` will be thrown. Developers can also set a testing endpoint using [`RequestBin`](https://requestb.in/).
112 | ```
113 | HyperLog.setURL("API URL");
114 | ```
115 |
116 | 2. Push Logs file to the given endpoint.
117 | ```
118 | HyperLog.pushLogs(this, false, new HLCallback() {
119 | @Override
120 | public void onSuccess(@NonNull Object response) {
121 |
122 | }
123 |
124 | @Override
125 | public void onError(@NonNull VolleyError HLErrorResponse) {
126 |
127 | }
128 | });
129 | ```
130 |
131 | ### **Follow steps to setup testing endpoint at [`RequestBin`](https://requestb.in/)**
132 |
133 | 1. Visit the [`RequestBin`](https://requestb.in/) site and create a `RequestBin`.
134 | 2. Once you have the bin created, copy the URL and set it to the `HyperLog.setURL`.
135 | 3. Now call `HyperLog.pushLogs` to push the logs file to given endpoint. This is asynchronous call.
136 | 4. After `HyperLog.pushLogs` success, reload the requestbin page to view exactly which requests were made, what headers were sent, and raw body and so on, all in a pretty graphical setting like below image.
137 | 5. Once you get the logs on `RequestBin` create your own endpoint on your server and start receiving logs on to your server for debugging.
138 | 6. (Optional) From your server you can directly push those to [`Logstash`](https://www.elastic.co/products/logstash) (part of [ELK](https://www.elastic.co/webinars/introduction-elk-stack) stack). We have discussed ELK in one of our [blog](https://www.hypertrack.com/blog/2017/02/10/centralized-logging-at-hypertrack/).
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 | Request Bin Sample Response
147 |
148 |
149 | ### **Setup example endpoint inside Django**
150 |
151 | The example code below will set you up with a view that can handle uploaded log files, decompress gzip, and print the contents of the file.
152 |
153 | ```python
154 | import zlib
155 |
156 | from backend_apps.hyperlogs.models import HyperLog
157 |
158 | try:
159 | from StringIO import StringIO
160 | except ImportError:
161 | from io import StringIO
162 | import logging
163 |
164 | logging.basicConfig()
165 | logger = logging.getLogger(__name__)
166 |
167 | from rest_framework import views, parsers
168 | from rest_framework.response import Response
169 |
170 | class SDKLogFileAPIView(views.APIView):
171 | '''
172 | SDK Log endpoint for file uploads
173 |
174 | Example curl call:
175 | curl -i -X POST
176 | -H "Content-Type: multipart/form-data"
177 | -H "Authorization: token pk_e6c9cf663714fb4b96c12d265df554349e0db79b"
178 | -H "Content-Disposition: attachment; filename=upload.txt"
179 | -F "data=@/Users/Arjun/Desktop/filename.txt"
180 | localhost:8000/api/v1/logs/
181 | '''
182 | parser_classes = (
183 | parsers.FileUploadParser,
184 | )
185 |
186 | def post(self, request):
187 | '''
188 | Prints logs to stdout (accepts file)
189 | '''
190 | if request.FILES:
191 | device_id = self.request.META.get('HTTP_DEVICE_ID', 'None')
192 | user_agent = self.request.META.get('HTTP_USER_AGENT', 'None')
193 | expect_header = self.request.META.get('HTTP_EXPECT', 'None')
194 | file_obj = request.FILES['file']
195 | logger.info('Received log file of size %s bytes from device id: %s and user agent: %s and expect header: %s' %
196 | (str(file_obj.size), device_id, user_agent, expect_header))
197 | self.decompress_file(file_obj)
198 |
199 | return Response({})
200 |
201 | def decompress_file(self, f):
202 | '''
203 | Decompress the gzip file and then print it to stdout
204 | so that logstash can pick it up. In case Content-Encoding
205 | is not gzip, then the normal method picks up the file.
206 | '''
207 | if not self.request.META.get('HTTP_CONTENT_ENCODING') == 'gzip':
208 | return self.handle_uploaded_file(f)
209 |
210 | result = StringIO()
211 |
212 | for chunk in f.chunks():
213 | chunk = str(chunk, errors='ignore')
214 | result.write(chunk)
215 |
216 | stringified_value = result.getvalue()
217 | result.close()
218 | decompressor = zlib.decompressobj(16 + zlib.MAX_WBITS)
219 | stringified_value = str.encode(stringified_value)
220 | logger.error('=================hyperlog=============')
221 | logger.error(stringified_value)
222 | decompressed = decompressor.decompress(stringified_value)
223 |
224 | for line in decompressed.split('\n'):
225 | print (line)
226 |
227 | def handle_uploaded_file(self, f):
228 | '''
229 | Handle django file to print, so that logstash
230 | can pick it up.
231 | '''
232 | for chunk in f.chunks():
233 | logger.error("================================hyperlog======================")
234 | logger.error(chunk)
235 | chunk = chunk.decode()
236 | lines = chunk.split('\n')
237 | logs=[]
238 | for line in lines:
239 | print (line)
240 | logs.append(line)
241 | HyperLog.objects.create(log=logs)
242 | ```
243 |
244 |
245 |
246 | **Note:**
247 | * Push logs file to server in compressed form to reduce the data consumption and response time.
248 | ```
249 | HyperLog.pushLogs(Context mContext, boolean compress, HyperLogCallback callback);
250 | ```
251 | * Logs will be compressed using `GZIP` encoding.
252 | * Logs will be deleted from database after successful push.
253 | * Logs will push to the server in batches. Each batch can have maximum of `5000 logs`.
254 |
255 | ## Custom Log Message Format
256 | Default Log Message that will store in database.
257 | ```
258 | timeStamp + " | " + appVersion + " : " + osVersion + " | " + deviceUUID + " | [" + logLevelName + "]: " + message
259 | ```
260 | ```
261 | 2017-10-05T14:46:36.541Z 1.0 | 0.0.1 : Android-7.1.1 | 62bb1162466c3eed | [INFO]: Log has been pushed
262 | ```
263 | This message can easily be customize.
264 | 1. Create a new class extending `LogFormat`.
265 | 2. Override `getFormattedLogMessage` method.
266 | 3. Now return the formatted message.
267 | ```
268 | class CustomLogMessageFormat extends LogFormat {
269 |
270 | CustomLog(Context context) {
271 | super(context);
272 | }
273 |
274 | public String getFormattedLogMessage(String logLevelName, String message, String timeStamp,
275 | String senderName, String osVersion, String deviceUUID) {
276 |
277 | //Custom Log Message Format
278 | String formattedMessage = timeStamp + " : " + logLevelName + " : " + deviceUUID + " : " + message;
279 |
280 | return formattedMessage;
281 | }
282 | }
283 |
284 | ```
285 | Custom Log Message Format example
286 | ```
287 | 2017-10-05T14:46:36.541Z 1.0 | INFO | 62bb1162466c3eed | Log has been pushed
288 |
289 | ```
290 |
291 | 4. Above created class instance then needs to be passed while initializing `HyperLog` or can be set later.
292 | ```
293 | HyperLog.initialize(this,new CustomLogMessageFormat(this));
294 |
295 | OR
296 |
297 | HyperLog.initialize(this);
298 | HyperLog.setLogFormat(new CustomLogMessageFormat(this));
299 | ```
300 | ## Additional Methods
301 | * Different types of log.
302 | ```
303 | HyperLog.d(TAG,"debug");
304 | HyperLog.i(TAG,"information");
305 | HyperLog.e(TAG,"error");
306 | HyperLog.v(TAG,"verbose");
307 | HyperLog.w(TAG,"warning");
308 | HyperLog.a(TAG,"assert");
309 | HyperLog.exception(TAG,"exception",throwable);
310 | ```
311 |
312 | * To check whether any device logs are available.
313 | ```
314 | HyperLog.hasPendingDeviceLogs();
315 | ```
316 |
317 | * Get the count of stored device logs.
318 | ```
319 | HyperLog.logCount();
320 | ```
321 |
322 | * Developer can pass additional headers along with API call while pushing logs to server.
323 | ```
324 | HashMap additionalHeaders = new HashMap<>();
325 | additionalHeaders.put("Authorization","Token");
326 | HyperLog.pushLogs(this, additionalHeaders, false, HLCallback);
327 | ```
328 |
329 | * By default, seven days older logs will get delete automatically from the database. You can change the expiry period of logs by defining `expiryTimeInSeconds`.
330 | ```
331 | HyperLog.initialize(@NonNull Context context, int expiryTimeInSeconds);
332 | ```
333 | * Developers can also get the device log as a list of `DeviceLog` model or list of `String` .By default, fetched logs will delete from the database. Developers can override to change the default functionality.
334 | ```
335 | HyperLog.getDeviceLogs(boolean deleteLogs);
336 | HyperLog.getDeviceLogsInFile(Context mContext, boolean deleteLogs);
337 | ```
338 | * By default, every get calls return data from first batch if there are one or more batch.
339 | * If there are more than one batches then developer can gets the specific batch data by providing batch number.
340 | ```
341 | HyperLog.getDeviceLogs(boolean deleteLogs, int batchNo);
342 | ```
343 | * Get the number of batches using `HyperLog.getDeviceLogBatchCount`.
344 | * Developer can manually delete the logs using `HyperLog.deleteLogs`.
345 |
346 | ## Documentation For Android using Kotlin
347 | Read the different methods and how to implement HyperLogs in Android using Kotlin [here](https://medium.com/better-programming/how-to-implement-hyperlog-with-kotlin-in-android-21f34a950c83?source=friends_link&sk=53464e017b4a5db6a81a586e61b03e43).
348 |
349 | ## Contribute
350 | Please use the [issues tracker](https://github.com/hypertrack/hyperlog-android/issues) to raise bug reports and feature requests. We'd love to see your pull requests, so send them in!
351 |
352 | ## About HyperTrack
353 | Developers use [HyperTrack](https://www.hypertrack.com?utm_source=github&utm_campaign=hyperlog_android) to build location features, not infrastructure. We reduce the complexity of building and operating location features to a few APIs that just work. [Sign up](https://www.hypertrack.com/signup?utm_source=github&utm_campaign=hyperlog_android) and start building! Join our [Slack community](http://slack.hypertrack.com) to connect with other developers building location features. Email us at help@hypertrack.com if you need any help.
354 |
355 | ## License
356 |
357 | ```
358 | MIT License
359 |
360 | Copyright (c) 2018 HyperTrack
361 |
362 | Permission is hereby granted, free of charge, to any person obtaining a copy
363 | of this software and associated documentation files (the "Software"), to deal
364 | in the Software without restriction, including without limitation the rights
365 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
366 | copies of the Software, and to permit persons to whom the Software is
367 | furnished to do so, subject to the following conditions:
368 |
369 | The above copyright notice and this permission notice shall be included in all
370 | copies or substantial portions of the Software.
371 |
372 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
373 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
374 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
375 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
376 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
377 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
378 | SOFTWARE.
379 | ```
380 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-hacker
--------------------------------------------------------------------------------
/asset/device_logger.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/asset/device_logger.gif
--------------------------------------------------------------------------------
/asset/request_bin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/asset/request_bin.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | maven { url 'https://maven.google.com' }
7 | //To add HyperLog library from maven
8 | google()
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.1.0'
12 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.6'
13 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5'
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 |
17 | }
18 | }
19 | allprojects {
20 | repositories {
21 | jcenter()
22 | maven { url 'maven.google.com'; }
23 | google()
24 | }
25 | }
26 |
27 | task clean(type: Delete) {
28 | delete rootProject.buildDir
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue May 08 14:29:10 IST 2018
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/hyperlog-demo-debug.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo-debug.apk
--------------------------------------------------------------------------------
/hyperlog-demo/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/hyperlog-demo/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 26
5 | buildToolsVersion '26.0.3'
6 | defaultConfig {
7 | applicationId "com.hypertrack.hyperlog_demo"
8 | minSdkVersion 14
9 | targetSdkVersion 26
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(include: ['*.jar'], dir: 'libs')
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support.constraint:constraint-layout:1.0.2'
28 | //compile 'com.hypertrack:hyperlog:0.0.7'
29 | compile(project(':hyperlog'));
30 | testCompile 'junit:junit:4.12'
31 | }
--------------------------------------------------------------------------------
/hyperlog-demo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/Aman/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/androidTest/java/com/hypertrack/hyperlog_demo/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.hypertrack.hyperlog_demo;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.hypertrack.devicelogging", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/java/com/hypertrack/hyperlog_demo/CustomLogMessageFormat.java:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | /**
25 | * Created by Aman on 04/10/17.
26 | */
27 | package com.hypertrack.hyperlog_demo;
28 |
29 | import android.content.Context;
30 |
31 | import com.hypertrack.hyperlog.LogFormat;
32 |
33 | class CustomLogMessageFormat extends LogFormat {
34 |
35 | CustomLogMessageFormat(Context context) {
36 | super(context);
37 | }
38 |
39 | @Override
40 | public String getFormattedLogMessage(String logLevelName, String tag, String message, String timeStamp,
41 | String senderName, String osVersion, String deviceUUID) {
42 | String formattedMessage = timeStamp + " : " + logLevelName+"/"+tag + " : " + deviceUUID + " : " + message;
43 | return formattedMessage;
44 | }
45 | }
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/java/com/hypertrack/hyperlog_demo/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.hypertrack.hyperlog_demo;
25 |
26 | import android.os.Bundle;
27 | import android.support.annotation.NonNull;
28 | import android.support.v7.app.AppCompatActivity;
29 | import android.text.TextUtils;
30 | import android.util.Log;
31 | import android.view.View;
32 | import android.widget.ArrayAdapter;
33 | import android.widget.EditText;
34 | import android.widget.ListView;
35 | import android.widget.Toast;
36 |
37 | import com.hypertrack.hyperlog.HLCallback;
38 | import com.hypertrack.hyperlog.HyperLog;
39 | import com.hypertrack.hyperlog.error.HLErrorResponse;
40 |
41 | import java.io.File;
42 | import java.util.ArrayList;
43 | import java.util.HashMap;
44 | import java.util.List;
45 | import java.util.TimeZone;
46 |
47 | /**
48 | * Created by Aman on 04/10/17.
49 | */
50 |
51 | public class MainActivity extends AppCompatActivity {
52 |
53 | private static final String TAG = MainActivity.class.getSimpleName();
54 | EditText editText, endPointUrl;
55 | ListView listView;
56 | List logsList = new ArrayList<>();
57 | ArrayAdapter listAdapter;
58 | int batchNumber = 1;
59 | int count = 0;
60 | String[] logs = new String[]{"Download Library", "Library Downloaded", "Initialize Library", "Library Initialized", "Log Message", "Message Logged",
61 | "Create Log File", "Log File Created", "Push Logs to Server", "Logs Pushed to Server", "Logs Deleted", "Library Downloaded", "Library Initialized", "Message Logged",
62 | "Log File Created", "Logs Pushed to Server", "Logs Deleted"};
63 | Toast toast;
64 |
65 | @Override
66 | protected void onCreate(Bundle savedInstanceState) {
67 | super.onCreate(savedInstanceState);
68 | setContentView(R.layout.activity_main);
69 | //Set Custom Log Message Format.
70 | HyperLog.setLogFormat(new CustomLogMessageFormat(this));
71 | endPointUrl = (EditText) findViewById(R.id.end_point_url);
72 | editText = (EditText) findViewById(R.id.logText);
73 | listView = (ListView) findViewById(R.id.listView);
74 | listAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, logsList);
75 | listView.setAdapter(listAdapter);
76 | }
77 |
78 | public void setEndPoint(View view) {
79 | String url = endPointUrl.getText().toString();
80 | if (TextUtils.isEmpty(url)) {
81 | Toast.makeText(this, "Url can't be empty.", Toast.LENGTH_SHORT).show();
82 | return;
83 | }
84 | HyperLog.setURL(url);
85 | }
86 |
87 | public void showLogs(View view) {
88 | logsList.clear();
89 | logsList.addAll(HyperLog.getDeviceLogsAsStringList(false));
90 | listAdapter.notifyDataSetChanged();
91 | batchNumber = 1;
92 | }
93 |
94 | public void addLog(View view) {
95 | if (!TextUtils.isEmpty(editText.getText().toString())) {
96 | HyperLog.i(TAG, editText.getText().toString());
97 | editText.getText().clear();
98 | editText.setText(logs[count++]);
99 | showLogs(view);
100 | showToast("Log Added");
101 | }
102 | }
103 |
104 | public void getFile(View view) {
105 | File file = HyperLog.getDeviceLogsInFile(this, false);
106 | if (file != null && file.exists())
107 | showToast("File Created at: " + file.getAbsolutePath());
108 | }
109 |
110 | public void deleteLogs(View view) {
111 | showToast("Logs deleted");
112 | HyperLog.deleteLogs();
113 | logsList.clear();
114 | listAdapter.notifyDataSetChanged();
115 | }
116 |
117 | public void nextLog(View view) {
118 | logsList.clear();
119 | logsList.addAll(HyperLog.getDeviceLogsAsStringList(false, ++batchNumber));
120 | listAdapter.notifyDataSetChanged();
121 | }
122 |
123 | public void pushLog(View view) {
124 |
125 | if (TextUtils.isEmpty(HyperLog.getURL())) {
126 | Toast.makeText(this, "Set EndPoint URL First", Toast.LENGTH_SHORT).show();
127 | endPointUrl.requestFocus();
128 | return;
129 | }
130 | //Extra header to post request
131 | HashMap params = new HashMap<>();
132 | params.put("timezone", TimeZone.getDefault().getID());
133 |
134 | HyperLog.pushLogs(this, params, true, new HLCallback() {
135 | @Override
136 | public void onSuccess(@NonNull Object response) {
137 | showToast("Log Pushed");
138 | Log.d(TAG, "onSuccess: " + response);
139 | logsList.clear();
140 | listAdapter.notifyDataSetChanged();
141 | }
142 |
143 | @Override
144 | public void onError(@NonNull HLErrorResponse HLErrorResponse) {
145 | showToast("Log Push Error");
146 | Log.e(TAG, "onError: " + HLErrorResponse.getErrorMessage());
147 | }
148 | });
149 | }
150 |
151 | private void showToast(String message) {
152 | if (toast != null)
153 | toast.cancel();
154 | toast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
155 | toast.show();
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/java/com/hypertrack/hyperlog_demo/MyApplication.java:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 | package com.hypertrack.hyperlog_demo;
25 |
26 | import android.app.Application;
27 | import android.util.Log;
28 |
29 | import com.hypertrack.hyperlog.HyperLog;
30 |
31 | /**
32 | * Created by Aman on 04/10/17.
33 | */
34 |
35 | public class MyApplication extends Application {
36 | @Override
37 | public void onCreate() {
38 | super.onCreate();
39 | HyperLog.initialize(this,new CustomLogMessageFormat(this));
40 | HyperLog.setLogLevel(Log.VERBOSE);
41 | HyperLog.setURL("");
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
34 |
35 |
47 |
48 |
59 |
60 |
74 |
75 |
84 |
85 |
96 |
97 |
111 |
112 |
126 |
127 |
128 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypertrack/hyperlog-android/d8e99da21d160cc543682430dc35e65274a545bc/hyperlog-demo/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | DeviceLogging
3 | Add Log
4 | Enter Log
5 | Show Logs
6 | Get File
7 | Delete
8 | Next Log
9 |
10 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/hyperlog-demo/src/test/java/com/hypertrack/hyperlog_demo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.hypertrack.hyperlog_demo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/hyperlog/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | .gradle
3 | /local.properties
4 | /captures
5 |
--------------------------------------------------------------------------------
/hyperlog/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'maven'
3 |
4 | ext {
5 | bintrayRepo = 'maven'
6 | bintrayName = 'hyperlog'
7 |
8 | publishedGroupId = 'com.hypertrack'
9 | libraryName = 'hyperlog'
10 | artifact = 'hyperlog'
11 |
12 | libraryDescription = 'A utility logger library for Android on top of standard Android Log class for debugging purpose. This is a simple library that will allow Android apps or library to store log into database so that developer can pull the logs from the database into File or push the logs to your remote server for debugging purpose.'
13 |
14 | siteUrl = 'https://github.com/hypertrack/hyperlog-android'
15 | gitUrl = 'https://github.com/hypertrack/hyperlog-android.git'
16 |
17 | libraryVersion = computeVersionName()
18 |
19 | developerId = 'piyushgupta27'
20 | developerName = 'Piyush Gupta'
21 | developerEmail = 'piyush@hypertrack.io'
22 |
23 | licenseName = 'The MIT License (MIT)'
24 | licenseUrl = 'http://opensource.org/licenses/MIT'
25 | allLicenses = ["MIT"]
26 | }
27 |
28 | android {
29 | compileSdkVersion 27
30 | buildToolsVersion '27.0.3'
31 |
32 | defaultConfig {
33 | minSdkVersion 14
34 | targetSdkVersion 27
35 | versionCode 1
36 | versionName "1.0"
37 |
38 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
39 |
40 | }
41 | buildTypes {
42 | release {
43 | minifyEnabled false
44 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
45 | }
46 | }
47 | testOptions {
48 | unitTests.returnDefaultValues = true
49 | }
50 | }
51 |
52 | dependencies {
53 | compile fileTree(dir: 'libs', include: ['*.jar'])
54 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
55 | exclude group: 'com.android.support', module: 'support-annotations'
56 | })
57 | compile 'com.android.support:appcompat-v7:27.1.1'
58 | compile 'com.android.volley:volley:1.0.0'
59 | compile 'com.google.code.gson:gson:2.8.1'
60 | testCompile 'junit:junit:4.12'
61 | }
62 |
63 | def computeVersionName() {
64 | def versionPropsFile = file('gradle.properties')
65 |
66 | if (versionPropsFile.canRead()) {
67 | def Properties versionProps = new Properties()
68 |
69 | versionProps.load(new FileInputStream(versionPropsFile))
70 |
71 | def value = 0
72 |
73 | def runTasks = gradle.startParameter.taskNames
74 | if ('internalRelease' in runTasks || 'iR' in runTasks) {
75 | value = 1;
76 | }
77 |
78 | def versionMajor = 0
79 | def versionMinor = 0
80 | def versionPatch = versionProps['VERSION_PATCH'].toInteger() + value
81 | def versionBuild = versionProps['VERSION_BUILD'].toInteger() + 1
82 |
83 | versionProps['VERSION_PATCH'] = versionPatch.toString()
84 | versionProps['VERSION_BUILD'] = versionBuild.toString()
85 | versionProps['version'] = versionMajor + "." + versionMinor + "." + versionPatch
86 | versionProps.store(versionPropsFile.newWriter(), null)
87 |
88 | return versionMajor + "." + versionMinor + "." + versionPatch
89 | } else {
90 | throw new GradleException("Could not read version.properties!")
91 | }
92 | }
93 |
94 | if (project.rootProject.file('local.properties').exists()) {
95 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/installv1.gradle'
96 | apply from: 'https://raw.githubusercontent.com/nuuneoi/JCenter/master/bintrayv1.gradle'
97 | }
98 |
--------------------------------------------------------------------------------
/hyperlog/gradle.properties:
--------------------------------------------------------------------------------
1 | #Tue May 08 14:37:36 IST 2018
2 | version=0.0.10
3 | VERSION_BUILD=405
4 | VERSION_PATCH=10
5 |
--------------------------------------------------------------------------------
/hyperlog/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/Aman/Library/Android/sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/hyperlog/src/androidTest/java/com/hypertrack/hyperlog/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.hypertrack.hyperlog;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.hypertrack.devicelogger.test", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/hyperlog/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
7 |
8 |
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/DeviceLogDataSource.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 | package com.hypertrack.hyperlog;
26 |
27 | import java.util.List;
28 |
29 | /**
30 | * Created by Aman on 22/09/17.
31 | */
32 |
33 | interface DeviceLogDataSource {
34 | long getDeviceLogCount();
35 |
36 | void addDeviceLog(String deviceLog);
37 |
38 | void deleteDeviceLog(List deviceLogList);
39 |
40 | void deleteAllDeviceLogs();
41 |
42 | List getDeviceLogs(int batch);
43 |
44 | int getDeviceLogBatchCount();
45 |
46 | void clearOldLogs(int expiryTimeInSeconds);
47 | }
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/DeviceLogDatabaseHelper.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 | package com.hypertrack.hyperlog;
26 |
27 | import android.content.Context;
28 | import android.database.sqlite.SQLiteDatabase;
29 | import android.database.sqlite.SQLiteOpenHelper;
30 | import android.util.Log;
31 |
32 | import java.util.List;
33 |
34 | /**
35 | * Created by Aman on 20/09/17.
36 | */
37 | class DeviceLogDatabaseHelper extends SQLiteOpenHelper implements DeviceLogDataSource {
38 |
39 | private static final String TAG = DeviceLogDatabaseHelper.class.getSimpleName();
40 | private static final String DATABASE_NAME = "com.hypertrack.common.device_logs.db";
41 | private static final int DATABASE_VERSION = 2;
42 |
43 | private static DeviceLogDatabaseHelper deviceLogDatabaseHelper;
44 | private SQLiteDatabase database;
45 |
46 | private DeviceLogDatabaseHelper(Context context) {
47 | super(context, DATABASE_NAME, null, DATABASE_VERSION);
48 | this.initializeDatabase();
49 | }
50 |
51 | private void initializeDatabase() {
52 | if (database == null)
53 | database = this.getWritableDatabase();
54 | }
55 |
56 | static DeviceLogDatabaseHelper getInstance(Context context) {
57 | if (deviceLogDatabaseHelper == null) {
58 | synchronized (DeviceLogDatabaseHelper.class) {
59 | if (deviceLogDatabaseHelper == null)
60 | deviceLogDatabaseHelper = new DeviceLogDatabaseHelper(context);
61 | }
62 | }
63 | return deviceLogDatabaseHelper;
64 | }
65 |
66 | @Override
67 | public void onCreate(SQLiteDatabase db) {
68 | DeviceLogTable.onCreate(db);
69 | Log.d(TAG, "DeviceLogDatabaseHelper onCreate called.");
70 | }
71 |
72 | @Override
73 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
74 | DeviceLogTable.onUpgrade(db, oldVersion, newVersion);
75 | Log.d(TAG, "DeviceLogDatabaseHelper onUpgrade called.");
76 | }
77 |
78 | @Override
79 | public long getDeviceLogCount() {
80 | // Initialize SQLiteDatabase if null
81 | initializeDatabase();
82 |
83 | return DeviceLogTable.getCount(database);
84 | }
85 |
86 | @Override
87 | public void addDeviceLog(String deviceLog) {
88 | // Initialize SQLiteDatabase if null
89 | initializeDatabase();
90 |
91 | DeviceLogTable.addDeviceLog(database, deviceLog);
92 | }
93 |
94 | @Override
95 | public void deleteDeviceLog(List deviceLogList) {
96 | // Initialize SQLiteDatabase if null
97 | initializeDatabase();
98 |
99 | DeviceLogTable.deleteDeviceLog(database, deviceLogList);
100 | }
101 |
102 | @Override
103 | public void deleteAllDeviceLogs() {
104 | // Initialize SQLiteDatabase if null
105 | initializeDatabase();
106 |
107 | DeviceLogTable.deleteAllDeviceLogs(database);
108 | }
109 |
110 | @Override
111 | public List getDeviceLogs(int batch) {
112 | // Initialize SQLiteDatabase if null
113 | initializeDatabase();
114 | List deviceLogList = null;
115 |
116 | try {
117 | deviceLogList = DeviceLogTable.getDeviceLogs(database,batch);
118 | } catch (OutOfMemoryError | Exception e) {
119 | e.printStackTrace();
120 | }
121 |
122 | return deviceLogList;
123 | }
124 |
125 | @Override
126 | public int getDeviceLogBatchCount() {
127 | initializeDatabase();
128 |
129 | return DeviceLogTable.getDeviceLogBatchCount(database);
130 | }
131 |
132 | @Override
133 | public void clearOldLogs(int expiryTimeInSeconds) {
134 | initializeDatabase();
135 |
136 | DeviceLogTable.clearOldLogs(database,expiryTimeInSeconds);
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/DeviceLogList.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 | package com.hypertrack.hyperlog;
26 |
27 | import android.text.TextUtils;
28 |
29 | import java.util.List;
30 |
31 | /**
32 | * Created by Aman on 22/09/17.
33 | */
34 | class DeviceLogList {
35 | private DeviceLogDataSource mDeviceLogDataSource;
36 |
37 | DeviceLogList(DeviceLogDataSource mDeviceLogDataSource) {
38 | this.mDeviceLogDataSource = mDeviceLogDataSource;
39 | }
40 |
41 | void addDeviceLog(String deviceLog) {
42 | if (TextUtils.isEmpty(deviceLog)) {
43 | return;
44 | }
45 |
46 | this.mDeviceLogDataSource.addDeviceLog(deviceLog);
47 | }
48 |
49 | void clearSavedDeviceLogs() {
50 | this.mDeviceLogDataSource.deleteAllDeviceLogs();
51 | }
52 |
53 | List getDeviceLogs(int batch) {
54 | return this.mDeviceLogDataSource.getDeviceLogs(batch);
55 | }
56 |
57 | void clearDeviceLogs(List pushedDeviceLogs) {
58 | if (pushedDeviceLogs == null || pushedDeviceLogs.isEmpty())
59 | return;
60 |
61 | this.mDeviceLogDataSource.deleteDeviceLog(pushedDeviceLogs);
62 | }
63 |
64 | long count() {
65 | return this.mDeviceLogDataSource.getDeviceLogCount();
66 | }
67 |
68 | int getDeviceLogBatchCount(){
69 | return this.mDeviceLogDataSource.getDeviceLogBatchCount();
70 | }
71 |
72 | void clearOldLogs(int expiryTimeInSeconds) {
73 | mDeviceLogDataSource.clearOldLogs(expiryTimeInSeconds);
74 | }
75 | }
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/DeviceLogModel.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 | package com.hypertrack.hyperlog;
26 |
27 | import com.google.gson.annotations.Expose;
28 |
29 | /**
30 | * Created by Aman Jain on 22/09/17.
31 | */
32 | /** package */
33 | public class DeviceLogModel {
34 |
35 | @Expose(serialize = false, deserialize = false)
36 | private int id;
37 |
38 | private String deviceLog;
39 |
40 | public int getId() {
41 | return id;
42 | }
43 |
44 | public void setId(int id) {
45 | this.id = id;
46 | }
47 |
48 | public String getDeviceLog() {
49 | return deviceLog;
50 | }
51 |
52 | public void setDeviceLog(String deviceLog) {
53 | this.deviceLog = deviceLog;
54 | }
55 |
56 | public DeviceLogModel(String deviceLog) {
57 | this.deviceLog = deviceLog;
58 | }
59 |
60 | public DeviceLogModel(int id, String deviceLog) {
61 | this.id = id;
62 | this.deviceLog = deviceLog;
63 | }
64 | }
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/DeviceLogTable.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 | package com.hypertrack.hyperlog;
26 |
27 | import android.content.ContentValues;
28 | import android.database.Cursor;
29 | import android.database.DatabaseUtils;
30 | import android.database.sqlite.SQLiteDatabase;
31 | import android.text.TextUtils;
32 |
33 | import com.hypertrack.hyperlog.utils.HLDateTimeUtility;
34 |
35 | import java.util.ArrayList;
36 | import java.util.Calendar;
37 | import java.util.List;
38 |
39 | /**
40 | * Created by Aman on 20/09/17.
41 | */
42 |
43 | class DeviceLogTable {
44 |
45 | private static final String TAG = DeviceLogTable.class.getSimpleName();
46 | private static final int DEVICE_LOG_REQUEST_QUERY_LIMIT = 5000;
47 |
48 | private static final String TABLE_NAME = "device_logs";
49 | private static final String COLUMN_ID = "_id";
50 | private static final String COLUMN_DEVICE_LOG = "device_log";
51 |
52 | private static final String DATABASE_CREATE = "CREATE TABLE IF NOT EXISTS "
53 | + TABLE_NAME
54 | + " ("
55 | + COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, "
56 | + COLUMN_DEVICE_LOG + " TEXT"
57 | + ");";
58 |
59 | static void onCreate(SQLiteDatabase db) {
60 | if (db == null) {
61 | return;
62 | }
63 |
64 | try {
65 | db.execSQL(DATABASE_CREATE);
66 | } catch (Exception e) {
67 | e.printStackTrace();
68 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while onCreate: " + e);
69 | }
70 | }
71 |
72 | static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
73 | if (db == null) {
74 | return;
75 | }
76 |
77 | try {
78 | db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
79 | onCreate(db);
80 |
81 | HyperLog.i("HYPERLOG", "DeviceLogTable onUpgrade called. Executing drop_table query to clear old logs.");
82 | } catch (Exception e) {
83 | e.printStackTrace();
84 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while onUpgrade: " + e);
85 | }
86 | }
87 |
88 | static long getCount(SQLiteDatabase db) {
89 | try {
90 | if (db == null) {
91 | return 0;
92 | }
93 |
94 | return DatabaseUtils.queryNumEntries(db, TABLE_NAME);
95 | } catch (Exception e) {
96 | e.printStackTrace();
97 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while getCount: " + e);
98 | return 0L;
99 | }
100 | }
101 |
102 | static int getDeviceLogBatchCount(SQLiteDatabase db) {
103 | try {
104 | if (db == null) {
105 | return 0;
106 | }
107 |
108 | return (int) Math.ceil(getCount(db) * 1.0f / DEVICE_LOG_REQUEST_QUERY_LIMIT);
109 |
110 | } catch (Exception e) {
111 | e.printStackTrace();
112 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while getDeviceLogBatchCount: " + e);
113 | return 0;
114 | }
115 | }
116 |
117 | static void addDeviceLog(SQLiteDatabase db, String deviceLog) {
118 | if (db == null || TextUtils.isEmpty(deviceLog)) {
119 | return;
120 | }
121 |
122 | ContentValues contentValues = new ContentValues();
123 | contentValues.put(COLUMN_DEVICE_LOG, deviceLog);
124 |
125 | try {
126 | db.insert(TABLE_NAME, null, contentValues);
127 | } catch (Exception e) {
128 | e.printStackTrace();
129 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while addDeviceLog: " + e);
130 | }
131 | }
132 |
133 | static void deleteDeviceLog(SQLiteDatabase db, List deviceLogList) {
134 | if (db == null)
135 | return;
136 |
137 | StringBuilder builder = new StringBuilder();
138 | for (DeviceLogModel deviceLog : deviceLogList) {
139 | if (deviceLog != null && deviceLog.getId() > 0) {
140 | builder.append(deviceLog.getId())
141 | .append(",");
142 | }
143 | }
144 |
145 | if (builder.length() == 0) {
146 | return;
147 | }
148 |
149 | try {
150 | String ids = builder.toString();
151 | ids = ids.substring(0, ids.length() - 1);
152 |
153 | String whereClause = COLUMN_ID +
154 | " IN (" +
155 | ids +
156 | ")";
157 |
158 | db.delete(TABLE_NAME, whereClause, null);
159 | } catch (Exception e) {
160 | e.printStackTrace();
161 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while deleteDeviceLog: " + e);
162 | }
163 | }
164 |
165 | static void deleteAllDeviceLogs(SQLiteDatabase db) {
166 | if (db == null) {
167 | return;
168 | }
169 |
170 | try {
171 | db.delete(TABLE_NAME, null, null);
172 | } catch (Exception e) {
173 | e.printStackTrace();
174 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while deleteAllDeviceLogs: " + e);
175 | }
176 | }
177 |
178 | static List getDeviceLogs(SQLiteDatabase db, int batch) {
179 | if (db == null) {
180 | return null;
181 | }
182 |
183 | int count = getDeviceLogBatchCount(db);
184 | batch--;
185 | if (count <= 1 || batch < 0) {
186 | batch = 0;
187 | }
188 |
189 | ArrayList deviceLogList = null;
190 |
191 | String limit = String.valueOf(batch * DEVICE_LOG_REQUEST_QUERY_LIMIT) + ", " + String.valueOf(DEVICE_LOG_REQUEST_QUERY_LIMIT);
192 |
193 | Cursor cursor = db.query(TABLE_NAME, new String[]{COLUMN_ID, COLUMN_DEVICE_LOG}, null, null,
194 | null, null, null, limit);
195 |
196 | if (cursor == null || cursor.isClosed()) {
197 | return null;
198 | }
199 | try {
200 | if (cursor.moveToFirst()) {
201 | deviceLogList = new ArrayList<>();
202 | do {
203 | if (cursor.isClosed()) {
204 | break;
205 | }
206 |
207 | String deviceLogString = cursor.getString(1);
208 | if (!TextUtils.isEmpty(deviceLogString)) {
209 | DeviceLogModel deviceLog = new DeviceLogModel(deviceLogString);
210 |
211 | // Get RowId for DeviceLogModel
212 | Integer rowId = Integer.valueOf(cursor.getString(0));
213 | deviceLog.setId(rowId != null ? rowId : 0);
214 |
215 | deviceLogList.add(deviceLog);
216 | }
217 | } while (cursor.moveToNext());
218 | }
219 | } catch (Exception e) {
220 | e.printStackTrace();
221 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while getDeviceLogs: " + e);
222 | } finally {
223 | cursor.close();
224 | }
225 |
226 | return deviceLogList;
227 | }
228 |
229 | public static void clearOldLogs(SQLiteDatabase db, int expiryTimeInSeconds) {
230 | if (db == null) {
231 | return;
232 | }
233 |
234 | try {
235 | Calendar calendar = Calendar.getInstance();
236 | //Set the calendar time to older time.
237 | calendar.add(Calendar.SECOND, -expiryTimeInSeconds);
238 |
239 | String date = HLDateTimeUtility.getFormattedTime(calendar.getTime());
240 |
241 | db.delete(TABLE_NAME, COLUMN_DEVICE_LOG + "", new String[]{date});
242 |
243 | } catch (Exception e) {
244 | e.printStackTrace();
245 | HyperLog.e("HYPERLOG", "DeviceLogTable: Exception occurred while deleteAllDeviceLogs: " + e);
246 | }
247 | }
248 | }
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/HLCallback.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | The MIT License (MIT)
4 |
5 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
6 |
7 | Permission is hereby granted, free of charge, to any person obtaining a copy
8 | of this software and associated documentation files (the "Software"), to deal
9 | in the Software without restriction, including without limitation the rights
10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | copies of the Software, and to permit persons to whom the Software is
12 | furnished to do so, subject to the following conditions:
13 |
14 | The above copyright notice and this permission notice shall be included in all
15 | copies or substantial portions of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | SOFTWARE.
24 | */
25 | package com.hypertrack.hyperlog;
26 |
27 | import android.support.annotation.NonNull;
28 |
29 | import com.hypertrack.hyperlog.error.HLErrorResponse;
30 |
31 | /**
32 | * Created by Aman Jain on 18/09/17.
33 | */
34 | public abstract class HLCallback {
35 |
36 | /**
37 | * Called when a request succeeds.
38 | *
39 | * @param response The successful response containing the responseObject.
40 | */
41 | public abstract void onSuccess(@NonNull Object response);
42 |
43 | /**
44 | * Called when a validation error occurs, request times out, or fails.
45 | *
46 | * @param HLErrorResponse The request status.
47 | */
48 | public abstract void onError(@NonNull HLErrorResponse HLErrorResponse);
49 |
50 | }
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/HLHTTPMultiPartPostRequest.java:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 |
26 | package com.hypertrack.hyperlog;
27 |
28 | import android.content.Context;
29 | import android.os.Build;
30 |
31 | import com.android.volley.NetworkResponse;
32 | import com.android.volley.ParseError;
33 | import com.android.volley.Request;
34 | import com.android.volley.Response;
35 | import com.android.volley.VolleyError;
36 | import com.android.volley.toolbox.HttpHeaderParser;
37 | import com.google.gson.Gson;
38 | import com.google.gson.JsonSyntaxException;
39 | import com.hypertrack.hyperlog.utils.CustomGson;
40 | import com.hypertrack.hyperlog.utils.HLDateTimeUtility;
41 | import com.hypertrack.hyperlog.utils.Utils;
42 |
43 | import java.io.ByteArrayInputStream;
44 | import java.io.ByteArrayOutputStream;
45 | import java.io.IOException;
46 | import java.io.UnsupportedEncodingException;
47 | import java.util.HashMap;
48 | import java.util.Iterator;
49 | import java.util.Map;
50 | import java.util.zip.GZIPInputStream;
51 | import java.util.zip.GZIPOutputStream;
52 |
53 | class HLHTTPMultiPartPostRequest extends Request {
54 |
55 | private static final String TAG = HLHTTPMultiPartPostRequest.class.getSimpleName();
56 | private final Gson mGson;
57 | private final Class mResponseType;
58 | private final Response.Listener mListener;
59 |
60 | private final Context context;
61 | private final byte[] multiPartRequestBody;
62 | private final String filename;
63 | private final String packageName;
64 |
65 | private final HashMap additionalHeaders;
66 | private static final String HEADER_ENCODING = "Content-Encoding";
67 | private static final String ENCODING_GZIP = "gzip";
68 | private final String boundary = "HyperLog -" + System.currentTimeMillis();
69 |
70 | private boolean mGzipEnabled = false;
71 |
72 | HLHTTPMultiPartPostRequest(String url, byte[] multiPartRequestBody, String filename, HashMap additionalHeaders,
73 | Context context, Class responseType, boolean compress,
74 | Response.Listener listener, Response.ErrorListener errorListener) {
75 |
76 | super(Method.POST, url, errorListener);
77 | this.context = context;
78 | if (compress)
79 | this.multiPartRequestBody = getRequestBody(multiPartRequestBody);
80 | else
81 | this.multiPartRequestBody = multiPartRequestBody;
82 | this.filename = filename;
83 | this.mResponseType = responseType;
84 | this.mListener = listener;
85 | this.mGson = CustomGson.gson();
86 | this.additionalHeaders = additionalHeaders;
87 | packageName = context.getPackageName();
88 | }
89 |
90 | private byte[] getCompressed(byte[] requestBody) {
91 | if (requestBody != null) {
92 | try {
93 | ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(requestBody.length);
94 | GZIPOutputStream gzipOutputStream;
95 | gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream, 32);
96 | gzipOutputStream.write(requestBody);
97 | gzipOutputStream.close();
98 | byte[] compressed = byteArrayOutputStream.toByteArray();
99 | byteArrayOutputStream.close();
100 | mGzipEnabled = true;
101 | return compressed;
102 |
103 | } catch (Exception exception) {
104 | HyperLog.e("HYPERLOG", "Exception occurred while getCompressed: " + exception);
105 | mGzipEnabled = false;
106 | } catch (OutOfMemoryError error) {
107 | HyperLog.e("HYPERLOG", "OutOfMemory Error occurred while getCompressed: " + error);
108 | mGzipEnabled = false;
109 | }
110 | }
111 |
112 | return null;
113 | }
114 |
115 | private byte[] getRequestBody(byte[] requestBody) {
116 | byte[] compressedRequestBody = getCompressed(requestBody);
117 | if (mGzipEnabled) {
118 | HyperLog.i("HYPERLOG", "Compressed FileSize: " + compressedRequestBody.length + " Bytes");
119 | return compressedRequestBody;
120 | } else {
121 | try {
122 | HyperLog.i("HYPERLOG", "Compressed FileSize: " + requestBody.length + " Bytes");
123 | return requestBody;
124 | } catch (Exception exception) {
125 | HyperLog.e("HYPERLOG", "Exception occurred while getRequestBody: " + exception);
126 | }
127 | }
128 | return null;
129 | }
130 |
131 | @Override
132 | public byte[] getBody() {
133 | return multiPartRequestBody;
134 | }
135 |
136 | /**
137 | * Utility method to decompress gzip. To be used when we start sending gzip responses.
138 | */
139 | public static String getDecompressed(byte[] compressed) throws IOException {
140 | try {
141 | final int BUFFER_SIZE = 32;
142 | ByteArrayInputStream is = new ByteArrayInputStream(compressed);
143 | GZIPInputStream gis = new GZIPInputStream(is, BUFFER_SIZE);
144 | StringBuilder string = new StringBuilder();
145 | byte[] data = new byte[BUFFER_SIZE];
146 | int bytesRead;
147 | while ((bytesRead = gis.read(data)) != -1) {
148 | string.append(new String(data, 0, bytesRead));
149 | }
150 | gis.close();
151 | is.close();
152 | return string.toString();
153 | } catch (Exception exception) {
154 | HyperLog.e("HYPERLOG", "Exception occurred while getDecompressed: " + exception);
155 | }
156 | return null;
157 | }
158 |
159 | @Override
160 | public Map getHeaders() {
161 |
162 | Map params = new HashMap<>();
163 | params.put("User-Agent", context.getPackageName() + " (Android " + Build.VERSION.RELEASE + ")");
164 | params.put("Device-Time", HLDateTimeUtility.getCurrentTime());
165 | params.put("Device-ID", Utils.getDeviceId(context));
166 | params.put("App-ID", packageName);
167 | //Header for file upload
168 | params.put("Content-Disposition", "attachment; filename=" + filename);
169 |
170 | if (mGzipEnabled) {
171 | params.put(HEADER_ENCODING, ENCODING_GZIP);
172 | }
173 |
174 | if (this.additionalHeaders != null) {
175 | Iterator> iterator = this.additionalHeaders.entrySet().iterator();
176 | while (iterator.hasNext()) {
177 | Map.Entry header = iterator.next();
178 | params.put(header.getKey(), header.getValue());
179 | }
180 | }
181 | return params;
182 | }
183 |
184 | @Override
185 | protected VolleyError parseNetworkError(VolleyError volleyError) {
186 |
187 | if (volleyError == null || volleyError.networkResponse == null)
188 | return super.parseNetworkError(volleyError);
189 |
190 | try {
191 | String json = new String(
192 | volleyError.networkResponse.data, HttpHeaderParser.parseCharset(volleyError.networkResponse.headers));
193 |
194 | HyperLog.i("HYPERLOG", "Status Code: " + volleyError.networkResponse.statusCode +
195 | " Data: " + json);
196 |
197 | } catch (Exception e) {
198 | HyperLog.e("HYPERLOG", "Exception occurred while HTTPPatchRequest parseNetworkError: " + e, e);
199 | }
200 |
201 | return super.parseNetworkError(volleyError);
202 | }
203 |
204 | @Override
205 | protected Response parseNetworkResponse(NetworkResponse response) {
206 | try {
207 | String json = new String(
208 | response.data, HttpHeaderParser.parseCharset(response.headers));
209 |
210 | return Response.success(
211 | mGson.fromJson(json, mResponseType), HttpHeaderParser.parseCacheHeaders(response));
212 |
213 | } catch (UnsupportedEncodingException e) {
214 | return Response.error(new ParseError(e));
215 | } catch (JsonSyntaxException e) {
216 | return Response.error(new ParseError(e));
217 | }
218 | }
219 |
220 | @Override
221 | protected void deliverResponse(T response) {
222 | HyperLog.i("HYPERLOG", "deliverResponse: ");
223 | if (mListener != null)
224 | mListener.onResponse(response);
225 | }
226 |
227 | @Override
228 | public String getBodyContentType() {
229 | return "multipart/form-data;boundary=" + boundary;
230 | }
231 | }
--------------------------------------------------------------------------------
/hyperlog/src/main/java/com/hypertrack/hyperlog/HyperLog.java:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015-2017 HyperTrack (http://hypertrack.com)
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | package com.hypertrack.hyperlog;
26 |
27 | import android.content.Context;
28 | import android.support.annotation.NonNull;
29 | import android.text.TextUtils;
30 | import android.util.Log;
31 |
32 | import com.android.volley.Response;
33 | import com.android.volley.VolleyError;
34 | import com.hypertrack.hyperlog.error.HLErrorResponse;
35 | import com.hypertrack.hyperlog.utils.HLDateTimeUtility;
36 | import com.hypertrack.hyperlog.utils.Utils;
37 | import com.hypertrack.hyperlog.utils.VolleyUtils;
38 |
39 | import java.io.File;
40 | import java.util.ArrayList;
41 | import java.util.HashMap;
42 | import java.util.List;
43 | import java.util.concurrent.ExecutorService;
44 | import java.util.concurrent.Executors;
45 |
46 | /**
47 | * Created by Aman on 04/10/17.
48 | */
49 | public class HyperLog {
50 |
51 | private static final String TAG = "HyperLog";
52 | public static final String TAG_ASSERT = "ASSERT";
53 | public static final String TAG_HYPERLOG = "HYPERLOG";
54 |
55 | private static int logLevel = Log.WARN;
56 |
57 | private static DeviceLogList mDeviceLogList;
58 | private static String URL;
59 | private static final int EXPIRY_TIME = 7 * 24 * 60 * 60;// 7 Days
60 | private static LogFormat mLogFormat;
61 | private static Context context;
62 | private static ExecutorService executorService;
63 |
64 | /**
65 | * Call this method to initialize HyperLog.
66 | * By default, seven days older logs will gets deleted automatically.
67 | *
68 | * @param context The current context.
69 | * @see #initialize(Context, int, LogFormat)
70 | */
71 | public static void initialize(@NonNull Context context) {
72 | initialize(context, EXPIRY_TIME, new LogFormat(context));
73 | }
74 |
75 | /**
76 | * Call this method to initialize HyperLog.
77 | * By default, seven days older logs will gets deleted automatically.
78 | *
79 | * @param context The current context.
80 | * @param logFormat {@link LogFormat} to set custom log message format.
81 | * @see #initialize(Context, int, LogFormat)
82 | */
83 | public static void initialize(@NonNull Context context, @NonNull LogFormat logFormat) {
84 | initialize(context, EXPIRY_TIME, logFormat);
85 | }
86 |
87 | /**
88 | * Call this method to initialize HyperLog.
89 | * By default, seven days older logs will gets deleted automatically.
90 | *
91 | * @param context The current context.
92 | * @param expiryTimeInSeconds Expiry time for logs in seconds.
93 | * @see #initialize(Context, int, LogFormat)
94 | */
95 | public static void initialize(@NonNull Context context, int expiryTimeInSeconds) {
96 | initialize(context, expiryTimeInSeconds, new LogFormat(context));
97 | }
98 |
99 | /**
100 | * Call this method to initialize HyperLog.
101 | * By default, seven days older logs will get expire automatically. You can change the expiry
102 | * period of logs by defining expiryTimeInSeconds.
103 | *
104 | * @param context The current context.
105 | * @param expiryTimeInSeconds Expiry time for logs in seconds.
106 | * @param logFormat {@link LogFormat} to set custom log message format.
107 | * @see #initialize(Context)
108 | */
109 | public static void initialize(@NonNull Context context, int expiryTimeInSeconds,
110 | @NonNull LogFormat logFormat) {
111 |
112 | if (context == null) {
113 | Log.e(TAG, "HyperLog isn't initialized: Context couldn't be null");
114 | return;
115 | }
116 |
117 | HyperLog.context = context.getApplicationContext();
118 |
119 | synchronized (HyperLog.class) {
120 | if (logFormat != null) {
121 | mLogFormat = logFormat;
122 | Utils.saveLogFormat(context, mLogFormat);
123 | } else {
124 | mLogFormat = Utils.getLogFormat(context);
125 | }
126 |
127 | if (mDeviceLogList == null) {
128 | DeviceLogDataSource logDataSource = DeviceLogDatabaseHelper.getInstance(context);
129 | mDeviceLogList = new DeviceLogList(logDataSource);
130 | mDeviceLogList.clearOldLogs(expiryTimeInSeconds);
131 | }
132 | }
133 | }
134 |
135 | /**
136 | * Call this method to define a custom log message format.
137 | *
138 | * @param logFormat LogFormat to set custom log message format.
139 | */
140 | public static void setLogFormat(@NonNull LogFormat logFormat) {
141 | if (mLogFormat != null) {
142 | mLogFormat = logFormat;
143 | Utils.saveLogFormat(context, logFormat);
144 | }
145 | }
146 |
147 | private static boolean isInitialize() {
148 | if (mDeviceLogList == null || mLogFormat == null) {
149 | initialize(context, null);
150 | return false;
151 | }
152 | return true;
153 | }
154 |
155 | /**
156 | * Call this method to set a valid end point URL where logs need to be pushed.
157 | *
158 | * @param url URL of the endpoint
159 | * @throws IllegalArgumentException if the url is empty or null
160 | */
161 | public static void setURL(String url) {
162 | if (TextUtils.isEmpty(url))
163 | throw new IllegalArgumentException("API URL cannot be null or empty");
164 | URL = url;
165 | }
166 |
167 | /**
168 | * Call this method to get a end point URL where logs need to be pushed.
169 | */
170 | public static String getURL() {
171 | return URL;
172 | }
173 |
174 | /**
175 | * Call this method to get a expiry time of logs. Expiry Time is in seconds.
176 | */
177 | public static long getExpiryTime() {
178 | return EXPIRY_TIME;
179 | }
180 |
181 | /**
182 | * Sets the level of logging to display, where each level includes all those below it.
183 | * The default level is LOG_LEVEL_NONE. Please ensure this is set to Log#ERROR
184 | * or LOG_LEVEL_NONE before deploying your app to ensure no sensitive information is
185 | * logged. The levels are:
186 | *
187 | *
{@link Log#ASSERT}
188 | *
{@link Log#VERBOSE}
189 | *
{@link Log#DEBUG}
190 | *
{@link Log#INFO}
191 | *
{@link Log#WARN}
192 | *
{@link Log#ERROR}
193 | *
194 | *
195 | * @param logLevel The level of logcat logging that Parse should do.
196 | */
197 | public static void setLogLevel(int logLevel) {
198 | HyperLog.logLevel = logLevel;
199 | }
200 |
201 | public static void v(String tag, String message, Throwable tr) {
202 | if (Log.VERBOSE >= logLevel) {
203 | Log.v(tag, message + '\n' + Log.getStackTraceString(tr));
204 | }
205 | r(getFormattedLog(Log.VERBOSE, tag, message));
206 | }
207 |
208 | public static void v(String tag, String message) {
209 | v(tag, message, null);
210 | }
211 |
212 | public static void d(String tag, String message, Throwable tr) {
213 | if (Log.DEBUG >= logLevel) {
214 | Log.d(tag, message + '\n' + Log.getStackTraceString(tr));
215 | }
216 | r(getFormattedLog(Log.DEBUG, tag, message));
217 |
218 | }
219 |
220 | public static void d(String tag, String message) {
221 | d(tag, message, null);
222 | }
223 |
224 | public static void i(String tag, String message, Throwable tr) {
225 | if (Log.INFO >= logLevel) {
226 | Log.i(tag, message + '\n' + Log.getStackTraceString(tr));
227 | }
228 |
229 | r(getFormattedLog(Log.INFO, tag, message));
230 | }
231 |
232 | /**
233 | * Info log level that will store into DB.
234 | */
235 | public static void i(String tag, String message) {
236 | i(tag, message, null);
237 | }
238 |
239 | public static void w(String tag, String message, Throwable tr) {
240 | if (Log.WARN >= logLevel) {
241 | Log.w(tag, message + '\n' + Log.getStackTraceString(tr));
242 | }
243 |
244 | r(getFormattedLog(Log.WARN, tag, message));
245 | }
246 |
247 | public static void w(String tag, String message) {
248 | w(tag, message, null);
249 | }
250 |
251 | public static void e(String tag, String message, Throwable tr) {
252 | if (Log.ERROR >= logLevel) {
253 | Log.e(tag, message + '\n' + Log.getStackTraceString(tr));
254 | }
255 |
256 | r(getFormattedLog(Log.ERROR, tag, message));
257 | }
258 |
259 | public static void e(String tag, String message) {
260 | e(tag, message, null);
261 | }
262 |
263 | public static void exception(String tag, String message, Throwable tr) {
264 | if (Log.ERROR >= logLevel) {
265 | Log.e(tag, "**********************************************");
266 | Log.e(tag, "EXCEPTION: " + getMethodName() + ", " + message + '\n' +
267 | Log.getStackTraceString(tr));
268 | Log.e(tag, "**********************************************");
269 | }
270 | r(getFormattedLog(Log.ERROR, tag, "EXCEPTION: " + getMethodName() + ", "
271 | + message));
272 | }
273 |
274 | public static void exception(String tag, String message) {
275 | exception(tag, message, null);
276 | }
277 |
278 | public static void exception(String tag, Exception e) {
279 | if (e == null)
280 | return;
281 |
282 | exception(tag, e.getMessage(), null);
283 | }
284 |
285 | public static void a(String message) {
286 | r(getFormattedLog(Log.ASSERT, TAG_ASSERT, message));
287 | }
288 |
289 | private static String getMethodName() {
290 | StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
291 | StackTraceElement e = stacktrace[1];//coz 0th will be getStackTrace so 1st
292 | return e.getMethodName();
293 | }
294 |
295 | private static void r(final String message) {
296 | try {
297 |
298 | if (executorService == null)
299 | executorService = Executors.newSingleThreadExecutor();
300 |
301 | Runnable runnable = new Runnable() {
302 | @Override
303 | public void run() {
304 | try {
305 | if (!isInitialize() || message == null || message.isEmpty())
306 | return;
307 |
308 | mDeviceLogList.addDeviceLog(message);
309 | } catch (Exception ex) {
310 | ex.printStackTrace();
311 | }
312 | }
313 | };
314 |
315 | executorService.submit(runnable);
316 |
317 | } catch (OutOfMemoryError | Exception e) {
318 | e.printStackTrace();
319 | }
320 | }
321 |
322 | /**
323 | * Call this method to get a list of stored Device Logs
324 | *
325 | * @return List of {@link DeviceLogModel}
326 | */
327 | public static List getDeviceLogs() {
328 | return getDeviceLogs(true);
329 | }
330 |
331 | /**
332 | * Call this method to get a list of stored Device Logs
333 | *
334 | * @param deleteLogs If true then logs will delete from the device.
335 | * @return List of {@link DeviceLogModel}
336 | */
337 | public static List getDeviceLogs(boolean deleteLogs) {
338 | return getDeviceLogs(deleteLogs, 1);
339 | }
340 |
341 | /**
342 | * Call this method to get a list of stored Device Logs.
343 | *
344 | * @param deleteLogs If true then logs will delete from the device.
345 | * @param batchNo If there are more than one batch of device log then specify the batch number.
346 | * Batch number should be greater than or equal to 1.
347 | * @return List of {@link DeviceLogModel} or empty list if batch number is greater than the
348 | * {@link HyperLog#getDeviceLogBatchCount()}
349 | */
350 | public static List getDeviceLogs(boolean deleteLogs, int batchNo) {
351 | List deviceLogs = new ArrayList<>();
352 | if (!isInitialize())
353 | return deviceLogs;
354 |
355 | deviceLogs = mDeviceLogList.getDeviceLogs(batchNo);
356 | if (deleteLogs) {
357 | mDeviceLogList.clearDeviceLogs(deviceLogs);
358 | }
359 |
360 | return deviceLogs;
361 | }
362 |
363 | /**
364 | * Call this method to get a list of stored Device Logs.
365 | * Device logs will gets deleted from device after fetching.
366 | *
367 | * @return List of {@link String}
368 | */
369 | public static List getDeviceLogsAsStringList() {
370 | return getDeviceLogsAsStringList(true);
371 | }
372 |
373 | /**
374 | * Call this method to get a list of stored Device Logs
375 | *
376 | * @param deleteLogs If true then logs will delete from the device.
377 | * @return List of {@link String}
378 | */
379 | public static List getDeviceLogsAsStringList(boolean deleteLogs) {
380 | return getDeviceLogsAsStringList(deleteLogs, 1);
381 | }
382 |
383 | /**
384 | * Call this method to get a list of stored Device Logs
385 | *
386 | * @param deleteLogs If true then logs will delete from the device.
387 | * @param batchNo If there are more than one batch of device log then specify the batch number.
388 | * Batch number should be greater than or equal to 1.
389 | * @return List of {@link String} or if the given batchNo is greater than the
390 | * {@link HyperLog#getDeviceLogBatchCount()} then returns empty list;
391 | */
392 | public static List getDeviceLogsAsStringList(boolean deleteLogs, int batchNo) {
393 | List logsList = new ArrayList<>();
394 | if (!isInitialize())
395 | return logsList;
396 |
397 | if (!hasPendingDeviceLogs()) {
398 | return logsList;
399 | }
400 |
401 | return getDeviceLogsAsStringList(getDeviceLogs(deleteLogs, batchNo));
402 | }
403 |
404 | /**
405 | * Method to get a list of stored Device Logs
406 | *
407 | * @param deviceLogList List of all device logs
408 | * @return List of {@link String}
409 | */
410 | private static List getDeviceLogsAsStringList(List deviceLogList) {
411 | List logsList = new ArrayList<>();
412 |
413 | if (deviceLogList == null) {
414 | return logsList;
415 | }
416 |
417 | for (DeviceLogModel deviceLog : deviceLogList) {
418 | logsList.add(deviceLog.getDeviceLog());
419 | }
420 |
421 | return logsList;
422 | }
423 |
424 | /**
425 | * Call this method to get a stored Device Logs as a File object.
426 | * A text file will create in the app folder containing all logs with the current date time as
427 | * name of the file.
428 | *
429 | * @param mContext The current context.
430 | * @return {@link File} object or {@code null} if there is not any logs in device.
431 | */
432 | public static File getDeviceLogsInFile(Context mContext) {
433 | return getDeviceLogsInFile(mContext, null);
434 | }
435 |
436 | /**
437 | * Call this method to get a stored Device Logs as a File object.
438 | * A text file will create in the app folder containing all logs with the current date time as
439 | * name of the file.
440 | *
441 | * @param mContext The current context.
442 | * @param deleteLogs If true then logs will delete from the device.
443 | * @return {@link File} object or {@code null} if there is not any logs in device.
444 | */
445 | public static File getDeviceLogsInFile(Context mContext, boolean deleteLogs) {
446 | return getDeviceLogsInFile(mContext, null, deleteLogs);
447 | }
448 |
449 | /**
450 | * Call this method to get a stored Device Logs as a File object.
451 | * A text file will create in the app folder containing all logs with the current date time as
452 | * name of the file.
453 | *
454 | * @param mContext The current context.
455 | * @param fileName Name of the file.
456 | * @return {@link File} object or {@code null} if there is not any logs in device.
457 | */
458 | public static File getDeviceLogsInFile(Context mContext, String fileName) {
459 | return getDeviceLogsInFile(mContext, fileName, true);
460 | }
461 |
462 | /**
463 | * Call this method to get a stored Device Logs as a File object.
464 | * A text file will create in the app folder containing all logs.
465 | *
466 | * @param mContext The current context.
467 | * @param fileName Name of the file.
468 | * @param deleteLogs If true then logs will delete from the device.
469 | * @return {@link File} object, or {@code null} if there is not any logs in device.
470 | */
471 | public static File getDeviceLogsInFile(Context mContext, String fileName, boolean deleteLogs) {
472 |
473 | if (!isInitialize())
474 | return null;
475 |
476 | File file = null;
477 |
478 | if (TextUtils.isEmpty(fileName)) {
479 | fileName = HLDateTimeUtility.getCurrentTime() + ".txt";
480 | fileName = fileName.replaceAll("[^a-zA-Z0-9_\\\\-\\\\.]", "_");
481 | }
482 |
483 | //Check how many batches of device logs are available to push
484 | int logsBatchCount = getDeviceLogBatchCount();
485 |
486 | while (logsBatchCount != 0) {
487 | List deviceLogList = getDeviceLogs(deleteLogs);
488 |
489 | if (deviceLogList != null && !deviceLogList.isEmpty()) {
490 | file = Utils.writeStringsToFile(mContext, getDeviceLogsAsStringList(deviceLogList),
491 | fileName);
492 | if (file != null) {
493 | if (deleteLogs)
494 | mDeviceLogList.clearDeviceLogs(deviceLogList);
495 | HyperLog.i("HYPERLOG", "Log File has been created at " +
496 | file.getAbsolutePath());
497 | }
498 | }
499 | logsBatchCount--;
500 | }
501 | return file;
502 | }
503 |
504 | /**
505 | * Call this method to check whether any device logs are available.
506 | *
507 | * @return true If device has some pending logs otherwise false.
508 | */
509 | public static boolean hasPendingDeviceLogs() {
510 | if (!isInitialize())
511 | return false;
512 |
513 | long deviceLogsCount = mDeviceLogList.count();
514 | return deviceLogsCount > 0L;
515 | }
516 |
517 | /**
518 | * Call this method to get the count of stored device logs.
519 | *
520 | * @return The number of device logs.
521 | */
522 | public static long getDeviceLogsCount() {
523 | if (!isInitialize())
524 | return 0;
525 |
526 | return mDeviceLogList.count();
527 | }
528 |
529 | /**
530 | * Call this method to get number of device logs batches. Each batch contains the 5000 device
531 | * logs.
532 | *
533 | * @return The number of device logs batches.
534 | */
535 | public static int getDeviceLogBatchCount() {
536 | if (!isInitialize())
537 | return 0;
538 |
539 | return mDeviceLogList.getDeviceLogBatchCount();
540 | }
541 |
542 | /**
543 | * Call this method to push logs from device to the server as a text file or gzip compressed file.
544 | *
545 | * Logs will get delete from the device once it successfully push to the server.
546 | *
547 | * If device log count is greater than {@value DeviceLogTable#DEVICE_LOG_REQUEST_QUERY_LIMIT} then
548 | * log will push to the server in batches.
549 | *
550 | * @param mContext The current context.
551 | * @param compress True, if logs will push to server in GZIP compressed format, false otherwise.
552 | * @param callback Instance of {@link HLCallback}.
553 | * @throws IllegalArgumentException if the API endpoint url is empty or null
554 | */
555 | public static void pushLogs(Context mContext, boolean compress, HLCallback callback) {
556 | pushLogs(mContext, null, null, compress, callback);
557 | }
558 |
559 | /**
560 | * Call this method to push logs from device to the server with custom filename as a text file
561 | * or gzip compressed file.
562 | *
563 | * Logs will get delete from the device once it successfully push to the server.
564 | *
565 | * If device log count is greater than {@value DeviceLogTable#DEVICE_LOG_REQUEST_QUERY_LIMIT} then
566 | * log will push to the server in batches.
567 | *
568 | * @param mContext The current context.
569 | * @param fileName Name of the file that you want to receive on your server.
570 | * @param compress True, if logs will push to server in GZIP compressed format, false otherwise.
571 | * @param callback Instance of {@link HLCallback}.
572 | * @throws IllegalArgumentException if the API endpoint url is empty or null
573 | */
574 | public static void pushLogs(Context mContext, String fileName, boolean compress,
575 | HLCallback callback) {
576 | pushLogs(mContext, fileName, null, compress, callback);
577 | }
578 |
579 | /**
580 | * Call this method to push logs from device to the server as a text file or gzip compressed file.
581 | *
582 | * Logs will get delete from the device once it successfully push to the server.
583 | *
584 | * If device log count is greater than {@value DeviceLogTable#DEVICE_LOG_REQUEST_QUERY_LIMIT} then
585 | * log will push to the server in batches.
586 | *
587 | * @param mContext The current context.
588 | * @param additionalHeaders Additional Headers to pass along with request.
589 | * @param compress True, if logs will push to server in GZIP compressed format,
590 | * false otherwise.
591 | * @param callback Instance of {@link HLCallback}.
592 | * @throws IllegalArgumentException if the API endpoint url is empty or null
593 | */
594 | public static void pushLogs(Context mContext, HashMap additionalHeaders,
595 | boolean compress, HLCallback callback) {
596 | pushLogs(mContext, null, additionalHeaders, compress, callback);
597 | }
598 |
599 | /**
600 | * Call this method to push logs from device to the server with custom filename as a text file
601 | * or gzip compressed file.
602 | *
603 | * Logs will get delete from the device once it successfully push to the server.
604 | *
605 | * If device log count is greater than {@value DeviceLogTable#DEVICE_LOG_REQUEST_QUERY_LIMIT}
606 | * then log will push to the server in batches.
607 | *
608 | * @param fileName Name of the file that you want to receive on your server.
609 | * @param mContext The current context.
610 | * @param additionalHeaders Additional Headers to pass along with request.
611 | * @param compress True, if logs will push to server in GZIP compressed format,
612 | * false otherwise.
613 | * @param callback Instance of {@link HLCallback}.
614 | * @throws IllegalArgumentException if the API endpoint url is empty or null
615 | */
616 | public static void pushLogs(Context mContext, String fileName, HashMap additionalHeaders, boolean compress, final HLCallback callback) {
618 |
619 | if (!isInitialize())
620 | return;
621 |
622 | if (TextUtils.isEmpty(URL)) {
623 | HyperLog.e("HYPERLOG", "API endpoint URL is missing. Set URL using " +
624 | "HyperLog.setURL method");
625 | return;
626 | }
627 |
628 | VolleyUtils.cancelPendingRequests(mContext, TAG);
629 |
630 | if (TextUtils.isEmpty(URL)) {
631 | HyperLog.e("HYPERLOG", "URL is missing. Please set the URL to push the logs.");
632 | return;
633 | }
634 | if (!hasPendingDeviceLogs())
635 | return;
636 |
637 | //Check how many batches of device logs are available to push
638 | int logsBatchCount = getDeviceLogBatchCount();
639 |
640 | final int[] temp = {logsBatchCount};
641 | final boolean[] isAllLogsPushed = {true};
642 |
643 | while (logsBatchCount != 0) {
644 |
645 | final List deviceLogs = getDeviceLogs(false, logsBatchCount);
646 | deviceLogs.add(new DeviceLogModel(getFormattedLog(Log.INFO, TAG_HYPERLOG,
647 | "Log Counts: " + deviceLogs.size() + " | File Size: " +
648 | deviceLogs.toString().length() + " bytes.")));
649 | //Get string data into byte format.
650 | byte[] bytes = Utils.getByteData(deviceLogs);
651 |
652 | if (TextUtils.isEmpty(fileName)) {
653 | fileName = HLDateTimeUtility.getCurrentTime() + ".txt";
654 | }
655 |
656 | HLHTTPMultiPartPostRequest hlHTTPMultiPartPostRequest =
657 | new HLHTTPMultiPartPostRequest<>(URL, bytes, fileName, additionalHeaders,
658 | mContext, Object.class, compress, new Response.Listener