Activity 泄露了 IntentReceiver - LollipopBrowserAccessibilityManager

Posted

技术标签:

【中文标题】Activity 泄露了 IntentReceiver - LollipopBrowserAccessibilityManager【英文标题】:Activity has leaked IntentReceiver - LollipopBrowserAccessibilityManager 【发布时间】:2018-01-26 10:41:41 【问题描述】:

我希望在这里找到一些帮助,因为我不熟悉 android 中的 BroadcastReceivers。这段代码会打开一个 WebView 将您重定向到登录页面,并在检测到 URL 更改后接收登录令牌。之后,Activity 就关闭了。

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);

    mLoginWebView = (WebView) findViewById(R.id.webview_login);

    redirectUrl = getString(R.string.app_redirect_url);


    //RECEIVE PLATFORM ID
    Bundle bundle = getIntent().getExtras();
    if(bundle != null)
        platform = bundle.getInt(ConstantsHelper.LOGIN_EXTRA_TOKEN);
    

    mLoginWebView.setWebViewClient(new WebViewClient() 

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) 

            Log.d(TAG, "URL change to to " + url + " was detected");

            if (url.contains(redirectUrl) || url.contains("passport.twitch.tv")) 

                Log.d(TAG, "Login with platform " + platform);

                switch (platform)

                    //GET INSTAGRAM AUTH TOKEN
                    case ConstantsHelper.ID_INSTAGRAM:
                        String accessToken = url.split("=")[1];

                        SharedPreferenceHelper.putString(ConstantsHelper.PREF_INST_ACCESS_TOKEN, accessToken);
                        NetworkManager.getInstance().catchTokens();

                    

                    //GET TWITCH AUTH TOKEN
                    case ConstantsHelper.ID_TWITCH:
                        String accessToken = url.substring(url.indexOf("=") + 1, url.indexOf("&"));

                        SharedPreferenceHelper.putString(ConstantsHelper.PREF_TWITCH_ACCESS_TOKEN, accessToken);
                        NetworkManager.getInstance().catchTokens();

                    

                
                finish(); //Activity is closed
                return true;
            
            return false;
        


    );

    switch (platform)
        case 1: mLoginWebView.loadUrl(NetworkManager.getInstance().getInstagramAuthUrl(getApplicationContext()));
        case 4: mLoginWebView.loadUrl(NetworkManager.getInstance().getTwitchAuthUrl(getApplicationContext()));
    



什么也没发生,LogCat 显示此错误:

Activity com.maximutan.socialmedia_feed_merger.activities.LoginActivity has leaked IntentReceiver org.chromium.content.browser.accessibility.LollipopBrowserAccessibilityManager$1@25014a that was originally registered here. Are you missing a call to unregisterReceiver()?
android.app.IntentReceiverLeaked: Activity com.maximutan.socialmedia_feed_merger.activities.LoginActivity has leaked IntentReceiver org.chromium.content.browser.accessibility.LollipopBrowserAccessibilityManager$1@25014a that was originally registered here. Are you missing a call to unregisterReceiver()?
at android.app.LoadedApk$ReceiverDispatcher.<init>(LoadedApk.java:962)
at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:763)
at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1179)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1159)
at android.app.ContextImpl.registerReceiver(ContextImpl.java:1153)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:554)
at android.content.ContextWrapper.registerReceiver(ContextWrapper.java:554)
at org.chromium.content.browser.accessibility.LollipopBrowserAccessibilityManager.<init>(LollipopBrowserAccessibilityManager.java:3)
at org.chromium.content.browser.accessibility.BrowserAccessibilityManager.create(BrowserAccessibilityManager.java:2)
at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)

at org.chromium.base.SystemMessageHandler.handleMessage(
SystemMessageHandler.java:7)  
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5527)
,at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(
ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)

我的问题是我不知道我必须取消注册哪个 BroadcastReceiver,因为我还没有创建和初始化一个。

感谢您的帮助

【问题讨论】:

我不知道怎么了,错误突然出现在我没有导航到的Activity中。 您的测试设备使用的是 Android O 吗? 没有 Android 6.0 @Abir Hasan 等待和标记 【参考方案1】:

您是否使用以下任何WebSettings

    settings.setAllowContentAccess(true);
    settings.setAllowFileAccessFromFileURLs(true);
    settings.setAllowUniversalAccessFromFileURLs(true);
    settings.setAllowFileAccess(true);

我发现通过禁用这些选项(在我的实例中我实际上并不需要它们),错误就消失了。我猜它与其中之一所需的兼容性库有关。

【讨论】:

不,我实际上并没有使用这些,但我仍然会尝试禁用它们【参考方案2】:

当 WebView 仍附加到其父视图时,在 WebView 上调用 destroy() 时会出现此问题。

可以通过在调用 destroy() 之前先从其父视图中删除 Webview 来解决崩溃。

请注意,即使您没有手动调用destroy()(就像我的情况一样),这种崩溃仍然可能发生。我发现关键是你必须明确地销毁一个 WebView(至少在一个片段中),因为 Android 不会为你处理这个,在这样做之前,你必须将它从其父视图中删除。

例如,如果你有一个 WebView 片段:

 @Override
    public void onDestroyView() 
        super.onDestroyView();

        // destroy the WebView completely
        if (mWebView != null) 
            // the WebView must be removed from the view hierarchy before calling destroy
            // to prevent a memory leak
            // See https://developer.android.com/reference/android/webkit/WebView.html#destroy%28%29
            ((ViewGroup) mWebView.getParent()).removeView(mWebView);
            mWebView.removeAllViews();
            mWebView.destroy();
            mWebView = null;
        
    

感谢比利·布劳纳:https://brawner.tech/2017/12/03/webview-memory-leak/

【讨论】:

以上是关于Activity 泄露了 IntentReceiver - LollipopBrowserAccessibilityManager的主要内容,如果未能解决你的问题,请参考以下文章

Activity 泄露了 IntentReceiver - LollipopBrowserAccessibilityManager

“Activity 已经泄露了原本添加在这里的窗口”

ProgressDialog.show() - Activity 已泄露窗口

属性动画导致的内存泄露

android内存优化-Activity, Thread引起的内存泄露0

Activity 已泄露窗口,Dialog