├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── _config.yml ├── asset ├── device_logger.gif └── request_bin.png ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── hyperlog-demo-debug.apk ├── hyperlog-demo ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hypertrack │ │ └── hyperlog_demo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── hypertrack │ │ │ └── hyperlog_demo │ │ │ ├── CustomLogMessageFormat.java │ │ │ ├── MainActivity.java │ │ │ └── MyApplication.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── hypertrack │ └── hyperlog_demo │ └── ExampleUnitTest.java ├── hyperlog ├── .gitignore ├── build.gradle ├── gradle.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── hypertrack │ │ └── hyperlog │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── hypertrack │ │ │ └── hyperlog │ │ │ ├── DeviceLogDataSource.java │ │ │ ├── DeviceLogDatabaseHelper.java │ │ │ ├── DeviceLogList.java │ │ │ ├── DeviceLogModel.java │ │ │ ├── DeviceLogTable.java │ │ │ ├── HLCallback.java │ │ │ ├── HLHTTPMultiPartPostRequest.java │ │ │ ├── HyperLog.java │ │ │ ├── LogData.java │ │ │ ├── LogFormat.java │ │ │ ├── error │ │ │ ├── HLErrorCode.java │ │ │ ├── HLErrorListener.java │ │ │ ├── HLErrorResponse.java │ │ │ └── HLNetworkErrorUtil.java │ │ │ └── utils │ │ │ ├── CustomGson.java │ │ │ ├── HLDateTimeUtility.java │ │ │ ├── Utils.java │ │ │ └── VolleyUtils.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── com │ └── hypertrack │ └── hyperlog │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # generated files 2 | bin/ 3 | gen/ 4 | 5 | # Local configuration file (sdk path, etc) 6 | local.properties 7 | 8 | # Windows thumbnail db 9 | Thumbs.db 10 | 11 | # OSX files 12 | .DS_Store 13 | 14 | # Eclipse project files 15 | .classpath 16 | .project 17 | 18 | # Android Studio 19 | *.iml 20 | .idea/ 21 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 22 | .gradle 23 | build/ 24 | gradlew.bat 25 | #NDK 26 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 1.8 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HyperLog Android 2 | 3 | [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | [ ![Download](https://api.bintray.com/packages/piyushgupta27/maven/hyperlog/images/download.svg) ](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 | Device Logger 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 | RequestBin 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 |