首页 > 解决方案 > 当我应用自定义 UI 管理器时,Facebook 帐户工具包活动崩溃

问题描述

现在我必须将我项目的整个代码库转换为 Kotlin,其中一个部分涉及 Facebook Account Kit,我必须使用我的手机号码登录应用程序,如下所示:

val intent = Intent(activity, AccountKitActivity::class.java)
val uiManager = CustomUIManager(ButtonType.CONTINUE, ButtonType.NEXT, TextPosition.ABOVE_BODY, R.style.AccountKitTheme)
val configurationBuilder = AccountKitConfiguration.AccountKitConfigurationBuilder(LoginType.PHONE,
        AccountKitActivity.ResponseType.CODE)
//TODO: disable until I figure out what's going on
//configurationBuilder.setUIManager(uiManager)
configurationBuilder.setReadPhoneStateEnabled(true)
configurationBuilder.setReceiveSMS(true)
val config = configurationBuilder.build();
intent.putExtra(AccountKitActivity.ACCOUNT_KIT_ACTIVITY_CONFIGURATION, config)
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
activity.overridePendingTransition(0, 0)
Log.i("account_kit_login", "start "+config.notificationChannels)
activity.startActivityForResult(intent, ACCOUNT.FACEBOOK.code)

这个uiManager类看起来像这样:

class CustomUIManager : BaseUIManager {
    private var confirmButton: ButtonType? = null
    private var entryButton: ButtonType? = null
    private var textPosition: TextPosition? = null

    constructor(
            confirmButton: ButtonType,
            entryButton: ButtonType,
            textPosition: TextPosition,
            themeResourceId: Int) : super(themeResourceId) {
        this.confirmButton = confirmButton
        this.entryButton = entryButton
        this.textPosition = textPosition
    }

    private constructor(source: Parcel) : super(source) {
        var s: String? = source.readString()
        val confirmButton = if (s == null) null else ButtonType.valueOf(s)
        s = source.readString()
        val entryButton = if (s == null) null else ButtonType.valueOf(s)
        s = source.readString()
        val textPosition = if (s == null) null else TextPosition.valueOf(s)
        this.confirmButton = confirmButton
        this.entryButton = entryButton
        this.textPosition = textPosition
    }

    override fun getHeaderFragment(state: LoginFlowState): Fragment? {
        val prefix: Int
        val type = 0
        when (state) {
            LoginFlowState.PHONE_NUMBER_INPUT -> prefix = R.string.header_phone_number_input
            LoginFlowState.SENDING_CODE -> {
                prefix = R.string.header_sending_code
                return PlaceholderFragment.newInstance(prefix, type, R.dimen.loading_placeholder_height)
            }
            LoginFlowState.SENT_CODE -> {
                prefix = R.string.header_sent_code
                return PlaceholderFragment.newInstance(prefix, type, R.dimen.loading_placeholder_height)
            }
            LoginFlowState.CODE_INPUT -> prefix = R.string.header_code_input
            LoginFlowState.VERIFYING_CODE -> prefix = R.string.header_verifying_code
            LoginFlowState.VERIFIED, LoginFlowState.ACCOUNT_VERIFIED, LoginFlowState.CONFIRM_ACCOUNT_VERIFIED, LoginFlowState.CONFIRM_INSTANT_VERIFICATION_LOGIN -> prefix = R.string.header_account_verified
            LoginFlowState.ERROR -> prefix = R.string.header_error
            else -> return super.getHeaderFragment(state)
        }
        return PlaceholderFragment.newInstance(prefix, type)
    }

    override fun getBodyFragment(state: LoginFlowState): Fragment? {
        val prefix: Int
        val type = 0
        when (state) {
            LoginFlowState.VERIFIED -> {
                prefix = R.string.body_verified
                return PlaceholderFragment.newInstance(prefix, type, R.dimen.loading_placeholder_height)
            }
            LoginFlowState.ERROR -> {
                prefix = R.string.body_error
                return PlaceholderFragment.newInstance(prefix, type, R.dimen.loading_placeholder_height)
            }
            LoginFlowState.CONFIRM_ACCOUNT_VERIFIED -> {
                prefix = R.string.body_confirm_account_verified
                return PlaceholderFragment.newInstance(prefix, type, R.dimen.loading_placeholder_height)
            }
            else -> return super.getBodyFragment(state)
        }
    }
    //
    //    @Nullable
    //    @Override
    //    public Fragment getFooterFragment(LoginFlowState state) {
    //        String prefix = "";
    //        switch (state) {
    //            case PHONE_NUMBER_INPUT:
    //                prefix = "custom footer phone input";
    //                break;
    //            case EMAIL_INPUT:
    //                prefix = "custom footer email input";
    //                break;
    //            case SENDING_CODE:
    //                prefix = "custom footer sending code";
    //                break;
    //            case SENT_CODE:
    //                prefix = "custom footer sent code";
    //                break;
    //            case CODE_INPUT:
    //                prefix = "custom footer code input";
    //                break;
    //            case EMAIL_VERIFY:
    //                prefix = "custom footer email verify";
    //                break;
    //            case CONFIRM_ACCOUNT_VERIFIED:
    //                prefix = "custom footer confirm account";
    //                break;
    //            case VERIFYING_CODE:
    //                prefix = "custom footer verified code";
    //                break;
    //            case CONFIRM_INSTANT_VERIFICATION_LOGIN:
    //                prefix = "custom footer confirm instant verification login";
    //                break;
    //            case VERIFIED:
    //                prefix = "custom footer verified";
    //                break;
    //            case RESEND:
    //                prefix = "custom footer resend";
    //                break;
    //            case ERROR:
    //                prefix = "custom footer error";
    //                break;
    //            case NONE:
    //                break;
    //        }
    //        return PlaceholderFragment.newInstance(prefix);
    //    }

    override fun getButtonType(state: LoginFlowState): ButtonType? {
        when (state) {
            LoginFlowState.PHONE_NUMBER_INPUT -> return entryButton
            LoginFlowState.EMAIL_INPUT -> return entryButton
            LoginFlowState.CODE_INPUT -> return confirmButton
            else -> return null
        }
    }

    override fun onError(error: AccountKitError?) {
        // handle error
        Trace.d("onError Custom AK: " + error!!.userFacingMessage)
    }

    override fun writeToParcel(dest: Parcel, flags: Int) {
        super.writeToParcel(dest, flags)
        dest.writeString(if (confirmButton != null) confirmButton!!.name else null)
        dest.writeString(if (entryButton != null) entryButton!!.name else null)
        dest.writeString(if (textPosition != null) textPosition!!.name else null)
    }

    companion object {

        val CREATOR: Parcelable.Creator<CustomUIManager> = object : Parcelable.Creator<CustomUIManager> {
            override fun createFromParcel(source: Parcel): CustomUIManager {
                return CustomUIManager(source)
            }

            override fun newArray(size: Int): Array<CustomUIManager?> {
                return arrayOfNulls(size)
            }
        }
    }
}

从第一个块的调用代码中可以看出,我必须禁用自定义 UI,这样应用程序才不会崩溃。以下是崩溃的堆栈跟踪:

onCommon()-- Feedback channel: {category=2, app_is_inner=0, is_root=0, sub_category=0, exp_key=java.lang.RuntimeException: Unable to start activity ComponentInfo{net.inovidea.playday/com.facebook.accountkit.ui.AccountKitActivity}: java.lang.ArrayIndexOutOfBoundsException: length=3; index=4522062
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2505)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2577)
    at android.app.ActivityThread.access$1000(ActivityThread.java:164)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1462)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:160)
    at android.app.ActivityThread.main(ActivityThread.java:5541)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:964)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:759)
 *****
 Caused by: java.lang.ArrayIndexOutOfBoundsException: length=3; index=4522062
    at com.facebook.accountkit.ui.AccountKitConfiguration.<init>(AccountKitConfiguration.java:167)
    at com.facebook.accountkit.ui.AccountKitConfiguration.<init>(AccountKitConfiguration.java:38)
    at com.facebook.accountkit.ui.AccountKitConfiguration$1.createFromParcel(AccountKitConfiguration.java:209)
    at com.facebook.accountkit.ui.AccountKitConfiguration$1.createFromParcel(AccountKitConfiguration.java:207)
    at android.os.Parcel.readParcelable(Parcel.java:2265)
    at android.os.Parcel.readValue(Parcel.java:2165)
    at android.os.Parcel.readArrayMapInternal(Parcel.java:2527)
    at android.os.BaseBundle.unparcel(BaseBundle.java:221)
    at android.os.Bundle.getParcelable(Bundle.java:755)
    at android.content.Intent.getParcelableExtra(Intent.java:5127)
    at com.facebook.accountkit.ui.AccountKitActivityBase.onCreate(AccountKitActivityBase.java:58)
    at com.facebook.accountkit.ui.AccountKitActivity.onCreate(AccountKitActivity.java:246)
    at android.app.Activity.performCreate(Activity.java:6093)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2458)
    ... 10 more, app_pack=net.inovidea.playday, client_time=2018-08-24 16:29:48}

当我试图在类内部查看堆栈跟踪中有问题的行时AccountKitConfiguration,它显然指向创建新 Int 数组并用指定NotificationChannel的 s 填充它的部分。再说一次,类文件是一个反编译的文件,所以我不确定它的指向是否正确。

当我注释掉该UIManager设置时,这个错误不会显示,奇怪的是。

我的有什么问题CustomUIManager吗?

标签: androidkotlinaccount-kit

解决方案


推荐阅读