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

SDK initialization causes ANR #1022

Closed
5 tasks done
baole opened this issue Nov 8, 2021 · 12 comments
Closed
5 tasks done

SDK initialization causes ANR #1022

baole opened this issue Nov 8, 2021 · 12 comments

Comments

@baole
Copy link

baole commented Nov 8, 2021

Checklist before submitting a bug report

Java version

Any

Android version

Any

Android SDK version

Any

Installation platform & version

Gradle

Package

Login

Goals

Facebook SDK currently uses com.facebook.internal.FacebookInitProvider class, a ContentProvider, to initilize its SDK. This class is automatically called on onCreate() method during the application (cold) starts. Among other things, it reads data from shared preferences, which reads files on the main thread. In consequence:

  • Causes ANRs
  • Take longer cold startup time
  • Violate StrickMode

This is against ContentProvider SDK as it says:

Implement this to initialize your content provider on startup. This method is called for all registered content providers on the application main thread at application launch time. It must not perform lengthy operations, or application startup will be delayed.

Android also suggests to not use SharedPreferences on the main thread and offers DataStore as an alternative API to read/write stored data asynchronously.

It's really bad as Facebook SDK now becomes the main reason causing ANR in our app.

Expected results

No I/O operation in the main thread, no ANR report.

Actual results

Here is one of the report from Firebase Crashlytics ANR

image

Steps to reproduce

No response

Code samples & details

No response

@linmx0130
Copy link

linmx0130 commented Nov 8, 2021

Hi @baole, thanks for raising this issue. We're sorry for the ANR that caused by the Facebook SDK.

However, this tracelog cannot happens on the main thread with the latest Facebook SDK. Since AppEventStore.readAndClearStore will throw an exception if it's called on the main thread. For more information, see https://github.com/facebook/facebook-android-sdk/blob/main/facebook-core/src/main/java/com/facebook/appevents/AppEventStore.kt#L65. All lengthy operations for initializing Facebook SDK will be executed in separated threads.

If the problem persists, you can choose to disable the auto-init of Facebook. One approach to do manually initializing of Facebook SDK is to add following lines into AndroidManifest.xml of the app:

<provider
    android:name="com.facebook.internal.FacebookInitProvider"
    android:authorities="${applicationId}.FacebookInitProvider"
    tools:node="remove"
    />

Then you can do manually initializing of the Facebook Android SDK by calling

FacebookSdk.sdkInitialize(context)

where context is the application context.

@baole
Copy link
Author

baole commented Nov 9, 2021

Thanks @linmx0130. It looks like a workaround as com.facebook.internal.FacebookInitProvider is an internal class. Using this approach may have an unexpected results in the future update.

I saw https://developers.facebook.com/docs/app-events/gdpr-compliance/#disabling-automatic-sdk-initialization but it doesn't prevent the SDK initialization, at least reading SharedPreferences.

Is there any chance to update this behaviour in the future SDK versions?

@baole
Copy link
Author

baole commented Nov 9, 2021

Also, FacebookSdk.sdkInitialize(context) is deprecated.

@linmx0130
Copy link

linmx0130 commented Nov 9, 2021

Hi @baole! Thanks for your response!
We will notify all developers if we will make any changes to com.facebook.internal.FacebookInitProvider. For the AutoInitEnabled , it can only prevent the fully initialization for GDPR compliance, but SharePreferences may still be loaded for checking configurations.

And for FacebookSdk.sdkInitialize(context), it's deprecated because we introduced the auto-init approach in 2017. In fact, FacebookInitProvider call it to init the SDK, so it won't be deleted without a 120-day notification.

@baole
Copy link
Author

baole commented Nov 10, 2021

@linmx0130 it's not necessary to delete FacebookInitProvider. I mean just moving all heavy work (I/O related) to somewhere else (or start a background thread/coroutines ), it will comply with ContentProvider documentation and avoid I/O operation on the main thread.

@linmx0130
Copy link

@baole That's why I feel strange because all heavy work are already moved to separated threads. As I said, the method that causes ANR in your tracelog cannot be called on the main thread. It may be possible that some devices have strange configurations so that the IO threads make UI freeze...

