Showing
16 changed files
with
608 additions
and
1070 deletions
... | @@ -3,13 +3,14 @@ apply plugin: 'com.google.gms.google-services' | ... | @@ -3,13 +3,14 @@ apply plugin: 'com.google.gms.google-services' |
3 | apply plugin: 'com.huawei.agconnect' | 3 | apply plugin: 'com.huawei.agconnect' |
4 | 4 | ||
5 | android { | 5 | android { |
6 | - compileSdkVersion 34 | 6 | + compileSdkVersion 35 |
7 | - buildToolsVersion "34.0.0" | 7 | + buildToolsVersion "35.0.0" |
8 | 8 | ||
9 | + namespace "warp.ly.android_sdk" | ||
9 | defaultConfig { | 10 | defaultConfig { |
10 | applicationId "warp.ly.android_sdk" | 11 | applicationId "warp.ly.android_sdk" |
11 | minSdkVersion 31 | 12 | minSdkVersion 31 |
12 | - targetSdkVersion 34 | 13 | + targetSdkVersion 35 |
13 | versionCode 100 | 14 | versionCode 100 |
14 | versionName "1.0.0" | 15 | versionName "1.0.0" |
15 | } | 16 | } | ... | ... |
... | @@ -8,9 +8,9 @@ buildscript { | ... | @@ -8,9 +8,9 @@ buildscript { |
8 | maven { url 'https://plugins.gradle.org/m2/' } | 8 | maven { url 'https://plugins.gradle.org/m2/' } |
9 | } | 9 | } |
10 | dependencies { | 10 | dependencies { |
11 | - classpath 'com.android.tools.build:gradle:8.8.0' | 11 | + classpath 'com.android.tools.build:gradle:8.7.3' |
12 | - classpath 'com.google.gms:google-services:4.4.2' | 12 | + classpath 'com.google.gms:google-services:4.4.3' |
13 | - classpath 'com.huawei.agconnect:agcp:1.9.1.300' | 13 | + classpath 'com.huawei.agconnect:agcp:1.9.1.301' |
14 | classpath 'io.github.gradle-nexus:publish-plugin:1.1.0' | 14 | classpath 'io.github.gradle-nexus:publish-plugin:1.1.0' |
15 | 15 | ||
16 | // NOTE: Do not place your application dependencies here; they belong | 16 | // NOTE: Do not place your application dependencies here; they belong |
... | @@ -18,6 +18,10 @@ buildscript { | ... | @@ -18,6 +18,10 @@ buildscript { |
18 | } | 18 | } |
19 | } | 19 | } |
20 | 20 | ||
21 | +plugins { | ||
22 | + id 'maven-publish' | ||
23 | +} | ||
24 | + | ||
21 | allprojects { | 25 | allprojects { |
22 | repositories { | 26 | repositories { |
23 | mavenCentral() | 27 | mavenCentral() |
... | @@ -27,5 +31,4 @@ allprojects { | ... | @@ -27,5 +31,4 @@ allprojects { |
27 | } | 31 | } |
28 | } | 32 | } |
29 | 33 | ||
30 | -apply plugin: 'io.github.gradle-nexus.publish-plugin' | ||
31 | apply from: "${rootDir}/scripts/publish-root.gradle" | 34 | apply from: "${rootDir}/scripts/publish-root.gradle" |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
1 | #Fri Jul 26 17:08:44 EEST 2024 | 1 | #Fri Jul 26 17:08:44 EEST 2024 |
2 | distributionBase=GRADLE_USER_HOME | 2 | distributionBase=GRADLE_USER_HOME |
3 | distributionPath=wrapper/dists | 3 | distributionPath=wrapper/dists |
4 | -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip | 4 | +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip |
5 | zipStoreBase=GRADLE_USER_HOME | 5 | zipStoreBase=GRADLE_USER_HOME |
6 | zipStorePath=wrapper/dists | 6 | zipStorePath=wrapper/dists | ... | ... |
... | @@ -40,7 +40,7 @@ afterEvaluate { | ... | @@ -40,7 +40,7 @@ afterEvaluate { |
40 | // Sources are now handled by the android block's singleVariant | 40 | // Sources are now handled by the android block's singleVariant |
41 | // artifact javadocJar | 41 | // artifact javadocJar |
42 | 42 | ||
43 | - // Mostly self-explanatory metadata | 43 | + // POM metadata for Maven Central |
44 | pom { | 44 | pom { |
45 | name = PUBLISH_ARTIFACT_ID | 45 | name = PUBLISH_ARTIFACT_ID |
46 | description = 'Warply Android SDK Maven Plugin' | 46 | description = 'Warply Android SDK Maven Plugin' |
... | @@ -60,8 +60,7 @@ afterEvaluate { | ... | @@ -60,8 +60,7 @@ afterEvaluate { |
60 | // Add all other devs here... | 60 | // Add all other devs here... |
61 | } | 61 | } |
62 | 62 | ||
63 | - // Version control info - if you're using GitHub, follow the | 63 | + // Version control info |
64 | - // format as seen here | ||
65 | scm { | 64 | scm { |
66 | connection = 'scm:git:git.warp.ly/open-source/warply_android_sdk_maven_plugin.git' | 65 | connection = 'scm:git:git.warp.ly/open-source/warply_android_sdk_maven_plugin.git' |
67 | developerConnection = 'scm:git:ssh://git.warp.ly/open-source/warply_android_sdk_maven_plugin.git' | 66 | developerConnection = 'scm:git:ssh://git.warp.ly/open-source/warply_android_sdk_maven_plugin.git' |
... | @@ -81,3 +80,365 @@ signing { | ... | @@ -81,3 +80,365 @@ signing { |
81 | ) | 80 | ) |
82 | sign publishing.publications | 81 | sign publishing.publications |
83 | } | 82 | } |
83 | + | ||
84 | +// Configuration for Central Publishing (similar to Maven plugin configuration) | ||
85 | +ext.centralPublishing = [ | ||
86 | + autoPublish : false, // Manual publishing for safety | ||
87 | + // waitUntil: "published", // Commented out - don't wait for publishing | ||
88 | + deploymentName: "Warply Android SDK ${PUBLISH_VERSION}", | ||
89 | + centralBaseUrl: "https://central.sonatype.com" | ||
90 | +] | ||
91 | + | ||
92 | +// Custom task that implements the same functionality as org.sonatype.central:central-publishing-maven-plugin:0.8.0 | ||
93 | +// This uses the Central Portal API directly to achieve the same result | ||
94 | +task publishToCentralPortal { | ||
95 | + dependsOn 'publishReleasePublicationToMavenLocal' | ||
96 | + | ||
97 | + description = 'Publishes to Maven Central Portal using the same API as central-publishing-maven-plugin:0.8.0' | ||
98 | + group = 'publishing' | ||
99 | + | ||
100 | + doLast { | ||
101 | + def username = rootProject.ext["centralPortalUsername"] | ||
102 | + def password = rootProject.ext["centralPortalPassword"] | ||
103 | + def config = project.ext.centralPublishing | ||
104 | + | ||
105 | + if (!username || !password) { | ||
106 | + throw new GradleException("Central Portal credentials not configured. Please set centralPortalUsername and centralPortalPassword in local.properties or environment variables.") | ||
107 | + } | ||
108 | + | ||
109 | + println "=== Central Portal Publishing ===" | ||
110 | + println "Deployment: ${config.deploymentName}" | ||
111 | + println "Auto-publish: ${config.autoPublish}" | ||
112 | + println "Portal URL: ${config.centralBaseUrl}" | ||
113 | + println "" | ||
114 | + | ||
115 | + // Step 1: Create deployment bundle | ||
116 | + println "Step 1: Creating deployment bundle..." | ||
117 | + def bundleFile = createDeploymentBundle() | ||
118 | + println "✓ Bundle created: ${bundleFile.name} (${bundleFile.length()} bytes)" | ||
119 | + | ||
120 | + // Step 2: Upload bundle to Central Portal | ||
121 | + println "\nStep 2: Uploading to Central Portal..." | ||
122 | + def deploymentId = uploadBundle(bundleFile, username, password, config) | ||
123 | + println "✓ Upload successful. Deployment ID: ${deploymentId}" | ||
124 | + | ||
125 | + // Step 3: Wait for validation | ||
126 | + println "\nStep 3: Waiting for validation..." | ||
127 | + def validationResult = waitForValidation(deploymentId, username, password, config) | ||
128 | + | ||
129 | + if (validationResult.success) { | ||
130 | + def state = validationResult.state | ||
131 | + println "✓ Validation successful! State: ${state}" | ||
132 | + | ||
133 | + if (config.autoPublish && state == "VALIDATED") { | ||
134 | + println "\nStep 4: Auto-publishing..." | ||
135 | + def publishResult = publishDeployment(deploymentId, username, password, config) | ||
136 | + if (publishResult.success) { | ||
137 | + println "✓ Published successfully to Maven Central!" | ||
138 | + } else { | ||
139 | + throw new GradleException("Auto-publishing failed: ${publishResult.error}") | ||
140 | + } | ||
141 | + } else if (state == "PUBLISHED") { | ||
142 | + println "✓ Already published to Maven Central!" | ||
143 | + def response = validationResult.response | ||
144 | + def purls = response.purls ?: [] | ||
145 | + if (purls) { | ||
146 | + println " Published artifacts:" | ||
147 | + purls.each { purl -> println " - ${purl}" } | ||
148 | + } | ||
149 | + } else { | ||
150 | + println "\n✓ Deployment uploaded and validated successfully!" | ||
151 | + println "📋 Manual action required:" | ||
152 | + println " Visit: ${config.centralBaseUrl}/publishing/deployments" | ||
153 | + println " Find deployment: ${config.deploymentName}" | ||
154 | + println " Click 'Publish' to complete the process" | ||
155 | + } | ||
156 | + } else { | ||
157 | + throw new GradleException("Validation failed: ${validationResult.error}") | ||
158 | + } | ||
159 | + | ||
160 | + println "\n=== Publishing Complete ===" | ||
161 | + } | ||
162 | +} | ||
163 | + | ||
164 | +def createDeploymentBundle() { | ||
165 | + def bundleDir = file("${buildDir}/central-publishing") | ||
166 | + def stagingDir = file("${bundleDir}/staging") | ||
167 | + | ||
168 | + // Clean and create directories | ||
169 | + bundleDir.deleteDir() | ||
170 | + stagingDir.mkdirs() | ||
171 | + | ||
172 | + // Create Maven repository structure | ||
173 | + def groupPath = PUBLISH_GROUP_ID.replace('.', '/') | ||
174 | + def artifactDir = file("${stagingDir}/${groupPath}/${PUBLISH_ARTIFACT_ID}/${PUBLISH_VERSION}") | ||
175 | + artifactDir.mkdirs() | ||
176 | + | ||
177 | + // Copy artifacts to staging area | ||
178 | + def artifacts = [:] | ||
179 | + | ||
180 | + // AAR file | ||
181 | + def aarFile = file("${buildDir}/outputs/aar/warply_android_sdk-release.aar") | ||
182 | + if (aarFile.exists()) { | ||
183 | + def targetAar = file("${artifactDir}/${PUBLISH_ARTIFACT_ID}-${PUBLISH_VERSION}.aar") | ||
184 | + copy { | ||
185 | + from aarFile | ||
186 | + into artifactDir | ||
187 | + rename { targetAar.name } | ||
188 | + } | ||
189 | + artifacts['aar'] = targetAar | ||
190 | + | ||
191 | + // Copy AAR signature if exists | ||
192 | + def aarSigFile = file("${aarFile.path}.asc") | ||
193 | + if (aarSigFile.exists()) { | ||
194 | + def targetAarSig = file("${targetAar.path}.asc") | ||
195 | + copy { | ||
196 | + from aarSigFile | ||
197 | + into artifactDir | ||
198 | + rename { targetAarSig.name } | ||
199 | + } | ||
200 | + artifacts['aar-sig'] = targetAarSig | ||
201 | + } | ||
202 | + } | ||
203 | + | ||
204 | + // Sources JAR | ||
205 | + def sourcesFile = file("${buildDir}/libs/warply_android_sdk-${PUBLISH_VERSION}-sources.jar") | ||
206 | + if (sourcesFile.exists()) { | ||
207 | + def targetSources = file("${artifactDir}/${PUBLISH_ARTIFACT_ID}-${PUBLISH_VERSION}-sources.jar") | ||
208 | + copy { | ||
209 | + from sourcesFile | ||
210 | + into artifactDir | ||
211 | + rename { targetSources.name } | ||
212 | + } | ||
213 | + artifacts['sources'] = targetSources | ||
214 | + | ||
215 | + // Copy sources signature if exists | ||
216 | + def sourcesSigFile = file("${sourcesFile.path}.asc") | ||
217 | + if (sourcesSigFile.exists()) { | ||
218 | + def targetSourcesSig = file("${targetSources.path}.asc") | ||
219 | + copy { | ||
220 | + from sourcesSigFile | ||
221 | + into artifactDir | ||
222 | + rename { targetSourcesSig.name } | ||
223 | + } | ||
224 | + artifacts['sources-sig'] = targetSourcesSig | ||
225 | + } | ||
226 | + } | ||
227 | + | ||
228 | + // POM file | ||
229 | + def pomFile = file("${buildDir}/publications/release/pom-default.xml") | ||
230 | + if (pomFile.exists()) { | ||
231 | + def targetPom = file("${artifactDir}/${PUBLISH_ARTIFACT_ID}-${PUBLISH_VERSION}.pom") | ||
232 | + copy { | ||
233 | + from pomFile | ||
234 | + into artifactDir | ||
235 | + rename { targetPom.name } | ||
236 | + } | ||
237 | + artifacts['pom'] = targetPom | ||
238 | + | ||
239 | + // Copy POM signature if exists | ||
240 | + def pomSigFile = file("${pomFile.path}.asc") | ||
241 | + if (pomSigFile.exists()) { | ||
242 | + def targetPomSig = file("${targetPom.path}.asc") | ||
243 | + copy { | ||
244 | + from pomSigFile | ||
245 | + into artifactDir | ||
246 | + rename { targetPomSig.name } | ||
247 | + } | ||
248 | + artifacts['pom-sig'] = targetPomSig | ||
249 | + } | ||
250 | + } | ||
251 | + | ||
252 | + // Generate checksums for all files | ||
253 | + artifacts.each { type, artifactFile -> | ||
254 | + if (artifactFile.exists()) { | ||
255 | + generateChecksums(artifactFile) | ||
256 | + } | ||
257 | + } | ||
258 | + | ||
259 | + // Create bundle ZIP | ||
260 | + def bundleFile = file("${bundleDir}/central-bundle.zip") | ||
261 | + ant.zip(destfile: bundleFile) { | ||
262 | + fileset(dir: stagingDir) | ||
263 | + } | ||
264 | + | ||
265 | + return bundleFile | ||
266 | +} | ||
267 | + | ||
268 | +def generateChecksums(File file) { | ||
269 | + ['md5', 'sha1', 'sha256', 'sha512'].each { algorithm -> | ||
270 | + def checksum = file.withInputStream { stream -> | ||
271 | + java.security.MessageDigest.getInstance(algorithm.toUpperCase()).digest(stream.bytes).encodeHex().toString() | ||
272 | + } | ||
273 | + new File("${file.path}.${algorithm}").text = checksum | ||
274 | + } | ||
275 | +} | ||
276 | + | ||
277 | +def uploadBundle(File bundleFile, String username, String password, Map config) { | ||
278 | + def url = "${config.centralBaseUrl}/api/v1/publisher/upload" | ||
279 | + def credentials = "${username}:${password}".bytes.encodeBase64().toString() | ||
280 | + | ||
281 | + // Add query parameters | ||
282 | + def publishingType = config.autoPublish ? "AUTOMATIC" : "USER_MANAGED" | ||
283 | + def urlWithParams = "${url}?publishingType=${publishingType}&name=${URLEncoder.encode(config.deploymentName, 'UTF-8')}" | ||
284 | + | ||
285 | + println " Uploading to: ${urlWithParams}" | ||
286 | + println " Publishing type: ${publishingType}" | ||
287 | + | ||
288 | + def connection = new URL(urlWithParams).openConnection() as HttpURLConnection | ||
289 | + connection.setRequestMethod("POST") | ||
290 | + connection.setRequestProperty("Authorization", "Bearer ${credentials}") | ||
291 | + connection.setDoOutput(true) | ||
292 | + connection.setDoInput(true) | ||
293 | + | ||
294 | + // Create multipart/form-data boundary | ||
295 | + def boundary = "----WebKitFormBoundary" + System.currentTimeMillis() | ||
296 | + connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=${boundary}") | ||
297 | + | ||
298 | + // Write multipart data | ||
299 | + connection.outputStream.withWriter("UTF-8") { writer -> | ||
300 | + writer.write("--${boundary}\r\n") | ||
301 | + writer.write("Content-Disposition: form-data; name=\"bundle\"; filename=\"${bundleFile.name}\"\r\n") | ||
302 | + writer.write("Content-Type: application/octet-stream\r\n") | ||
303 | + writer.write("\r\n") | ||
304 | + writer.flush() | ||
305 | + | ||
306 | + // Write file content | ||
307 | + bundleFile.withInputStream { input -> | ||
308 | + connection.outputStream << input | ||
309 | + } | ||
310 | + | ||
311 | + writer.write("\r\n--${boundary}--\r\n") | ||
312 | + writer.flush() | ||
313 | + } | ||
314 | + | ||
315 | + // Get response | ||
316 | + def responseCode = connection.responseCode | ||
317 | + if (responseCode == 201) { | ||
318 | + def deploymentId = connection.inputStream.text.trim() | ||
319 | + println " ✓ Upload successful (HTTP ${responseCode})" | ||
320 | + return deploymentId | ||
321 | + } else { | ||
322 | + def errorMessage = connection.errorStream?.text ?: "Unknown error" | ||
323 | + throw new GradleException("Upload failed (HTTP ${responseCode}): ${errorMessage}") | ||
324 | + } | ||
325 | +} | ||
326 | + | ||
327 | +def waitForValidation(String deploymentId, String username, String password, Map config) { | ||
328 | + def credentials = "${username}:${password}".bytes.encodeBase64().toString() | ||
329 | + def maxAttempts = 60 // 5 minutes with 5-second intervals | ||
330 | + def attempt = 0 | ||
331 | + | ||
332 | + while (attempt < maxAttempts) { | ||
333 | + attempt++ | ||
334 | + | ||
335 | + def url = "${config.centralBaseUrl}/api/v1/publisher/status?id=${deploymentId}" | ||
336 | + def connection = new URL(url).openConnection() as HttpURLConnection | ||
337 | + connection.setRequestMethod("POST") | ||
338 | + connection.setRequestProperty("Authorization", "Bearer ${credentials}") | ||
339 | + connection.setRequestProperty("Content-Type", "application/json") | ||
340 | + | ||
341 | + def responseCode = connection.responseCode | ||
342 | + if (responseCode == 200) { | ||
343 | + def response = new groovy.json.JsonSlurper().parseText(connection.inputStream.text) | ||
344 | + def state = response.deploymentState | ||
345 | + | ||
346 | + println " Status check ${attempt}: ${state}" | ||
347 | + | ||
348 | + switch (state) { | ||
349 | + case "PENDING": | ||
350 | + case "VALIDATING": | ||
351 | + // Continue waiting | ||
352 | + Thread.sleep(5000) | ||
353 | + break | ||
354 | + case "VALIDATED": | ||
355 | + return [success: true, state: state, response: response] | ||
356 | + case "PUBLISHED": | ||
357 | + return [success: true, state: state, response: response] | ||
358 | + case "FAILED": | ||
359 | + def errors = response.errors ?: ["Unknown validation error"] | ||
360 | + return [success: false, error: "Validation failed: ${errors.join(', ')}", response: response] | ||
361 | + default: | ||
362 | + return [success: false, error: "Unknown deployment state: ${state}", response: response] | ||
363 | + } | ||
364 | + } else { | ||
365 | + def errorMessage = connection.errorStream?.text ?: "Unknown error" | ||
366 | + throw new GradleException("Status check failed (HTTP ${responseCode}): ${errorMessage}") | ||
367 | + } | ||
368 | + } | ||
369 | + | ||
370 | + return [success: false, error: "Timeout waiting for validation (${maxAttempts * 5} seconds)"] | ||
371 | +} | ||
372 | + | ||
373 | +def publishDeployment(String deploymentId, String username, String password, Map config) { | ||
374 | + def credentials = "${username}:${password}".bytes.encodeBase64().toString() | ||
375 | + def url = "${config.centralBaseUrl}/api/v1/publisher/deployment/${deploymentId}" | ||
376 | + | ||
377 | + println " Calling publish API..." | ||
378 | + | ||
379 | + def connection = new URL(url).openConnection() as HttpURLConnection | ||
380 | + connection.setRequestMethod("POST") | ||
381 | + connection.setRequestProperty("Authorization", "Bearer ${credentials}") | ||
382 | + | ||
383 | + def responseCode = connection.responseCode | ||
384 | + if (responseCode == 204) { | ||
385 | + println " ✓ Publish request successful (HTTP ${responseCode})" | ||
386 | + | ||
387 | + // Wait for publishing to complete | ||
388 | + println " Waiting for publishing to complete..." | ||
389 | + def result = waitForPublishing(deploymentId, username, password, config) | ||
390 | + return result | ||
391 | + } else { | ||
392 | + def errorMessage = connection.errorStream?.text ?: "Unknown error" | ||
393 | + throw new GradleException("Publish failed (HTTP ${responseCode}): ${errorMessage}") | ||
394 | + } | ||
395 | +} | ||
396 | + | ||
397 | +def waitForPublishing(String deploymentId, String username, String password, Map config) { | ||
398 | + def credentials = "${username}:${password}".bytes.encodeBase64().toString() | ||
399 | + def maxAttempts = 120 // 10 minutes with 5-second intervals | ||
400 | + def attempt = 0 | ||
401 | + | ||
402 | + while (attempt < maxAttempts) { | ||
403 | + attempt++ | ||
404 | + | ||
405 | + def url = "${config.centralBaseUrl}/api/v1/publisher/status?id=${deploymentId}" | ||
406 | + def connection = new URL(url).openConnection() as HttpURLConnection | ||
407 | + connection.setRequestMethod("POST") | ||
408 | + connection.setRequestProperty("Authorization", "Bearer ${credentials}") | ||
409 | + connection.setRequestProperty("Content-Type", "application/json") | ||
410 | + | ||
411 | + def responseCode = connection.responseCode | ||
412 | + if (responseCode == 200) { | ||
413 | + def response = new groovy.json.JsonSlurper().parseText(connection.inputStream.text) | ||
414 | + def state = response.deploymentState | ||
415 | + | ||
416 | + println " Publishing status ${attempt}: ${state}" | ||
417 | + | ||
418 | + switch (state) { | ||
419 | + case "PUBLISHING": | ||
420 | + // Continue waiting | ||
421 | + Thread.sleep(5000) | ||
422 | + break | ||
423 | + case "PUBLISHED": | ||
424 | + def purls = response.purls ?: [] | ||
425 | + println " ✓ Successfully published to Maven Central!" | ||
426 | + if (purls) { | ||
427 | + println " Published artifacts:" | ||
428 | + purls.each { purl -> println " - ${purl}" } | ||
429 | + } | ||
430 | + return [success: true, state: state, response: response] | ||
431 | + case "FAILED": | ||
432 | + def errors = response.errors ?: ["Unknown publishing error"] | ||
433 | + return [success: false, error: "Publishing failed: ${errors.join(', ')}", response: response] | ||
434 | + default: | ||
435 | + return [success: false, error: "Unexpected state during publishing: ${state}", response: response] | ||
436 | + } | ||
437 | + } else { | ||
438 | + def errorMessage = connection.errorStream?.text ?: "Unknown error" | ||
439 | + throw new GradleException("Publishing status check failed (HTTP ${responseCode}): ${errorMessage}") | ||
440 | + } | ||
441 | + } | ||
442 | + | ||
443 | + return [success: false, error: "Timeout waiting for publishing (${maxAttempts * 5} seconds)"] | ||
444 | +} | ... | ... |
1 | // Create variables with empty default values | 1 | // Create variables with empty default values |
2 | 2 | ||
3 | +// Central Portal credentials | ||
4 | +ext["centralPortalUsername"] = '' | ||
5 | +ext["centralPortalPassword"] = '' | ||
6 | + | ||
3 | // keyId is the last 8 characters of the GPG key | 7 | // keyId is the last 8 characters of the GPG key |
4 | ext["signing.keyId"] = '' | 8 | ext["signing.keyId"] = '' |
5 | // password is the passphrase of the GPG key | 9 | // password is the passphrase of the GPG key |
6 | ext["signing.password"] = '' | 10 | ext["signing.password"] = '' |
7 | // key is the base64 private GPG key | 11 | // key is the base64 private GPG key |
8 | ext["signing.key"] = '' | 12 | ext["signing.key"] = '' |
9 | -// osshrUsername and ossrhPassword are the account details for MavenCentral | ||
10 | -// which we’ve chosen at the Jira registration step (Sonatype site)) | ||
11 | -ext["ossrhUsername"] = '' | ||
12 | -ext["ossrhPassword"] = '' | ||
13 | -ext["sonatypeStagingProfileId"] = '' | ||
14 | 13 | ||
15 | File secretPropsFile = project.rootProject.file('local.properties') | 14 | File secretPropsFile = project.rootProject.file('local.properties') |
16 | if (secretPropsFile.exists()) { | 15 | if (secretPropsFile.exists()) { |
... | @@ -19,24 +18,11 @@ if (secretPropsFile.exists()) { | ... | @@ -19,24 +18,11 @@ if (secretPropsFile.exists()) { |
19 | new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) } | 18 | new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) } |
20 | p.each { name, value -> ext[name] = value } | 19 | p.each { name, value -> ext[name] = value } |
21 | } else { | 20 | } else { |
22 | - // Use system environment variables | 21 | + // Use system environment variables for signing |
23 | - ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') | ||
24 | - ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') | ||
25 | - ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID') | ||
26 | ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') | 22 | ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') |
27 | ext["signing.password"] = System.getenv('SIGNING_PASSWORD') | 23 | ext["signing.password"] = System.getenv('SIGNING_PASSWORD') |
28 | ext["signing.key"] = System.getenv('SIGNING_KEY') | 24 | ext["signing.key"] = System.getenv('SIGNING_KEY') |
29 | -} | 25 | + // Central Portal credentials can also come from environment |
30 | - | 26 | + ext["centralPortalUsername"] = System.getenv('CENTRAL_PORTAL_USERNAME') |
31 | -// Set up Sonatype repository | 27 | + ext["centralPortalPassword"] = System.getenv('CENTRAL_PORTAL_PASSWORD') |
32 | -nexusPublishing { | ||
33 | - repositories { | ||
34 | - sonatype { | ||
35 | - stagingProfileId = sonatypeStagingProfileId | ||
36 | - username = ossrhUsername | ||
37 | - password = ossrhPassword | ||
38 | - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) | ||
39 | - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) | ||
40 | - } | ||
41 | - } | ||
42 | } | 28 | } | ... | ... |
... | @@ -5,15 +5,15 @@ android.buildFeatures.buildConfig = true | ... | @@ -5,15 +5,15 @@ android.buildFeatures.buildConfig = true |
5 | 5 | ||
6 | ext { | 6 | ext { |
7 | PUBLISH_GROUP_ID = 'ly.warp' | 7 | PUBLISH_GROUP_ID = 'ly.warp' |
8 | - PUBLISH_VERSION = '4.5.5.4deh2' | 8 | + PUBLISH_VERSION = '4.5.5.4deh3' |
9 | PUBLISH_ARTIFACT_ID = 'warply-android-sdk' | 9 | PUBLISH_ARTIFACT_ID = 'warply-android-sdk' |
10 | } | 10 | } |
11 | 11 | ||
12 | apply from: "${rootProject.projectDir}/scripts/publish-module.gradle" | 12 | apply from: "${rootProject.projectDir}/scripts/publish-module.gradle" |
13 | 13 | ||
14 | android { | 14 | android { |
15 | - compileSdkVersion 34 | 15 | + compileSdkVersion 35 |
16 | - buildToolsVersion "34.0.0" | 16 | + buildToolsVersion "35.0.0" |
17 | 17 | ||
18 | useLibrary 'org.apache.http.legacy' | 18 | useLibrary 'org.apache.http.legacy' |
19 | 19 | ||
... | @@ -27,7 +27,7 @@ android { | ... | @@ -27,7 +27,7 @@ android { |
27 | 27 | ||
28 | defaultConfig { | 28 | defaultConfig { |
29 | minSdkVersion 31 | 29 | minSdkVersion 31 |
30 | - targetSdkVersion 34 | 30 | + targetSdkVersion 35 |
31 | consumerProguardFiles 'proguard-rules.pro' | 31 | consumerProguardFiles 'proguard-rules.pro' |
32 | vectorDrawables.useSupportLibrary = true | 32 | vectorDrawables.useSupportLibrary = true |
33 | } | 33 | } |
... | @@ -61,45 +61,42 @@ android { | ... | @@ -61,45 +61,42 @@ android { |
61 | 61 | ||
62 | dependencies { | 62 | dependencies { |
63 | //------------------------------ Support -----------------------------// | 63 | //------------------------------ Support -----------------------------// |
64 | - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' | 64 | + implementation 'androidx.appcompat:appcompat:1.7.1' |
65 | - implementation 'androidx.appcompat:appcompat:1.4.1' | 65 | + implementation "androidx.security:security-crypto:1.1.0" |
66 | - api "androidx.security:security-crypto:1.1.0-alpha03" | ||
67 | // For minSDK 23 use 1.0.0, for minSDK 21 use 1.1.0 that is currently in alpha | 66 | // For minSDK 23 use 1.0.0, for minSDK 21 use 1.1.0 that is currently in alpha |
68 | - api 'org.altbeacon:android-beacon-library:2.19.3' | 67 | + implementation 'org.altbeacon:android-beacon-library:2.19.3' |
69 | - api 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' | 68 | + implementation 'org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2' |
70 | - api 'io.reactivex.rxjava3:rxjava:3.1.8' | 69 | + implementation 'io.reactivex.rxjava3:rxjava:3.1.8' |
71 | - api 'io.reactivex.rxjava3:rxandroid:3.0.2' | 70 | + implementation 'io.reactivex.rxjava3:rxandroid:3.0.2' |
72 | - implementation 'com.google.android.material:material:1.5.0' | 71 | + implementation 'com.google.android.material:material:1.12.0' |
73 | implementation 'org.greenrobot:eventbus:3.3.1' | 72 | implementation 'org.greenrobot:eventbus:3.3.1' |
74 | - api 'com.google.guava:guava:30.1-android' | 73 | + implementation 'com.google.guava:guava:33.0.0-android' |
75 | 74 | ||
76 | //------------------------------ Firebase -----------------------------// | 75 | //------------------------------ Firebase -----------------------------// |
77 | - api platform('com.google.firebase:firebase-bom:29.0.3') | 76 | + implementation platform('com.google.firebase:firebase-bom:34.2.0') |
78 | implementation('com.google.firebase:firebase-messaging') { | 77 | implementation('com.google.firebase:firebase-messaging') { |
79 | exclude group: 'com.google.android.gms', module: 'play-services-location' | 78 | exclude group: 'com.google.android.gms', module: 'play-services-location' |
80 | } | 79 | } |
81 | 80 | ||
82 | //------------------------------ GMS -----------------------------// | 81 | //------------------------------ GMS -----------------------------// |
83 | - api 'com.google.android.gms:play-services-base:18.1.0' | 82 | + implementation 'com.google.android.gms:play-services-base:18.7.2' |
84 | - implementation 'com.google.android.gms:play-services-location:19.0.1' | 83 | + implementation 'com.google.android.gms:play-services-location:21.3.0' |
85 | 84 | ||
86 | //------------------------------ Work Manager -----------------------------// | 85 | //------------------------------ Work Manager -----------------------------// |
87 | - api 'androidx.work:work-runtime:2.7.1' | 86 | + implementation 'androidx.work:work-runtime:2.10.3' |
88 | 87 | ||
89 | //------------------------------ Glide -----------------------------// | 88 | //------------------------------ Glide -----------------------------// |
90 | - implementation 'com.github.bumptech.glide:glide:4.12.0' | 89 | + implementation 'com.github.bumptech.glide:glide:4.16.0' |
91 | - annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' | 90 | + annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0' |
92 | 91 | ||
93 | //------------------------------ Huawei -----------------------------// | 92 | //------------------------------ Huawei -----------------------------// |
94 | - implementation 'com.huawei.agconnect:agconnect-core:1.7.2.300' | 93 | + implementation 'com.huawei.agconnect:agconnect-core:1.9.3.301' |
95 | - implementation 'com.huawei.hms:base:6.6.0.300' | 94 | + implementation 'com.huawei.hms:base:6.13.0.303' |
96 | - implementation 'com.huawei.hms:push:6.7.0.300' | 95 | + implementation 'com.huawei.hms:push:6.10.0.300' |
97 | - implementation 'com.huawei.hms:ads-identifier:3.4.56.300' | 96 | + implementation 'com.huawei.hms:ads-identifier:3.4.62.300' |
98 | - | 97 | + |
99 | - //------------------------------ SQLCipher -----------------------------// | 98 | + //------------------------------ SQLite (Standard Android) -----------------------------// |
100 | - api "net.zetetic:android-database-sqlcipher:4.5.2" | 99 | + implementation 'androidx.sqlite:sqlite:2.5.2' |
101 | - api "androidx.sqlite:sqlite:2.2.0" | ||
102 | - api 'com.getkeepsafe.relinker:relinker:1.4.4' | ||
103 | 100 | ||
104 | //------------------------------ Retrofit -----------------------------// | 101 | //------------------------------ Retrofit -----------------------------// |
105 | implementation 'com.squareup.retrofit2:retrofit:2.9.0' | 102 | implementation 'com.squareup.retrofit2:retrofit:2.9.0' | ... | ... |
... | @@ -52,7 +52,6 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation | ... | @@ -52,7 +52,6 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation |
52 | mBottomNavigationView = findViewById(R.id.bt_tabs); | 52 | mBottomNavigationView = findViewById(R.id.bt_tabs); |
53 | 53 | ||
54 | if (WarplyDBHelper.getInstance(this).isTableNotEmpty("auth")) { | 54 | if (WarplyDBHelper.getInstance(this).isTableNotEmpty("auth")) { |
55 | - WarplyManager.getSupermarketCampaign(mCampaignsCallback); | ||
56 | WarplyManager.getRedeemedSMHistory(mSMHistoryReceiver); | 55 | WarplyManager.getRedeemedSMHistory(mSMHistoryReceiver); |
57 | } | 56 | } |
58 | 57 | ||
... | @@ -138,18 +137,6 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation | ... | @@ -138,18 +137,6 @@ public class BaseFragmentActivity extends FragmentActivity implements Navigation |
138 | // Inner and Anonymous Classes | 137 | // Inner and Anonymous Classes |
139 | // =========================================================== | 138 | // =========================================================== |
140 | 139 | ||
141 | - private final CallbackReceiver<ArrayList<Campaign>> mCampaignsCallback = new CallbackReceiver<ArrayList<Campaign>>() { | ||
142 | - @Override | ||
143 | - public void onSuccess(ArrayList<Campaign> result) { | ||
144 | - Toast.makeText(BaseFragmentActivity.this, "Campaigns Success " + String.valueOf(result.size()), Toast.LENGTH_SHORT).show(); | ||
145 | - } | ||
146 | - | ||
147 | - @Override | ||
148 | - public void onFailure(int errorCode) { | ||
149 | - Toast.makeText(BaseFragmentActivity.this, "Campaigns Error", Toast.LENGTH_SHORT).show(); | ||
150 | - } | ||
151 | - }; | ||
152 | - | ||
153 | private final CallbackReceiver<RedeemedSMHistoryModel> mSMHistoryReceiver = new CallbackReceiver<RedeemedSMHistoryModel>() { | 140 | private final CallbackReceiver<RedeemedSMHistoryModel> mSMHistoryReceiver = new CallbackReceiver<RedeemedSMHistoryModel>() { |
154 | @Override | 141 | @Override |
155 | public void onSuccess(RedeemedSMHistoryModel result) { | 142 | public void onSuccess(RedeemedSMHistoryModel result) { | ... | ... |
... | @@ -7,32 +7,18 @@ import android.content.Context; | ... | @@ -7,32 +7,18 @@ import android.content.Context; |
7 | import android.database.Cursor; | 7 | import android.database.Cursor; |
8 | import android.database.SQLException; | 8 | import android.database.SQLException; |
9 | import android.text.TextUtils; | 9 | import android.text.TextUtils; |
10 | -import android.util.Log; | ||
11 | 10 | ||
12 | import androidx.annotation.Nullable; | 11 | import androidx.annotation.Nullable; |
13 | 12 | ||
14 | -import com.getkeepsafe.relinker.ReLinker; | 13 | +import android.database.DatabaseUtils; |
14 | +import android.database.sqlite.SQLiteDatabase; | ||
15 | +import android.database.sqlite.SQLiteOpenHelper; | ||
15 | 16 | ||
16 | -import net.sqlcipher.DatabaseUtils; | ||
17 | -import net.sqlcipher.database.SQLiteDatabase; | ||
18 | -import net.sqlcipher.database.SQLiteOpenHelper; | ||
19 | -import net.sqlcipher.database.SQLiteStatement; | ||
20 | - | ||
21 | -import org.json.JSONArray; | ||
22 | -import org.json.JSONObject; | ||
23 | - | ||
24 | -import java.io.File; | ||
25 | -import java.io.FileNotFoundException; | ||
26 | -import java.io.IOException; | ||
27 | import java.util.ArrayList; | 17 | import java.util.ArrayList; |
28 | import java.util.List; | 18 | import java.util.List; |
29 | -import java.util.concurrent.ExecutorService; | ||
30 | -import java.util.concurrent.Executors; | ||
31 | -import java.util.concurrent.Future; | ||
32 | -import java.util.concurrent.TimeUnit; | ||
33 | -import java.util.concurrent.TimeoutException; | ||
34 | 19 | ||
35 | import ly.warp.sdk.utils.constants.WarpConstants; | 20 | import ly.warp.sdk.utils.constants.WarpConstants; |
21 | +import ly.warp.sdk.utils.CryptoUtils; | ||
36 | 22 | ||
37 | public class WarplyDBHelper extends SQLiteOpenHelper { | 23 | public class WarplyDBHelper extends SQLiteOpenHelper { |
38 | 24 | ||
... | @@ -40,17 +26,8 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -40,17 +26,8 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
40 | // Constants | 26 | // Constants |
41 | // =========================================================== | 27 | // =========================================================== |
42 | 28 | ||
43 | - private enum State { | 29 | + private static final String DB_NAME = "warply_v2.db"; |
44 | - DOES_NOT_EXIST, UNENCRYPTED, ENCRYPTED | 30 | + private static final int DB_VERSION = 1; |
45 | - } | ||
46 | - | ||
47 | - private static final String DB_NAME = "warply.db"; | ||
48 | - private static final int DB_VERSION = 14; | ||
49 | - private static final String KEY_CIPHER = "tn#mpOl3v3Dy1pr@W"; | ||
50 | - | ||
51 | - // Timeout constants | ||
52 | - private static final int CONNECTION_TIMEOUT_MS = 5000; // 5 seconds for database connection | ||
53 | - private static final int OPERATION_TIMEOUT_MS = 5000; // 5 seconds for database operations | ||
54 | 31 | ||
55 | //------------------------------ Fields -----------------------------// | 32 | //------------------------------ Fields -----------------------------// |
56 | private static String TABLE_REQUESTS = "requests"; | 33 | private static String TABLE_REQUESTS = "requests"; |
... | @@ -64,16 +41,12 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -64,16 +41,12 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
64 | private static String TABLE_CLIENT = "client"; | 41 | private static String TABLE_CLIENT = "client"; |
65 | private static String TABLE_AUTH = "auth"; | 42 | private static String TABLE_AUTH = "auth"; |
66 | private static String TABLE_TAGS = "tags"; | 43 | private static String TABLE_TAGS = "tags"; |
67 | - private static String TABLE_TELEMATICS = "telematics"; | ||
68 | public static final String KEY_TAG = "tag"; | 44 | public static final String KEY_TAG = "tag"; |
69 | public static final String KEY_TAG_LAST_ADD_DATE = "last_add_date"; | 45 | public static final String KEY_TAG_LAST_ADD_DATE = "last_add_date"; |
70 | public static final String KEY_CLIENT_ID = "client_id"; | 46 | public static final String KEY_CLIENT_ID = "client_id"; |
71 | public static final String KEY_CLIENT_SECRET = "client_secret"; | 47 | public static final String KEY_CLIENT_SECRET = "client_secret"; |
72 | public static final String KEY_ACCESS_TOKEN = "access_token"; | 48 | public static final String KEY_ACCESS_TOKEN = "access_token"; |
73 | public static final String KEY_REFRESH_TOKEN = "refresh_token"; | 49 | public static final String KEY_REFRESH_TOKEN = "refresh_token"; |
74 | - public static final String KEY_TIMESTAMP = "timestamp"; | ||
75 | - public static final String KEY_ACCELERATION = "acceleration"; | ||
76 | - public static final String KEY_SPEED = "speed"; | ||
77 | 50 | ||
78 | //------------------------------ Tables -----------------------------// | 51 | //------------------------------ Tables -----------------------------// |
79 | public static final String CREATE_TABLE_REQUESTS = "create table if not exists " | 52 | public static final String CREATE_TABLE_REQUESTS = "create table if not exists " |
... | @@ -115,12 +88,6 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -115,12 +88,6 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
115 | + KEY_ACCESS_TOKEN + " text, " | 88 | + KEY_ACCESS_TOKEN + " text, " |
116 | + KEY_REFRESH_TOKEN + " text)"; | 89 | + KEY_REFRESH_TOKEN + " text)"; |
117 | 90 | ||
118 | - public static final String CREATE_TABLE_TELEMATICS = "create table if not exists " | ||
119 | - + TABLE_TELEMATICS + " (" | ||
120 | - + KEY_TIMESTAMP + " text, " | ||
121 | - + KEY_ACCELERATION + " real, " | ||
122 | - + KEY_SPEED + " real)"; | ||
123 | - | ||
124 | // =========================================================== | 91 | // =========================================================== |
125 | // Fields | 92 | // Fields |
126 | // =========================================================== | 93 | // =========================================================== |
... | @@ -128,21 +95,12 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -128,21 +95,12 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
128 | private SQLiteDatabase mDb; | 95 | private SQLiteDatabase mDb; |
129 | private static WarplyDBHelper mDBHelperInstance; | 96 | private static WarplyDBHelper mDBHelperInstance; |
130 | 97 | ||
131 | - // Single-threaded executor for database operations | ||
132 | - private final ExecutorService dbExecutor = Executors.newSingleThreadExecutor(); | ||
133 | - | ||
134 | // =========================================================== | 98 | // =========================================================== |
135 | // Constructors | 99 | // Constructors |
136 | // =========================================================== | 100 | // =========================================================== |
137 | 101 | ||
138 | public static synchronized WarplyDBHelper getInstance(Context context) { | 102 | public static synchronized WarplyDBHelper getInstance(Context context) { |
139 | if (mDBHelperInstance == null) { | 103 | if (mDBHelperInstance == null) { |
140 | -// SQLiteDatabase.loadLibs(context); //old implementation | ||
141 | - SQLiteDatabase.loadLibs(context, libraries -> { | ||
142 | - for (String library : libraries) { | ||
143 | - ReLinker.loadLibrary(context, library); | ||
144 | - } | ||
145 | - }); | ||
146 | mDBHelperInstance = new WarplyDBHelper(context); | 104 | mDBHelperInstance = new WarplyDBHelper(context); |
147 | } | 105 | } |
148 | return mDBHelperInstance; | 106 | return mDBHelperInstance; |
... | @@ -150,141 +108,26 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -150,141 +108,26 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
150 | 108 | ||
151 | private WarplyDBHelper(Context context) { | 109 | private WarplyDBHelper(Context context) { |
152 | super(context, DB_NAME, null, DB_VERSION); | 110 | super(context, DB_NAME, null, DB_VERSION); |
153 | - State tempDatabaseState = getDatabaseState(context, DB_NAME); | ||
154 | - if (tempDatabaseState.equals(State.UNENCRYPTED)) { | ||
155 | - encrypt(context, context.getDatabasePath(DB_NAME), KEY_CIPHER.getBytes()); | ||
156 | - } | ||
157 | } | 111 | } |
158 | 112 | ||
159 | /** | 113 | /** |
160 | - * Gets a writable database connection on a background thread with timeout. | 114 | + * Get standard SQLite database connection |
161 | - * This prevents ANR issues by ensuring database operations don't block the main thread. | ||
162 | */ | 115 | */ |
163 | private SQLiteDatabase getDb() { | 116 | private SQLiteDatabase getDb() { |
164 | if (mDb == null || !mDb.isOpen()) { | 117 | if (mDb == null || !mDb.isOpen()) { |
165 | - try { | 118 | + mDb = getWritableDatabase(); |
166 | - // Submit task to executor and get future | ||
167 | - Future<SQLiteDatabase> future = dbExecutor.submit(() -> getWritableDatabase(KEY_CIPHER)); | ||
168 | - | ||
169 | - // Wait for result with timeout | ||
170 | - mDb = future.get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS); | ||
171 | - | ||
172 | - // Set busy timeout on the database connection | ||
173 | - if (mDb != null && mDb.isOpen()) { | ||
174 | - mDb.rawExecSQL("PRAGMA busy_timeout = " + CONNECTION_TIMEOUT_MS); | ||
175 | - } | ||
176 | - } catch (TimeoutException e) { | ||
177 | - Log.e("WarplyDBHelper", "Timeout getting writable database connection", e); | ||
178 | - // Return null or handle timeout as appropriate | ||
179 | - } catch (Exception e) { | ||
180 | - Log.e("WarplyDBHelper", "Error getting writable database connection", e); | ||
181 | - // Handle other exceptions | ||
182 | - } | ||
183 | - } | ||
184 | - return mDb; | ||
185 | - } | ||
186 | - | ||
187 | - /** | ||
188 | - * Gets a readable database connection on a background thread with timeout. | ||
189 | - * This prevents ANR issues by ensuring database operations don't block the main thread. | ||
190 | - */ | ||
191 | - private SQLiteDatabase getReadableDb() { | ||
192 | - if (mDb == null || !mDb.isOpen()) { | ||
193 | - try { | ||
194 | - // Submit task to executor and get future | ||
195 | - Future<SQLiteDatabase> future = dbExecutor.submit(() -> getReadableDatabase(KEY_CIPHER)); | ||
196 | - | ||
197 | - // Wait for result with timeout | ||
198 | - mDb = future.get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS); | ||
199 | - | ||
200 | - // Set busy timeout on the database connection | ||
201 | - if (mDb != null && mDb.isOpen()) { | ||
202 | - mDb.rawExecSQL("PRAGMA busy_timeout = " + CONNECTION_TIMEOUT_MS); | ||
203 | - } | ||
204 | - } catch (TimeoutException e) { | ||
205 | - Log.e("WarplyDBHelper", "Timeout getting readable database connection", e); | ||
206 | - // Return null or handle timeout as appropriate | ||
207 | - } catch (Exception e) { | ||
208 | - Log.e("WarplyDBHelper", "Error getting readable database connection", e); | ||
209 | - // Handle other exceptions | ||
210 | - } | ||
211 | } | 119 | } |
212 | return mDb; | 120 | return mDb; |
213 | } | 121 | } |
214 | 122 | ||
215 | - /** | ||
216 | - * Close database connection - should only be called when app is being destroyed | ||
217 | - * or when database won't be used for a long time | ||
218 | - */ | ||
219 | - private void closeDb() { | ||
220 | - if (mDb != null && mDb.isOpen()) { | ||
221 | - mDb.close(); | ||
222 | - mDb = null; | ||
223 | - } | ||
224 | - } | ||
225 | - | ||
226 | - /** | ||
227 | - * Initialize database connection on a background thread. | ||
228 | - * Call this during app startup to prevent ANR issues. | ||
229 | - */ | ||
230 | - public void initialize() { | ||
231 | - if (mDb == null || !mDb.isOpen()) { | ||
232 | - try { | ||
233 | - // Submit task to executor and get future | ||
234 | - Future<SQLiteDatabase> future = dbExecutor.submit(() -> getWritableDatabase(KEY_CIPHER)); | ||
235 | - | ||
236 | - // Wait for result with timeout | ||
237 | - mDb = future.get(CONNECTION_TIMEOUT_MS, TimeUnit.MILLISECONDS); | ||
238 | - | ||
239 | - // Set busy timeout on the database connection | ||
240 | - if (mDb != null && mDb.isOpen()) { | ||
241 | - mDb.rawExecSQL("PRAGMA busy_timeout = " + CONNECTION_TIMEOUT_MS); | ||
242 | - } | ||
243 | - } catch (TimeoutException e) { | ||
244 | - Log.e("WarplyDBHelper", "Timeout initializing database connection", e); | ||
245 | - } catch (Exception e) { | ||
246 | - Log.e("WarplyDBHelper", "Error initializing database connection", e); | ||
247 | - } | ||
248 | - } | ||
249 | - } | ||
250 | - | ||
251 | - /** | ||
252 | - * Shutdown database connection and executor service. | ||
253 | - * Call this when app is being destroyed. | ||
254 | - */ | ||
255 | - public void shutdown() { | ||
256 | - closeDb(); | ||
257 | - | ||
258 | - // Shutdown executor service | ||
259 | - dbExecutor.shutdown(); | ||
260 | - try { | ||
261 | - if (!dbExecutor.awaitTermination(5, TimeUnit.SECONDS)) { | ||
262 | - dbExecutor.shutdownNow(); | ||
263 | - } | ||
264 | - } catch (InterruptedException e) { | ||
265 | - dbExecutor.shutdownNow(); | ||
266 | - Thread.currentThread().interrupt(); | ||
267 | - } | ||
268 | - } | ||
269 | - | ||
270 | @Override | 123 | @Override |
271 | public void onCreate(SQLiteDatabase db) { | 124 | public void onCreate(SQLiteDatabase db) { |
272 | - // Create tables | ||
273 | db.execSQL(CREATE_TABLE_REQUESTS); | 125 | db.execSQL(CREATE_TABLE_REQUESTS); |
274 | db.execSQL(CREATE_TABLE_TAGS); | 126 | db.execSQL(CREATE_TABLE_TAGS); |
275 | db.execSQL(CREATE_TABLE_PUSH_REQUESTS); | 127 | db.execSQL(CREATE_TABLE_PUSH_REQUESTS); |
276 | db.execSQL(CREATE_TABLE_PUSH_ACK_REQUESTS); | 128 | db.execSQL(CREATE_TABLE_PUSH_ACK_REQUESTS); |
277 | db.execSQL(CREATE_TABLE_CLIENT); | 129 | db.execSQL(CREATE_TABLE_CLIENT); |
278 | db.execSQL(CREATE_TABLE_AUTH); | 130 | db.execSQL(CREATE_TABLE_AUTH); |
279 | - db.execSQL(CREATE_TABLE_TELEMATICS); | ||
280 | - | ||
281 | - // Create indexes for frequently queried columns to improve performance | ||
282 | - db.execSQL("CREATE INDEX IF NOT EXISTS idx_requests_force ON " + TABLE_REQUESTS + "(" + KEY_REQUESTS_FORCE + ")"); | ||
283 | - db.execSQL("CREATE INDEX IF NOT EXISTS idx_requests_date ON " + TABLE_REQUESTS + "(" + KEY_REQUESTS_DATE_ADDED + ")"); | ||
284 | - db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_requests_force ON " + TABLE_PUSH_REQUESTS + "(" + KEY_REQUESTS_FORCE + ")"); | ||
285 | - db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_requests_date ON " + TABLE_PUSH_REQUESTS + "(" + KEY_REQUESTS_DATE_ADDED + ")"); | ||
286 | - db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_ack_requests_force ON " + TABLE_PUSH_ACK_REQUESTS + "(" + KEY_REQUESTS_FORCE + ")"); | ||
287 | - db.execSQL("CREATE INDEX IF NOT EXISTS idx_push_ack_requests_date ON " + TABLE_PUSH_ACK_REQUESTS + "(" + KEY_REQUESTS_DATE_ADDED + ")"); | ||
288 | } | 131 | } |
289 | 132 | ||
290 | @Override | 133 | @Override |
... | @@ -297,7 +140,6 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -297,7 +140,6 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
297 | db.execSQL("drop table if exists " + TABLE_TAGS); | 140 | db.execSQL("drop table if exists " + TABLE_TAGS); |
298 | db.execSQL("drop table if exists " + TABLE_CLIENT); | 141 | db.execSQL("drop table if exists " + TABLE_CLIENT); |
299 | db.execSQL("drop table if exists " + TABLE_AUTH); | 142 | db.execSQL("drop table if exists " + TABLE_AUTH); |
300 | - db.execSQL("drop table if exists " + TABLE_TELEMATICS); | ||
301 | onCreate(db); | 143 | onCreate(db); |
302 | } | 144 | } |
303 | } | 145 | } |
... | @@ -310,7 +152,6 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -310,7 +152,6 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
310 | db.execSQL("drop table if exists " + TABLE_TAGS); | 152 | db.execSQL("drop table if exists " + TABLE_TAGS); |
311 | db.execSQL("drop table if exists " + TABLE_CLIENT); | 153 | db.execSQL("drop table if exists " + TABLE_CLIENT); |
312 | db.execSQL("drop table if exists " + TABLE_AUTH); | 154 | db.execSQL("drop table if exists " + TABLE_AUTH); |
313 | - db.execSQL("drop table if exists " + TABLE_TELEMATICS); | ||
314 | onCreate(db); | 155 | onCreate(db); |
315 | } | 156 | } |
316 | 157 | ||
... | @@ -337,45 +178,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -337,45 +178,36 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
337 | public synchronized void clearTable(String tableName) { | 178 | public synchronized void clearTable(String tableName) { |
338 | SQLiteDatabase db = getDb(); | 179 | SQLiteDatabase db = getDb(); |
339 | db.delete(tableName, null, null); | 180 | db.delete(tableName, null, null); |
340 | - // Don't close the database here to improve performance | ||
341 | } | 181 | } |
342 | 182 | ||
343 | public synchronized void insert(String tableName, ContentValues values) { | 183 | public synchronized void insert(String tableName, ContentValues values) { |
344 | SQLiteDatabase db = getDb(); | 184 | SQLiteDatabase db = getDb(); |
345 | db.insert(tableName, null, values); | 185 | db.insert(tableName, null, values); |
346 | - // Don't close the database here to improve performance | ||
347 | } | 186 | } |
348 | 187 | ||
349 | public synchronized void update(String tableName, ContentValues values) { | 188 | public synchronized void update(String tableName, ContentValues values) { |
350 | SQLiteDatabase db = getDb(); | 189 | SQLiteDatabase db = getDb(); |
351 | db.update(tableName, values, null, null); | 190 | db.update(tableName, values, null, null); |
352 | - // Don't close the database here to improve performance | ||
353 | } | 191 | } |
354 | 192 | ||
355 | public synchronized boolean isTableNotEmpty(String tableName) { | 193 | public synchronized boolean isTableNotEmpty(String tableName) { |
356 | - boolean isNotEmpty = false; | 194 | + Cursor cursor = getDb().rawQuery("SELECT COUNT(*) FROM " + tableName, |
357 | - Cursor cursor = null; | 195 | + null); |
358 | - try { | ||
359 | - cursor = getReadableDb().rawQuery("SELECT COUNT(*) FROM " + tableName, null); | ||
360 | if (cursor != null && cursor.moveToFirst()) { | 196 | if (cursor != null && cursor.moveToFirst()) { |
361 | - isNotEmpty = cursor.getInt(0) > 0; | 197 | + boolean isNotEmpty = cursor.getInt(0) > 0; |
362 | - } | ||
363 | - } finally { | ||
364 | - if (cursor != null) { | ||
365 | cursor.close(); | 198 | cursor.close(); |
366 | - } | ||
367 | - // Don't close the database here to improve performance | ||
368 | - } | ||
369 | return isNotEmpty; | 199 | return isNotEmpty; |
200 | + } else | ||
201 | + return false; | ||
370 | } | 202 | } |
371 | 203 | ||
372 | - //------------------------------ Auth -----------------------------// | 204 | + //------------------------------ Auth (with field-level encryption) -----------------------------// |
373 | public synchronized void saveClientAccess(String clientId, String clientSecret) { | 205 | public synchronized void saveClientAccess(String clientId, String clientSecret) { |
374 | ContentValues values = new ContentValues(); | 206 | ContentValues values = new ContentValues(); |
375 | if (!TextUtils.isEmpty(clientId)) | 207 | if (!TextUtils.isEmpty(clientId)) |
376 | - values.put(KEY_CLIENT_ID, clientId); | 208 | + values.put(KEY_CLIENT_ID, CryptoUtils.encrypt(clientId)); |
377 | if (!TextUtils.isEmpty(clientSecret)) | 209 | if (!TextUtils.isEmpty(clientSecret)) |
378 | - values.put(KEY_CLIENT_SECRET, clientSecret); | 210 | + values.put(KEY_CLIENT_SECRET, CryptoUtils.encrypt(clientSecret)); |
379 | if (isTableNotEmpty(TABLE_CLIENT)) | 211 | if (isTableNotEmpty(TABLE_CLIENT)) |
380 | update(TABLE_CLIENT, values); | 212 | update(TABLE_CLIENT, values); |
381 | else | 213 | else |
... | @@ -385,9 +217,9 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -385,9 +217,9 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
385 | public synchronized void saveAuthAccess(String accessToken, String refreshToken) { | 217 | public synchronized void saveAuthAccess(String accessToken, String refreshToken) { |
386 | ContentValues values = new ContentValues(); | 218 | ContentValues values = new ContentValues(); |
387 | if (!TextUtils.isEmpty(accessToken)) | 219 | if (!TextUtils.isEmpty(accessToken)) |
388 | - values.put(KEY_ACCESS_TOKEN, accessToken); | 220 | + values.put(KEY_ACCESS_TOKEN, CryptoUtils.encrypt(accessToken)); |
389 | if (!TextUtils.isEmpty(refreshToken)) | 221 | if (!TextUtils.isEmpty(refreshToken)) |
390 | - values.put(KEY_REFRESH_TOKEN, refreshToken); | 222 | + values.put(KEY_REFRESH_TOKEN, CryptoUtils.encrypt(refreshToken)); |
391 | if (isTableNotEmpty(TABLE_AUTH)) | 223 | if (isTableNotEmpty(TABLE_AUTH)) |
392 | update(TABLE_AUTH, values); | 224 | update(TABLE_AUTH, values); |
393 | else | 225 | else |
... | @@ -397,36 +229,24 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -397,36 +229,24 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
397 | @Nullable | 229 | @Nullable |
398 | public synchronized String getAuthValue(String columnName) { | 230 | public synchronized String getAuthValue(String columnName) { |
399 | String columnValue = ""; | 231 | String columnValue = ""; |
400 | - Cursor cursor = null; | 232 | + Cursor cursor = getDb().query(TABLE_AUTH, new String[]{columnName}, null, null, null, null, null); |
401 | - try { | ||
402 | - cursor = getReadableDb().query(TABLE_AUTH, new String[]{columnName}, null, null, null, null, null); | ||
403 | if (cursor != null && cursor.moveToFirst()) { | 233 | if (cursor != null && cursor.moveToFirst()) { |
404 | - columnValue = cursor.getString(cursor.getColumnIndex(columnName)); | 234 | + String encryptedValue = cursor.getString(cursor.getColumnIndex(columnName)); |
405 | - } | 235 | + columnValue = CryptoUtils.decrypt(encryptedValue); |
406 | - } finally { | ||
407 | - if (cursor != null) { | ||
408 | cursor.close(); | 236 | cursor.close(); |
409 | } | 237 | } |
410 | - // Don't close the database here to improve performance | ||
411 | - } | ||
412 | return columnValue; | 238 | return columnValue; |
413 | } | 239 | } |
414 | 240 | ||
415 | @Nullable | 241 | @Nullable |
416 | public synchronized String getClientValue(String columnName) { | 242 | public synchronized String getClientValue(String columnName) { |
417 | String columnValue = ""; | 243 | String columnValue = ""; |
418 | - Cursor cursor = null; | 244 | + Cursor cursor = getDb().query(TABLE_CLIENT, new String[]{columnName}, null, null, null, null, null); |
419 | - try { | ||
420 | - cursor = getReadableDb().query(TABLE_CLIENT, new String[]{columnName}, null, null, null, null, null); | ||
421 | if (cursor != null && cursor.moveToFirst()) { | 245 | if (cursor != null && cursor.moveToFirst()) { |
422 | - columnValue = cursor.getString(cursor.getColumnIndex(columnName)); | 246 | + String encryptedValue = cursor.getString(cursor.getColumnIndex(columnName)); |
423 | - } | 247 | + columnValue = CryptoUtils.decrypt(encryptedValue); |
424 | - } finally { | ||
425 | - if (cursor != null) { | ||
426 | cursor.close(); | 248 | cursor.close(); |
427 | } | 249 | } |
428 | - // Don't close the database here to improve performance | ||
429 | - } | ||
430 | return columnValue; | 250 | return columnValue; |
431 | } | 251 | } |
432 | 252 | ||
... | @@ -439,37 +259,25 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -439,37 +259,25 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
439 | } | 259 | } |
440 | 260 | ||
441 | //------------------------------ Api requests -----------------------------// | 261 | //------------------------------ Api requests -----------------------------// |
442 | - /** | ||
443 | - * Gets all requests from the database. | ||
444 | - * NOTE: The caller is responsible for closing the returned Cursor when done with it. | ||
445 | - */ | ||
446 | public synchronized Cursor getAllRequests() { | 262 | public synchronized Cursor getAllRequests() { |
447 | - // We don't close the database here because the cursor needs it to remain open | 263 | + |
448 | - return getReadableDb().query(TABLE_REQUESTS, | 264 | + return getDb().query(TABLE_REQUESTS, |
449 | new String[]{KEY_REQUESTS_ID, | 265 | new String[]{KEY_REQUESTS_ID, |
450 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, | 266 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, |
451 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); | 267 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); |
452 | } | 268 | } |
453 | 269 | ||
454 | - /** | ||
455 | - * Gets all push requests from the database. | ||
456 | - * NOTE: The caller is responsible for closing the returned Cursor when done with it. | ||
457 | - */ | ||
458 | public synchronized Cursor getAllPushRequests() { | 270 | public synchronized Cursor getAllPushRequests() { |
459 | - // We don't close the database here because the cursor needs it to remain open | 271 | + |
460 | - return getReadableDb().query(TABLE_PUSH_REQUESTS, | 272 | + return getDb().query(TABLE_PUSH_REQUESTS, |
461 | new String[]{KEY_REQUESTS_ID, | 273 | new String[]{KEY_REQUESTS_ID, |
462 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, | 274 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, |
463 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); | 275 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); |
464 | } | 276 | } |
465 | 277 | ||
466 | - /** | ||
467 | - * Gets all push acknowledgment requests from the database. | ||
468 | - * NOTE: The caller is responsible for closing the returned Cursor when done with it. | ||
469 | - */ | ||
470 | public synchronized Cursor getAllPushAckRequests() { | 278 | public synchronized Cursor getAllPushAckRequests() { |
471 | - // We don't close the database here because the cursor needs it to remain open | 279 | + |
472 | - return getReadableDb().query(TABLE_PUSH_ACK_REQUESTS, | 280 | + return getDb().query(TABLE_PUSH_ACK_REQUESTS, |
473 | new String[]{KEY_REQUESTS_ID, | 281 | new String[]{KEY_REQUESTS_ID, |
474 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, | 282 | KEY_REQUESTS_MICROAPP, KEY_REQUESTS_ENTITY}, null, null, null, null, |
475 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); | 283 | KEY_REQUESTS_DATE_ADDED + " asc", "20"); |
... | @@ -488,6 +296,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -488,6 +296,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
488 | } | 296 | } |
489 | 297 | ||
490 | public synchronized long addRequest(String microapp, String entity, boolean force) { | 298 | public synchronized long addRequest(String microapp, String entity, boolean force) { |
299 | + | ||
491 | ContentValues values = new ContentValues(); | 300 | ContentValues values = new ContentValues(); |
492 | values.put(KEY_REQUESTS_MICROAPP, microapp); | 301 | values.put(KEY_REQUESTS_MICROAPP, microapp); |
493 | values.put(KEY_REQUESTS_ENTITY, entity); | 302 | values.put(KEY_REQUESTS_ENTITY, entity); |
... | @@ -498,6 +307,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -498,6 +307,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
498 | } | 307 | } |
499 | 308 | ||
500 | public synchronized long addPushRequest(String microapp, String entity, boolean force) { | 309 | public synchronized long addPushRequest(String microapp, String entity, boolean force) { |
310 | + | ||
501 | ContentValues values = new ContentValues(); | 311 | ContentValues values = new ContentValues(); |
502 | values.put(KEY_REQUESTS_MICROAPP, microapp); | 312 | values.put(KEY_REQUESTS_MICROAPP, microapp); |
503 | values.put(KEY_REQUESTS_ENTITY, entity); | 313 | values.put(KEY_REQUESTS_ENTITY, entity); |
... | @@ -508,6 +318,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -508,6 +318,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
508 | } | 318 | } |
509 | 319 | ||
510 | public synchronized long addPushAckRequest(String microapp, String entity, boolean force) { | 320 | public synchronized long addPushAckRequest(String microapp, String entity, boolean force) { |
321 | + | ||
511 | ContentValues values = new ContentValues(); | 322 | ContentValues values = new ContentValues(); |
512 | values.put(KEY_REQUESTS_MICROAPP, microapp); | 323 | values.put(KEY_REQUESTS_MICROAPP, microapp); |
513 | values.put(KEY_REQUESTS_ENTITY, entity); | 324 | values.put(KEY_REQUESTS_ENTITY, entity); |
... | @@ -518,32 +329,19 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -518,32 +329,19 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
518 | } | 329 | } |
519 | 330 | ||
520 | public synchronized long getRequestsInQueueCount() { | 331 | public synchronized long getRequestsInQueueCount() { |
521 | - SQLiteDatabase db = getReadableDb(); | 332 | + return DatabaseUtils.queryNumEntries(getReadableDatabase(), TABLE_REQUESTS); |
522 | - long count = DatabaseUtils.queryNumEntries(db, TABLE_REQUESTS); | ||
523 | - // Don't close the database here to improve performance | ||
524 | - return count; | ||
525 | } | 333 | } |
526 | 334 | ||
527 | public synchronized long getPushRequestsInQueueCount() { | 335 | public synchronized long getPushRequestsInQueueCount() { |
528 | - SQLiteDatabase db = getReadableDb(); | 336 | + return DatabaseUtils.queryNumEntries(getReadableDatabase(), TABLE_PUSH_REQUESTS); |
529 | - long count = DatabaseUtils.queryNumEntries(db, TABLE_PUSH_REQUESTS); | ||
530 | - // Don't close the database here to improve performance | ||
531 | - return count; | ||
532 | } | 337 | } |
533 | 338 | ||
534 | public synchronized long getPushAckRequestsInQueueCount() { | 339 | public synchronized long getPushAckRequestsInQueueCount() { |
535 | - SQLiteDatabase db = getReadableDb(); | 340 | + return DatabaseUtils.queryNumEntries(getReadableDatabase(), TABLE_PUSH_ACK_REQUESTS); |
536 | - long count = DatabaseUtils.queryNumEntries(db, TABLE_PUSH_ACK_REQUESTS); | ||
537 | - // Don't close the database here to improve performance | ||
538 | - return count; | ||
539 | } | 341 | } |
540 | 342 | ||
541 | public synchronized void deleteRequests(Long... ids) { | 343 | public synchronized void deleteRequests(Long... ids) { |
542 | - if (ids.length == 0) return; | ||
543 | 344 | ||
544 | - SQLiteDatabase db = getDb(); | ||
545 | - try { | ||
546 | - db.beginTransaction(); | ||
547 | StringBuilder strFilter = new StringBuilder(); | 345 | StringBuilder strFilter = new StringBuilder(); |
548 | for (int i = 0; i < ids.length; i++) { | 346 | for (int i = 0; i < ids.length; i++) { |
549 | if (i > 0) { | 347 | if (i > 0) { |
... | @@ -553,20 +351,11 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -553,20 +351,11 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
553 | strFilter.append("="); | 351 | strFilter.append("="); |
554 | strFilter.append(ids[i]); | 352 | strFilter.append(ids[i]); |
555 | } | 353 | } |
556 | - db.delete(TABLE_REQUESTS, strFilter.toString(), null); | 354 | + getDb().delete(TABLE_REQUESTS, strFilter.toString(), null); |
557 | - db.setTransactionSuccessful(); | ||
558 | - } finally { | ||
559 | - db.endTransaction(); | ||
560 | - // Don't close the database here to improve performance | ||
561 | - } | ||
562 | } | 355 | } |
563 | 356 | ||
564 | public synchronized void deletePushRequests(Long... ids) { | 357 | public synchronized void deletePushRequests(Long... ids) { |
565 | - if (ids.length == 0) return; | ||
566 | 358 | ||
567 | - SQLiteDatabase db = getDb(); | ||
568 | - try { | ||
569 | - db.beginTransaction(); | ||
570 | StringBuilder strFilter = new StringBuilder(); | 359 | StringBuilder strFilter = new StringBuilder(); |
571 | for (int i = 0; i < ids.length; i++) { | 360 | for (int i = 0; i < ids.length; i++) { |
572 | if (i > 0) { | 361 | if (i > 0) { |
... | @@ -576,20 +365,11 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -576,20 +365,11 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
576 | strFilter.append("="); | 365 | strFilter.append("="); |
577 | strFilter.append(ids[i]); | 366 | strFilter.append(ids[i]); |
578 | } | 367 | } |
579 | - db.delete(TABLE_PUSH_REQUESTS, strFilter.toString(), null); | 368 | + getDb().delete(TABLE_PUSH_REQUESTS, strFilter.toString(), null); |
580 | - db.setTransactionSuccessful(); | ||
581 | - } finally { | ||
582 | - db.endTransaction(); | ||
583 | - // Don't close the database here to improve performance | ||
584 | - } | ||
585 | } | 369 | } |
586 | 370 | ||
587 | public synchronized void deletePushAckRequests(Long... ids) { | 371 | public synchronized void deletePushAckRequests(Long... ids) { |
588 | - if (ids.length == 0) return; | ||
589 | 372 | ||
590 | - SQLiteDatabase db = getDb(); | ||
591 | - try { | ||
592 | - db.beginTransaction(); | ||
593 | StringBuilder strFilter = new StringBuilder(); | 373 | StringBuilder strFilter = new StringBuilder(); |
594 | for (int i = 0; i < ids.length; i++) { | 374 | for (int i = 0; i < ids.length; i++) { |
595 | if (i > 0) { | 375 | if (i > 0) { |
... | @@ -599,127 +379,69 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -599,127 +379,69 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
599 | strFilter.append("="); | 379 | strFilter.append("="); |
600 | strFilter.append(ids[i]); | 380 | strFilter.append(ids[i]); |
601 | } | 381 | } |
602 | - db.delete(TABLE_PUSH_ACK_REQUESTS, strFilter.toString(), null); | 382 | + getDb().delete(TABLE_PUSH_ACK_REQUESTS, strFilter.toString(), null); |
603 | - db.setTransactionSuccessful(); | ||
604 | - } finally { | ||
605 | - db.endTransaction(); | ||
606 | - // Don't close the database here to improve performance | ||
607 | - } | ||
608 | } | 383 | } |
609 | 384 | ||
610 | public synchronized boolean isForceRequestsExist() { | 385 | public synchronized boolean isForceRequestsExist() { |
611 | - boolean result = false; | 386 | + Cursor cursor = getDb().query(TABLE_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", |
612 | - Cursor cursor = null; | ||
613 | - try { | ||
614 | - cursor = getReadableDb().query(TABLE_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", | ||
615 | null, null, null, null); | 387 | null, null, null, null); |
388 | + boolean result = false; | ||
616 | if (cursor != null) { | 389 | if (cursor != null) { |
617 | result = cursor.getCount() > 0; | 390 | result = cursor.getCount() > 0; |
618 | - } | ||
619 | - } finally { | ||
620 | - if (cursor != null) { | ||
621 | cursor.close(); | 391 | cursor.close(); |
622 | } | 392 | } |
623 | - // Don't close the database here to improve performance | ||
624 | - } | ||
625 | return result; | 393 | return result; |
626 | } | 394 | } |
627 | 395 | ||
628 | public synchronized boolean isForcePushRequestsExist() { | 396 | public synchronized boolean isForcePushRequestsExist() { |
629 | - boolean result = false; | 397 | + Cursor cursor = getDb().query(TABLE_PUSH_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", |
630 | - Cursor cursor = null; | ||
631 | - try { | ||
632 | - cursor = getReadableDb().query(TABLE_PUSH_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", | ||
633 | null, null, null, null); | 398 | null, null, null, null); |
399 | + boolean result = false; | ||
634 | if (cursor != null) { | 400 | if (cursor != null) { |
635 | result = cursor.getCount() > 0; | 401 | result = cursor.getCount() > 0; |
636 | - } | ||
637 | - } finally { | ||
638 | - if (cursor != null) { | ||
639 | cursor.close(); | 402 | cursor.close(); |
640 | } | 403 | } |
641 | - // Don't close the database here to improve performance | ||
642 | - } | ||
643 | return result; | 404 | return result; |
644 | } | 405 | } |
645 | 406 | ||
646 | public synchronized boolean isForcePushAckRequestsExist() { | 407 | public synchronized boolean isForcePushAckRequestsExist() { |
647 | - boolean result = false; | 408 | + Cursor cursor = getDb().query(TABLE_PUSH_ACK_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", |
648 | - Cursor cursor = null; | ||
649 | - try { | ||
650 | - cursor = getReadableDb().query(TABLE_PUSH_ACK_REQUESTS, null, KEY_REQUESTS_FORCE + "=1", | ||
651 | null, null, null, null); | 409 | null, null, null, null); |
410 | + boolean result = false; | ||
652 | if (cursor != null) { | 411 | if (cursor != null) { |
653 | result = cursor.getCount() > 0; | 412 | result = cursor.getCount() > 0; |
654 | - } | ||
655 | - } finally { | ||
656 | - if (cursor != null) { | ||
657 | cursor.close(); | 413 | cursor.close(); |
658 | } | 414 | } |
659 | - // Don't close the database here to improve performance | ||
660 | - } | ||
661 | return result; | 415 | return result; |
662 | } | 416 | } |
663 | 417 | ||
664 | //------------------------------ Tags -----------------------------// | 418 | //------------------------------ Tags -----------------------------// |
665 | public synchronized void saveTags(String[] tags) { | 419 | public synchronized void saveTags(String[] tags) { |
420 | + | ||
666 | if (tags != null && tags.length > 0) { | 421 | if (tags != null && tags.length > 0) { |
667 | - SQLiteDatabase db = getDb(); | 422 | + |
668 | try { | 423 | try { |
669 | - db.beginTransaction(); | 424 | + getDb().beginTransaction(); |
670 | ContentValues values = new ContentValues(); | 425 | ContentValues values = new ContentValues(); |
671 | for (String tag : tags) { | 426 | for (String tag : tags) { |
672 | - values.clear(); | ||
673 | values.put(KEY_TAG, tag); | 427 | values.put(KEY_TAG, tag); |
674 | values.put(KEY_TAG_LAST_ADD_DATE, System.currentTimeMillis()); | 428 | values.put(KEY_TAG_LAST_ADD_DATE, System.currentTimeMillis()); |
675 | - db.insert(TABLE_TAGS, null, values); | 429 | + insert(TABLE_TAGS, values); |
676 | } | 430 | } |
677 | - db.setTransactionSuccessful(); | 431 | + getDb().setTransactionSuccessful(); |
432 | + | ||
678 | } catch (SQLException e) { | 433 | } catch (SQLException e) { |
679 | if (WarpConstants.DEBUG) { | 434 | if (WarpConstants.DEBUG) { |
680 | e.printStackTrace(); | 435 | e.printStackTrace(); |
681 | } | 436 | } |
682 | } finally { | 437 | } finally { |
683 | - db.endTransaction(); | 438 | + getDb().endTransaction(); |
684 | - // Don't close the database here to improve performance | ||
685 | - } | ||
686 | - } | ||
687 | - } | ||
688 | - | ||
689 | - public synchronized void saveTelematics(JSONArray jsonArray) { | ||
690 | - if (jsonArray != null && jsonArray.length() > 0) { | ||
691 | - SQLiteDatabase db = getDb(); | ||
692 | - try { | ||
693 | - db.beginTransaction(); | ||
694 | - ContentValues values = new ContentValues(); | ||
695 | - for (int i = 0; i < jsonArray.length(); i++) { | ||
696 | - JSONObject jsonobject = jsonArray.optJSONObject(i); | ||
697 | - if (jsonobject != null) { | ||
698 | - values.clear(); | ||
699 | - String timestamp = jsonobject.keys().next(); | ||
700 | - values.put(KEY_TIMESTAMP, timestamp); | ||
701 | - JSONObject jobjData = jsonobject.optJSONObject(timestamp); | ||
702 | - if (jobjData != null) { | ||
703 | - values.put(KEY_ACCELERATION, jobjData.optDouble(KEY_ACCELERATION)); | ||
704 | - values.put(KEY_SPEED, jobjData.optDouble(KEY_SPEED)); | ||
705 | - } | ||
706 | - db.insert(TABLE_TELEMATICS, null, values); | ||
707 | - } | ||
708 | - } | ||
709 | - db.setTransactionSuccessful(); | ||
710 | - } finally { | ||
711 | - db.endTransaction(); | ||
712 | - // Don't close the database here to improve performance | ||
713 | } | 439 | } |
714 | } | 440 | } |
715 | } | 441 | } |
716 | 442 | ||
717 | public synchronized void removeTags(String[] tags) { | 443 | public synchronized void removeTags(String[] tags) { |
718 | - if (tags.length == 0) return; | ||
719 | 444 | ||
720 | - SQLiteDatabase db = getDb(); | ||
721 | - try { | ||
722 | - db.beginTransaction(); | ||
723 | StringBuilder strFilter = new StringBuilder(); | 445 | StringBuilder strFilter = new StringBuilder(); |
724 | for (int i = 0; i < tags.length; i++) { | 446 | for (int i = 0; i < tags.length; i++) { |
725 | if (i > 0) { | 447 | if (i > 0) { |
... | @@ -731,12 +453,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -731,12 +453,7 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
731 | strFilter.append(tags[i]); | 453 | strFilter.append(tags[i]); |
732 | strFilter.append("'"); | 454 | strFilter.append("'"); |
733 | } | 455 | } |
734 | - db.delete(TABLE_TAGS, strFilter.toString(), null); | 456 | + getDb().delete(TABLE_TAGS, strFilter.toString(), null); |
735 | - db.setTransactionSuccessful(); | ||
736 | - } finally { | ||
737 | - db.endTransaction(); | ||
738 | - // Don't close the database here to improve performance | ||
739 | - } | ||
740 | } | 457 | } |
741 | 458 | ||
742 | public synchronized void removeAllTags() { | 459 | public synchronized void removeAllTags() { |
... | @@ -745,84 +462,18 @@ public class WarplyDBHelper extends SQLiteOpenHelper { | ... | @@ -745,84 +462,18 @@ public class WarplyDBHelper extends SQLiteOpenHelper { |
745 | 462 | ||
746 | @Nullable | 463 | @Nullable |
747 | public synchronized String[] getTags() { | 464 | public synchronized String[] getTags() { |
465 | + | ||
748 | List<String> tags = null; | 466 | List<String> tags = null; |
749 | - Cursor cursor = null; | 467 | + Cursor cursor = getDb().query(TABLE_TAGS, null, null, null, null, null, null); |
750 | - try { | ||
751 | - cursor = getReadableDb().query(TABLE_TAGS, null, null, null, null, null, null); | ||
752 | if (cursor != null) { | 468 | if (cursor != null) { |
469 | + | ||
753 | tags = new ArrayList<>(cursor.getCount()); | 470 | tags = new ArrayList<>(cursor.getCount()); |
754 | while (cursor.moveToNext()) { | 471 | while (cursor.moveToNext()) { |
755 | tags.add(cursor.getString(cursor.getColumnIndex(KEY_TAG))); | 472 | tags.add(cursor.getString(cursor.getColumnIndex(KEY_TAG))); |
756 | } | 473 | } |
757 | - } | ||
758 | - } finally { | ||
759 | - if (cursor != null) { | ||
760 | cursor.close(); | 474 | cursor.close(); |
761 | } | 475 | } |
762 | - // Don't close the database here to improve performance | ||
763 | - } | ||
764 | return tags != null ? tags.toArray(new String[tags.size()]) : null; | 476 | return tags != null ? tags.toArray(new String[tags.size()]) : null; |
765 | } | 477 | } |
766 | 478 | ||
767 | - private State getDatabaseState(Context context, String dbName) { | ||
768 | - SQLiteDatabase.loadLibs(context); | ||
769 | - | ||
770 | - return (getDatabaseState(context.getDatabasePath(dbName))); | ||
771 | - } | ||
772 | - | ||
773 | - private static State getDatabaseState(File dbPath) { | ||
774 | - if (dbPath.exists()) { | ||
775 | - SQLiteDatabase db = null; | ||
776 | - try { | ||
777 | - db = SQLiteDatabase.openDatabase(dbPath.getAbsolutePath(), "", null, SQLiteDatabase.OPEN_READONLY); | ||
778 | - db.getVersion(); | ||
779 | - | ||
780 | - return (State.UNENCRYPTED); | ||
781 | - } catch (Exception e) { | ||
782 | - return (State.ENCRYPTED); | ||
783 | - } finally { | ||
784 | - if (db != null) { | ||
785 | - db.close(); | ||
786 | - } | ||
787 | - } | ||
788 | - } | ||
789 | - | ||
790 | - return (State.DOES_NOT_EXIST); | ||
791 | - } | ||
792 | - | ||
793 | - private void encrypt(Context context, File originalFile, byte[] passphrase) { | ||
794 | - SQLiteDatabase.loadLibs(context); | ||
795 | - | ||
796 | - try { | ||
797 | - if (originalFile.exists()) { | ||
798 | - File newFile = File.createTempFile("sqlcipherutils", "tmp", context.getCacheDir()); | ||
799 | - SQLiteDatabase db = SQLiteDatabase.openDatabase(originalFile.getAbsolutePath(), | ||
800 | - "", null, SQLiteDatabase.OPEN_READWRITE); | ||
801 | - int version = db.getVersion(); | ||
802 | - | ||
803 | - db.close(); | ||
804 | - | ||
805 | - db = SQLiteDatabase.openDatabase(newFile.getAbsolutePath(), passphrase, | ||
806 | - null, SQLiteDatabase.OPEN_READWRITE, null, null); | ||
807 | - | ||
808 | - final SQLiteStatement st = db.compileStatement("ATTACH DATABASE ? AS plaintext KEY ''"); | ||
809 | - | ||
810 | - st.bindString(1, originalFile.getAbsolutePath()); | ||
811 | - st.execute(); | ||
812 | - | ||
813 | - db.rawExecSQL("SELECT sqlcipher_export('main', 'plaintext')"); | ||
814 | - db.rawExecSQL("DETACH DATABASE plaintext"); | ||
815 | - db.setVersion(version); | ||
816 | - st.close(); | ||
817 | - db.close(); | ||
818 | - | ||
819 | - originalFile.delete(); | ||
820 | - newFile.renameTo(originalFile); | ||
821 | - } else { | ||
822 | - throw new FileNotFoundException(originalFile.getAbsolutePath() + " not found"); | ||
823 | - } | ||
824 | - } catch (IOException ex) { | ||
825 | - Log.v("WarplyDB Exception: ", ex.getMessage()); | ||
826 | - } | ||
827 | - } | ||
828 | } | 479 | } | ... | ... |
... | @@ -14,26 +14,19 @@ import android.widget.Toast; | ... | @@ -14,26 +14,19 @@ import android.widget.Toast; |
14 | 14 | ||
15 | import androidx.annotation.NonNull; | 15 | import androidx.annotation.NonNull; |
16 | import androidx.fragment.app.Fragment; | 16 | import androidx.fragment.app.Fragment; |
17 | -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; | ||
18 | 17 | ||
19 | import org.json.JSONObject; | 18 | import org.json.JSONObject; |
20 | 19 | ||
21 | -import java.util.ArrayList; | ||
22 | - | ||
23 | import ly.warp.sdk.R; | 20 | import ly.warp.sdk.R; |
24 | import ly.warp.sdk.activities.HomeActivity; | 21 | import ly.warp.sdk.activities.HomeActivity; |
25 | import ly.warp.sdk.db.WarplyDBHelper; | 22 | import ly.warp.sdk.db.WarplyDBHelper; |
26 | import ly.warp.sdk.io.callbacks.CallbackReceiver; | 23 | import ly.warp.sdk.io.callbacks.CallbackReceiver; |
27 | -import ly.warp.sdk.io.models.Campaign; | ||
28 | -import ly.warp.sdk.io.models.RedeemedSMHistoryModel; | ||
29 | import ly.warp.sdk.utils.WarplyManagerHelper; | 24 | import ly.warp.sdk.utils.WarplyManagerHelper; |
30 | import ly.warp.sdk.utils.managers.WarplyManager; | 25 | import ly.warp.sdk.utils.managers.WarplyManager; |
31 | 26 | ||
32 | -public class HomeFragment extends Fragment implements View.OnClickListener, SwipeRefreshLayout.OnRefreshListener { | 27 | +public class HomeFragment extends Fragment implements View.OnClickListener { |
33 | - | ||
34 | private RelativeLayout mOptionOne, mOptionTwo, mOptionThree, mPbLoading; | 28 | private RelativeLayout mOptionOne, mOptionTwo, mOptionThree, mPbLoading; |
35 | private TextView mTvUsername, mTvUser; | 29 | private TextView mTvUsername, mTvUser; |
36 | - private SwipeRefreshLayout mSwipeRefresh; | ||
37 | private EditText mEtGuid; | 30 | private EditText mEtGuid; |
38 | private LinearLayout mLlAuthLogin, mLlAuthLogout, mRlSmFlow, mRlSmMap; | 31 | private LinearLayout mLlAuthLogin, mLlAuthLogout, mRlSmFlow, mRlSmMap; |
39 | 32 | ||
... | @@ -45,8 +38,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip | ... | @@ -45,8 +38,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip |
45 | public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { | 38 | public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { |
46 | super.onViewCreated(view, savedInstanceState); | 39 | super.onViewCreated(view, savedInstanceState); |
47 | 40 | ||
48 | - mSwipeRefresh = view.findViewById(R.id.sw_refresh); | ||
49 | - mSwipeRefresh.setOnRefreshListener(this); | ||
50 | mOptionOne = view.findViewById(R.id.info_button); | 41 | mOptionOne = view.findViewById(R.id.info_button); |
51 | TextView mOptionOneText = mOptionOne.findViewById(R.id.option_text); | 42 | TextView mOptionOneText = mOptionOne.findViewById(R.id.option_text); |
52 | ImageView mOptionOneImage = mOptionOne.findViewById(R.id.option_icon); | 43 | ImageView mOptionOneImage = mOptionOne.findViewById(R.id.option_icon); |
... | @@ -100,17 +91,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip | ... | @@ -100,17 +91,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip |
100 | } | 91 | } |
101 | 92 | ||
102 | @Override | 93 | @Override |
103 | - public void onRefresh() { | ||
104 | - if (WarplyDBHelper.getInstance(getActivity()).isTableNotEmpty("auth")) { | ||
105 | - WarplyManager.getSupermarketCampaign(mCampaignsCallback); | ||
106 | - WarplyManager.getRedeemedSMHistory(mSMHistoryReceiver); | ||
107 | - mSwipeRefresh.setRefreshing(false); | ||
108 | - } else { | ||
109 | - mSwipeRefresh.setRefreshing(false); | ||
110 | - } | ||
111 | - } | ||
112 | - | ||
113 | - @Override | ||
114 | public void onClick(View view) { | 94 | public void onClick(View view) { |
115 | if (view.getId() == R.id.ll_auth_login) { | 95 | if (view.getId() == R.id.ll_auth_login) { |
116 | //6012049321, 6012049322, 6012049323, 7000000831 history, 7000000826, 7000000831 shared coupons | 96 | //6012049321, 6012049322, 6012049323, 7000000831 history, 7000000826, 7000000831 shared coupons |
... | @@ -141,18 +121,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip | ... | @@ -141,18 +121,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip |
141 | return homeFragment; | 121 | return homeFragment; |
142 | } | 122 | } |
143 | 123 | ||
144 | - private final CallbackReceiver<ArrayList<Campaign>> mCampaignsCallback = new CallbackReceiver<ArrayList<Campaign>>() { | ||
145 | - @Override | ||
146 | - public void onSuccess(ArrayList<Campaign> result) { | ||
147 | - Toast.makeText(getActivity(), "Campaigns Success", Toast.LENGTH_SHORT).show(); | ||
148 | - } | ||
149 | - | ||
150 | - @Override | ||
151 | - public void onFailure(int errorCode) { | ||
152 | - Toast.makeText(getActivity(), "Campaigns Error", Toast.LENGTH_SHORT).show(); | ||
153 | - } | ||
154 | - }; | ||
155 | - | ||
156 | private final CallbackReceiver<JSONObject> mLogoutReceiver = new CallbackReceiver<JSONObject>() { | 124 | private final CallbackReceiver<JSONObject> mLogoutReceiver = new CallbackReceiver<JSONObject>() { |
157 | @Override | 125 | @Override |
158 | public void onSuccess(JSONObject result) { | 126 | public void onSuccess(JSONObject result) { |
... | @@ -180,16 +148,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip | ... | @@ -180,16 +148,6 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip |
180 | mLlAuthLogout.setVisibility(View.VISIBLE); | 148 | mLlAuthLogout.setVisibility(View.VISIBLE); |
181 | mTvUser.setVisibility(View.VISIBLE); | 149 | mTvUser.setVisibility(View.VISIBLE); |
182 | mTvUser.setText(mEtGuid.getText().toString()); | 150 | mTvUser.setText(mEtGuid.getText().toString()); |
183 | -// if (WarplyManagerHelper.getConsumerInternal() != null) { | ||
184 | -// JSONObject profMetadata = WarpJSONParser.getJSONFromString(WarplyManagerHelper.getConsumerInternal().getProfileMetadata()); | ||
185 | -// if (profMetadata != null && profMetadata.has("guid")) { | ||
186 | -// String userGuid = profMetadata.optString("guid", ""); | ||
187 | -// mTvUser.setText(userGuid); | ||
188 | -// } | ||
189 | -// } | ||
190 | - | ||
191 | - WarplyManager.getSupermarketCampaign(mCampaignsCallback); | ||
192 | - WarplyManager.getRedeemedSMHistory(mSMHistoryReceiver); | ||
193 | } | 151 | } |
194 | 152 | ||
195 | @Override | 153 | @Override |
... | @@ -198,16 +156,4 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip | ... | @@ -198,16 +156,4 @@ public class HomeFragment extends Fragment implements View.OnClickListener, Swip |
198 | Toast.makeText(getActivity(), "LOGIN ERROR", Toast.LENGTH_SHORT).show(); | 156 | Toast.makeText(getActivity(), "LOGIN ERROR", Toast.LENGTH_SHORT).show(); |
199 | } | 157 | } |
200 | }; | 158 | }; |
201 | - | ||
202 | - private final CallbackReceiver<RedeemedSMHistoryModel> mSMHistoryReceiver = new CallbackReceiver<RedeemedSMHistoryModel>() { | ||
203 | - @Override | ||
204 | - public void onSuccess(RedeemedSMHistoryModel result) { | ||
205 | - Toast.makeText(getActivity(), "SM HISTORY SUCCESS", Toast.LENGTH_SHORT).show(); | ||
206 | - } | ||
207 | - | ||
208 | - @Override | ||
209 | - public void onFailure(int errorCode) { | ||
210 | - Toast.makeText(getActivity(), "SM HISTORY ERROR", Toast.LENGTH_SHORT).show(); | ||
211 | - } | ||
212 | - }; | ||
213 | } | 159 | } |
... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
warply_android_sdk/src/main/java/ly/warp/sdk/io/models/MarketPassDetailsModel.java
deleted
100644 → 0
1 | -/* | ||
2 | - * Copyright 2010-2013 Warply Ltd. All rights reserved. | ||
3 | - * | ||
4 | - * Redistribution and use in source and binary forms, without modification, are | ||
5 | - * permitted provided that the following conditions are met: | ||
6 | - * | ||
7 | - * 1. Redistributions of source code must retain the above copyright notice, | ||
8 | - * this list of conditions and the following disclaimer. | ||
9 | - * | ||
10 | - * 2. Redistributions in binary form must reproduce the above copyright notice, | ||
11 | - * this list of conditions and the following disclaimer in the documentation | ||
12 | - * and/or other materials provided with the distribution. | ||
13 | - * | ||
14 | - * THIS SOFTWARE IS PROVIDED BY THE WARPLY LTD ``AS IS'' AND ANY EXPRESS OR | ||
15 | - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
16 | - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO | ||
17 | - * EVENT SHALL WARPLY LTD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
18 | - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
19 | - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, | ||
20 | - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
21 | - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
22 | - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | ||
23 | - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
24 | - */ | ||
25 | - | ||
26 | -package ly.warp.sdk.io.models; | ||
27 | - | ||
28 | -import org.json.JSONArray; | ||
29 | -import org.json.JSONException; | ||
30 | -import org.json.JSONObject; | ||
31 | - | ||
32 | -import java.util.ArrayList; | ||
33 | - | ||
34 | -import ly.warp.sdk.utils.WarpUtils; | ||
35 | -import ly.warp.sdk.utils.constants.WarpConstants; | ||
36 | - | ||
37 | -/** | ||
38 | - * Created by Panagiotis Triantafyllou on 20-Jan-25. | ||
39 | - */ | ||
40 | - | ||
41 | -public class MarketPassDetailsModel { | ||
42 | - private static final String BARCODE = "barcode"; | ||
43 | - private static final String SUPERMARKETS = "supermarkets"; | ||
44 | - private static final String TOTAL_DISCOUNT = "total_available_discount"; | ||
45 | - private static final String NEW_OFFERS = "new_offers"; | ||
46 | - | ||
47 | - private ArrayList<Supermarkets> supermarkets = new ArrayList<Supermarkets>(); | ||
48 | - private String barcode = ""; | ||
49 | - private double totalDiscount = 0.0d; | ||
50 | - private int newOffers = 0; | ||
51 | - | ||
52 | - public MarketPassDetailsModel() { | ||
53 | - this.supermarkets = new ArrayList<Supermarkets>(); | ||
54 | - this.barcode = ""; | ||
55 | - this.totalDiscount = 0.0d; | ||
56 | - this.newOffers = 0; | ||
57 | - } | ||
58 | - | ||
59 | - /** | ||
60 | - * Basic constructor used to create an object from a String, representing a | ||
61 | - * JSON Object | ||
62 | - * | ||
63 | - * @param json The String, representing the JSON Object | ||
64 | - * @throws JSONException Thrown if the String cannot be converted to JSON | ||
65 | - */ | ||
66 | - public MarketPassDetailsModel(String json) throws JSONException { | ||
67 | - this(new JSONObject(json)); | ||
68 | - } | ||
69 | - | ||
70 | - /** | ||
71 | - * Constructor used to create an Object from a given JSON Object | ||
72 | - * | ||
73 | - * @param json JSON Object used to create the Campaign | ||
74 | - */ | ||
75 | - public MarketPassDetailsModel(JSONObject json) { | ||
76 | - if (json != null) { | ||
77 | - if (json.optJSONArray(SUPERMARKETS) != null) { | ||
78 | - JSONArray tempSupermarkets = json.optJSONArray(SUPERMARKETS); | ||
79 | - if (tempSupermarkets != null && tempSupermarkets.length() > 0) { | ||
80 | - for (int i = 0, lim = tempSupermarkets.length(); i < lim; ++i) { | ||
81 | - this.supermarkets.add(new Supermarkets(tempSupermarkets.optJSONObject(i))); | ||
82 | - } | ||
83 | - } | ||
84 | - } | ||
85 | - this.barcode = json.isNull(BARCODE) ? "" : json.optString(BARCODE); | ||
86 | - this.totalDiscount = json.optDouble(TOTAL_DISCOUNT); | ||
87 | - this.newOffers = json.optInt(NEW_OFFERS); | ||
88 | - } | ||
89 | - } | ||
90 | - | ||
91 | - /** | ||
92 | - * Converts the Campaign into a JSON Object | ||
93 | - * | ||
94 | - * @return The JSON Object created from this campaign | ||
95 | - */ | ||
96 | - public JSONObject toJSONObject() { | ||
97 | - JSONObject jObj = new JSONObject(); | ||
98 | - try { | ||
99 | - jObj.putOpt(BARCODE, this.barcode); | ||
100 | - jObj.putOpt(TOTAL_DISCOUNT, this.totalDiscount); | ||
101 | - jObj.putOpt(SUPERMARKETS, this.supermarkets); | ||
102 | - jObj.putOpt(NEW_OFFERS, this.newOffers); | ||
103 | - } catch (JSONException e) { | ||
104 | - if (WarpConstants.DEBUG) { | ||
105 | - e.printStackTrace(); | ||
106 | - } | ||
107 | - } | ||
108 | - return jObj; | ||
109 | - } | ||
110 | - | ||
111 | - /** | ||
112 | - * String representation of the Campaign, as a JSON object | ||
113 | - * | ||
114 | - * @return A String representation of JSON object | ||
115 | - */ | ||
116 | - public String toString() { | ||
117 | - if (toJSONObject() != null) | ||
118 | - return toJSONObject().toString(); | ||
119 | - return null; | ||
120 | - } | ||
121 | - | ||
122 | - /** | ||
123 | - * String representation of the Campaign, as a human readable JSON object | ||
124 | - * | ||
125 | - * @return A human readable String representation of JSON object | ||
126 | - */ | ||
127 | - public String toHumanReadableString() { | ||
128 | - String humanReadableString = null; | ||
129 | - try { | ||
130 | - humanReadableString = toJSONObject().toString(2); | ||
131 | - } catch (JSONException e) { | ||
132 | - WarpUtils.warn("Failed converting Campaign JSON object to String", | ||
133 | - e); | ||
134 | - } | ||
135 | - return humanReadableString; | ||
136 | - } | ||
137 | - | ||
138 | - public class Supermarkets { | ||
139 | - private static final String LOGO = "logo"; | ||
140 | - private static final String NAME = "name"; | ||
141 | - private static final String UUID = "uuid"; | ||
142 | - | ||
143 | - | ||
144 | - private String logo = ""; | ||
145 | - private String name = ""; | ||
146 | - private String uuid = ""; | ||
147 | - | ||
148 | - public Supermarkets() { | ||
149 | - this.logo = ""; | ||
150 | - this.name = ""; | ||
151 | - this.uuid = ""; | ||
152 | - } | ||
153 | - | ||
154 | - public Supermarkets(JSONObject json) { | ||
155 | - if (json != null) { | ||
156 | - this.logo = json.isNull(LOGO) ? "" : json.optString(LOGO); | ||
157 | - this.name = json.isNull(NAME) ? "" : json.optString(NAME); | ||
158 | - this.uuid = json.isNull(UUID) ? "" : json.optString(UUID); | ||
159 | - } | ||
160 | - } | ||
161 | - | ||
162 | - public String getLogo() { | ||
163 | - return logo; | ||
164 | - } | ||
165 | - | ||
166 | - public void setLogo(String logo) { | ||
167 | - this.logo = logo; | ||
168 | - } | ||
169 | - | ||
170 | - public String getName() { | ||
171 | - return name; | ||
172 | - } | ||
173 | - | ||
174 | - public void setName(String name) { | ||
175 | - this.name = name; | ||
176 | - } | ||
177 | - | ||
178 | - public String getUuid() { | ||
179 | - return uuid; | ||
180 | - } | ||
181 | - | ||
182 | - public void setUuid(String uuid) { | ||
183 | - this.uuid = uuid; | ||
184 | - } | ||
185 | - } | ||
186 | - | ||
187 | - // ================================================================================ | ||
188 | - // Getters | ||
189 | - // ================================================================================ | ||
190 | - | ||
191 | - | ||
192 | - public ArrayList<Supermarkets> getSupermarkets() { | ||
193 | - return supermarkets; | ||
194 | - } | ||
195 | - | ||
196 | - public void setSupermarkets(ArrayList<Supermarkets> supermarkets) { | ||
197 | - this.supermarkets = supermarkets; | ||
198 | - } | ||
199 | - | ||
200 | - public String getBarcode() { | ||
201 | - return barcode; | ||
202 | - } | ||
203 | - | ||
204 | - public void setBarcode(String barcode) { | ||
205 | - this.barcode = barcode; | ||
206 | - } | ||
207 | - | ||
208 | - public double getTotalDiscount() { | ||
209 | - return totalDiscount; | ||
210 | - } | ||
211 | - | ||
212 | - public void setTotalDiscount(double totalDiscount) { | ||
213 | - this.totalDiscount = totalDiscount; | ||
214 | - } | ||
215 | - | ||
216 | - public int getNewOffers() { | ||
217 | - return newOffers; | ||
218 | - } | ||
219 | - | ||
220 | - public void setNewOffers(int newOffers) { | ||
221 | - this.newOffers = newOffers; | ||
222 | - } | ||
223 | -} |
1 | +package ly.warp.sdk.utils; | ||
2 | + | ||
3 | +import android.security.keystore.KeyGenParameterSpec; | ||
4 | +import android.security.keystore.KeyProperties; | ||
5 | +import android.util.Base64; | ||
6 | +import android.util.Log; | ||
7 | + | ||
8 | +import java.security.KeyStore; | ||
9 | + | ||
10 | +import javax.crypto.Cipher; | ||
11 | +import javax.crypto.KeyGenerator; | ||
12 | +import javax.crypto.SecretKey; | ||
13 | +import javax.crypto.spec.GCMParameterSpec; | ||
14 | + | ||
15 | +/** | ||
16 | + * Utility class for encrypting and decrypting sensitive data using Android Keystore | ||
17 | + */ | ||
18 | +public class CryptoUtils { | ||
19 | + | ||
20 | + private static final String TAG = "CryptoUtils"; | ||
21 | + private static final String TRANSFORMATION = "AES/GCM/NoPadding"; | ||
22 | + private static final String ANDROID_KEYSTORE = "AndroidKeyStore"; | ||
23 | + private static final String KEY_ALIAS = "tn#mpOl3v3Dy1pr@W"; | ||
24 | + private static final int GCM_IV_LENGTH = 12; | ||
25 | + private static final int GCM_TAG_LENGTH = 16; | ||
26 | + | ||
27 | + /** | ||
28 | + * Encrypt a plain text string | ||
29 | + * | ||
30 | + * @param plainText The text to encrypt | ||
31 | + * @return Base64 encoded encrypted string, or original text if encryption fails | ||
32 | + */ | ||
33 | + public static String encrypt(String plainText) { | ||
34 | + if (plainText == null || plainText.isEmpty()) { | ||
35 | + return plainText; | ||
36 | + } | ||
37 | + | ||
38 | + try { | ||
39 | + SecretKey secretKey = getOrCreateSecretKey(); | ||
40 | + Cipher cipher = Cipher.getInstance(TRANSFORMATION); | ||
41 | + cipher.init(Cipher.ENCRYPT_MODE, secretKey); | ||
42 | + | ||
43 | + byte[] iv = cipher.getIV(); | ||
44 | + byte[] encryptedData = cipher.doFinal(plainText.getBytes("UTF-8")); | ||
45 | + | ||
46 | + // Combine IV + encrypted data | ||
47 | + byte[] combined = new byte[iv.length + encryptedData.length]; | ||
48 | + System.arraycopy(iv, 0, combined, 0, iv.length); | ||
49 | + System.arraycopy(encryptedData, 0, combined, iv.length, encryptedData.length); | ||
50 | + | ||
51 | + return Base64.encodeToString(combined, Base64.DEFAULT); | ||
52 | + } catch (Exception e) { | ||
53 | + Log.e(TAG, "Encryption failed, returning original text", e); | ||
54 | + // Return original text if encryption fails - graceful degradation | ||
55 | + return plainText; | ||
56 | + } | ||
57 | + } | ||
58 | + | ||
59 | + /** | ||
60 | + * Decrypt an encrypted string | ||
61 | + * | ||
62 | + * @param encryptedText The Base64 encoded encrypted text | ||
63 | + * @return Decrypted plain text, or original text if decryption fails | ||
64 | + */ | ||
65 | + public static String decrypt(String encryptedText) { | ||
66 | + if (encryptedText == null || encryptedText.isEmpty()) { | ||
67 | + return encryptedText; | ||
68 | + } | ||
69 | + | ||
70 | + try { | ||
71 | + SecretKey secretKey = getOrCreateSecretKey(); | ||
72 | + byte[] combined = Base64.decode(encryptedText, Base64.DEFAULT); | ||
73 | + | ||
74 | + // Extract IV and encrypted data | ||
75 | + byte[] iv = new byte[GCM_IV_LENGTH]; | ||
76 | + byte[] encryptedData = new byte[combined.length - GCM_IV_LENGTH]; | ||
77 | + System.arraycopy(combined, 0, iv, 0, GCM_IV_LENGTH); | ||
78 | + System.arraycopy(combined, GCM_IV_LENGTH, encryptedData, 0, encryptedData.length); | ||
79 | + | ||
80 | + Cipher cipher = Cipher.getInstance(TRANSFORMATION); | ||
81 | + GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, iv); | ||
82 | + cipher.init(Cipher.DECRYPT_MODE, secretKey, spec); | ||
83 | + | ||
84 | + byte[] decryptedData = cipher.doFinal(encryptedData); | ||
85 | + return new String(decryptedData, "UTF-8"); | ||
86 | + } catch (Exception e) { | ||
87 | + Log.e(TAG, "Decryption failed, returning original text", e); | ||
88 | + // Return original text if decryption fails - might be unencrypted legacy data | ||
89 | + return encryptedText; | ||
90 | + } | ||
91 | + } | ||
92 | + | ||
93 | + /** | ||
94 | + * Get or create the secret key in Android Keystore | ||
95 | + */ | ||
96 | + private static SecretKey getOrCreateSecretKey() throws Exception { | ||
97 | + KeyStore keyStore = KeyStore.getInstance(ANDROID_KEYSTORE); | ||
98 | + keyStore.load(null); | ||
99 | + | ||
100 | + if (!keyStore.containsAlias(KEY_ALIAS)) { | ||
101 | + KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, ANDROID_KEYSTORE); | ||
102 | + KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(KEY_ALIAS, | ||
103 | + KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) | ||
104 | + .setBlockModes(KeyProperties.BLOCK_MODE_GCM) | ||
105 | + .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE) | ||
106 | + .setRandomizedEncryptionRequired(true) | ||
107 | + .build(); | ||
108 | + keyGenerator.init(keyGenParameterSpec); | ||
109 | + keyGenerator.generateKey(); | ||
110 | + } | ||
111 | + | ||
112 | + return ((KeyStore.SecretKeyEntry) keyStore.getEntry(KEY_ALIAS, null)).getSecretKey(); | ||
113 | + } | ||
114 | + | ||
115 | + /** | ||
116 | + * Check if a string appears to be encrypted (Base64 format) | ||
117 | + * | ||
118 | + * @param text The text to check | ||
119 | + * @return true if text appears to be encrypted | ||
120 | + */ | ||
121 | + public static boolean isEncrypted(String text) { | ||
122 | + if (text == null || text.isEmpty()) { | ||
123 | + return false; | ||
124 | + } | ||
125 | + | ||
126 | + try { | ||
127 | + byte[] decoded = Base64.decode(text, Base64.DEFAULT); | ||
128 | + // Check if decoded length is reasonable for encrypted data (IV + data + tag) | ||
129 | + return decoded.length > GCM_IV_LENGTH + GCM_TAG_LENGTH; | ||
130 | + } catch (Exception e) { | ||
131 | + return false; | ||
132 | + } | ||
133 | + } | ||
134 | +} |
... | @@ -30,7 +30,7 @@ public class WarpConstants { | ... | @@ -30,7 +30,7 @@ public class WarpConstants { |
30 | /** | 30 | /** |
31 | * The version of the SDK installed in the device | 31 | * The version of the SDK installed in the device |
32 | */ | 32 | */ |
33 | - public static final String SDK_VERSION = "4.5.5.4"; | 33 | + public static final String SDK_VERSION = "4.5.5.5"; |
34 | 34 | ||
35 | /** | 35 | /** |
36 | * The URL of the server where it should ping | 36 | * The URL of the server where it should ping | ... | ... |
... | @@ -63,7 +63,6 @@ import ly.warp.sdk.io.models.Campaign; | ... | @@ -63,7 +63,6 @@ import ly.warp.sdk.io.models.Campaign; |
63 | import ly.warp.sdk.io.models.Coupon; | 63 | import ly.warp.sdk.io.models.Coupon; |
64 | import ly.warp.sdk.io.models.CouponList; | 64 | import ly.warp.sdk.io.models.CouponList; |
65 | import ly.warp.sdk.io.models.LoyaltySDKDynatraceEventModel; | 65 | import ly.warp.sdk.io.models.LoyaltySDKDynatraceEventModel; |
66 | -import ly.warp.sdk.io.models.MarketPassDetailsModel; | ||
67 | import ly.warp.sdk.io.models.NewCampaign; | 66 | import ly.warp.sdk.io.models.NewCampaign; |
68 | import ly.warp.sdk.io.models.RedeemedSMHistoryModel; | 67 | import ly.warp.sdk.io.models.RedeemedSMHistoryModel; |
69 | import ly.warp.sdk.io.request.WarplyRefreshTokenRequest; | 68 | import ly.warp.sdk.io.request.WarplyRefreshTokenRequest; |
... | @@ -227,7 +226,7 @@ public class WarplyManager { | ... | @@ -227,7 +226,7 @@ public class WarplyManager { |
227 | }); | 226 | }); |
228 | } | 227 | } |
229 | 228 | ||
230 | - public static void getCosmoteUser(String guid, final CallbackReceiver<JSONObject> receiver) { | 229 | + public static void getDehUser(String guid, final CallbackReceiver<JSONObject> receiver) { |
231 | WarpUtils.log("************* WARPLY Cosmote User Request ********************"); | 230 | WarpUtils.log("************* WARPLY Cosmote User Request ********************"); |
232 | WarpUtils.log("[WARP Trace] WARPLY Cosmote User Request is active"); | 231 | WarpUtils.log("[WARP Trace] WARPLY Cosmote User Request is active"); |
233 | WarpUtils.log("**************************************************"); | 232 | WarpUtils.log("**************************************************"); |
... | @@ -930,88 +929,6 @@ public class WarplyManager { | ... | @@ -930,88 +929,6 @@ public class WarplyManager { |
930 | return future; | 929 | return future; |
931 | } | 930 | } |
932 | 931 | ||
933 | - private static ListenableFuture<MarketPassDetailsModel> getMarketPassDetails(ApiService service) { | ||
934 | - SettableFuture<MarketPassDetailsModel> future = SettableFuture.create(); | ||
935 | - | ||
936 | - String timeStamp = DateFormat.format("yyyy-MM-dd hh:mm:ss", System.currentTimeMillis()).toString(); | ||
937 | - String apiKey = WarpUtils.getApiKey(Warply.getWarplyContext()); | ||
938 | - String webId = WarpUtils.getWebId(Warply.getWarplyContext()); | ||
939 | - | ||
940 | - Map<String, Object> jsonParamsMarketPassDetails = new ArrayMap<>(); | ||
941 | - Map<String, Object> jsonParams = new ArrayMap<>(); | ||
942 | - jsonParams.put("action", "integration"); | ||
943 | - jsonParams.put("method", "supermarket_profile"); | ||
944 | - | ||
945 | - jsonParamsMarketPassDetails.put("consumer_data", jsonParams); | ||
946 | - RequestBody marketPassDetailsRequest = RequestBody.create(MediaType.get("application/json; charset=utf-8"), (new JSONObject(jsonParamsMarketPassDetails)).toString()); | ||
947 | - | ||
948 | - Call<ResponseBody> marketPassDetailsCall = service.getMarketPassDetails(WarplyProperty.getAppUuid(Warply.getWarplyContext()), marketPassDetailsRequest, timeStamp, "android:" + Warply.getWarplyContext().getPackageName(), new WarplyDeviceInfoCollector(Warply.getWarplyContext()).getUniqueDeviceId(), "mobile", webId, WarpUtils.produceSignature(apiKey + timeStamp), "Bearer " + WarplyDBHelper.getInstance(Warply.getWarplyContext()).getAuthValue("access_token")); | ||
949 | - | ||
950 | - marketPassDetailsCall.enqueue(new Callback<ResponseBody>() { | ||
951 | - @Override | ||
952 | - public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) { | ||
953 | - if (response.code() == 200 && response.body() != null) { | ||
954 | - JSONObject marketPassDetailsResponse = null; | ||
955 | - try { | ||
956 | - marketPassDetailsResponse = new JSONObject(response.body().string()); | ||
957 | - } catch (Exception e) { | ||
958 | - e.printStackTrace(); | ||
959 | - } | ||
960 | - | ||
961 | - if (marketPassDetailsResponse != null && marketPassDetailsResponse.has("status") && marketPassDetailsResponse.optString("status", "2").equals("1")) { | ||
962 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
963 | - dynatraceEvent.setEventName("custom_success_market_pass_details"); | ||
964 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
965 | - | ||
966 | - final ExecutorService executorMarketPassDetails = Executors.newFixedThreadPool(1); | ||
967 | - final JSONObject finalMarketPassDetailsResponse = marketPassDetailsResponse; | ||
968 | - executorMarketPassDetails.submit(() -> { | ||
969 | - JSONObject marketPassDetailsBody = null; | ||
970 | - try { | ||
971 | - marketPassDetailsBody = finalMarketPassDetailsResponse.optJSONObject("result"); | ||
972 | - } catch (Exception e) { | ||
973 | - e.printStackTrace(); | ||
974 | - } | ||
975 | - | ||
976 | - if (marketPassDetailsBody != null) { | ||
977 | - MarketPassDetailsModel marketPassDetailsModel = new MarketPassDetailsModel(marketPassDetailsBody); | ||
978 | - executorMarketPassDetails.shutdownNow(); | ||
979 | - future.set(marketPassDetailsModel); | ||
980 | - } else { | ||
981 | - LoyaltySDKDynatraceEventModel dynatraceEvent2 = new LoyaltySDKDynatraceEventModel(); | ||
982 | - dynatraceEvent2.setEventName("custom_error_market_pass_details"); | ||
983 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent2)); | ||
984 | - future.set(new MarketPassDetailsModel()); | ||
985 | - } | ||
986 | - }); | ||
987 | - } else { | ||
988 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
989 | - dynatraceEvent.setEventName("custom_error_market_pass_details"); | ||
990 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
991 | - future.set(new MarketPassDetailsModel()); | ||
992 | - } | ||
993 | - } else { | ||
994 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
995 | - dynatraceEvent.setEventName("custom_error_market_pass_details"); | ||
996 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
997 | -// future.set(new JSONObject()); | ||
998 | - future.setException(new Throwable()); | ||
999 | - } | ||
1000 | - } | ||
1001 | - | ||
1002 | - @Override | ||
1003 | - public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) { | ||
1004 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
1005 | - dynatraceEvent.setEventName("custom_error_market_pass_details"); | ||
1006 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
1007 | -// future.set(new JSONObject()); | ||
1008 | - future.setException(new Throwable()); | ||
1009 | - } | ||
1010 | - }); | ||
1011 | - | ||
1012 | - return future; | ||
1013 | - } | ||
1014 | - | ||
1015 | private static ListenableFuture<RedeemedSMHistoryModel> getSMCouponsUniversalRetro(ApiService service, int tries, SettableFuture<RedeemedSMHistoryModel> future) { | 932 | private static ListenableFuture<RedeemedSMHistoryModel> getSMCouponsUniversalRetro(ApiService service, int tries, SettableFuture<RedeemedSMHistoryModel> future) { |
1016 | String timeStamp = DateFormat.format("yyyy-MM-dd hh:mm:ss", System.currentTimeMillis()).toString(); | 933 | String timeStamp = DateFormat.format("yyyy-MM-dd hh:mm:ss", System.currentTimeMillis()).toString(); |
1017 | String apiKey = WarpUtils.getApiKey(Warply.getWarplyContext()); | 934 | String apiKey = WarpUtils.getApiKey(Warply.getWarplyContext()); |
... | @@ -1301,220 +1218,6 @@ public class WarplyManager { | ... | @@ -1301,220 +1218,6 @@ public class WarplyManager { |
1301 | }, null); | 1218 | }, null); |
1302 | } | 1219 | } |
1303 | 1220 | ||
1304 | - public static void getMarketPassDetails(final CallbackReceiver<MarketPassDetailsModel> receiver) { | ||
1305 | - WarpUtils.log("************* WARPLY Market Pass Details Request ********************"); | ||
1306 | - WarpUtils.log("[WARP Trace] WARPLY Market Pass Details is active"); | ||
1307 | - WarpUtils.log("**************************************************"); | ||
1308 | - | ||
1309 | - ApiService service = ApiClient.getRetrofitInstance().create(ApiService.class); | ||
1310 | - ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1)); | ||
1311 | - | ||
1312 | - ListenableFuture<MarketPassDetailsModel> futureMarketPassDetails = getMarketPassDetails(service); | ||
1313 | - | ||
1314 | - ListenableFuture<List<Object>> allResultsFuture = Futures.allAsList(futureMarketPassDetails); | ||
1315 | - ListenableFuture<MarketPassDetailsModel> mergedResultFuture = Futures.transformAsync(allResultsFuture, results -> { | ||
1316 | - MarketPassDetailsModel resultMarketPassDetails = (MarketPassDetailsModel) results.get(0); | ||
1317 | - return executorService.submit(() -> resultMarketPassDetails); | ||
1318 | - }, executorService); | ||
1319 | - | ||
1320 | - Futures.addCallback(mergedResultFuture, new FutureCallback<MarketPassDetailsModel>() { | ||
1321 | - @Override | ||
1322 | - public void onSuccess(MarketPassDetailsModel mergedResult) { | ||
1323 | - executorService.shutdownNow(); | ||
1324 | - new Handler(Looper.getMainLooper()).post(() -> receiver.onSuccess(mergedResult)); | ||
1325 | - } | ||
1326 | - | ||
1327 | - @Override | ||
1328 | - public void onFailure(Throwable throwable) { | ||
1329 | - executorService.shutdownNow(); | ||
1330 | - new Handler(Looper.getMainLooper()).post(() -> receiver.onFailure(2)); | ||
1331 | - } | ||
1332 | - }, executorService); | ||
1333 | - } | ||
1334 | - | ||
1335 | - private static /*void*/ ListenableFuture<ArrayList<Campaign>> getSupermarketCampaignRetro(ApiService service/*, final CallbackReceiver<ArrayList<Campaign>> receiver*/) { | ||
1336 | - SettableFuture<ArrayList<Campaign>> future = SettableFuture.create(); | ||
1337 | - | ||
1338 | - String timeStamp = DateFormat.format("yyyy-MM-dd hh:mm:ss", System.currentTimeMillis()).toString(); | ||
1339 | - String apiKey = WarpUtils.getApiKey(Warply.getWarplyContext()); | ||
1340 | - String webId = WarpUtils.getWebId(Warply.getWarplyContext()); | ||
1341 | - | ||
1342 | - Map<String, Object> jsonParamsCampaigns = new ArrayMap<>(); | ||
1343 | - Map<String, Object> jsonParams = new ArrayMap<>(); | ||
1344 | - JSONObject jFilters = new JSONObject(); | ||
1345 | - JSONObject jExtra = new JSONObject(); | ||
1346 | - try { | ||
1347 | - jFilters.putOpt("communication_category", "more_for_you"); | ||
1348 | - jExtra.putOpt("filter", "supermarket"); | ||
1349 | - jExtra.putOpt("version", "magenta"); | ||
1350 | - jFilters.putOpt("extra_fields", jExtra); | ||
1351 | - } catch (JSONException e) { | ||
1352 | - throw new RuntimeException(e); | ||
1353 | - } | ||
1354 | - jsonParams.put("action", "retrieve"); | ||
1355 | - jsonParams.put("filters", jFilters); | ||
1356 | - jsonParams.put("language", WarpUtils.getApplicationLocale(Warply.getWarplyContext())); | ||
1357 | - | ||
1358 | - jsonParamsCampaigns.put("campaigns", jsonParams); | ||
1359 | - RequestBody campaignsRequest = RequestBody.create(MediaType.get("application/json; charset=utf-8"), (new JSONObject(jsonParamsCampaigns)).toString()); | ||
1360 | - | ||
1361 | - Call<ResponseBody> campaignsCall = service.getCampaigns(WarplyProperty.getAppUuid(Warply.getWarplyContext()), campaignsRequest, timeStamp, "android:" + Warply.getWarplyContext().getPackageName(), new WarplyDeviceInfoCollector(Warply.getWarplyContext()).getUniqueDeviceId(), "mobile", webId, WarpUtils.produceSignature(apiKey + timeStamp)); | ||
1362 | - | ||
1363 | - campaignsCall.enqueue(new Callback<ResponseBody>() { | ||
1364 | - @Override | ||
1365 | - public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) { | ||
1366 | - if (response.code() == 200 && response.body() != null) { | ||
1367 | - JSONObject jobjCampaignsResponse = null; | ||
1368 | - try { | ||
1369 | - jobjCampaignsResponse = new JSONObject(response.body().string()); | ||
1370 | - } catch (Exception e) { | ||
1371 | - e.printStackTrace(); | ||
1372 | - } | ||
1373 | - | ||
1374 | - if (jobjCampaignsResponse != null && jobjCampaignsResponse.has("status") && jobjCampaignsResponse.optString("status", "2").equals("1")) { | ||
1375 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
1376 | - dynatraceEvent.setEventName("custom_success_supermarket_campaign_loyalty"); | ||
1377 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
1378 | - | ||
1379 | - JSONArray jCampaignsBody = null; | ||
1380 | - try { | ||
1381 | - jCampaignsBody = jobjCampaignsResponse.optJSONObject("context").optJSONObject("MAPP_CAMPAIGNING").optJSONArray("campaigns"); | ||
1382 | - } catch (Exception e) { | ||
1383 | - e.printStackTrace(); | ||
1384 | - } | ||
1385 | - | ||
1386 | - if (jCampaignsBody != null) { | ||
1387 | - ArrayList<NewCampaign> tempCampaigns = new ArrayList<>(); | ||
1388 | - ArrayList<Campaign> mCampaignsList = new ArrayList<>(); | ||
1389 | - | ||
1390 | - final ExecutorService executorCampaigns = Executors.newFixedThreadPool(1); | ||
1391 | - JSONArray finalCampaignsJBody = jCampaignsBody; | ||
1392 | - executorCampaigns.submit(() -> { | ||
1393 | - for (int i = 0; i < finalCampaignsJBody.length(); ++i) { | ||
1394 | - tempCampaigns.add(new NewCampaign(finalCampaignsJBody.optJSONObject(i))); | ||
1395 | - } | ||
1396 | - for (NewCampaign newCamp : tempCampaigns) { | ||
1397 | - Campaign camp = new Campaign(); | ||
1398 | - camp.setIndexUrl(newCamp.getIndexUrl()); | ||
1399 | - camp.setLogoUrl(newCamp.getLogoUrl()); | ||
1400 | - camp.setMessage(newCamp.getMessage()); | ||
1401 | - camp.setOfferCategory(newCamp.getCommunicationCategory()); | ||
1402 | - camp.setSessionUUID(newCamp.getCommunicationUUID()); | ||
1403 | - camp.setTitle(newCamp.getTitle()); | ||
1404 | - camp.setSubtitle(newCamp.getSubtitle()); | ||
1405 | - camp.setSorting(newCamp.getSorting()); | ||
1406 | - camp.setNew(newCamp.getIsNew()); | ||
1407 | - camp.setType(newCamp.getCampaignType()); | ||
1408 | - camp.setEndDate(newCamp.getEndDate()); | ||
1409 | - camp.setStartDate(newCamp.getStartDate()); | ||
1410 | - camp.setShowExpiration(newCamp.isShowExpiration()); | ||
1411 | - camp.setCouponImg(newCamp.getCouponImg()); | ||
1412 | - camp.setFilter(newCamp.getFilter()); | ||
1413 | - try { | ||
1414 | - camp.setExtraFields(newCamp.getExtraFields().toString()); | ||
1415 | - if (!TextUtils.isEmpty(newCamp.getExtraFields().toString())) { | ||
1416 | - JSONObject extraFieldsResp = WarpJSONParser.getJSONFromString(newCamp.getExtraFields().toString()); | ||
1417 | - if (extraFieldsResp != null) { | ||
1418 | - if (extraFieldsResp.has("Banner_title")) { | ||
1419 | - camp.setBannerTitle(extraFieldsResp.optString("Banner_title", "")); | ||
1420 | - } | ||
1421 | - if (extraFieldsResp.has("Banner_img")) { | ||
1422 | - camp.setBannerImage(extraFieldsResp.optString("Banner_img", "")); | ||
1423 | - } | ||
1424 | - if (extraFieldsResp.has("category_id")) { | ||
1425 | - camp.setCategoryId(extraFieldsResp.optString("category_id", "")); | ||
1426 | - } | ||
1427 | - } | ||
1428 | - } else { | ||
1429 | - camp.setBannerImage(""); | ||
1430 | - camp.setBannerTitle(""); | ||
1431 | - camp.setCategoryId(""); | ||
1432 | - } | ||
1433 | - } catch (NullPointerException e) { | ||
1434 | - camp.setExtraFields(""); | ||
1435 | - camp.setBannerImage(""); | ||
1436 | - camp.setBannerTitle(""); | ||
1437 | - camp.setCategoryId(""); | ||
1438 | - e.printStackTrace(); | ||
1439 | - } | ||
1440 | - | ||
1441 | - try { | ||
1442 | - camp.setCampaignTypeSettings(newCamp.getSettings().toString()); | ||
1443 | - } catch (NullPointerException e) { | ||
1444 | - camp.setCampaignTypeSettings(""); | ||
1445 | - e.printStackTrace(); | ||
1446 | - } | ||
1447 | - mCampaignsList.add(camp); | ||
1448 | - } | ||
1449 | - | ||
1450 | - executorCampaigns.shutdownNow(); | ||
1451 | -// receiver.onSuccess(mCampaignsList); | ||
1452 | - future.set(mCampaignsList); | ||
1453 | - }); | ||
1454 | - } | ||
1455 | - } else { | ||
1456 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
1457 | - dynatraceEvent.setEventName("custom_error_supermarket_campaign_loyalty"); | ||
1458 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
1459 | -// receiver.onFailure(2); | ||
1460 | - future.set(new ArrayList<Campaign>()); | ||
1461 | - } | ||
1462 | - } else { | ||
1463 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
1464 | - dynatraceEvent.setEventName("custom_error_supermarket_campaign_loyalty"); | ||
1465 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
1466 | -// receiver.onFailure(response.code()); | ||
1467 | -// future.set(new ArrayList<Campaign>()); | ||
1468 | - future.setException(new Throwable()); | ||
1469 | - } | ||
1470 | - } | ||
1471 | - | ||
1472 | - @Override | ||
1473 | - public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) { | ||
1474 | - LoyaltySDKDynatraceEventModel dynatraceEvent = new LoyaltySDKDynatraceEventModel(); | ||
1475 | - dynatraceEvent.setEventName("custom_error_supermarket_campaign_loyalty"); | ||
1476 | - EventBus.getDefault().post(new WarplyEventBusManager(dynatraceEvent)); | ||
1477 | -// receiver.onFailure(2); | ||
1478 | -// future.set(new ArrayList<Campaign>()); | ||
1479 | - future.setException(new Throwable()); | ||
1480 | - } | ||
1481 | - }); | ||
1482 | - | ||
1483 | - return future; | ||
1484 | - } | ||
1485 | - | ||
1486 | - public static void getSupermarketCampaign(final CallbackReceiver<ArrayList<Campaign>> receiver) { | ||
1487 | - WarpUtils.log("************* WARPLY Get Supermarket Campaigns Request ********************"); | ||
1488 | - WarpUtils.log("[WARP Trace] WARPLY Get Supermarket Campaigns Request is active"); | ||
1489 | - WarpUtils.log("**************************************************"); | ||
1490 | - | ||
1491 | - ApiService service = ApiClient.getRetrofitInstance().create(ApiService.class); | ||
1492 | - ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(1)); | ||
1493 | - | ||
1494 | - ListenableFuture<ArrayList<Campaign>> futureCampaigns = getSupermarketCampaignRetro(service); | ||
1495 | - | ||
1496 | - ListenableFuture<List<Object>> allResultsFuture = Futures.allAsList(futureCampaigns); | ||
1497 | - ListenableFuture<ArrayList<Campaign>> mergedResultFuture = Futures.transformAsync(allResultsFuture, results -> { | ||
1498 | - ArrayList<Campaign> resultCampaigns = (ArrayList<Campaign>) results.get(0); | ||
1499 | - return executorService.submit(() -> resultCampaigns); | ||
1500 | - }, executorService); | ||
1501 | - | ||
1502 | - Futures.addCallback(mergedResultFuture, new FutureCallback<ArrayList<Campaign>>() { | ||
1503 | - @Override | ||
1504 | - public void onSuccess(ArrayList<Campaign> mergedResult) { | ||
1505 | - WarplyManagerHelper.setSupermarketCampaigns(mergedResult); | ||
1506 | - executorService.shutdownNow(); | ||
1507 | - new Handler(Looper.getMainLooper()).post(() -> receiver.onSuccess(mergedResult)); | ||
1508 | - } | ||
1509 | - | ||
1510 | - @Override | ||
1511 | - public void onFailure(Throwable throwable) { | ||
1512 | - executorService.shutdownNow(); | ||
1513 | - new Handler(Looper.getMainLooper()).post(() -> receiver.onFailure(2)); | ||
1514 | - } | ||
1515 | - }, executorService); | ||
1516 | - } | ||
1517 | - | ||
1518 | public static void getRedeemedSMHistory(final CallbackReceiver<RedeemedSMHistoryModel> receiver) { | 1221 | public static void getRedeemedSMHistory(final CallbackReceiver<RedeemedSMHistoryModel> receiver) { |
1519 | WarpUtils.log("************* WARPLY User Redeemed History Request ********************"); | 1222 | WarpUtils.log("************* WARPLY User Redeemed History Request ********************"); |
1520 | WarpUtils.log("[WARP Trace] WARPLY User Redeemed History Request is active"); | 1223 | WarpUtils.log("[WARP Trace] WARPLY User Redeemed History Request is active"); | ... | ... |
... | @@ -568,8 +568,8 @@ public class WarpView extends WebView implements DefaultLifecycleObserver { | ... | @@ -568,8 +568,8 @@ public class WarpView extends WebView implements DefaultLifecycleObserver { |
568 | public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) { | 568 | public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) { |
569 | if (WarpActivity != null && !WarpActivity.isFinishing()) { | 569 | if (WarpActivity != null && !WarpActivity.isFinishing()) { |
570 | AlertDialog.Builder builder = new AlertDialog.Builder(WarpActivity); | 570 | AlertDialog.Builder builder = new AlertDialog.Builder(WarpActivity); |
571 | - builder.setTitle(getContext().getString(R.string.lbl_cosmote_webview_permission_title)); | 571 | + builder.setTitle(getContext().getString(R.string.webview_permission_title)); |
572 | - builder.setMessage(getContext().getString(R.string.lbl_cosmote_webview_permission_message)) | 572 | + builder.setMessage(getContext().getString(R.string.webview_permission_message)) |
573 | .setCancelable(false) | 573 | .setCancelable(false) |
574 | .setPositiveButton(getContext().getString(R.string.lbl_take_photo_accept), (dialog, id) -> checkForPermissions(origin, callback)) | 574 | .setPositiveButton(getContext().getString(R.string.lbl_take_photo_accept), (dialog, id) -> checkForPermissions(origin, callback)) |
575 | .setNegativeButton(getContext().getString(R.string.lbl_take_photo_decline), (dialog, id) -> callback.invoke(origin, false, false)); | 575 | .setNegativeButton(getContext().getString(R.string.lbl_take_photo_decline), (dialog, id) -> callback.invoke(origin, false, false)); | ... | ... |
1 | <?xml version="1.0" encoding="utf-8"?> | 1 | <?xml version="1.0" encoding="utf-8"?> |
2 | - | 2 | +<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" |
3 | -<androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
4 | xmlns:app="http://schemas.android.com/apk/res-auto" | 3 | xmlns:app="http://schemas.android.com/apk/res-auto" |
5 | xmlns:tools="http://schemas.android.com/tools" | 4 | xmlns:tools="http://schemas.android.com/tools" |
6 | - android:id="@+id/sw_refresh" | ||
7 | - android:layout_width="match_parent" | ||
8 | - android:layout_height="match_parent" | ||
9 | - android:background="@color/cos_skyblue2"> | ||
10 | - | ||
11 | - <ScrollView | ||
12 | android:layout_width="match_parent" | 5 | android:layout_width="match_parent" |
13 | android:layout_height="match_parent" | 6 | android:layout_height="match_parent" |
14 | android:background="@color/cos_skyblue2"> | 7 | android:background="@color/cos_skyblue2"> |
... | @@ -261,5 +254,4 @@ | ... | @@ -261,5 +254,4 @@ |
261 | </RelativeLayout> | 254 | </RelativeLayout> |
262 | 255 | ||
263 | </RelativeLayout> | 256 | </RelativeLayout> |
264 | - </ScrollView> | 257 | +</ScrollView> |
265 | -</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> | ... | ... |
1 | <resources> | 1 | <resources> |
2 | - <string name="lbl_cosmote_webview_permission_title">Demo App</string> | 2 | + <string name="webview_permission_title">Demo App</string> |
3 | - <string name="lbl_cosmote_webview_permission_message">Το Demo App ζητάει πρόσβαση στην τοποθεσία σας.</string> | 3 | + <string name="webview_permission_message">Το Demo App ζητάει πρόσβαση στην τοποθεσία σας.</string> |
4 | <string name="lbl_take_photo_accept">Οκ</string> | 4 | <string name="lbl_take_photo_accept">Οκ</string> |
5 | <string name="lbl_take_photo_decline">Άκυρο</string> | 5 | <string name="lbl_take_photo_decline">Άκυρο</string> |
6 | <string name="welcome_user">Γεια σου %1$s !</string> | 6 | <string name="welcome_user">Γεια σου %1$s !</string> | ... | ... |
-
Please register or login to post a comment