customerio / customerio-android Goto Github PK
View Code? Open in Web Editor NEWThis is the official Customer.io SDK for Android.
License: MIT License
This is the official Customer.io SDK for Android.
License: MIT License
SDK version: v3.1.1
Environment: Production
Are logs available?
main (blocked):tid=1 systid=32402 | waiting to lock <0x0844ef67> (ic.b) held by thread 95
at io.customer.sdk.util.AndroidSimpleTimer.timerDone(AndroidSimpleTimer.java:73)
at io.customer.sdk.util.AndroidSimpleTimer.access$timerDone(AndroidSimpleTimer.java:21)
at io.customer.sdk.util.AndroidSimpleTimer$scheduleAndCancelPrevious$1$newTimer$1$1.onFinish(SimpleTimer.kt:47)
at android.os.CountDownTimer$1.handleMessage(CountDownTimer.java:142)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8741)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
DefaultDispatcher-worker-11 (blocked):tid=95 systid=3863 | waiting to lock <0x06f58114> (ic.a$a) held by thread 1
at android.os.CountDownTimer.cancel(CountDownTimer.java)
at io.customer.sdk.util.AndroidSimpleTimer.unsafeCancel(SimpleTimer.kt:97)
at io.customer.sdk.util.AndroidSimpleTimer.cancel(SimpleTimer.kt:83)
at io.customer.sdk.queue.QueueImpl.run(Queue.kt:106)
at io.customer.sdk.queue.QueueImpl$runAsync$1.invokeSuspend(Queue.kt:124)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.java:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Describe the bug
This randomly happens on different device brands and OS versions ranging from SDK 28 to 33.
To Reproduce
Expected behavior
The library should not be causing an ANR.
Screenshots
Additional context
Version(s) of SDK bug appears: 3.0.0-beta.1
I have tested in-app messages by sending some test to my phone :
The message is displayed in my test, but I got a dangerous error message on the Logcat
It seems that the Banner (or Dialog) is created from a non-UI Thread
Phone Model :
OnePlus 5T - Android 10
Huawei P20 - Android 10
OnePlus 6T - Android 11
App Target :
Send an in-app Example Banner
or Example Welcome
const val targetSdkVersion = 32
const val compileSdkVersion = 32
The Overlay should be created from UI Thread
SDK version: 3.1.0
Environment: Production
Are logs available?
Fatal Exception: java.lang.NullPointerException: null cannot be cast to non-null type io.customer.messagingpush.MessagingPushModuleConfig at java.util.Objects.requireNonNull(Objects.java:228) at io.customer.messagingpush.di.DiGraphMessagingPushKt.getModuleConfig(DiGraphMessagingPush.kt:23) at io.customer.messagingpush.CustomerIOPushNotificationHandler.getModuleConfig(CustomerIOPushNotificationHandler.kt:62) at io.customer.messagingpush.CustomerIOPushNotificationHandler.handleNotification(CustomerIOPushNotificationHandler.kt:198) at io.customer.messagingpush.CustomerIOPushNotificationHandler.handleMessage(CustomerIOPushNotificationHandler.kt:105) at io.customer.messagingpush.CustomerIOFirebaseMessagingService$Companion.handleMessageReceived(CustomerIOFirebaseMessagingService.kt:56) at io.customer.messagingpush.CustomerIOFirebaseMessagingService$Companion.onMessageReceived(CustomerIOFirebaseMessagingService.kt:31) at io.customer.messagingpush.CustomerIOFirebaseMessagingService$Companion.onMessageReceived$default(CustomerIOFirebaseMessagingService.kt:27) at io.customer.messagingpush.CustomerIOFirebaseMessagingService$Companion.onMessageReceived(CustomerIOFirebaseMessagingService.kt:8) at cz.ai.aschool.movies.fcm.FirebaseMessagingServiceMooveez.onMessageReceived(FirebaseMessagingServiceMooveez.java:99)
Describe the bug
After upgrade from customer io 2.1.1 to 3.1.0 Firebase Push Notification causes crash of our app.
I can provide you e-mails and times when crash occured.
Code in our class FirebaseMessagingServiceMooveez only bypasses RemoteMessage received.
Write the documentation for the SDK. Documentation to give to our customer's engineering team to implement and use the SDK.
To help our customers succeed, we can provide to them documentation on how to get up and running quick and easy with our mobile SDK. Get the SDK into their app and help them start using it, quick.
This is a docs change, only. No QA needed.
This is done when we have provided the docs team with everything that they need to publish our SDK documentation for customers to use.
In order for our customers to use the SDK, they must give us some information in order for us to be able to send data to their CIO workspace. This task is to get this information and save it on the device. With this task, we are going to cater the authentication process along with the storage of authentication token
, also create an interface for the customer to interact and configure the SDK accordingly.
This task is required for our customers to use the SDK. The SDK cannot do any work successfully without this task.
Not much to test here. If future tasks such as identify a customer works after this task, we have tested it successfully.
CIO.configure(siteId: String, apiKey: String)
Save the siteId
and apiKey
to shared preferences to be reused and add the region
entity to be configured.
Create a queue task to test credentials valid. In development mode, throw an IllegalArgumentException()
. If not in development, ignore the request so no siteid or apikey get saved.
Create a queue task to find account region. Once response comes back from that, save the country code.
SDK version: 3.3.0 - 3.4.2
Environment: Production
Are logs available?
Error fetching messages: canceled due to java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/Base64;
2023-05-06 17:05:04.673 22480-22563 AndroidRuntime cz.ai.aschool.movies E FATAL EXCEPTION: OkHttp Dispatcher
Process: cz.ai.aschool.movies, PID: 22480
java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/Base64;
at build.gist.data.listeners.Queue$gistQueueService$2.invoke$lambda-2(Queue.kt:35)
at build.gist.data.listeners.Queue$gistQueueService$2.$r8$lambda$PAgpBkRd0H90geyu2KeSV3WZpLE(Queue.kt)
at build.gist.data.listeners.Queue$gistQueueService$2$$ExternalSyntheticLambda0.intercept(D8$$SyntheticClass)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.ClassNotFoundException: Didn't find class "java.util.Base64" on path: DexPathList[[zip file "/data/app/cz.ai.aschool.movies-2/base.apk"],nativeLibraryDirectories=[/data/app/cz.ai.aschool.movies-2/lib/x86, /data/app/cz.ai.aschool.movies-2/base.apk!/lib/x86, /vendor/lib, /system/lib]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
at build.gist.data.listeners.Queue$gistQueueService$2.invoke$lambda-2(Queue.kt:35)
at build.gist.data.listeners.Queue$gistQueueService$2.$r8$lambda$PAgpBkRd0H90geyu2KeSV3WZpLE(Queue.kt)
at build.gist.data.listeners.Queue$gistQueueService$2$$ExternalSyntheticLambda0.intercept(D8$$SyntheticClass)
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.kt:109)
at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(RealCall.kt:201)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:517)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Suppressed: java.lang.ClassNotFoundException: java.util.Base64
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 10 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
2023-05-06 17:05:08.756 22480-22554 Gist cz.ai.aschool.movies E Error fetching messages: canceled due to java.lang.NoClassDefFoundError: Failed resolution of: Ljava/util/Base64;
Describe the bug
After updating to version 3.3.2 I have found, that my app starts crashing. Last working cio SKD version is 3.2.0.
I suspect Gist dependency update as a root cause of the problem, as java.util.Base64 is available from Android 8.
But cio declares support for Android 5 so this is why i consider it to be a bug.
To Reproduce
Run your SDK on Android 5-7
Expected behavior
Screenshots
Additional context
SDK version: 3.6.3
**Environment:**Production
Are logs available?
Fatal Exception: java.util.ConcurrentModificationException:
at java.util.ArrayList$Itr.next(ArrayList.java:860)
at io.customer.messaginginapp.gist.presentation.GistSdk.handleGistError$messaginginapp_release(GistSdk.kt:228)
at io.customer.messaginginapp.gist.presentation.GistView.error(GistView.kt:138)
at io.customer.messaginginapp.gist.presentation.engine.EngineWebView$setupTimeout$1.run(EngineWebView.kt:98)
at java.util.TimerThread.mainLoop(Timer.java:562)
at java.util.TimerThread.run(Timer.java:512)
Describe the bug
Crash but user without any inapp message (not deployed on our automations)
To Reproduce
no idea
Expected behavior
no cash
Is your feature request related to a problem? Please describe.
If users open a push with the app open, the app restarts. That means discarding whatever state and progress users had in the app, and potentially re-running unnecessary app start logic. We don’t see a reason for having this default behavior and we believe the app should be the one in control of what happens with the navigation stack when a push notification is opened. We’d love to hear from your end if there’s any reason for the existing behavior, but it’s currently not bringing any benefits for us.
Describe the solution you'd like
The root cause is here:
private val notificationIntentFlags: Int = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
So the easiest solution is to simply drop these flags.
Describe alternatives you've considered
In order to keep the current behavior for existing clients, you could introduce a way to configure this so clients can opt out of these flags.
Additional context
Right now the iOS SDK doesn’t restart the iOS app whenever a push is opened, so this change would make the SDK behavior more consistent across platforms.
SDK version: 3.6.5
Environment: Production Android
Are logs available?
Describe the bug
Crash
In order to send a push notification to a mobile device, you need to:
This issue has to do with item 2 above.
Note: This task is assumed that you can add/update device token in the SDK already.
Today, our customers delete push notification device tokens from CIO via (1) 3rd party services like Segment.io or (2) they write custom code in their apps to send the token to CIO via our API. This issue is to do item (2) for our customers. Deleting a push notification device token from CIO will now just be 1 line of code:
Customers.deviceToken = null
...and that's it!
Our SDK can also help our customers by handling various use case scenarios for them. Example, if someone logs out of an account in your app and logs into a different account. Our SDK should have a default behavior of deleting the device token from the original account and then add the same device token to the newly logged in user. Our customers would need to handle all of these scenarios manually (causing possible bugs to their workspace).
There are some use cases that this issue needs to be able to handle.
Customers
singleton. The API for the customer should be:Customers.deviceToken = null
Customers
singleton. The API for the customer should be:Customers.deleteDeviceToken()
This is a convenient function that matches our API. Does the same thing as Customers.deviceToken = null
.
Create tasks in the queue system to delete device tokens when this function is called.
When Customers.updateX()
functions are called to logout the customer, make a queue task to delete the device token from the person in CIO. Do not delete the token from persistent storage, however. The device token is shared with all people who log into accounts in the mobile app on the same 1 device.
Add an argument that allows customer to not automatically delete device token from account: Customers.updateX(...., deleteDeviceToken = true)
. Note the default value.
Customers.deviceToken = "XXX"
so when it's called with a non-null value, create a queue task to delete the previously set device token if there is a device token already saved in persistent storage.Customers.setDeviceToken(null)
Customers.deleteDeviceToken()
Version(s) of SDK bug appears:
implementation 'io.customer.android:tracking:3.0.0-beta.2'
implementation 'io.customer.android:messaging-push-fcm:3.0.0-beta.2'
implementation 'io.customer.android:messaging-in-app:3.0.0-beta.2'
In App Message doesn't appear. However I can see following logs:
I/Gist: Current gist route set to: Home
I/Gist: Messages timer started
I/Gist: Fetching user messages
I/Gist: No messages found for user
I/Gist: Fetching user messages
I/Gist: No messages found for user
I/Gist: Fetching user messages
I/Gist: No messages found for user
Following is in Application class:
CustomerIO.Builder(
siteId = "xxxxx",
apiKey = "xxxxx",
appContext = this
)
.addCustomerIOModule(ModuleMessagingPushFCM())
.addCustomerIOModule(ModuleMessagingInApp("xxxxxxxxx"))
.autoTrackScreenViews(true)
.setRequestTimeout(8000L)
.build()
Following code is called on App Launch (HomeViewModel):
CustomerIO.instance().identify(
identifier = profile.userId?.toString()!!,
attributes = mapOf("email" to (profile.email ?: ""), "firstName" to profile.firstName!!)
)
HomeActivity has label "Home" in manifest
In App Message Should Appear On Home Screen
SDK version: 3.6.4
Environment: Development and Production
Are logs available? I don’t think it’s relevant
Describe the bug
When users grant push notifications permission, CIO doesn’t update and still has push_enabled
as false
for that particular device. It only gets updated after the app is killed and opened again. This issue is also present on iOS.
Looking at here I kinda see why this is the case since we simply make that call once and that’s it, and it seems it’s similar on iOS as well.
To Reproduce
push_enabled
is false
push_enabled
is still false
push_enabled
is updated to true
Expected behavior
Either the SDK should automatically notice the permission was granted so it can update itself right away (I don’t think there’s a good way to achieve that, though, since what Accompanist currently does for that is to simply check the permission in the resume lifecycle event, for instance), or it should provide an API that we can call to update this as soon as the permission is granted. Is there currently an API for this that I’m missing? Do I simply need to call identify
again or should I simply restart CIO if the permission is granted?
I also think the documentation should highlight this case as it’s quite critical for us that this is updated as soon as our users grant permission. Maybe here you could say that if an identified user grants permission, there’s still something we need to do to make sure this is immediately reflected on the customerio side?
SDK version:
3.6.6
Environment: Development or Production
Production
Are logs available?
Fatal Exception: android.util.AndroidRuntimeException: android.util.AndroidRuntimeException: android.webkit.WebViewFactory$MissingWebViewPackageException: Failed to load WebView provider: No WebView installed
at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:382)
at android.webkit.WebView.getFactory(WebView.java:2599)
at android.webkit.WebView.ensureProviderCreated(WebView.java:2593)
at android.webkit.WebView.setOverScrollMode(WebView.java:2661)
at android.view.View.<init>(View.java:5648)
at android.view.View.<init>(View.java:5823)
at android.view.ViewGroup.<init>(ViewGroup.java:707)
at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:59)
at android.webkit.WebView.<init>(WebView.java:426)
at android.webkit.WebView.<init>(WebView.java:368)
at android.webkit.WebView.<init>(WebView.java:350)
at android.webkit.WebView.<init>(WebView.java:337)
at android.webkit.WebView.<init>(WebView.java:327)
at io.customer.messaginginapp.gist.presentation.engine.EngineWebView.<init>(EngineWebView.kt:28)
at io.customer.messaginginapp.gist.presentation.engine.EngineWebView.<init>(EngineWebView.kt:20)
at io.customer.messaginginapp.gist.presentation.GistView.<init>(GistView.kt:27)
at io.customer.messaginginapp.gist.presentation.GistSdk.init$lambda$0(GistSdk.kt:106)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8757)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by android.util.AndroidRuntimeException: android.webkit.WebViewFactory$MissingWebViewPackageException: Failed to load WebView provider: No WebView installed
at android.webkit.WebViewFactory.getProviderClass(WebViewFactory.java:554)
at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:353)
at android.webkit.WebView.getFactory(WebView.java:2599)
at android.webkit.WebView.ensureProviderCreated(WebView.java:2593)
at android.webkit.WebView.setOverScrollMode(WebView.java:2661)
at android.view.View.<init>(View.java:5648)
at android.view.View.<init>(View.java:5823)
at android.view.ViewGroup.<init>(ViewGroup.java:707)
at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:59)
at android.webkit.WebView.<init>(WebView.java:426)
at android.webkit.WebView.<init>(WebView.java:368)
at android.webkit.WebView.<init>(WebView.java:350)
at android.webkit.WebView.<init>(WebView.java:337)
at android.webkit.WebView.<init>(WebView.java:327)
at io.customer.messaginginapp.gist.presentation.engine.EngineWebView.<init>(EngineWebView.kt:28)
at io.customer.messaginginapp.gist.presentation.engine.EngineWebView.<init>(EngineWebView.kt:20)
at io.customer.messaginginapp.gist.presentation.GistView.<init>(GistView.kt:27)
at io.customer.messaginginapp.gist.presentation.GistSdk.init$lambda$0(GistSdk.kt:106)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8757)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Caused by android.webkit.WebViewFactory$MissingWebViewPackageException: Failed to load WebView provider: No WebView installed
at android.webkit.WebViewFactory.getWebViewContextAndSetProvider(WebViewFactory.java:447)
at android.webkit.WebViewFactory.getProviderClass(WebViewFactory.java:512)
at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:353)
at android.webkit.WebView.getFactory(WebView.java:2599)
at android.webkit.WebView.ensureProviderCreated(WebView.java:2593)
at android.webkit.WebView.setOverScrollMode(WebView.java:2661)
at android.view.View.<init>(View.java:5648)
at android.view.View.<init>(View.java:5823)
at android.view.ViewGroup.<init>(ViewGroup.java:707)
at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:59)
at android.webkit.WebView.<init>(WebView.java:426)
at android.webkit.WebView.<init>(WebView.java:368)
at android.webkit.WebView.<init>(WebView.java:350)
at android.webkit.WebView.<init>(WebView.java:337)
at android.webkit.WebView.<init>(WebView.java:327)
at io.customer.messaginginapp.gist.presentation.engine.EngineWebView.<init>(EngineWebView.kt:28)
at io.customer.messaginginapp.gist.presentation.engine.EngineWebView.<init>(EngineWebView.kt:20)
at io.customer.messaginginapp.gist.presentation.GistView.<init>(GistView.kt:27)
at io.customer.messaginginapp.gist.presentation.GistSdk.init$lambda$0(GistSdk.kt:106)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8757)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
Describe the bug
It seam something related with the in app message.
To Reproduce
No clear path. I'm getting this exception on Firebase.
Expected behavior
No crash.
We have the goal of allowing customers to show rich push notifications on a device on day 1 of signing up for CIO. Let's have the SDK to the heavy-lifting for you to showing rich push notifications for you.
What is rich push? These are push notifications that contain:
Rich push can do more then this but this task is focused only on the 2-3 items above.
This task is only for the FCM service. No other Android push notification service planned for this specific task at this time.
Today, if a customer wants to send rich push notifications to their device, it requires custom code in the mobile app. We want to add feature to the SDK to give the ability to display rich push notifications with little work on the engineer's end. We require some setup from the engineering team but after setup, CIO can take care of the rest.
Customers will be using the existing CIO custom payload feature they are already using in the CIO editor. We will provide a JSON template to modify to be able to send push notifications that the mobile SDK can interpret.
FCM's custom payload follows a strict format. Here are some of the rules:
notification
key is reserved by the FCM Android and iOS SDK to display a push notification for you. This is very similar to what we will be doing as well - you provide information to us and the CIO SDK will display a push notification for you.data
key is used to provide custom data to the app. This allows you to send data that the FCM Android and iOS SDK ignores and passes to your app to process. This is what we must use to pass data to the CIO SDK. data
is an object with string values, only.FYI: If a custom payload does not have
data
in the custom payload, there is a chance that the SDK will not be given the FCM custom payload at all to process.
This means that the custom payload will look like this:
{
"data": {
"CIO-title": "title of push notification",
"CIO-body": "message of push",
"CIO-image": "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpawsindoorssouthend.com%2Fwp-content%2Fuploads%2F2020%2F04%2Ftips-for-choosing-doggy-day-care.jpg",
"CIO-action": "remote-habits://deep?message=hello&message2=world",
"CIO-button1-title": "Shop",
"CIO-button1-action": "remote-habits://deep?message=go&message2=shopping!",
"CIO-button2-title": "Open",
"CIO-button2-action": "remote-habits://deep?message=action&message2=opened",
"CIO-channel-id": "channel-id-push"
}
}
The SDK will see the CIO-
prefix and handle it for you.
This is a feature add task so QA is required.
CIO-image
to not display an image).Tip: See prototype code for help
RemoteMessage
in the FCM SDK so it can parse it.Messaging.onMessageReceived(message: RemoteMessage): MessagingResult?
that is provided the FCM message. Our SDK will not provide it's own FirebaseMessagingService
subclass but instead will have this function get called when a message is received by FCM.
data
key with the prefix CIO-
then an object will be returned. This object will have fields in it such as: didDisplayNotification
saying if a push notification was presented on the device by the SDK. This will help the engineers determine what they should do next with the push notification if the push contains extra data
it needs to process.CIO-image
is missing, don't show an image).
BroadcastReceiver
that will get called when the push notification is touched or the action buttons are touched.
BroadcastReceiver
.There might be a case where registerToken
might get called before identify
We need to come up with a way, where we fix the sequence, either in Background queue or come up with an automated way of fetching token again after identify
.
Add to our mobile SDK the ability to identify a person. This is very similar to adding/updating a customer with the CIO API, but with different API unique to the mobile SDK. This task is useful for customers who have mobile apps with user accounts and they want to identify the customers in CIO workspaces.
Customers
singleton. The customer API will be:Customers.identify(id: String, attributes: Map<String, String | Int | Bool>? = null)
Add client-side validation for the ID. Make sure it's 150 characters or less in length. In development mode, throw IllegalArgument exception if given ID that's too long. Not in development mode, ignore the request.
Save the identifier in persistent storage (shared prefs) to give the SDK a state.
Note: It may be better to use Pair
data type or something else. This is open for discussion.
Create a queue task to add/update a customer with this given identifier and optional attributes.
Add functions to the Customers
singleton. The customer API will be:
Customers.update(attributes: Map<String, String | Int | Bool>)
This will create a new task to the queue to update a customer.
Note: In development mode: throw exception if a customer has not yet been identified. Non-development, ignore the function call.
SDK version: 3.1.1
Describe the issue
I had an integration with Customer.IO without SDK, but i want to monitor events like opened and delivery, so I add the Customer IO SDK for android following the documentation, but my deeplinks was stop working, when I click in notification it redirect me for main activity, if the deeplink is a web page, it opens the page on browser but stay in background, with app in main activity.
OBS: The notification is delivery and monitory correct, only problem is the handle of deeplinks.
In order to send a push notification to a mobile device from CIO, you need to:
This task here has to do with item 2 above.
Note: Deleting device tokens is not in the scope of this task. That's in another task
Today, our customers send push notification device tokens to CIO via (1) 3rd party services like Segment or (2) they write custom code in their apps to send the token to CIO via our API. This task is to do item (2) for our customers. Sending a push notification device token to CIO will now just be 1 line of code:
Customers.deviceToken = "XXXXXXXXXXXXX"
...and that's it!
Along with sending a device token, this task will also set the platform
and last_used
properties automatically.
This is a feature add task which means we require QA testing on this task.
This use case is covered by a different issue, not in this task's scope.
Customers
singleton. The API for the customer should be:Customers.deviceToken = "XXXXXXXXXXXXX"
For now, we do not allow null
to be passed in.
There is no client side validation to make sure token is valid. We accept anything.
Whatever string value is provided to us via the singleton, we capture to persistent storage (shared prefs) in our case.
Create tasks in the queue system to add/update token.
In this task, we add device
object to request:
"device": {
"id": "<token>",
"platform": "android",
"last_used": Date.now
}
When Customer.updateX()
functions are called to login a new customer, make a queue task to add/update device token to person if a device token already exists for the device.
When the initialization code is called, add to queue a new update device token task so we can update last_used
.
Customers.setDeviceToken("XXXX")
SDK version: 3.6.4
Environment: Development and Production
Are logs available?
There’s something interesting in the logs: while the app is in the background (open or closed), when I send a notification with deep link, I see this:
Received message with empty deliveryId
Handling push message. Bundle: …
But when the notification doesn’t have a deep link, I only see the first message, even though the notification shows up as usual:
Received message with empty deliveryId
So it’s like this is never being called for some reason?
Describe the bug
CustomerIOPushNotificationCallback
isn’t being called if we send a notification without a deep link while the app is in the background (open or closed). It works fine if the app is in the foreground, or if the notification has a deep link.
To Reproduce
CustomerIOPushNotificationCallback
won’t be calledExpected behavior
CustomerIOPushNotificationCallback
should always be called.
Additional context
I’ve reproduced this on a Pixel 4a running Android 13 so far.
Is your feature request related to a problem? Please describe.
Hello!
We're trying to merge duplicated users in our App.
According to the documentation you provide, this can be done via web management, or calling the /api/v1/merge_customers
endpoint.
I see there is no function to merge
users in customer.io sdk for Android, nor iOS.
Are you planning to include a function to merge two users in the sdk?
Thanks in advance!
Describe the solution you'd like
An idea to user as starting point could be
Android (CustomerIO.kt
)
fun merge(identifier: String, newIdentifier: String) {
... // call to /api/v1/merge_customers
}
iOS (CustomerIO.swift
)
func merge(
identifier: String,
newIdentifier: String
)
Additional context
Having it in a newer version of the library would be awesome!
The notification icon is currently set to the application icon inside CustomerIOPushNotificationHandler. I'd like a way to set a different notification icon as for the majority of cases, the application icon will have a shape background which will be masked on Lollipop+ devices (Display a white circle/square).
--
Send test notification when a custom notification icon has been set.
Currently setting the application icon when building the notification:
FCM has some documentation that sets defaults when the icon does not exists. Unfortunately because the call to setSmallIcon
these defaults do not seem to take.
<!-- Set custom default icon. This is used when no icon is set for incoming notification messages.
See README(https://goo.gl/l4GJaQ) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@drawable/ic_stat_ic_notification" />
<!-- Set color used with incoming notification messages. This is used when no color is set for the incoming
notification message. See README(https://goo.gl/6BKBk7) for more. -->
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />
I'm not sure if I'd prefer to set ApplicationManifest metadata to set the notification, or if a programmatic method similar to CustomerIOFirebaseMessagingService.onMessageReceived
in order to achieve this.
SDK version: 3.5.2
Are logs available?
[CIO]: identify profile d7061a7254bbf5e8
D/[CIO]: identify profile d7061a7254bbf5e8, {reason=-, device_model=HD1901, app_version=20.2.0, cio_sdk_version=30, timezone=Asia/Kolkata, created_at=1687502615, device_region=in, language=en, device_os=Android, unsubscribed=false, subscribe_source=Mobile_App, push_enabled=true, id=d7061a7254bbf5e8, email=}
I/[CIO]: adding queue task IdentifyProfile
D/[CIO]: added queue task data {"identifier":"d7061a7254bbf5e8","attributes":{"reason":"-","device_model":"HD1901","app_version":"20.2.0","cio_sdk_version":30,"timezone":"Asia/Kolkata","created_at":1687502615,"device_region":"in","language":"en","device_os":"Android","unsubscribed":"false","subscribe_source":"Mobile_App","push_enabled":"true","id":"d7061a7254bbf5e8","email":""}}
D/[CIO]: processing queue status QueueStatus(siteId=06f9c82b54a139b44d51, numTasksInQueue=1)
I/[CIO]: queue timer: scheduled to run queue in 30.0 seconds seconds
D/[CIO]: storing identifier on device storage d7061a7254bbf5e8
D/[CIO]: first time identified or changing identified profile
D/[CIO]: automatically registering device token to newly identified profile
I/[CIO]: registering device token fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8, attributes: {device_os=30, device_model=HD1901, device_manufacturer=OnePlus, app_version=3.3.46, cio_sdk_version=3.5.1, device_locale=en-IN, push_enabled=true}
D/[CIO]: storing device token to device storage fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8
I/[CIO]: adding queue task RegisterDeviceToken
D/[CIO]: added queue task data {"profileIdentified":"d7061a7254bbf5e8","device":{"id":"fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8","platform":"android","lastUsed":1687502615,"attributes":{"device_os":30,"device_model":"HD1901","device_manufacturer":"OnePlus","app_version":"3.3.46","cio_sdk_version":"3.5.1","device_locale":"en-IN","push_enabled":true}}}
D/[CIO]: processing queue status QueueStatus(siteId=06f9c82b54a139b44d51, numTasksInQueue=2)
I/[CIO]: queue timer: scheduled to run queue in 30.0 seconds seconds
I/[CIO]: registering device token fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8, attributes: {device_os=30, device_model=HD1901, device_manufacturer=OnePlus, app_version=3.3.46, cio_sdk_version=3.5.1, device_locale=en-IN, push_enabled=true}
D/[CIO]: storing device token to device storage fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8
I/[CIO]: adding queue task RegisterDeviceToken
D/[CIO]: added queue task data {"profileIdentified":"d7061a7254bbf5e8","device":{"id":"fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8","platform":"android","lastUsed":1687502615,"attributes":{"device_os":30,"device_model":"HD1901","device_manufacturer":"OnePlus","app_version":"3.3.46","cio_sdk_version":"3.5.1","device_locale":"en-IN","push_enabled":true}}}
D/[CIO]: processing queue status QueueStatus(siteId=06f9c82b54a139b44d51, numTasksInQueue=3)
I/[CIO]: queue timer: scheduled to run queue in 30.0 seconds seconds
D/[CIO]: Timer czvaaoihae making a timer for 30.0 seconds
D/[CIO]: Timer czvaaoihae making a timer for 30.0 seconds
I/System.out: 2131296975permission was granted
V/FA: Activity resumed, time: 268653351
D/DecorView: onWindowFocusChangedFromViewRoot hasFocus: true, DecorView@7711e71[NewHomeActivity]
D/ViewRootImpl[NewHomeActivity]: windowFocusChanged hasFocus=true inTouchMode=true
V/FA: Inactivity, disconnecting from the service
D/[CIO]: Timer czvaaoihae timer is done! It's been reset
I/[CIO]: queue timer: now running queue
D/[CIO]: Timer czvaaoihae timer is being cancelled
D/[CIO]: queue starting to run tasks...
D/[CIO]: queue querying next task. criteria: QueueQueryCriteria(excludeGroups=[])
D/[CIO]: queue tasks left to run: 3 out of 3
D/[CIO]: queue next task to run: 8ee6b040-1db1-49f2-8175-3383905e8e4d, IdentifyProfile, {"identifier":"d7061a7254bbf5e8","attributes":{"reason":"-","device_model":"HD1901","app_version":"20.2.0","cio_sdk_version":30,"timezone":"Asia/Kolkata","created_at":1687502615,"device_region":"in","language":"en","device_os":"Android","unsubscribed":"false","subscribe_source":"Mobile_App","push_enabled":"true","id":"d7061a7254bbf5e8","email":""}}, QueueTaskRunResults(totalRuns=0)
D/[CIO]: queue task 8ee6b040-1db1-49f2-8175-3383905e8e4d ran successfully
D/[CIO]: queue deleting task 8ee6b040-1db1-49f2-8175-3383905e8e4d
D/[CIO]: queue querying next task. criteria: QueueQueryCriteria(excludeGroups=[])
D/[CIO]: queue tasks left to run: 2 out of 3
D/[CIO]: queue next task to run: 4f3b4f3c-b0c3-40b3-8907-4f229427e1a8, RegisterDeviceToken, {"profileIdentified":"d7061a7254bbf5e8","device":{"id":"fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8","platform":"android","lastUsed":1687502615,"attributes":{"device_os":30,"device_model":"HD1901","device_manufacturer":"OnePlus","app_version":"3.3.46","cio_sdk_version":"3.5.1","device_locale":"en-IN","push_enabled":true}}}, QueueTaskRunResults(totalRuns=0)
D/[CIO]: queue task 4f3b4f3c-b0c3-40b3-8907-4f229427e1a8 ran successfully
D/[CIO]: queue deleting task 4f3b4f3c-b0c3-40b3-8907-4f229427e1a8
D/[CIO]: queue querying next task. criteria: QueueQueryCriteria(excludeGroups=[])
D/[CIO]: queue tasks left to run: 1 out of 3
D/[CIO]: queue next task to run: ed7a4097-beec-4a19-8f22-a299c9030e68, RegisterDeviceToken, {"profileIdentified":"d7061a7254bbf5e8","device":{"id":"fSX-oAfVT46HdIRA1CnsiC:APA91bHunTrg0iJi47nRCs8am3eAs_L3UBkEcaqWcHWkp2FqJRvy_Dm_bcq0PMrb0EoaB1i4xCjkvd61IWvsVtomMPU8e_YYwQPSGitsSzjGZhdt4uiS52l3e2ZKMVfTrneNcRcGTlI8","platform":"android","lastUsed":1687502615,"attributes":{"device_os":30,"device_model":"HD1901","device_manufacturer":"OnePlus","app_version":"3.3.46","cio_sdk_version":"3.5.1","device_locale":"en-IN","push_enabled":true}}}, QueueTaskRunResults(totalRuns=0)
D/[CIO]: queue task ed7a4097-beec-4a19-8f22-a299c9030e68 ran successfully
D/[CIO]: queue deleting task ed7a4097-beec-4a19-8f22-a299c9030e68
D/[CIO]: queue done running tasks
D/[CIO]: resetting queue tasks query criteria
Describe the issue
Some of the device id is not creating the profile on UAT environment but the same device id is working fine on Production environment.
Screenshots
Additional context
Don't write any code here. Get out some paper and pencil and design the API for the customer for how they will interact with the SDK.
When a customer has the SDK in their mobile app, any change that we make to the SDK might require that our customers have their engineers tweak their mobile app code to work with our SDK. We want to avoid this as much as possible. To prepare for that, let's design many of our SDK's functions we plan to implement before we get into writing code. That way we know the customer facing API will not change after we begin writing code.
Note: No matter how much we prepare there is always the chance that we introduce changes to the SDK that requires our customers making a change. This task will, however, help to avoid it.
This task is done by product and engineering team feedback.
FirebaseMessagingService
subclass, then call functions on our SDK.
Version(s) of SDK bug appears: 1.0.1
Hello,
First of all, great work releasing the native SDKs for mobile platforms.
I start to integrate your SDK, all it's working well the track of the events, the identity of the user, but when I go to the user data in Customer.io the device list is always empty and the FCM Token isn't associated.
I'm calling CustomerIOFirebaseMessagingService.onNewToken(token)
in the onNewToken()
function from the FirebaseMessagingService, and when I test send a static push notification everything works fine, the only problem is the association between the user and the token in the Customer.io platform.
Can you help me understand if missing something?
There are a lot of dependencies being used along with the plugins that need to be updated also,
Android Studio naming convention has changed and according to the Google docs current stable version is Arctic Fox | 2020.3.1
This is internal cleanup of SDK dependencies, plugins, build process, and dependencies management.
Developers to test it and verify.
SDK version:
3.2.0-alpha2
Environment:
Development and Production
Are logs available?
Describe the bug
The rich notifications are never seen as opened by the android SDK if target SDK is greater than 30
To Reproduce
Try rich push with an application with target SDK set to 33
Additional context
The problem is situated in io.customer.messagingpush.CustomerIOPushNotificationHandler#createIntentFromLink. If the targetSDK is higher than 30, io.customer.messagingpush.util.DeepLinkUtilImpl#queryDeepLinksForHostApp is called and this creates an intent with ACTION_VIEW and not a CustomerIOPushReceiver.ACTION intent
Note that this notifications also restart applications using android:launchMode="singleTask" which probably would defeat the tracking anyway because the CustomerIO SDK may not be initialized before the broadcastReceiver is executed.
SDK version: 3.8.2
Are logs available?
No
Describe the issue
How to disable push notifications in Android? I didn't find anything related on the official site.
SDK version: 3.1.0
Environment: Production
Are logs available?
This is compile time issues because MessagingPushModuleConfig we can't use it due to private constructor
Describe the bug
For reference of this link https://www.customer.io/docs/sdk/android/migrate-upgrade/ below code snippet attached to the documented site.
ModuleMessagingPushFCM( config = MessagingPushModuleConfig( notificationCallback = this, redirectDeepLinksToOtherApps = false, ) )
In this code block MessagingPushModuleConfig required 3 param but documentation mentions 2 param that is first bug also MessagingPushModuleConfig object can't able to create due to private constructor or way of code snippet wrote that is wrong.
To Reproduce
This is compile time issue so it is easily reproduced if you can write code like mention is above link it is easily reproduce the issue.
SDK version: 3.1.1
Environment: Development or Production
Are logs available?
Yes but there are no logs from CIO, only the stacktrace:
FATAL EXCEPTION: Firebase-Messaging-Intent-Handle
Process: de.climatelabs.planetwild.debug, PID: 20818
java.lang.IllegalStateException: CustomerIO.Builder::build() must be called before obtaining CustomerIO instance
at io.customer.sdk.CustomerIO$Companion.instance(CustomerIO.kt:119)
at io.customer.messagingpush.CustomerIOFirebaseMessagingService$Companion.getDiGraph(CustomerIOFirebaseMessagingService.kt:14)
at io.customer.messagingpush.CustomerIOFirebaseMessagingService$Companion.handleMessageReceived(CustomerIOFirebaseMessagingService.kt:56)
at io.customer.messagingpush.CustomerIOFirebaseMessagingService$Companion.handleMessageReceived$default(CustomerIOFirebaseMessagingService.kt:51)
at io.customer.messagingpush.CustomerIOFirebaseMessagingService.onMessageReceived(CustomerIOFirebaseMessagingService.kt:65)
at com.google.firebase.messaging.FirebaseMessagingService.dispatchMessage(com.google.firebase:firebase-messaging@@22.0.0:13)
at com.google.firebase.messaging.FirebaseMessagingService.passMessageIntentToSdk(com.google.firebase:firebase-messaging@@22.0.0:8)
at com.google.firebase.messaging.FirebaseMessagingService.handleMessageIntent(com.google.firebase:firebase-messaging@@22.0.0:3)
at com.google.firebase.messaging.FirebaseMessagingService.handleIntent(com.google.firebase:firebase-messaging@@22.0.0:3)
at com.google.firebase.messaging.EnhancedIntentService.lambda$processIntent$0$EnhancedIntentService(com.google.firebase:firebase-messaging@@22.0.0:1)
at com.google.firebase.messaging.EnhancedIntentService$$Lambda$0.run(Unknown Source:6)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
at com.google.android.gms.common.util.concurrent.zza.run(com.google.android.gms:play-services-basement@@18.1.0:2)
at java.lang.Thread.run(Thread.java:1012)
Describe the bug
App process crashes and notification isn't rendered when we send a rich push with an image while the app process is dead.
To Reproduce
Expected behavior
Notification is rendered and process doesn't crash.
Screenshots
N/A
Additional context
The error message may make it seem like we're not properly setting up the SDK, but we are. Everything is working and we're able to receive notifications without images while the app process is dead (and everything works fine while the app is open). But as soon as we add images, this happens, so I believe there's an issue on the SDK side.
I've found this issue on a Pixel 4 running Android 13 but I also tried on an emulator running Android 11 and I was also able to reproduce it there, so it doesn't really seem to be device or Android version specific.
When push notifications are touched on the device, we want to track that a push notification sent by CIO was touched.
Note: This task does not involve other push metrics like delivered
Note: This task depends on rich push integration.
CIO gives you the ability today to track when a push notification is opened (aka clicked). This task in the SDK will do all the work for the customer so they don't have to write the code to interact with our API themselves.
The API for how the customer reports push notifications is not yet decided.
This task is a feature change so it needs QA testing.
data
payload for the CIO-Delivery-
values and add those to the Intent that goes to the BroadcastReceiver
.opened
event to the API.BroadcastReciever
is opened because of a push notification being touched, get the values from the Intent and create a new queue background task to do the reporting.SDK version: v3.1.0
Environment: Production
Are logs available?
Fatal Exception: java.io.FileNotFoundException: /data/user/0/ng.com.fairmoney.fairmoney/files/io.customer/24485baaaacb896e63da/queue/tasks/1152fc26-8470-4294-9100-138b237eed53.json: open failed: ENOENT (No such file or directory)
at libcore.io.IoBridge.open(IoBridge.java:574)
at java.io.FileInputStream.<init>(FileInputStream.java:160)
at kotlin.io.FilesKt__FileReadWriteKt.readText$default(FileReadWrite.kt:125)
at kotlin.io.FilesKt__FileReadWriteKt.readText$default(FileReadWrite.kt:125)
at io.customer.sdk.data.store.FileStorage.get(FileStorage.kt:62)
at io.customer.sdk.queue.QueueStorageImpl.get(QueueStorage.kt:103)
at io.customer.sdk.queue.QueueRunRequestImpl.runTasks(QueueRunRequest.kt:37)
at io.customer.sdk.queue.QueueRunRequestImpl.runTasks$default(QueueRunRequest.kt:26)
at io.customer.sdk.queue.QueueRunRequestImpl.run(QueueRunRequest.kt:23)
at io.customer.sdk.queue.QueueImpl.run(Queue.kt:114)
at io.customer.sdk.queue.QueueImpl$runAsync$1.invokeSuspend(Queue.kt:124)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Caused by android.system.ErrnoException: open failed: ENOENT (No such file or directory)
at libcore.io.Linux.open(Linux.java)
at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
at libcore.io.BlockGuardOs.open(BlockGuardOs.java:274)
at libcore.io.ForwardingOs.open(ForwardingOs.java:563)
at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:8523)
at libcore.io.IoBridge.open(IoBridge.java:560)
at java.io.FileInputStream.<init>(FileInputStream.java:160)
at kotlin.io.FilesKt__FileReadWriteKt.readText$default(FileReadWrite.kt:125)
at kotlin.io.FilesKt__FileReadWriteKt.readText$default(FileReadWrite.kt:125)
at io.customer.sdk.data.store.FileStorage.get(FileStorage.kt:62)
at io.customer.sdk.queue.QueueStorageImpl.get(QueueStorage.kt:103)
at io.customer.sdk.queue.QueueRunRequestImpl.runTasks(QueueRunRequest.kt:37)
at io.customer.sdk.queue.QueueRunRequestImpl.runTasks$default(QueueRunRequest.kt:26)
at io.customer.sdk.queue.QueueRunRequestImpl.run(QueueRunRequest.kt:23)
at io.customer.sdk.queue.QueueImpl.run(Queue.kt:114)
at io.customer.sdk.queue.QueueImpl$runAsync$1.invokeSuspend(Queue.kt:124)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Describe the bug
This randomly happens and is currently affecting a lot of our users across several device brands
To Reproduce
Expected behavior
Device token is registered successfully without crashes
Screenshots
Additional context
Version(s) of SDK bug appears: 2.0.1
Android versions: 9-12
Kotlin version: 1.7.10
The app is crashed in first 5 seconds.
Initialise customer io sdk with this code:
CustomerIO.Builder(
siteId = application.getString(R.string.customer_io_site_id),
apiKey = application.getString(R.string.customer_io_api_key),
appContext = application,
region = Region.EU
).autoTrackScreenViews(false).build()
The app shouldn't be crashed.
Any other info?
Stack trace:
Fatal Exception: com.squareup.moshi.JsonEncodingException: Use JsonReader.setLenient(true) to accept malformed JSON at path $
at com.squareup.moshi.JsonReader.syntaxError(JsonReader.java:243)
at com.squareup.moshi.JsonUtf8Reader.checkLenient(JsonUtf8Reader.java:1152)
at com.squareup.moshi.JsonUtf8Reader.doPeek(JsonUtf8Reader.java:326)
at com.squareup.moshi.JsonUtf8Reader.peek(JsonUtf8Reader.java:206)
at com.squareup.moshi.JsonAdapter.fromJson(JsonAdapter.java:71)
at io.customer.sdk.queue.QueueStorageImpl.getInventory(QueueStorage.kt:172)
at io.customer.sdk.queue.QueueStorageImpl.deleteExpired(QueueStorage.kt:131)
at io.customer.sdk.queue.QueueImpl.deleteExpiredTasks(Queue.kt:215)
at io.customer.sdk.repository.CleanupRepositoryImpl.cleanup(CleanupRepository.kt:17)
at io.customer.sdk.CustomerIO$postInitialize$1.invokeSuspend(CustomerIO.kt:232)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:749)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664)
Target SDK: 31
Min SDK: 21
Kotlin Version: 1.6.10
Gradle Wrapper: https://services.gradle.org/distributions/gradle-7.3.3-all.zip
Gradle Android: com.android.tools.build:gradle:7.0.4
JVM: 11
Execution failed for task ':app:transformClassesWithRealmTransformerForHomolog'.
> Could not resolve all files for configuration ':app:homologRuntimeClasspath'.
> Failed to transform moshi-1.14.0.jar (com.squareup.moshi:moshi:1.14.0) to match attributes {artifactType=android-asm-instrumented-jars, asm-transformed-variant=homolog, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.environment=standard-jvm, org.gradle.jvm.version=8, org.gradle.libraryelements=jar, org.gradle.status=release, org.gradle.usage=java-runtime, org.jetbrains.kotlin.platform.type=jvm}.
> Execution failed for AsmClassesTransform: /home/thiago/.gradle/caches/transforms-3/8d8b915a258fe961ebeefbe46c277915/transformed/jetified-moshi-1.14.0.jar.
> Record requires ASM8
I have been add the CustomerIO libs, but when i try build my project this error hapens, i have tryed upgrade ASM to version 8, add moshi to ignorelist in Jetifier, and even disable Jetifier, but nothing works.
I have a long time in this bug, and nothing of i view in web works.
Can you help me?
We need the ability to track a customer event.
CIO gives you the ability today to track an event, we need to cater that in the Android SDK.
Upon tracking any event through SDK it should be reflected on Portal as well, also integration test.
After the customer is identified, store the identifier in preferences. Provide a method in the CustomerIo
class to track an event, also able to stop identifying.
CustomerIO.track()
CustomerIO. identifyStop()
Version(s) of SDK bug appears: 3.0.0
We use iOS/Android Deep Link action in the In-App message, but when the app is opened, and we get the in-app message, after pressing Yes! button which triggers the action, the app then reopens again.
The app shouldn't reopen because it is already in foreground.
Any other info?
In order to move the SDK to the beta phase, we need to have unit tests written for all the components of the SDK.
Tests help to make us and customers feel more confident our SDK is stable and this would give customers guidance into how to test our SDK in their apps if needed.
We have a unit test coverage reaching every basic module and component of the SDK.
We Will be adding unit tests for the following for now
alpha
branch failed. 🚨I recommend you give this issue a high priority, so other packages depending on you can benefit from your bug fixes and new features again.
You can find below the list of errors reported by semantic-release. Each one of them has to be resolved in order to automatically publish your package. I’m sure you can fix this 💪.
Errors are usually caused by a misconfiguration or an authentication problem. With each error reported below you will find explanation and guidance to help you to resolve it.
Once all the errors are resolved, semantic-release will release your package the next time you push a commit to the alpha
branch. You can also manually restart the failed CI job that runs semantic-release.
If you are not sure how to resolve this, here are some links that can help you:
If those don’t help, or if this issue is reporting something you think isn’t right, you can always ask the humans behind semantic-release.
Unfortunately this error doesn't have any additional information. Feel free to kindly ask the author of the @semantic-release/exec
plugin to add more helpful information.
Good luck with your project ✨
Your semantic-release bot 📦🚀
Technical requirement in order for the SDK to perform requests to the CIO API.
Today, our customers need to write custom code in their apps to perform requests to the CIO API to add data to their workspace. This task will setup the technical code in order for us to perform the API calls on your behalf.
The end goal is to perform a successful HTTP request to the CIO API in an Android app via the SDK. This includes:
Not 100% sure. The end goal is keeping the SDK slim so not using retrofit or volley is a great start.
My current idea is to use kotlin coroutines. Google gave a nice code snippet in it's docs:
sealed class Result<out R> {
data class Success<out T>(val data: T) : Result<T>()
data class Error(val exception: Exception) : Result<Nothing>()
}
class LoginRepository(private val responseParser: LoginResponseParser) {
private const val loginUrl = "https://example.com/login"
// Function that makes the network request, blocking the current thread
fun makeLoginRequest(
jsonBody: String
): Result<LoginResponse> {
val url = URL(loginUrl)
(url.openConnection() as? HttpURLConnection)?.run {
requestMethod = "POST"
setRequestProperty("Content-Type", "application/json; utf-8")
setRequestProperty("Accept", "application/json")
doOutput = true
outputStream.write(jsonBody.toByteArray())
return Result.Success(responseParser.parse(inputStream))
}
return Result.Error(Exception("Cannot open HttpURLConnection"))
}
}
Decide how we will do HTTP networking calls. Implement that code in the SDK.
Add User-Agent
header for all requests. Value set to Customer.io Android SDK vX.X.X, Y Android app vX.X.X
where Y
is the name of the customer's Android app. Thinking you can specify an optional app identifier in the configuration?
Create a common module to be shared among different modules and possible extension methods for networking, as well as common request/response models
I am having a bit of a hard time understanding why would we need to pause
making any HTTP requests?
Shouldn't be either rate-limiting from the start so this issue never arise? if we throttle our requests when making from BQ, we wont get to the point that it starts impacting our APIs performance? Thoughts?
Maybe we can take this to the squad as well for their input on this. ?
Originally posted by @Shahroz16 in #85 (comment)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.