@baole
Copy link
Author

baole commented Nov 12, 2021

@linmx0130 it's still loading SharedPreferences on the thread where it's executing. You can easily check it by enable StrickMode

@linmx0130
Copy link

@baole Thanks for the report! I will do a fully check on disk IO during the initialization. In our internal testing apps, there are some StrictMode.DiskReadViolation emitted during the whole lifecycle of the apps, but none of them are caused in the initialization stage.

@linmx0130
Copy link

Hi @baole, I think I got what you mean... Facebook Android SDK does access some SharedPreferences during its initialization because according to Google's document, it's safe to do so on main thread by using apply() method of it. Back to the original post, in fact, Android has never suggested not to use SharedPreferences on the main thread. It just suggests to use apply() instead of commit(). These are not considered as "lengthy operations".

The ANR reported by Firebase Crashlytics ANR is also not from the main thread. I think they're two independent procedures.

We are still working on reducing the time cost in Facebook Android SDK initialization. For now, I would suggest to turn off the auto-init of SDK for now if that's the main reason of long delay in your app start.

@sergei-mikhailovskii-idf

problem is still actual

@Allen-ZXJ
Copy link

Hi @baole, thanks for raising this issue. We're sorry for the ANR that caused by the Facebook SDK.

However, this tracelog cannot happens on the main thread with the latest Facebook SDK. Since AppEventStore.readAndClearStore will throw an exception if it's called on the main thread. For more information, see https://github.com/facebook/facebook-android-sdk/blob/main/facebook-core/src/main/java/com/facebook/appevents/AppEventStore.kt#L65. All lengthy operations for initializing Facebook SDK will be executed in separated threads.

If the problem persists, you can choose to disable the auto-init of Facebook. One approach to do manually initializing of Facebook SDK is to add following lines into AndroidManifest.xml of the app:

<provider
    android:name="com.facebook.internal.FacebookInitProvider"
    android:authorities="${applicationId}.FacebookInitProvider"
    tools:node="remove"
    />

Then you can do manually initializing of the Facebook Android SDK by calling

FacebookSdk.sdkInitialize(context)

where context is the application context.
If the manual initialization is like this, will the application fail to pass the review in Google Play?

@sleepym09
Copy link

Hi @linmx0130
I disable the auto-init of Faacebook, and move the business logic to the callback of FacebookSdk.sdkInitialize , The number of ANR is reduced, but I occasionally encounter a problem, below is the exception stack:

Fatal Exception: java.lang.RuntimeException
Unable to start activity ComponentInfo{com.mypackage.name/com.facebook.FacebookActivity}: The SDK has not been initialized, make sure to call FacebookSdk.sdkInitialize() first.

