Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pinpoint Analytics causes crash - SQLiteReadOnlyDatabaseException: attempt to write a readonly database #3565

Open
frogoscar opened this issue Apr 16, 2024 · 6 comments
Labels
bug Something isn't working pending-response Issue is pending response from the issue requestor pinpoint Issues with the AWS Android SDK for Pinpoint.

Comments

@frogoscar
Copy link

frogoscar commented Apr 16, 2024

Describe the bug
After integrating AWS Pinpoint Analytics into my Android app, I notice many crashes reported on my Google Play Console, as below :

Exception android.database.sqlite.SQLiteReadOnlyDatabaseException: attempt to write a readonly database - SQLITE_READONLY_DBMOVED (Sqlite code 1032 SQLITE_READONLY_DBMOVED), (OS error - 2:No such file or directory)
  at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount
  at android.database.sqlite.SQLiteConnection.executeForChangedRowCount (SQLiteConnection.java:875)
  at android.database.sqlite.SQLiteSession.executeForChangedRowCount (SQLiteSession.java:776)
  at android.database.sqlite.SQLiteStatement.executeUpdateDelete (SQLiteStatement.java:66)
  at android.database.sqlite.SQLiteDatabase.delete (SQLiteDatabase.java:1694)
  at com.amazonaws.mobileconnectors.pinpoint.internal.event.PinpointDBBase.delete (PinpointDBBase.java:206)
  at com.amazonaws.mobileconnectors.pinpoint.internal.event.PinpointDBUtil.deleteEvent (PinpointDBUtil.java:111)
  at com.amazonaws.mobileconnectors.pinpoint.internal.event.EventRecorder.processEvents (EventRecorder.java:330)
  at com.amazonaws.mobileconnectors.pinpoint.internal.event.EventRecorder$1.run (EventRecorder.java:256)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
  at java.lang.Thread.run (Thread.java:929)

This crash is encountered mostly when opening the Android app.

The log of this crash is likely the same to #2520 .

From the log, I can say the crash occurs when AWS Pinpoint calls method submitEvents() . Please look at my usage as below.

I firstly initialize AWS (in an Kotlin object class named AnalyticsUtils 's init() method) Pinpoint Analytics Client as below

object AnalyticsUtils {
    lateinit var pinpointAnalyticsClient: AnalyticsClient

    fun init(context: Context) {
        val appId = "xxxxxxx"
        val identityPoolId = "xxxxxxx"
        
        val configMap = mapOf(
            "PinpointAnalytics" to mapOf(
            "AppId" to appId,
            "Region" to "us-west-2"
            )
        )
        val pinpointConfig = PinpointConfiguration(
            context,
            CognitoCredentialsProvider(identityPoolId, Regions.US_WEST_2),
            AWSConfiguration(JSONObject(configMap))
        )
        pinpointAnalyticsClient = PinpointManager(pinpointConfig).analyticsClient
    }
}

Record an event as below

fun logEvent(eventString: String, params: HashMap<String, String>?) {
    if (eventString.isEmpty()) {
        Log.w(TAG, "Event name is empty, skip")
        return
    }
    
    if (this::firebaseAnalytics.isInitialized) {
        val event = pinpointAnalyticsClient.createEvent(eventString)
        params?.map { entry -> event.addAttribute(entry.key, entry.value) }
        pinpointAnalyticsClient.recordEvent(event)
    }
}

Submit all events recorded in local SQLite database when app is launched (in the onCreate() method of the inherited Application class) as below

override fun onCreate() {
    super.onCreate()
     
    // init Pinpoint Analytics Client
    AnalyticsUtils.init(this)

    // submit all Pinpoint events saved in local Sqlite database
    AnalyticsUtils.pinpointSubmitEvents()
}

pinpointSubmitEvents() method is defined in AnalyticsUtils.kt

fun pinpointSubmitEvents() {
    if (this::pinpointAnalyticsClient.isInitialized) {
        pinpointAnalyticsClient.submitEvents()
    }
}

Could you tell me if I use the Pinpoint SDK incorrectly, how can I fix this crash ?
Or should I use the new Amplify SDK for Pinpoint Analytics instead ?

Thank you very much!

To Reproduce

The problem is that I can not reproduce this crash on my own physical Android device (which is OPPO K10x), it works fine. But when the Prod release is on Google Play, my users encounter crash, some users say that they encounter crash when opening my app.

Which AWS service(s) are affected?
AWS Pinpoint

Expected behavior
No crash.

Screenshots
AWS Pinpoint crash

Environment Information (please complete the following information):

  • AWS Android SDK Version: [2.74.0] (I use com.amazonaws:aws-android-sdk-core:2.74.0 and com.amazonaws:aws-android-sdk-pinpoint:2.74.0 . Not the new Amplify SDK )
  • Device: [Many devices of users, but not my own device. Like Huawei, Xiaomi, Samsung, OPPO, Google, Vivo, etc]
  • Android Version: [Android 8 ~ Android 14]
  • Specific to simulators: [No]

Additional context
Add any other context about the problem here.

@frogoscar
Copy link
Author

Any kind help ? Thanks a lot~

@joon-won
Copy link
Contributor

Hi @frogoscar , thank you for your patience, our team will look into the issue

@joon-won joon-won self-assigned this Apr 17, 2024
@joon-won joon-won added the bug Something isn't working label Apr 17, 2024
@joon-won joon-won removed their assignment Apr 17, 2024
@joon-won joon-won added the pinpoint Issues with the AWS Android SDK for Pinpoint. label Apr 22, 2024
@vincetran
Copy link

Hi @frogoscar, thanks for your patient. I started to look at this and have a question about how you're calling SubmitEvents. From the snippits you provided it looks like you're submitting Pinpoint events immediately after you initialize the Pinpoint client. So how I read your flow is:

App launch > Initialize Pinpoint > Submit local events > App has finished starting > Events are logged.

I don't know the full workings of the Pinpoint client yet but I'm wondering if you're attempting to submit the events too early and running into a race condition where on certain user's devices, the database client isn't fully initialized and thus ready for writes. The issue that you linked was explicitly found during unit testing so the scenario for encountering that issue is pretty different than the real-life scenario you're encountering.

Is there a reason you're trying to submit events so early/in the Application class? From documentation it looks like general best practice is to submit events at the end of the user's session. For cases of fatal recoveries, you can always try to submit events in some primary activity like your login, home, or similar activity.

@vincetran vincetran added the pending-response Issue is pending response from the issue requestor label Apr 22, 2024
@frogoscar
Copy link
Author

frogoscar commented Apr 23, 2024

Hi @frogoscar, thanks for your patient. I started to look at this and have a question about how you're calling SubmitEvents. From the snippits you provided it looks like you're submitting Pinpoint events immediately after you initialize the Pinpoint client. So how I read your flow is:

App launch > Initialize Pinpoint > Submit local events > App has finished starting > Events are logged.

I don't know the full workings of the Pinpoint client yet but I'm wondering if you're attempting to submit the events too early and running into a race condition where on certain user's devices, the database client isn't fully initialized and thus ready for writes. The issue that you linked was explicitly found during unit testing so the scenario for encountering that issue is pretty different than the real-life scenario you're encountering.

Is there a reason you're trying to submit events so early/in the Application class? From documentation it looks like general best practice is to submit events at the end of the user's session. For cases of fatal recoveries, you can always try to submit events in some primary activity like your login, home, or similar activity.

@vincetran @joon-won

Hi, thank you very much for your kind reply.

So maybe the reason is that I call submitEvents() too early (like vincetran says) ?

So if I remove the code that calls submitEvents() at Application 's onCreate(), and put submitEvents() in the code location in an Activity when the app switches from Foreground to Background (At that moment I think the database client is fully initialized and thus ready for writes), will it be ok ?

Thanks a lot!

@vincetran
Copy link

vincetran commented Apr 23, 2024

That sounds more reasonable! If you take a look at the docs, there's an example that demonstrates that exact usecase (albeit written in Java): https://docs.amplify.aws/android/sdk/analytics/events/#reporting-session-events

Basically, when the app enters foreground, you call startSession() and when it enters background, it calls both stopSession() and submitEvents().

Hopefully that fixes your problem but at a higher level suggestion, we do recommend you migrate over to use the Amplify SDK at your earliest convenience.

@frogoscar
Copy link
Author

frogoscar commented Apr 24, 2024

That sounds more reasonable! If you take a look at the docs, there's an example that demonstrates that exact usecase (albeit written in Java): https://docs.amplify.aws/android/sdk/analytics/events/#reporting-session-events

Basically, when the app enters foreground, you call startSession() and when it enters background, it calls both stopSession() and submitEvents().

Hopefully that fixes your problem but at a higher level suggestion, we do recommend you migrate over to use the Amplify SDK at your earliest convenience.

@vincetran Thanks a lot.

The calls of startSession() and stopSession() are not mandatory, right ?

I would like to use the new Amplify SDK for Android, of course.

But my Android app's minSdk is 21, while the latest Amplify SDK for Android (from version 2.0.0) requires Android minSdk >= 24).

I have some customs whose Android devices still use Android 5 (Android SDK 21) ~ Android 6 (Android SDK 23).

The latest version of Amplify SDK for Android that satisfies the condition of minSdk 21 is 1.38.8 (1.38.8 uses underlying version 2.73.0 of AWS SDK for Android ).

Currently I use version 2.75.0 of AWS SDK for Android.

In the future when I set my Android minSdk >= 24 , I will migrate to Amplify SDK for Android .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working pending-response Issue is pending response from the issue requestor pinpoint Issues with the AWS Android SDK for Pinpoint.
Projects
None yet
Development

No branches or pull requests

3 participants