optimizely / android-sdk

Android SDK for Optimizely Feature Experimentation and Optimizely Full Stack (legacy)
https://docs.developers.optimizely.com/experimentation/v4.0.0-full-stack/docs/android-sdk
Apache License 2.0
55 stars 39 forks source link

Crash with IllegalStateException - Apps may not schedule more than 100 distinct jobs #234

Closed benvonhandorf closed 6 years ago

benvonhandorf commented 6 years ago

We're seeing a crash in the Optimizely stack around scheduling jobs with the JobScheduler. The app also makes use of JobScheduler, via the WorkManager library, but the app currently only schedules 3-5 jobs, maximum.

These crashes are mostly happening in the background, according to fabric.

Relevant library versions:

implementation('com.optimizely.ab:android-sdk:2.1.0') android.arch.work:work-runtime: 1.0.0-alpha10 android.arch.work:work-firebase: 1.0.0-alpha10 com.firebase:firebase-jobdispatcher:0.8.5

Fatal Exception: java.lang.IllegalStateException: Apps may not schedule more than 100 distinct jobs
       at android.os.Parcel.readException(Parcel.java:1967)
       at android.os.Parcel.readException(Parcel.java:1905)
       at android.app.job.IJobScheduler$Stub$Proxy.schedule(IJobScheduler.java:180)
       at android.app.JobSchedulerImpl.schedule(JobSchedulerImpl.java:44)
       at com.optimizely.ab.android.shared.ServiceScheduler.setRepeating(ServiceScheduler.java:134)
       at com.optimizely.ab.android.shared.ServiceScheduler.schedule(ServiceScheduler.java:83)
       at com.optimizely.ab.android.datafile_handler.DefaultDatafileHandler.startBackgroundUpdates(DefaultDatafileHandler.java:122)
       at com.optimizely.ab.android.sdk.OptimizelyManager.injectOptimizely(OptimizelyManager.java:442)
       at com.optimizely.ab.android.sdk.OptimizelyManager$2.onDatafileLoaded(OptimizelyManager.java:343)
       at com.optimizely.ab.android.datafile_handler.DefaultDatafileHandler$1.onDatafileLoaded(DefaultDatafileHandler.java:78)
       at com.optimizely.ab.android.datafile_handler.DatafileLoader.notify(DatafileLoader.java:81)
       at com.optimizely.ab.android.datafile_handler.DatafileLoader.access$000(DatafileLoader.java:35)
       at com.optimizely.ab.android.datafile_handler.DatafileLoader$RequestDatafileFromClientTask.onPostExecute(DatafileLoader.java:134)
       at com.optimizely.ab.android.datafile_handler.DatafileLoader$RequestDatafileFromClientTask.onPostExecute(DatafileLoader.java:85)
       at android.os.AsyncTask.finish(AsyncTask.java:695)
       at android.os.AsyncTask.-wrap1(Unknown Source)
       at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:712)
       at android.os.Handler.dispatchMessage(Handler.java:105)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6938)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
benvonhandorf commented 6 years ago

It appears all of these crashes are on Android versions 8.X and 9. It is not limited to any manufacturer or phone.

mikeproeng37 commented 6 years ago

Thanks for reporting this. We'll look into it!

thomaszurkan-optimizely commented 6 years ago

@benvonhandorf are you reinitializing ever time you get a datafile update?

benvonhandorf commented 6 years ago

Currently I only call initialize as part of app startup.

thomaszurkan-optimizely commented 6 years ago

Thanks @benvonhandorf ! We are looking into it now.

thomaszurkan-optimizely commented 6 years ago

@benvonhandorf I'd like to know some more about what you are doing. Under normal circumstances, the OptimizelyManager.onDatafileDownloaded would only be called once. Are you doing anything special with the DefaultDatafileManager? Or, using the DatafileServiceConnetion in some other way?

benvonhandorf commented 6 years ago

Here is all my interaction with the Optimizely in my code:

As part of app startup:

        OptimizelyManager optimizelyManager = OptimizelyManager.builder(this.applicationContext.getResources().getString(R.string.optimizely_project_id))
                .withLogger(new ATLogLogger(TAG + "-Optimizely"))
                .withDatafileDownloadInterval(12 * 60 * 60)
                .withErrorHandler(this)
                .build(this.applicationContext);

        optimizelyManager.initialize(this.applicationContext, this);

I'm using callbacks for my own book-keeping around the state of optimizely (in onStart) and error logging, but the only other interactions I have is dumping the state of the world after initialization:

    private void postOptimizelyInitialization() {
        ATLog.i(TAG, "postOptimizelyInitialization");

        //If setup needs to be done for audience, that should be cached and
        //done here as well to help with race conditions.

        if (optimizelyClient.getProjectConfig() != null) {
            ATLog.i(TAG, String.format("Optimizely project: %s revision %s", optimizelyClient.getProjectConfig().getProjectId(), optimizelyClient.getProjectConfig().getRevision()));
            if (optimizelyClient.getProjectConfig().getExperiments() != null) {
                for (Experiment experiment : optimizelyClient.getProjectConfig().getExperiments()) {
                    ATLog.i(TAG, String.format("Optimizely experiment available: %s", experiment.getKey()));
                }
            }
        }
    }

and tracking individual events, e.g.:

    public void recordRegistration() {
        ATLog.i(TAG, "recordRegistration");
//        if (optimizelyClient != null) {
//            optimizelyClient.track(Goals.kRegistrationSuccessfulGoal, installationId);
//        } else {
//            ATLog.w(TAG, "No optimizely client, skipping track");
//        }
    }

Currently we have no optimizely experiments running. I have taken optimizely out entirely in a point release and this crash stopped, so it definitely seems related to the SDK, even if there are aggravating factors from other SDKs or code, which is possible.

thomaszurkan-optimizely commented 6 years ago

@benvonhandorf Thanks for the feedback.

Can the initialize happen while the app is backgrounded?
Have you duplicated this in debug?

Again, thanks for the help.

benvonhandorf commented 6 years ago

Yes, we will attempt to initialized if the app is in the background. Our app startup is currently monolithic and Optimizely is started as part of it... so if a scheduled job fires it will do all our normal startup, including Optimizely.

Unfortunately I haven't seen it in debug yet.

thomaszurkan-optimizely commented 6 years ago

@benvonhandorf Interesting. It sounds like we may just be the straw that broke the camels back. But, we can at least wrap that schedule in a try catch. We will add that today. Thanks!

thomaszurkan-optimizely commented 6 years ago

@benvonhandorf We released 2.1.1 which includes a fix for this.

thomaszurkan-optimizely commented 6 years ago

@benvonhandorf officially tagged in release 2.1.2. I'm going to close this for now. Please feel free to reopen if you find something else wrong.

ingridswiftconnect commented 1 year ago

Optimizely is crashing on my android app with this error message java.lang.ExceptionInInitializerError caused by java.lang.IllegalStateException: FileLogger is not initialized, Forgot to call Log4O.init()? It seems that have another library in my project using this lib 'com.noveogroup.android:android-logger:1.3.5'

jaeopt commented 1 year ago

@ingridswiftconnect it looks like not related to the original issue here. Can you file a new one with your issue? It'll be helpful if you can share the full stack trace as well. Thanks.

ingridswiftconnect commented 1 year ago

Hello,

Could you tell me where to file the issue? Thank you!

On Fri, Feb 17, 2023 at 12:21 PM Jae Kim @.***> wrote:

@ingridswiftconnect https://github.com/ingridswiftconnect it looks like not related to the original issue here. Can you file a new one with your issue? It'll be helpful if you can share the full stack trace as well. Thanks.

— Reply to this email directly, view it on GitHub https://github.com/optimizely/android-sdk/issues/234#issuecomment-1434969386, or unsubscribe https://github.com/notifications/unsubscribe-auth/AYDUJUUG7U6QMKZ2LEU5QKLWX6XRBANCNFSM4GACTRNA . You are receiving this because you were mentioned.Message ID: @.***>