com.facebook.internal.Validate.sdkInitialized (Validate.kt:117)
com.facebook.FacebookSdk.getApplicationId (FacebookSdk.kt:833)
com.facebook.login.LoginMethodHandler.getRedirectUrl (LoginMethodHandler.kt:71)
com.facebook.login.CustomTabLoginMethodHandler.getDeveloperDefinedRedirectURI (CustomTabLoginMethodHandler.kt:53)
com.facebook.login.CustomTabLoginMethodHandler.<init> (CustomTabLoginMethodHandler.kt:196)
com.facebook.login.CustomTabLoginMethodHandler$Companion$CREATOR$1.createFromParcel (CustomTabLoginMethodHandler.kt:214)
com.facebook.login.CustomTabLoginMethodHandler$Companion$CREATOR$1.createFromParcel (CustomTabLoginMethodHandler.kt:212)
android.os.Parcel.readParcelableInternal (Parcel.java:4806)
android.os.Parcel.readParcelableArrayInternal (Parcel.java:4996)
android.os.Parcel.readParcelableArray (Parcel.java:4969)
com.facebook.login.LoginClient.<init> (LoginClient.kt:654)
com.facebook.login.LoginClient$Companion$CREATOR$1.createFromParcel (LoginClient.kt:695)
com.facebook.login.LoginClient$Companion$CREATOR$1.createFromParcel (LoginClient.kt:693)
android.os.Parcel.readParcelableInternal (Parcel.java:4806)
android.os.Parcel.readValue (Parcel.java:4563)
android.os.Parcel.readValue (Parcel.java:4343)
android.os.Parcel.-$$Nest$mreadValue
android.os.Parcel$LazyValue.apply (Parcel.java:4441)
android.os.Parcel$LazyValue.apply (Parcel.java:4400)
android.os.BaseBundle.getValueAt (BaseBundle.java:394)
android.os.BaseBundle.getValue (BaseBundle.java:374)
android.os.BaseBundle.getValue (BaseBundle.java:357)
android.os.BaseBundle.getValue (BaseBundle.java:350)
android.os.Bundle.getParcelable (Bundle.java:913)
com.facebook.login.LoginFragment.onCreate (LoginFragment.kt:44)
androidx.fragment.app.Fragment.performCreate (Fragment.java:3094)
androidx.fragment.app.FragmentStateManager.create (FragmentStateManager.java:504)
androidx.fragment.app.FragmentStateManager.moveToExpectedState (FragmentStateManager.java:268)
androidx.fragment.app.FragmentStore.moveToExpectedState (FragmentStore.java:114)
androidx.fragment.app.FragmentManager.moveToState (FragmentManager.java:1455)
androidx.fragment.app.FragmentManager.dispatchStateChange (FragmentManager.java:3034)
androidx.fragment.app.FragmentManager.dispatchCreate (FragmentManager.java:2941)
androidx.fragment.app.FragmentController.dispatchCreate (FragmentController.java:252)
androidx.fragment.app.FragmentActivity.onCreate (FragmentActivity.java:219)
com.facebook.FacebookActivity.onCreate (FacebookActivity.kt:46)
android.app.Activity.performCreate (Activity.java:8328)
android.app.Activity.performCreate (Activity.java:8307)
android.app.Instrumentation.callActivityOnCreate (Instrumentation.java:1384)
android.app.ActivityThread.performLaunchActivity (ActivityThread.java:3750)
android.app.ActivityThread.handleLaunchActivity (ActivityThread.java:3907)
android.app.servertransaction.LaunchActivityItem.execute (LaunchActivityItem.java:101)
android.app.servertransaction.TransactionExecutor.executeCallbacks (TransactionExecutor.java:137)
android.app.servertransaction.TransactionExecutor.execute (TransactionExecutor.java:97)
android.app.ActivityThread$H.handleMessage (ActivityThread.java:2393)
android.os.Handler.dispatchMessage (Handler.java:106)
android.os.Looper.loopOnce (Looper.java:201)
android.os.Looper.loop (Looper.java:288)
android.app.ActivityThread.main (ActivityThread.java:8061)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:703)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:923)

More Infomations:

  • The Android sdk version is 17.0.0.
  • The exception always happens in the application startup stage.
  • I didn't use any Facebook sdk method in the application startup stage.

Do you have any opinion on this issue?
Thanks for your time.

Hi @baole, thanks for raising this issue. We're sorry for the ANR that caused by the Facebook SDK.

However, this tracelog cannot happens on the main thread with the latest Facebook SDK. Since AppEventStore.readAndClearStore will throw an exception if it's called on the main thread. For more information, see https://github.com/facebook/facebook-android-sdk/blob/main/facebook-core/src/main/java/com/facebook/appevents/AppEventStore.kt#L65. All lengthy operations for initializing Facebook SDK will be executed in separated threads.

If the problem persists, you can choose to disable the auto-init of Facebook. One approach to do manually initializing of Facebook SDK is to add following lines into AndroidManifest.xml of the app:

<provider
    android:name="com.facebook.internal.FacebookInitProvider"
    android:authorities="${applicationId}.FacebookInitProvider"
    tools:node="remove"
    />

Then you can do manually initializing of the Facebook Android SDK by calling

FacebookSdk.sdkInitialize(context)

where context is the application context.

riderx referenced this issue in Cap-go/capacitor-social-login Jan 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants