Search code examples
xamarin.androidchrome-custom-tabs

chromecustomtab xamarin android MainActivity has leaked ServiceConnection CustomTabsServiceConnectionImpl@43a61ad that was originally bound here


I used chromecustomtab in my xamarin android project, i can bind service using CustomTabActivityManger class, but there is no option for unbind the service in that class.

and as i am not unbinding, it always throws me error of memory leak.

I am using Nuget - xamarin.Android.Support.CustomTabs version 26.1.0.1

code is as below

namespace Android.Support.CustomTabs
{
  public class CustomTabsActivityManager
  {
    public CustomTabsActivityManager(Activity parentActivity);

    public CustomTabsSession Session { get; }
    public Activity ParentActivity { get; }
    public CustomTabsClient Client { get; }

    public event CustomTabsServiceDisconnectedDelegate CustomTabsServiceDisconnected;
    public event CustomTabsServiceConnectedDelegate CustomTabsServiceConnected;
    public event ExtraCallbackDelegate ExtraCallback;
    public event NavigationEventDelegate NavigationEvent;

    public static CustomTabsActivityManager From(Activity parentActivity, string servicePackageName = null);
    public bool BindService(string servicePackageName = null);
    public void LaunchUrl(string url, CustomTabsIntent customTabsIntent = null);
    public bool MayLaunchUrl(string url, Bundle extras, List<string> otherLikelyUrls);
    public bool Warmup(long flags = 0);

    public class ExtraCallbackEventArgs
    {
        public ExtraCallbackEventArgs();

        public string CallbackName { get; set; }
        public Bundle Args { get; set; }
    }

    public delegate void NavigationEventDelegate(int navigationEvent, Bundle extras);
    public delegate void ExtraCallbackDelegate(object sender, ExtraCallbackEventArgs e);
    public delegate void CustomTabsServiceConnectedDelegate(ComponentName name, CustomTabsClient client);
    public delegate void CustomTabsServiceDisconnectedDelegate(ComponentName name);
}

Solution

  • I can bind service using CustomTabActivityManger class, but there is no option for unbind the service in that class

    Analyze:

    Usually we could directly use unbindService to unbind the Service. But in the CustomTabActivityManger source code we could found there no UnBindService() method. And you can't get the CustomTabsServiceConnection instance from outside so that it's hard to unbind the service in your Activity:

    public class CustomTabsActivityManager
    {
        ...
        CustomTabsServiceConnectionImpl connection;
        ...
    
        public bool BindService (string servicePackageName = null)
        {
            ...
    
            connection = new CustomTabsServiceConnectionImpl {
                CustomTabsServiceConnectedHandler = (name, client) => {
                    Client = client;
                    var evt = CustomTabsServiceConnected;
                    if (evt != null)
                        evt (name, client);
                },
                OnServiceDisconnectedHandler = (name) => {
                    var evt = CustomTabsServiceDisconnected;
                    if (evt != null)
                        evt (name);
                }
            };
    
            return CustomTabsClient.BindCustomTabsService (ParentActivity, servicePackageName, connection);
        }
    } 
    
    class CustomTabsServiceConnectionImpl : CustomTabsServiceConnection
    {
         ...
    }
    

    Solution:

    You could create a custom CustomTabsActivityManager class and add the UnBindService() method:

    public class MyCustomTabsActivityManager
    {
         CustomTabsServiceConnectionImpl connection;
    
         public Activity ParentActivity { get; private set; }
         public CustomTabsClient Client { get; private set; }
    
         CustomTabsSession session = null;
    
         ...
    
         public void UnBindService()
         {
             if (connection != null)
             {
                 ParentActivity.UnbindService(connection);
                 Client = null;
                 session = null;
              }
         }
    }
    

    Then, you could use this UnBindService() in your Activity:

    protected override void OnDestroy()
    {
        myCustomTabsActivityManager.UnBindService();
        base.OnDestroy();
    }