Hi, I’m integrating CI360 SDK in React Native, specifically the android part, and when I launch de app locally everything seems to work fine. I can see the spot, I receive notifications, etc. But when I create an APK I got the following logs in Android Studio:
The SDK seems to not be able to send events to the tenant.
I’m not sure why this behavior is happening in the APK. If I analyze the APK with Android Studio and I’ve got:
As you can see the location of SASCollector.properties is different from the others files.properties in the APK.
Can this difference in locations affect the sending of events to the tenant?
I followed the steps provided in the official React Native SAS Cookbook.
Thank you in advance!
PD: Sorry for my English level, I’m still learning the language.
Hi @LucasAcuna Thank you for reporting the issue. We will look at what is causing it and getting back to you when we find out.
Hi @LucasAcuna I did a release build, and then installed the release APK on a simulator. I can still get all the functionalities. I didn't have the issue that you had. I wonder if you created a release APK? If it is a debug APK, then you need to have Metro running first. Here is my release APK structure.
@LucasAcuna I see that your APK is also a release APK. So that is not the issue. But from your log, I can see "Session not yet established, deferring...". That indicates a problem. Can you get the log at the start of running your app? That may contain information on why initialization was not successful. You can look for information such as:
1. Context is null, unable to initialize.
2. Mobile spots not supported on Android OS version: ...
3. Context is neither Application nor Activity, unable to initialize
4. SASCollector SDK failed to initialize: App does not have internet permissions.
5. GSON Parsing library not available, please include it in your project dependencies.
6. Unable to load SASCollector.properties configuration file.
7. Error initializing SASCollector: (your app name) (error message)
There may be other initialization errors in log.
A successful initialization will have a log like this:
2023-04-05 08:42:41.804 9762-9762/? I/SASCollector::SASCOLLECTOR_API: initialize: [ com.mobile_sdk_test.MainApplication@841b58b]
2023-04-05 08:42:41.804 9762-9762/? D/SASCollector::SASCollector: SASCollector initializing (com.mobile_sdk_test.MainApplication@841b58b)
2023-04-05 08:42:41.805 9762-9762/? D/SASCollector::AppEnvironment: AppEnvironment initialized. Internet=true Location=false PlayServices=true SDKIntentService=true
2023-04-05 08:42:41.822 9762-9762/? I/SASCollector::SASCollector: Loading configuration from assets/SASCollector.properties
2023-04-05 08:42:41.822 9762-9762/? I/SASCollector::SASCollector: Properties (3):
2023-04-05 08:42:41.822 9762-9762/? I/SASCollector::SASCollector: application.id=react_native_test_sdk
2023-04-05 08:42:41.822 9762-9762/? I/SASCollector::SASCollector: tenant.id=5f301a8a070001019cc023d7
2023-04-05 08:42:41.822 9762-9762/? I/SASCollector::SASCollector: tag.server=https://eventsingest-dev.cidev.sas.us/t/mobile
2023-04-05 08:42:41.823 9762-9762/? D/SASCollector::SASCollector: DeviceID from SharedPreferences: c8550524-8ecc-4e6a-bf7a-a733e2149fd3
2023-04-05 08:42:41.823 9762-9762/? D/SASCollector::SASCollector: DeviceID seed is c8d3
2023-04-05 08:42:41.827 9762-9762/? D/SASCollector::SASCollector: SASCollector initialized.
Hi @wwen, thank you for you answer! Sorry for the delay in answering! Yes the apk was built in release mode. I’ll take a look to the logs in Android Studio when the app starts, maybe I’m doing the sdk initialization in the wrong place.
If I’ve got another problem I’ll let you know.
I’ll notify you if I solve the problem.
Thank you for your time.
Hi @wwen
I was doing some test with my apk and the logs I got in Android Studio when the app starts are:
I/SASCollector::SASCOLLECTOR_API: setPushNotificationChannelId: [ ReactNativePushChannel2] W/SASCollector::e: SASCollector is not initialized, unable to set push notificiation channel. I/SASCollector::SASCOLLECTOR_API: setMobileMessagingDelegate2: [ com.services.movistar.ar.MainActivity$a@40e09fe] I/SASCollector::SASCOLLECTOR_API: initialize: [ com.services.movistar.ar.MainApplication@f1c9521] D/SASCollector::e: SASCollector initializing (com.services.movistar.ar.MainApplication@f1c9521) D/SASCollector::b: AppEnvironment initialized. Internet=true Location=false PlayServices=true SDKIntentService=true I/SASCollector::e: Loading configuration from assets/SASCollector.properties I/SASCollector::e: Properties (3): I/SASCollector::e: application.id=Test.AppMobile.Desa I/SASCollector::e: tenant.id=a8a352b2d200011483d50aec I/SASCollector::e: tag.server=https://execution-ci360.nop.movistar.com.ar/t/mobile D/SASCollector::e: Generated new device ID: d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 D/SASCollector::e: DeviceID seed is d9e4 D/SASCollector::e: SASCollector initialized. D/SASCollector::k: Executing e.u.b.a.a.p.c D/SASCollector::a: Event Manager is running. D/SASCollector::b: Using base server URL: https://execution-ci360.nop.movistar.com.ar/t/mobile D/SASCollector::b: Resolving host execution-ci360.nop.movistar.com.ar D/SASCollector::c: Begin remote image cleanup... D/SASCollector::c: Remote image dir does not exist: /data/user/0/com.services.movistar.ar.integration/cache/sas/remote_files D/SASCollector::c: Cleanup completed. Deleted 0 D/SASCollector::a: Activity destroyed: com.zoontek.rnbootsplash.RNBootSplashActivity D/SASCollector::b: Resolved to 13.227.83.19 D/SASCollector::a: Server is available. D/SASCollector::a: Buffer was empty. D/SASCollector::a: Events data source is open with 1 connections. D/SASCollector::a: Retrieved 0 recent events. D/SASCollector::a: All events are deleted. D/SASCollector::a: Events data source is closed. D/SASCollector::a: Pulled 0 from DB D/SASCollector::a: No more events to send, entering deep sleep. I/SASCollector::SASCOLLECTOR_API: registerForMobileMessages: [ ee4XOdJDQRWKuJIV3vfhvT:APA91bGbIvbI0F95Jhg2wH9wpqKsp5Du_ISzuR1-EHmx5kkPTEbO3qIl8zd0ojzcrfKFxJvcPOmyUgB9quwLGSRtZIeqq0u-kjh3Z0AnWSSEMliYhvylfGEWR-9l6GUSjfS66VQN8A0s] D/SASCollector::k: Executing e.u.b.a.a.p.l D/SASCollector::l: Sending token ee4XOdJDQRWKuJIV3vfhvT:APA91bGbIvbI0F95Jhg2wH9wpqKsp5Du_ISzuR1-EHmx5kkPTEbO3qIl8zd0ojzcrfKFxJvcPOmyUgB9quwLGSRtZIeqq0u-kjh3Z0AnWSSEMliYhvylfGEWR-9l6GUSjfS66VQN8A0s for device d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 D/SASCollector::b: Outbound request: PUT https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 D/SASCollector::b: JSON data for e.u.b.a.a.j.l : {"a":"d96f8fd5-0614-4de4-8d9c-a6385d8c06e4","b":"Android-ee4XOdJDQRWKuJIV3vfhvT:APA91bGbIvbI0F95Jhg2wH9wpqKsp5Du_ISzuR1-EHmx5kkPTEbO3qIl8zd0ojzcrfKFxJvcPOmyUgB9quwLGSRtZIeqq0u-kjh3Z0AnWSSEMliYhvylfGEWR-9l6GUSjfS66VQN8A0s","c":"Test.AppMobile.Desa"} D/SASCollector::b: Content-Length: 248 E/SASCollector::NEW_TOKEN: ee4XOdJDQRWKuJIV3vfhvT:APA91bGbIvbI0F95Jhg2wH9wpqKsp5Du_ISzuR1-EHmx5kkPTEbO3qIl8zd0ojzcrfKFxJvcPOmyUgB9quwLGSRtZIeqq0u-kjh3Z0AnWSSEMliYhvylfGEWR-9l6GUSjfS66VQN8A0s I/SASCollector::SASCOLLECTOR_API: registerForMobileMessages: [ ee4XOdJDQRWKuJIV3vfhvT:APA91bGbIvbI0F95Jhg2wH9wpqKsp5Du_ISzuR1-EHmx5kkPTEbO3qIl8zd0ojzcrfKFxJvcPOmyUgB9quwLGSRtZIeqq0u-kjh3Z0AnWSSEMliYhvylfGEWR-9l6GUSjfS66VQN8A0s] D/SASCollector::k: Executing e.u.b.a.a.p.l D/SASCollector::a: Activity paused: com.services.movistar.ar.MainActivity D/SASCollector::b: Response Code: 400 D/SASCollector::b: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 AWSALB=vg0NF//ygR/IWXZX8hlvJjvU1M512fUHKpLMWE9kQWOjmgbcbC41j49c+CszMoGwaUFDRsXszfBvlNUcLHN5T9mDYehv7uCvdZIAZisU8LsuO93nBUq9PcZ5+ehD; Expires=Fri, 21 Apr 2023 13:22:15 GMT; Path=/ D/SASCollector::b: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 AWSALBCORS=vg0NF//ygR/IWXZX8hlvJjvU1M512fUHKpLMWE9kQWOjmgbcbC41j49c+CszMoGwaUFDRsXszfBvlNUcLHN5T9mDYehv7uCvdZIAZisU8LsuO93nBUq9PcZ5+ehD; Expires=Fri, 21 Apr 2023 13:22:15 GMT; Path=/; SameSite=None; Secure E/SASCollector::b: Unexpected status code from server: 400 2023-04-14 10:22:15.101 14652-14848/com.services.movistar.ar.integration D/SASCollector::l: Sending token ee4XOdJDQRWKuJIV3vfhvT:APA91bGbIvbI0F95Jhg2wH9wpqKsp5Du_ISzuR1-EHmx5kkPTEbO3qIl8zd0ojzcrfKFxJvcPOmyUgB9quwLGSRtZIeqq0u-kjh3Z0AnWSSEMliYhvylfGEWR-9l6GUSjfS66VQN8A0s for device d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 D/SASCollector::b: Outbound request: PUT https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 D/SASCollector::b: JSON data for e.u.b.a.a.j.l : {"a":"d96f8fd5-0614-4de4-8d9c-a6385d8c06e4","b":"Android-ee4XOdJDQRWKuJIV3vfhvT:APA91bGbIvbI0F95Jhg2wH9wpqKsp5Du_ISzuR1-EHmx5kkPTEbO3qIl8zd0ojzcrfKFxJvcPOmyUgB9quwLGSRtZIeqq0u-kjh3Z0AnWSSEMliYhvylfGEWR-9l6GUSjfS66VQN8A0s","c":"Test.AppMobile.Desa"} D/SASCollector::b: Content-Length: 248 D/SASCollector::b: Response Code: 400 D/SASCollector::b: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 AWSALB=qR+cN+C5Wqe3Yx52jJDkTsTQP+GdI993fhVqhGbn8vteEBldecZyJptRIq/L4tHa2lLfhk2D/0rOOZ6N/5Ic9FpdrwXs6CHFpV/e9MsT1gxiIgMFJOYvfqVQXnrn; Expires=Fri, 21 Apr 2023 13:22:16 GMT; Path=/ D/SASCollector::b: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/d96f8fd5-0614-4de4-8d9c-a6385d8c06e4 AWSALBCORS=qR+cN+C5Wqe3Yx52jJDkTsTQP+GdI993fhVqhGbn8vteEBldecZyJptRIq/L4tHa2lLfhk2D/0rOOZ6N/5Ic9FpdrwXs6CHFpV/e9MsT1gxiIgMFJOYvfqVQXnrn; Expires=Fri, 21 Apr 2023 13:22:16 GMT; Path=/; SameSite=None; Secure E/SASCollector::b: Unexpected status code from server: 400 D/SASCollector::a: Activity resumed: com.services.movistar.ar.MainActivity
If I filter the android studio logs by the key word "initialized" I got:
I/FA: App measurement initialized, version: 42004
W/SASCollector::e: SASCollector is not initialized, unable to set push notificiation channel.
I/RNFusedLocation: RNFusedLocation initialized
D/SASCollector::b: AppEnvironment initialized. Internet=true Location=false PlayServices=true SDKIntentService=true
D/SASCollector::e: SASCollector initialized.
W/Adjust: Adjust not initialized, can't perform onResume
W/SASCollector::e: SASCollector is not initialized, ignoring request to start location monitoring.
W/SASCollector::e: SASCollector is not initialized, discarding events
W/SASCollector::e: SASCollector is not initialized, discarding events
W/SASCollector::SASCollectorAd: SASCollector is not initialized, unable to load spot.
W/SASCollector::SASCollectorInterstitialAd: SASCollector is not initialized, unable to load spot.
W/SASCollector::e: SASCollector is not initialized, discarding events
As you can see, at first SASCollector is initialized, then SASCollector in not initialized and after that SASCollector is not initialized again.
Hi @LucasAcuna I suspect that something went wrong with your internet? Can you please check if there are logs like these:
1. SSLException (“error”) in HTTPS comms: msg
2. Error in background task: msg
In above logs, error and msg are placeholders. If you did see one or both logs, then that explains why SASCollector was shut down and was set back to uninitialized.
In addition, I also saw that registerForMobileMessages returned a 400 error. You can check the token to see if it is valid or anything else that could cause this.
What more I found in your first screenshot is that you tried to set push notification channel before SASCollector was initialized. Can you please make sure that you do it after initialization?
Hi @wwen , I did some test in the release apk and I wasn't able to find any error related to "SSLException" and "Error in background task". I also changed the set up of push notifications after the SDK initialization as you mentioned.
In addition I also did another tests in order to try to find out whats happening with my apk. I create a debug apk and everything works fine, and its folder structure include:
As you can see in the path com.sas.mkt.mobile.sdk it has got the SASCollector module.
If I build an apk in release mode and inspect its content I'm not able to find the SASCollector module:
I'm not sure why this is happening in release mode, we have no problem with another SDKs in the app.
Do you think you need information on how I made the configuration of the SDK in the app? Maybe I did some mistakes.
Thank you!
Hi @LucasAcuna , I took a look at my release and debug APKs. I don't have any of the java classes. In fact, there are no java classes even in other libraries like okhttp3. If I build a native Android APK (not React Native), there won't be any java classes either. Most are just .properties, or image files (png), or other resource files. Please see my screenshots below. As you can see, there's no difference in the files under com.sas between debug and release APKs. I used Android Studio to create the APKs. How did you create your APKs?
If possible, could you please provide a full list of the logs for debugging? Yes, your configuration of the SDK is helpful too.
Hi @wwen , I saw inside of my apk in release mode and in the root directory I also have got a folder called com, and inside of it there is practically the same content that you show me before (red and yellow rectangles):
But also I have (in the root directory) a .dex file in my case called classes2.dex (green rectangle). Inside of it there are some files and folders. One of these folders is com, and it contains the sas folder with the SDK dependencies. In this folder I couldn't find the SASCollector class that allows the app initialize the apk. In the path com/sas/mkt/mobile/sdk there is no SASCollector module, so I think (I'm not sure) that when the MainApplication.java run this import:
import com.sas.mkt.mobile.sdk.SASCollector;
it isn't able to processing it correctly.
In the debug apk the SASCollector class is inside of the path described above.
When the apk in debug mode starts the app logs are:
I/SASCollector::SASCOLLECTOR_API: initialize: [ com.services.movistar.ar.MainApplication@9de060e] D/SASCollector::SASCollector: SASCollector initializing (com.services.movistar.ar.MainApplication@9de060e) D/SASCollector::AppEnvironment: AppEnvironment initialized. Internet=true Location=false PlayServices=true SDKIntentService=true I/SASCollector::SASCollector: Loading configuration from assets/SASCollector.properties I/SASCollector::SASCollector: Properties (3): I/SASCollector::SASCollector: application.id=Test.AppMobile.Desa I/SASCollector::SASCollector: tenant.id=a8a352b2d200011483d50aec I/SASCollector::SASCollector: tag.server=https://execution-ci360.nop.movistar.com.ar/t/mobile D/SASCollector::SASCollector: DeviceID from SharedPreferences: 10ac7910-69b2-4077-bcc4-e31d21464843 D/SASCollector::SASCollector: DeviceID seed is 1043 D/SASCollector::OfflineEventManager: Event Manager is running. D/SASCollector::SASCollector: SASCollector initialized. D/SASCollector::SASCollectorExecutor: Executing com.sas.mkt.mobile.sdk.tasks.CleanRemoteImagesTask D/SASCollector::CleanRemoteImagesTask: Begin remote image cleanup... D/SASCollector::CleanRemoteImagesTask: Remote image dir does not exist: /data/user/0/com.services.movistar.ar.integration/cache/sas/remote_files D/SASCollector::CleanRemoteImagesTask: Cleanup completed. Deleted 0 D/SASCollector::MidtierServices: Using base server URL: https://execution-ci360.nop.movistar.com.ar/t/mobile D/SASCollector::MidtierServices: Resolving host execution-ci360.nop.movistar.com.ar I/SASCollector::SASCOLLECTOR_API: setPushNotificationChannelId: [ ReactNativePushChannel2] D/SASCollector::ActivityLifecycleListener: Activity created: com.zoontek.rnbootsplash.RNBootSplashActivity D/SASCollector::MidtierServices: Resolved to 3.160.119.101 D/SASCollector::OfflineEventManager: Server is available. D/SASCollector::OfflineEventManager: Buffer was empty. D/SASCollector::EventsDataSource: Events data source is open with 1 connections. D/SASCollector::EventsDataSource: Retrieved 0 recent events. D/SASCollector::ActivityLifecycleListener: Activity created: com.services.movistar.ar.MainActivity D/SASCollector::EventsDataSource: All events are deleted. D/SASCollector::EventsDataSource: Events data source is closed. D/SASCollector::OfflineEventManager: Pulled 0 from DB I/SASCollector::SASCOLLECTOR_API: setMobileMessagingDelegate2: [ com.services.movistar.ar.MainActivity$1@be5e863] D/SASCollector::ActivityLifecycleListener: Activity started: com.services.movistar.ar.MainActivity D/SASCollector::SASCollectorExecutor: Executing com.sas.mkt.mobile.sdk.tasks.QueueEventTask D/SASCollector::ActivityLifecycleListener: Foreground counter : 1 D/SASCollector::QueueEventTask: Queuing event: focus D/SASCollector::OfflineEventManager: Session timed out. D/SASCollector::OfflineEventManager: Session indicator is NONE D/SASCollector::OfflineEventManager: Starting new session. 1681838104797 1681838104797 120000 600000 null 10ac7910-69b2-4077-bcc4-e31d21464843 I/SASCollector::DeviceAndApplicationInfoHelper: SDK Version: 1.79.0 D/SASCollector::ActivityLifecycleListener: Activity resumed: com.services.movistar.ar.MainActivity D/SASCollector::OfflineEventManager: Adding event (focus) to buffer. I/SASCollector::SASCOLLECTOR_API: registerForMobileMessages: [ cHQg-UXURzuV2F6M1Rekv7:APA91bG_RY3-BTYAJwyjwJXgkk3wU45Ld1LEw1vADw-n1Z47jRGYrfnLM5osqGuX-dPuSErdp3zfxW9H5W-DWVm2qqY6tGXDd_euNW83LMfcIBaFEto57vIZxmrkOOZQUWs8mYozbS-x] D/SASCollector::SASCollectorExecutor: Executing com.sas.mkt.mobile.sdk.tasks.UpdateToken D/SASCollector::UpdateToken: Sending token cHQg-UXURzuV2F6M1Rekv7:APA91bG_RY3-BTYAJwyjwJXgkk3wU45Ld1LEw1vADw-n1Z47jRGYrfnLM5osqGuX-dPuSErdp3zfxW9H5W-DWVm2qqY6tGXDd_euNW83LMfcIBaFEto57vIZxmrkOOZQUWs8mYozbS-x for device 10ac7910-69b2-4077-bcc4-e31d21464843 D/SASCollector::MidtierServices: Outbound request: PUT https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/10ac7910-69b2-4077-bcc4-e31d21464843 D/SASCollector::MidtierServices: JSON data for com.sas.mkt.mobile.sdk.domain.TokenData : {"appId":"Test.AppMobile.Desa","deviceId":"10ac7910-69b2-4077-bcc4-e31d21464843","token":"Android-cHQg-UXURzuV2F6M1Rekv7:APA91bG_RY3-BTYAJwyjwJXgkk3wU45Ld1LEw1vADw-n1Z47jRGYrfnLM5osqGuX-dPuSErdp3zfxW9H5W-DWVm2qqY6tGXDd_euNW83LMfcIBaFEto57vIZxmrkOOZQUWs8mYozbS-x"} D/SASCollector::MidtierServices: Content-Length: 263 D/SASCollector::ActivityLifecycleListener: Activity destroyed: com.zoontek.rnbootsplash.RNBootSplashActivity D/SASCollector::MidtierServices: Using base server URL: https://execution-ci360.nop.movistar.com.ar/t/mobile D/SASCollector::MidtierServices: Resolving host execution-ci360.nop.movistar.com.ar D/SASCollector::MidtierServices: Resolved to 3.160.119.101 D/SASCollector::OfflineEventManager: Server is available. D/SASCollector::OfflineEventManager: Flushing 1 buffered events. D/SASCollector::PostEventsTask: PostEventsTask created. D/SASCollector::SASCollectorExecutor: Executing com.sas.mkt.mobile.sdk.tasks.PostEventsTask D/SASCollector::OfflineEventManager: DB is clean. D/SASCollector::MidtierServices: Response Code: 200 D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/10ac7910-69b2-4077-bcc4-e31d21464843 AWSALB=1vctTBA00OZyjzL/VMZpdmbKK6G//Fz6Nqa+UGIgAk90n1n0s1ZbkUnQEpvOAxA/BqzqXZB7k2FUyP8+l9c/hcpjLXbmvJGbm18DLYxW8glk3wgIalM95CuMYFlXOuQnfPoqu/RtnJVNS4tWF1qrZXEEb1Ds75Lr0wp6w0MIWZxstyXempEas4JMFoMD0w==; Expires=Tue, 25 Apr 2023 17:15:05 GMT; Path=/ D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/10ac7910-69b2-4077-bcc4-e31d21464843 AWSALBCORS=1vctTBA00OZyjzL/VMZpdmbKK6G//Fz6Nqa+UGIgAk90n1n0s1ZbkUnQEpvOAxA/BqzqXZB7k2FUyP8+l9c/hcpjLXbmvJGbm18DLYxW8glk3wgIalM95CuMYFlXOuQnfPoqu/RtnJVNS4tWF1qrZXEEb1Ds75Lr0wp6w0MIWZxstyXempEas4JMFoMD0w==; Expires=Tue, 25 Apr 2023 17:15:05 GMT; Path=/; SameSite=None; Secure D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/tokens/a8a352b2d200011483d50aec/10ac7910-69b2-4077-bcc4-e31d21464843 _SI_M_DID.a8a352b2d200011483d50aec=f67c9ea7-ae5f-3422-9653-7ddb686bd5a2; Path=/t/mobile; Secure; HttpOnly; SameSite=None D/SASCollector::PostEventsTask: Execute PostEventsTask. D/SASCollector::PostEventsTask: Posting 1 events for CSI: 1681838104798 D/SASCollector::MidtierServices: Outbound request: POST https://execution-ci360.nop.movistar.com.ar/t/mobile/e/a8a352b2d200011483d50aec D/SASCollector::MidtierServices: JSON data for com.sas.mkt.mobile.sdk.domain.EventList : [{"appId":"Test.AppMobile.Desa","csi":1681838104798,"deviceId":"10ac7910-69b2-4077-bcc4-e31d21464843","eventAttributes":{"mobile_device_model":"Android SDK built for arm64","mobile_device_language":"en","mobile_sdk_version":"1.79.0","mobile_screen_height":"2872","mobile_platform":"Android","mobile_carrier_name":"Android","flags":"ns|nl","mobile_country_code":"310","uri":"Test.AppMobile.Desa/","visitor_state":"returning","mobile_platform_version":"10","mobile_device_type":"phone","mobile_screen_width":"1440","mobile_app_version":"412110700","mobile_device_mfg":"Google","mobile_network_code":"260","mobile_app_language":"en"},"eventDateTime":"2023-04-18T17:15:04.797Z","eventType":"focus","loadId":"b24e0324441043661a7c40a9"}] D/SASCollector::MidtierServices: Content-Length: 731 D/SASCollector::MidtierServices: Response Code: 200 D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/e/a8a352b2d200011483d50aec AWSALB=bcrfQ7EJraIc96DfxRBVe9K9P33AeLHKa71LK6uhcjioIga2+O2LnVJyud5ANzLbNxtTJMAdlrRglt4viwGm6cTcsbbyKHFFNojEvpYNmnOV3utgktBw9nCST0rLQ2Vk7QzvWQB2CW6kNte+u8tcNCHrVR7FK3bPfV5ilink6fXA3IH8XH+KiLWF9OIJ1Q==; Expires=Tue, 25 Apr 2023 17:15:05 GMT; Path=/ D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/e/a8a352b2d200011483d50aec AWSALBCORS=bcrfQ7EJraIc96DfxRBVe9K9P33AeLHKa71LK6uhcjioIga2+O2LnVJyud5ANzLbNxtTJMAdlrRglt4viwGm6cTcsbbyKHFFNojEvpYNmnOV3utgktBw9nCST0rLQ2Vk7QzvWQB2CW6kNte+u8tcNCHrVR7FK3bPfV5ilink6fXA3IH8XH+KiLWF9OIJ1Q==; Expires=Tue, 25 Apr 2023 17:15:05 GMT; Path=/; SameSite=None; Secure D/SASCollector::MidtierServices: Part _SI_M_SID=69a9dd7a6dfb2a5fb0b9c805.30.720 2 D/SASCollector::MidtierServices: Subpart 69a9dd7a6dfb2a5fb0b9c805.30.720 3 D/SASCollector::MidtierServices: Timeout update session: 1800000 max: 43200000 D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/e/a8a352b2d200011483d50aec _SI_M_SID=69a9dd7a6dfb2a5fb0b9c805.30.720; Max-Age=1800; Expires=Tue, 18 Apr 2023 17:45:05 GMT; Path=/; Secure; HttpOnly D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/e/a8a352b2d200011483d50aec _SI_M_VID=10ac791069b24077bcc4e31d21464843; Max-Age=1800; Expires=Tue, 18 Apr 2023 17:45:05 GMT; Path=/; Secure; HttpOnly D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/e/a8a352b2d200011483d50aec _SI_M_DLT=893; Max-Age=1800; Expires=Tue, 18 Apr 2023 17:45:05 GMT; Path=/; Secure; HttpOnly D/SASCollector::MidtierServices: Setting cookie https://execution-ci360.nop.movistar.com.ar/t/mobile/e/a8a352b2d200011483d50aec _SI_M_DID.a8a352b2d200011483d50aec=f67c9ea7-ae5f-3422-9653-7ddb686bd5a2; Path=/t/mobile; Secure; HttpOnly D/SASCollector::OfflineEventManager: 1 Events successfully posted. D/SASCollector::OfflineEventManager: No more events to send, entering deep sleep. D/SASCollector::ActivityLifecycleListener: Activity paused: com.services.movistar.ar.MainActivity D/SASCollector::ActivityLifecycleListener: Activity resumed: com.services.movistar.ar.MainActivity
We are using React Native, and inside of the path android/app/libs we've got the SASCollector.jar, and inside of the path android/app/src/main/assets we've got the SASCollector.properties.
In our build.gradle file we've got:
apply plugin: "com.android.application" // project.ext.envConfigFiles = [ // production: ".env.production", // certification: ".env.certification", // integration: ".env.integration", // local: ".env.local", // ] // apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.gradle" // apply plugin: 'com.google.gms.google-services' apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" import com.android.build.OutputFile /** * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets * and bundleReleaseJsAndAssets). * These basically call `react-native bundle` with the correct arguments during the Android build * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the * bundle directly from the development server. Below you can see all the possible configurations * and their defaults. If you decide to add a configuration block, make sure to add it before the * `apply from: "../../node_modules/react-native/react.gradle"` line. * * project.ext.react = [ * // the name of the generated asset file containing your JS bundle * bundleAssetName: "index.android.bundle", * * // the entry file for bundle generation. If none specified and * // "index.android.js" exists, it will be used. Otherwise "index.js" is * // default. Can be overridden with ENTRY_FILE environment variable. * entryFile: "index.android.js", * * // https://reactnative.dev/docs/performance#enable-the-ram-format * bundleCommand: "ram-bundle", * * // whether to bundle JS and assets in debug mode * bundleInDebug: false, * * // whether to bundle JS and assets in release mode * bundleInRelease: true, * * // whether to bundle JS and assets in another build variant (if configured). * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants * // The configuration property can be in the following formats * // 'bundleIn${productFlavor}${buildType}' * // 'bundleIn${buildType}' * // bundleInFreeDebug: true, * // bundleInPaidRelease: true, * // bundleInBeta: true, * * // whether to disable dev mode in custom build variants (by default only disabled in release) * // for example: to disable dev mode in the staging build type (if configured) * devDisabledInStaging: true, * // The configuration property can be in the following formats * // 'devDisabledIn${productFlavor}${buildType}' * // 'devDisabledIn${buildType}' * * // the root of your project, i.e. where "package.json" lives * root: "../../", * * // where to put the JS bundle asset in debug mode * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", * * // where to put the JS bundle asset in release mode * jsBundleDirRelease: "$buildDir/intermediates/assets/release", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in debug mode * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", * * // where to put drawable resources / React Native assets, e.g. the ones you use via * // require('./image.png')), in release mode * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", * * // by default the gradle tasks are skipped if none of the JS files or assets change; this means * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to * // date; if you have any other folders that you want to ignore for performance reasons (gradle * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ * // for example, you might want to remove it from here. * inputExcludes: ["android/**", "ios/**"], * * // override which node gets called and with what additional arguments * nodeExecutableAndArgs: ["node"], * * // supply additional arguments to the packager * extraPackagerArgs: [] * ] */ project.ext.react = [ enableHermes: true, // clean and rebuild if changing ] apply from: "../../node_modules/react-native/react.gradle" /** * Set this to true to create two separate APKs instead of one: * - An APK that only works on ARM devices * - An APK that only works on x86 devices * The advantage is the size of the APK is reduced by about 4MB. * Upload all the APKs to the Play Store and people will download * the correct one based on the CPU architecture of their device. */ def enableSeparateBuildPerCPUArchitecture = false /** * Run Proguard to shrink the Java bytecode in release builds. */ def enableProguardInReleaseBuilds = true /** * The preferred build flavor of JavaScriptCore. * * For example, to use the international variant, you can use: * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` * * The international variant includes ICU i18n library and necessary data * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that * give correct results when using with locales other than en-US. Note that * this variant is about 6MiB larger per architecture than default. */ def jscFlavor = 'org.webkit:android-jsc:+' /** * Whether to enable the Hermes VM. * * This should be set on project.ext.react and mirrored here. If it is not set * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode * and the benefits of using Hermes will therefore be sharply reduced. */ def enableHermes = project.ext.react.get("enableHermes", false); def keystorePropertiesFile = rootProject.file("keystore.properties"); def keystoreProperties = new Properties() keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) def keysPropertiesFile = rootProject.file("keys.properties") def keysProperties = new Properties() keysProperties.load(new FileInputStream(keysPropertiesFile)) android { compileSdkVersion rootProject.ext.compileSdkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } dexOptions { javaMaxHeapSize "4g" } defaultConfig { applicationId "com.services.movistar.ar" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion multiDexEnabled true versionCode 412110700 versionName "12.0.23" vectorDrawables.useSupportLibrary = true resValue "string", "build_config_package", "com.services.movistar.ar" setProperty("archivesBaseName", "MiMovistar-$versionName") } splits { abi { reset() enable enableSeparateBuildPerCPUArchitecture universalApk false // If true, also generate a universal APK include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" } } signingConfigs { debug { storeFile file('debug.keystore') storePassword 'android' keyAlias 'androiddebugkey' keyPassword 'android' } release { if(keystorePropertiesFile.exists()){ storeFile file(keystoreProperties['MYAPP_UPLOAD_STORE_FILE']) storePassword keystoreProperties['MYAPP_UPLOAD_STORE_PASSWORD'] keyAlias keystoreProperties['MYAPP_UPLOAD_KEY_ALIAS'] keyPassword keystoreProperties['MYAPP_UPLOAD_KEY_PASSWORD'] enableV3Signing = true // v1SigningEnabled false } } } buildTypes { debug { signingConfig signingConfigs.debug debuggable true matchingFallbacks = ['debug', 'release'] } release { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. debuggable false signingConfig signingConfigs.release minifyEnabled enableProguardInReleaseBuilds shrinkResources enableProguardInReleaseBuilds zipAlignEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } flavorDimensions "default" productFlavors { production { buildConfigField("String", "SWRVE_API_KEY", keysProperties['SWRVE_API_KEY']) buildConfigField("int", "SWRVE_APP_ID", keysProperties['SWRVE_APP_ID']) buildConfigField "boolean", "IS_DEBUGGABLE", "false" buildConfigField("String", "FIREBASE_APP_ID", keysProperties['FIREBASE_APP_ID']) buildConfigField("String", "FIREBASE_API_KEY", keysProperties['FIREBASE_API_KEY']) buildConfigField("String", "FIREBASE_SENDER_ID", keysProperties['FIREBASE_SENDER_ID']) buildConfigField("String", "FIREBASE_STORAGE_BUCKET", keysProperties['FIREBASE_STORAGE_BUCKET']) buildConfigField("String", "FIREBASE_PROJECT_ID", keysProperties['FIREBASE_PROJECT_ID']) buildConfigField("String", "AES_SECRET_KEY", keysProperties['AES_SECRET_KEY']) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", keysProperties['IS_NEW_ARCHITECTURE_ENABLED']) } f5 { applicationIdSuffix '.f5' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion resValue "string", "build_config_package", "com.services.movistar.ar" buildConfigField("String", "SWRVE_API_KEY", keysProperties['SWRVE_API_KEY']) buildConfigField("int", "SWRVE_APP_ID", keysProperties['SWRVE_APP_ID']) buildConfigField "boolean", "IS_DEBUGGABLE", "false" buildConfigField("String", "FIREBASE_APP_ID", keysProperties['FIREBASE_APP_ID']) buildConfigField("String", "FIREBASE_API_KEY", keysProperties['FIREBASE_API_KEY']) buildConfigField("String", "FIREBASE_SENDER_ID", keysProperties['FIREBASE_SENDER_ID']) buildConfigField("String", "FIREBASE_STORAGE_BUCKET", keysProperties['FIREBASE_STORAGE_BUCKET']) buildConfigField("String", "FIREBASE_PROJECT_ID", keysProperties['FIREBASE_PROJECT_ID']) buildConfigField("String", "AES_SECRET_KEY", keysProperties['AES_SECRET_KEY']) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", keysProperties['IS_NEW_ARCHITECTURE_ENABLED']) } certification { applicationIdSuffix '.certification' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion resValue "string", "build_config_package", "com.services.movistar.ar" buildConfigField("String", "SWRVE_API_KEY", keysProperties['SWRVE_API_KEY_CERT']) buildConfigField("int", "SWRVE_APP_ID", keysProperties['SWRVE_APP_ID_CERT']) buildConfigField "boolean", "IS_DEBUGGABLE", "false" buildConfigField("String", "FIREBASE_APP_ID", keysProperties['FIREBASE_APP_ID_CERT']) buildConfigField("String", "FIREBASE_API_KEY", keysProperties['FIREBASE_API_KEY_CERT']) buildConfigField("String", "FIREBASE_SENDER_ID", keysProperties['FIREBASE_SENDER_ID_CERT']) buildConfigField("String", "FIREBASE_STORAGE_BUCKET", keysProperties['FIREBASE_STORAGE_BUCKET_CERT']) buildConfigField("String", "FIREBASE_PROJECT_ID", keysProperties['FIREBASE_PROJECT_ID_CERT']) buildConfigField("String", "AES_SECRET_KEY", keysProperties['AES_SECRET_KEY']) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", keysProperties['IS_NEW_ARCHITECTURE_ENABLED']) } hotfix { applicationIdSuffix '.hotfix' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion resValue "string", "build_config_package", "com.services.movistar.ar" buildConfigField("String", "SWRVE_API_KEY", keysProperties['SWRVE_API_KEY_CERT']) buildConfigField("int", "SWRVE_APP_ID", keysProperties['SWRVE_APP_ID_CERT']) buildConfigField "boolean", "IS_DEBUGGABLE", "true" buildConfigField("String", "FIREBASE_APP_ID", keysProperties['FIREBASE_APP_ID_CERT']) buildConfigField("String", "FIREBASE_API_KEY", keysProperties['FIREBASE_API_KEY_CERT']) buildConfigField("String", "FIREBASE_SENDER_ID", keysProperties['FIREBASE_SENDER_ID_CERT']) buildConfigField("String", "FIREBASE_STORAGE_BUCKET", keysProperties['FIREBASE_STORAGE_BUCKET_CERT']) buildConfigField("String", "FIREBASE_PROJECT_ID", keysProperties['FIREBASE_PROJECT_ID_CERT']) buildConfigField("String", "AES_SECRET_KEY", keysProperties['AES_SECRET_KEY']) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", keysProperties['IS_NEW_ARCHITECTURE_ENABLED']) } bugfix { applicationIdSuffix '.bugfix' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion resValue "string", "build_config_package", "com.services.movistar.ar" buildConfigField("String", "SWRVE_API_KEY", keysProperties['SWRVE_API_KEY_CERT']) buildConfigField("int", "SWRVE_APP_ID", keysProperties['SWRVE_APP_ID_CERT']) buildConfigField "boolean", "IS_DEBUGGABLE", "true" buildConfigField("String", "FIREBASE_APP_ID", keysProperties['FIREBASE_APP_ID_CERT']) buildConfigField("String", "FIREBASE_API_KEY", keysProperties['FIREBASE_API_KEY_CERT']) buildConfigField("String", "FIREBASE_SENDER_ID", keysProperties['FIREBASE_SENDER_ID_CERT']) buildConfigField("String", "FIREBASE_STORAGE_BUCKET", keysProperties['FIREBASE_STORAGE_BUCKET_CERT']) buildConfigField("String", "FIREBASE_PROJECT_ID", keysProperties['FIREBASE_PROJECT_ID_CERT']) buildConfigField("String", "AES_SECRET_KEY", keysProperties['AES_SECRET_KEY']) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", keysProperties['IS_NEW_ARCHITECTURE_ENABLED']) } integration { applicationIdSuffix '.integration' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion resValue "string", "build_config_package", "com.services.movistar.ar" buildConfigField("String", "SWRVE_API_KEY", keysProperties['SWRVE_API_KEY_CERT']) buildConfigField("int", "SWRVE_APP_ID", keysProperties['SWRVE_APP_ID_CERT']) buildConfigField "boolean", "IS_DEBUGGABLE", "true" buildConfigField("String", "FIREBASE_APP_ID", keysProperties['FIREBASE_APP_ID_CERT']) buildConfigField("String", "FIREBASE_API_KEY", keysProperties['FIREBASE_API_KEY_CERT']) buildConfigField("String", "FIREBASE_SENDER_ID", keysProperties['FIREBASE_SENDER_ID_CERT']) buildConfigField("String", "FIREBASE_STORAGE_BUCKET", keysProperties['FIREBASE_STORAGE_BUCKET_CERT']) buildConfigField("String", "FIREBASE_PROJECT_ID", keysProperties['FIREBASE_PROJECT_ID_CERT']) buildConfigField("String", "AES_SECRET_KEY", keysProperties['AES_SECRET_KEY']) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", keysProperties['IS_NEW_ARCHITECTURE_ENABLED']) } local { applicationIdSuffix '.local' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion resValue "string", "build_config_package", "com.services.movistar.ar" buildConfigField("String", "SWRVE_API_KEY", keysProperties['SWRVE_API_KEY_CERT']) buildConfigField("int", "SWRVE_APP_ID", keysProperties['SWRVE_APP_ID_CERT']) buildConfigField "boolean", "IS_DEBUGGABLE", "false" buildConfigField("String", "FIREBASE_APP_ID", keysProperties['FIREBASE_APP_ID_CERT']) buildConfigField("String", "FIREBASE_API_KEY", keysProperties['FIREBASE_API_KEY_CERT']) buildConfigField("String", "FIREBASE_SENDER_ID", keysProperties['FIREBASE_SENDER_ID_CERT']) buildConfigField("String", "FIREBASE_STORAGE_BUCKET", keysProperties['FIREBASE_STORAGE_BUCKET_CERT']) buildConfigField("String", "FIREBASE_PROJECT_ID", keysProperties['FIREBASE_PROJECT_ID_CERT']) buildConfigField("String", "AES_SECRET_KEY", keysProperties['AES_SECRET_KEY']) buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", keysProperties['IS_NEW_ARCHITECTURE_ENABLED']) } } // applicationVariants are e.g. debug, release applicationVariants.all { variant -> variant.outputs.each { output -> // For each separate APK per architecture, set a unique version code as described here: // https://developer.android.com/studio/build/configure-apk-splits.html def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] def abi = output.getFilter(OutputFile.ABI) if (abi != null) { // null for the universal-debug, universal-release variants output.versionCodeOverride = versionCodes.get(abi) * 1048576 + defaultConfig.versionCode } } } } dependencies { implementation 'com.swrve.sdk.android:swrve-firebase:10.8.0' implementation platform('com.google.firebase:firebase-bom:28.0.1') implementation("com.google.firebase:firebase-iid") implementation fileTree(dir: "libs", include: ["*.jar", "*.aar"]) //noinspection GradleDynamicVersion implementation "com.facebook.react:react-native:+" // From node_modules implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" implementation project(':react-native-splash-screen') implementation 'com.google.android.gms:play-services-tagmanager:17.0.0' implementation 'com.android.installreferrer:installreferrer:2.2' // Add the following if you are using the Adjust SDK inside web views on your app implementation 'com.adjust.sdk:adjust-android-webbridge:4.28.2' implementation 'com.android.volley:volley:1.2.1' implementation 'com.google.android.gms:play-services-ads-identifier:17.0.1' // Libreria para IVR //implementation(name: 'DialMyAppLib-release', ext: 'aar') implementation files('libs/DialMyAppLib-release.aar') implementation 'com.googlecode.libphonenumber:libphonenumber:8.10.6' implementation 'org.apache.cordova:framework:8.1.0' implementation 'com.google.guava:guava:27.0.1-android' implementation 'commons-io:commons-io:2.6' implementation 'com.google.android.gms:play-services-maps:17.0.0' implementation 'com.google.android.gms:play-services-location:19.0.1' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'org.greenrobot:eventbus:3.1.1' implementation 'androidx.work:work-runtime:2.5.0' implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava' implementation 'com.android.installreferrer:installreferrer:2.2' implementation 'com.google.android.gms:play-services-auth-api-phone:17.4.0' //CI360
implementation files('libs/SASCollector.jar') implementation 'com.google.firebase:firebase-core' implementation 'com.google.firebase:firebase-messaging' implementation 'com.google.code.gson:gson:2.8.9' debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { exclude group:'com.facebook.fbjni' } debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' exclude group:'com.squareup.okhttp3', module:'okhttp' } debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { exclude group:'com.facebook.flipper' } if (enableHermes) { def hermesPath = "../../node_modules/hermes-engine/android/"; debugImplementation files(hermesPath + "hermes-debug.aar") releaseImplementation files(hermesPath + "hermes-release.aar") } else { implementation jscFlavor } } // Run this once to be able to run the application with BUCK // puts all compile dependencies into folder libs for BUCK to use task copyDownloadableDepsToLibs(type: Copy) { from configurations.compile into 'libs' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
MainApplication.java:
package com.services.movistar.ar; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.sas.mkt.mobile.sdk.util.SLog; import com.swrve.reactnative.SwrvePlugin; import com.swrve.sdk.SwrveNotificationConfig; import com.swrve.sdk.config.SwrveConfig; import com.swrve.sdk.config.SwrveStack; import android.app.Application; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import com.facebook.react.PackageList; import com.facebook.react.ReactApplication; import com.facebook.react.ReactInstanceManager; import com.facebook.react.ReactNativeHost; import com.facebook.react.ReactPackage; import com.facebook.soloader.SoLoader; import java.lang.reflect.InvocationTargetException; import java.util.List; import android.content.res.Configuration; import android.graphics.Color; import android.webkit.WebView; import android.util.Log; import androidx.annotation.RequiresApi; import com.sas.mkt.mobile.sdk.SASCollector; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override public boolean getUseDeveloperSupport() { Log.v("Swrve", "swrve_api_key=" + BuildConfig.SWRVE_API_KEY); Log.v("Swrve", "swrve_app_id=" + BuildConfig.SWRVE_APP_ID); Log.v("Mi Movistar", "IS_DEBUGGABLE=" + BuildConfig.IS_DEBUGGABLE); return BuildConfig.DEBUG; } @Override protected List<ReactPackage> getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List<ReactPackage> packages = new PackageList(this).getPackages(); // Packages that cannot be autolinked yet can be added manually here, for // example: // packages.add(new MyReactNativePackage()); packages.add(new MyAppPackage()); return packages; } @Override protected String getJSMainModuleName() { return "index"; } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } @Override public void onCreate() { super.onCreate(); SLog.setLevel(SLog.VERBOSE); SASCollector.getInstance().initialize(this); initializeFirebase(this); org.mbte.dialmyapp.app.InjectingRef.defineApplication(this, org.mbte.dialmyapp.app.DialMyAppComponent.class); SwrveConfig swrveConfig = new SwrveConfig(); // To use the EU stack, include this in your config swrveConfig.setSelectedStack(SwrveStack.EU); NotificationChannel channel = null; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { channel = new NotificationChannel("123", "Devapp swrve default channel", NotificationManager.IMPORTANCE_DEFAULT); channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); if (getSystemService(Context.NOTIFICATION_SERVICE) != null) { NotificationManager notificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); } } SwrveNotificationConfig.Builder notificationConfig = new SwrveNotificationConfig.Builder( R.mipmap.ic_launcher_round, R.mipmap.ic_launcher_round, channel) .activityClass(MainActivity.class) .largeIconDrawableId(R.mipmap.ic_launcher_round) .accentColorHex("#00a9e0"); swrveConfig.setNotificationConfig(notificationConfig.build()); SwrvePlugin.createInstance(this, BuildConfig.SWRVE_APP_ID, BuildConfig.SWRVE_API_KEY, swrveConfig); SoLoader.init(this, /* native exopackage */ false); initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); //WebView.setWebContentsDebuggingEnabled(true); // WEBVIEW DEBUG WebView.setWebContentsDebuggingEnabled(false); // WEBVIEW RELEASE if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { setPushChannel(); } } @Override public void onConfigurationChanged(Configuration newConfiguration) { super.onConfigurationChanged(newConfiguration); SASCollector.getInstance().onConfigurationChanged(newConfiguration); } /** * Loads Flipper in React Native templates. Call this in the onCreate method * with something like * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); * * @param context * @param reactInstanceManager */ private static void initializeFlipper( Context context, ReactInstanceManager reactInstanceManager) { if (BuildConfig.DEBUG) { try { /* * We use reflection here to pick up the class that initializes Flipper, * since Flipper library is not available in release mode */ Class<?> aClass = Class.forName("com.services.ReactNativeFlipper"); aClass .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) .invoke(null, context, reactInstanceManager); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } public void initializeFirebase(Context context) { Log.v("Firebase", "Inicializando SDK: " + BuildConfig.FIREBASE_PROJECT_ID); // .setApiKey(Utils.decryptKey(BuildConfig.FIREBASE_API_KEY, // BuildConfig.AES_SECRET_KEY)) if (FirebaseApp.getApps(context).isEmpty()) { FirebaseOptions firebaseOptions = new FirebaseOptions.Builder() .setApplicationId(BuildConfig.FIREBASE_APP_ID) .setApiKey(BuildConfig.FIREBASE_API_KEY) .setGcmSenderId(BuildConfig.FIREBASE_SENDER_ID) .setStorageBucket(BuildConfig.FIREBASE_STORAGE_BUCKET) .setProjectId(BuildConfig.FIREBASE_PROJECT_ID) .build(); FirebaseApp.initializeApp(context, firebaseOptions); } } @RequiresApi(api = android.os.Build.VERSION_CODES.O) private void setPushChannel() { NotificationManager notificationManager = (NotificationManager) this.getSystemService(this.NOTIFICATION_SERVICE); String customAndroidChannel = "ReactNativePushChannel2"; CharSequence channelName = "React Native Channel2"; int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel notificationChannel = new NotificationChannel(customAndroidChannel, channelName, importance); notificationChannel.enableLights(true); notificationChannel.setLightColor(Color.RED); notificationChannel.enableVibration(true); notificationChannel.setShowBadge(true); notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); notificationManager.createNotificationChannel(notificationChannel); SASCollector.getInstance().setPushNotificationChannelId(customAndroidChannel); } }
Our native module is called CI360AndroidModule.java:
package com.services.movistar.ar; import android.os.Handler; import android.os.Looper; import android.util.Log; import androidx.annotation.NonNull; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; import com.sas.mkt.mobile.sdk.SASCollector; import java.util.HashMap; import java.util.Map; public class CI360AndroidModule extends ReactContextBaseJavaModule { public static final String NAME = "CI360AndroidModule"; CI360AndroidModule(ReactApplicationContext context) { super(context); if(!SASCollector.getInstance().isInitialized()) { SASCollector.getInstance().initialize(context.getApplicationContext()); } } @Override @NonNull public String getName() { return NAME; } @ReactMethod public void newPage(String uri) { SASCollector.getInstance().newPage(uri); } @ReactMethod public void addAppEvent(String eventKey, ReadableMap data) { if (data == null) { SASCollector.getInstance().addAppEvent(eventKey, null); return; } HashMap<String, Object> rawData = data.toHashMap(); HashMap<String, String> convertedData = new HashMap<>(); for (Map.Entry<String, Object> entry : rawData.entrySet()) { if(entry.getValue() instanceof String) { convertedData.put(entry.getKey(), (String)entry.getValue()); } } SASCollector.getInstance().addAppEvent(eventKey, convertedData); } @ReactMethod public void sendCI360EventAndroid(String eventId, String keyEventName, String eventValue) { Map <String, String> myEventAttributeMap = new HashMap<>(); myEventAttributeMap.put("Start_Button", "Botón Comenzar fué presionado"); SASCollector.getInstance().addAppEvent("Button_Pressed", myEventAttributeMap); Log.d("EventID", eventId); Log.d("KeyEventName", keyEventName); Log.d("EventValue", eventValue); } @ReactMethod public void sendCI360EventAndroidInApp() { Map <String, String> myEventAttributeMap = new HashMap<>(); SASCollector.getInstance().addAppEvent("test_event_for_in_app", null); Log.d("EventInApp: ", "Fired"); } @ReactMethod public void identity(String value, String type, Promise promise) { SASCollector.getInstance().identity(value, SASCollector.IDENTITY_TYPE_CUSTOMER_ID, new SASCollector.IdentityCallback() { @Override public void onComplete(boolean b) { Log.d("Identity", "Identity called with: " + (b ? "success" : "failure")); new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { promise.resolve(b); } }); } }); } @ReactMethod public void detachIdentity(Promise promise) { //SASCollector.DetachIdentityCallback callback SASCollector.getInstance().detachIdentity(new SASCollector.DetachIdentityCallback() { @Override public void onComplete(boolean b) { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { promise.resolve(b); } }); } }); } @ReactMethod public void startMonitoringLocation() { SASCollector.getInstance().startMonitoringLocation(); } @ReactMethod public void disableLocationMonitoring() { SASCollector.getInstance().disableLocationMonitoring(); } @ReactMethod public void resetDeviceID() { SASCollector.getInstance().resetDeviceID(); } @ReactMethod public void getDeviceID(Callback callback) { callback.invoke(SASCollector.getInstance().getDeviceID()); } @ReactMethod public void getTenantID(Callback callback) { callback.invoke(SASCollector.getInstance().getTenantID()); } @ReactMethod public void getAppVersion(Callback callback) { callback.invoke(SASCollector.getInstance().getApplicationVersion()); } @ReactMethod public void getTagServer(Callback callback) { callback.invoke(SASCollector.getInstance().getTagServer()); } @ReactMethod public void registerForMobileMessage(String token) { SASCollector.getInstance().registerForMobileMessages(token); } @ReactMethod public void handleMobileMessage(Map<String, String> data) { SASCollector.getInstance().handleMobileMessage(data); } }
And we also include the native module in the package in order to use it from react native:
package com.services.movistar.ar; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.uimanager.ViewManager; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class MyAppPackage implements ReactPackage { @Override public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) { //return Collections.emptyList(); return Arrays.<ViewManager>asList( new CI360InlineAdViewManager(reactContext), new CI360InterstitialAdViewManager(reactContext) ); } @Override public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) { List<NativeModule> modules = new ArrayList<>(); modules.add(new SharedPreferencesModule(reactContext)); modules.add(new OpenAppModule(reactContext)); modules.add(new AdditionalPermissionsModule(reactContext)); modules.add(new CI360AndroidModule(reactContext)); return modules; } }
As you can see, we also have another native SDK integrated in our app called DialMyAppLib-release.aar inside of the libs folder and its native module AdditionalPermissionsModule.java. The configuration of this SDK is so similar to CI360, and we have no problem with DialMyApp in our apk in release mode. I'm not telling you that CI360 sdk is the problem, but it's strange why in the release apk it isn´t working correctly.
Hi @LucasAcuna Now I see you were referring to the contents of the dex files in debug and release APKs. Yes, they are the same in both my debug and release dex files. I agree that is an indication something is not right with your release APK.
Looking at your project structure in VSCode, I see you put SASCollector.jar in your app's android/app/libs folder. This is not what I do. I wonder if you create your CI360 Module as a separate library project? If you did like in the cookbook, you will have put SASCollector.jar in your CI360 module project. From your app project, you simply reference your CI360 module's SASCollector.jar. It's not recommended to use two copies of SASCollector.jar. Here is what I did in my app project's app level build.gradle:
implementation files('../../../mobile-sdk-react-native/android/libs/SASCollector.jar')
Here is my project structure. You can see that I have my CI360 library (module-sdk-react-native) in my project:
Hi @wwen , thank you for your answer.
I did the sdk integration (in the same way I showed you) in another react native application in order to see if the original application has some configuration that generates problems when I build an apk in release mode.
The result has surprised me, the sdk in this react native test application works perfectly in the release apk:
As you can see the folder structure and configuration is practically the same with the original application:
So I think that there is something wrong with the configuration of the original project when it tries to generate an apk in release mode. I'll try to figure out what's happening.
If I have no success I'll try to implement the sdk integration in the way you showed me and I'll let you know.
Thank you for your time!
Hi @wwen , I did some test with my project and I finally solved the problem.
This behavior happens because sometimes when the android compiler creates a release apk, it makes some optimizations in order to reduce the apk’s size, deleting unused code and renaming classes and methods.
You can avoid this default behavior of the compiler setting up a rule in the proguard-rules.pro file in the path: android/app.
In our case the rule is:
-keep class com.sas.mkt.mobile.sdk.** { *; }
And that’s all! Everything works as I expected:
Thank you for your time!
Hi @LucasAcuna I am so glad that you solved your problem, and thank you for letting me know of your solution.
If you also build iOS app, there is a bug I want you to be aware of. It is in identity and detachIdentity. If you try to log in without an internet connection, the app will crash. We will have an updated cookbook to address this issue soon. So please keep an eye on it.
Hi @wwen , thank you for the information about the sdk integration on the IOS platform, I'll keep an eye on it when I start to implement that part.
Have a good day!
Want to review SAS CI360? G2 is offering a gift card or charitable donation for each accepted review. Use this link to opt out of receiving anything of value for your review.
Listen to the Reimagine Marketing podcast
Assess your marketing efforts with a free tool
SAS Customer Intelligence Learning Subscription (login required)
Compatibility notice re: SAS 9.4M8 (TS1M8) or later
SAS' Peter Ansbacher shows you how to use the dashboard in SAS Customer Intelligence 360 for better results.
Find more tutorials on the SAS Users YouTube channel.
Want to review SAS CI360? G2 is offering a gift card or charitable donation for each accepted review. Use this link to opt out of receiving anything of value for your review.
Listen to the Reimagine Marketing podcast
Assess your marketing efforts with a free tool
SAS Customer Intelligence Learning Subscription (login required)
Compatibility notice re: SAS 9.4M8 (TS1M8) or later