user5729996
user5729996

Reputation:

Unexpectedly crashing of service when activity is stopped in Xamarin Android

I start a service and create new thread (downloading a large file). When my activity is opened application works properly - download first part, second part, third part etc. It can be seen in the film: https://youtu.be/qVItEjR00UY

But when I close my activities, my app unexpectedly crash (not immediately but after some time): https://youtu.be/-Pe-vNgAy1U

Why? When I run application from Visual Studio I have the same situation (without error message).

My service:

[Service]
class DownloadsService : Service
{
    DownloadsBroadcastReceiver receiver;
    Notification.Builder notificationBuilder;
    DownloadsData downloadsData;
    int uniqueNumber = 1000;
    bool isStarted;
    bool pauseTask;

    public override void OnCreate()
    {
        base.OnCreate();
        RegisterReceiver(receiver, new IntentFilter("com.xamarin.example.TEST"));
    }

    public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
    {
        string downloadsDataToParse = intent.GetStringExtra("downloadsData");
        if (downloadsDataToParse != null)
            downloadsData = JsonConvert.DeserializeObject<DownloadsData>(downloadsDataToParse);
        pauseTask = intent.GetBooleanExtra("pauseTask", false);
        if (isStarted && !pauseTask)
            Log.Info("DAMIAN", "Usługa została już wcześniej uruchomiona");
        else if (isStarted && pauseTask)
        {
            PauseTask();
            Log.Info("DAMIAN", "Wstrzymano");
            UpdateNotification("Wstrzymano");
        }
        else
        {
            Log.Info("DAMIAN", "Usługa została uruchomiona");
            DispatchNotificationThatServiceIsRunning(downloadsData.Nazwa, "Rozpoczynanie");
            new Thread(new ThreadStart(() =>
            {
                MakeDownload(downloadsData.Zadania, downloadsData.Nazwa, downloadsData.AccountsList);
            })).Start();
            isStarted = true;
        }
        return StartCommandResult.Sticky;
    }

    public override IBinder OnBind(Intent intent)
    {
        return null;
    }

    public override void OnDestroy()
    {
        Log.Info("DAMIAN", "Usuwanie usługi");
        var notificationManager = (NotificationManager)GetSystemService(NotificationService);
        notificationManager.Cancel(uniqueNumber);
        isStarted = false;
        base.OnDestroy();
    }

    private void DispatchNotificationThatServiceIsRunning(string title, string content)
    {
        Intent stopIntent = new Intent(this, typeof(DownloadsBroadcastReceiver));
        stopIntent.PutExtra("action", "actionName");
        PendingIntent stopPi = PendingIntent.GetBroadcast(this, 4, stopIntent, PendingIntentFlags.UpdateCurrent);
        Intent intent = new Intent(this, typeof(MainActivity));
        TaskStackBuilder stackBuilder = TaskStackBuilder.Create(this);
        stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(MainActivity)));
        stackBuilder.AddNextIntent(intent);
        PendingIntent resultPendingIntent = stackBuilder.GetPendingIntent(0, PendingIntentFlags.UpdateCurrent);
        Notification.Action pauseAction = new Notification.Action.Builder(Resource.Drawable.Pause, "Wstrzymaj", stopPi).Build();
        Notification.Action removeAction = new Notification.Action.Builder(Resource.Drawable.Remove, "Usuń", resultPendingIntent).Build();
        notificationBuilder = new Notification.Builder(this)
            .SetSmallIcon(Resource.Drawable.Icon)
            .SetContentIntent(resultPendingIntent)
            .SetContentTitle(title)
            .SetContentText(content)
            .AddAction(pauseAction)
            .AddAction(removeAction);
        var notificationManager = (NotificationManager)GetSystemService(NotificationService);
        notificationManager.Notify(uniqueNumber, notificationBuilder.Build());
    }

    private void UpdateNotification(string content)
    {
        notificationBuilder.SetContentText(content);
        var notificationManager = (NotificationManager)GetSystemService(NotificationService);
        notificationManager.Notify(uniqueNumber, notificationBuilder.Build());
    }

    private void MakeDownload()
    {
        //download file
    }

    private void PauseTask()
    {
        //pause downloading
    }
}

Upvotes: 0

Views: 417

Answers (2)

user5729996
user5729996

Reputation:

I solved this problem with Foreground Services. In OnStartCommand I call StartForeground(uniqueNumber, notification); and service works even after closing acitivities.

Upvotes: 0

Grace Feng
Grace Feng

Reputation: 16652

But when I close my activities, my app unexpectedly crash (not immediately but after some time)

Sounds like that you didn't unbind the service when your activities is closed. Please refer to the Bound Service Lifecycle.

Try to unbind the service in the OnStop() or OnDestroy() method of the activity where you bind the service for example:

protected override void OnStop()
{
    UnbindService(serviceConnection);
    base.OnStop();
}

Or

protected override void OnDestroy ()
{
        base.OnDestroy ();

        if (isBound) {
                UnbindService (demoServiceConnection);
                isBound = false;
        }
}

Upvotes: 1

Related Questions