Forum Xamarin Xamarin.Forms

Error when creating repeated local notifications using Xamarin.Forms on Android

I have been searching for how to create repeated local notifications, for instance a reminders app, I want to implement this logic on my xamarin.forms app so I have been testing with this piece of code (and understanding it) that I found on the web but the following error just I dont understand it.

Failed to create JavaTypeInfo for class: Android.Support.V4.View.Accessibility.AccessibilityManagerCompat/IAccessibilityStateChangeListenerImplementor due to MAX_PATH: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\andre\source\repos\LocalRepeatedNotificationsApp\LocalRepeatedNotificationsApp\LocalRepeatedNotificationsApp.Android\obj\Debug\90\android\src\mono\android\support\v4\view\accessibility\AccessibilityManagerCompat_AccessibilityStateChangeListenerImplementor.java'.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.File.InternalDelete(String path, Boolean checkHost)
   at System.IO.File.Delete(String path)
   at Xamarin.Android.Tools.Files.CopyIfStreamChanged(Stream stream, String destination)
   at Xamarin.Android.Tasks.Generator.CreateJavaSources(TaskLoggingHelper log, IEnumerable`1 javaTypes, String outputPath, String applicationJavaClass, String androidSdkPlatform, Boolean useSharedRuntime, Boolean generateOnCreateOverrides, Boolean hasExportReference) LocalRepeatedNotificationsApp.Android           

My code for sending local notifications in a repeated way:

public class LocalNotificationService : ILocalNotificationService
    {
        int _notificationIconId { get; set; }
        readonly DateTime _jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        internal string _randomNumber;

        public void LocalNotification(string title, string body, int id, DateTime notifyTime)
        {

            //long repeateDay = 1000 * 60 * 60 * 24;    
            long repeateForMinute = 60000; // In milliseconds   
            long totalMilliSeconds = (long)(notifyTime.ToUniversalTime() - _jan1st1970).TotalMilliseconds;
            if (totalMilliSeconds < JavaSystem.CurrentTimeMillis())
            {
                totalMilliSeconds = totalMilliSeconds + repeateForMinute;
            }

            var intent = CreateIntent(id);
            var localNotification = new LocalNotification();
            localNotification.Title = title;
            localNotification.Body = body;
            localNotification.Id = id;
            localNotification.NotifyTime = notifyTime;

            if (_notificationIconId != 0)
            {
                localNotification.IconId = _notificationIconId;
            }
            else
            {
                localNotification.IconId = Resource.Drawable.OlympiaLogo;
            }

            var serializedNotification = SerializeNotification(localNotification);
            intent.PutExtra(ScheduledAlarmHandler.LocalNotificationKey, serializedNotification);

            Random generator = new Random();
            _randomNumber = generator.Next(100000, 999999).ToString("D6");

            var pendingIntent = PendingIntent.GetBroadcast(Application.Context, Convert.ToInt32(_randomNumber), intent, PendingIntentFlags.Immutable);
            var alarmManager = GetAlarmManager();
            alarmManager.SetRepeating(AlarmType.RtcWakeup, totalMilliSeconds, repeateForMinute, pendingIntent);
        }

        public void Cancel(int id)
        {

            var intent = CreateIntent(id);
            var pendingIntent = PendingIntent.GetBroadcast(Application.Context, Convert.ToInt32(_randomNumber), intent, PendingIntentFlags.Immutable);
            var alarmManager = GetAlarmManager();
            alarmManager.Cancel(pendingIntent);
            var notificationManager = NotificationManagerCompat.From(Application.Context);
            notificationManager.CancelAll();
            notificationManager.Cancel(id);
        }

        public static Intent GetLauncherActivity()
        {

            var packageName = Application.Context.PackageName;
            return Application.Context.PackageManager.GetLaunchIntentForPackage(packageName);
        }


        private Intent CreateIntent(int id)
        {

            return new Intent(Application.Context, typeof(ScheduledAlarmHandler))
                .SetAction("LocalNotifierIntent" + id);
        }

        private AlarmManager GetAlarmManager()
        {

            var alarmManager = Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
            return alarmManager;
        }

        private string SerializeNotification(LocalNotification notification)
        {

            var xmlSerializer = new XmlSerializer(notification.GetType());

            using (var stringWriter = new StringWriter())
            {
                xmlSerializer.Serialize(stringWriter, notification);
                return stringWriter.ToString();
            }
        }
    }

    [BroadcastReceiver(Enabled = true, Label = "Local Notifications Broadcast Receiver")]
    public class ScheduledAlarmHandler : BroadcastReceiver
    {

        public const string LocalNotificationKey = "LocalNotification";

        public override void OnReceive(Context context, Intent intent)
        {
            var extra = intent.GetStringExtra(LocalNotificationKey);
            var notification = DeserializeNotification(extra);
            //Generating notification    
            var builder = new NotificationCompat.Builder(Application.Context)
                .SetContentTitle(notification.Title)
                .SetContentText(notification.Body)
                .SetSmallIcon(notification.IconId)
                .SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Ringtone))
                .SetAutoCancel(true);

            var resultIntent = LocalNotificationService.GetLauncherActivity();
            resultIntent.SetFlags(ActivityFlags.NewTask | ActivityFlags.ClearTask);
            var stackBuilder = Android.Support.V4.App.TaskStackBuilder.Create(Application.Context);
            stackBuilder.AddNextIntent(resultIntent);

            Random random = new Random();
            int randomNumber = random.Next(9999 - 1000) + 1000;

            var resultPendingIntent =
                stackBuilder.GetPendingIntent(randomNumber, (int)PendingIntentFlags.Immutable);
            builder.SetContentIntent(resultPendingIntent);
            // Sending notification    
            var notificationManager = NotificationManagerCompat.From(Application.Context);
            notificationManager.Notify(randomNumber, builder.Build());
        }

        private LocalNotification DeserializeNotification(string notificationString)
        {

            var xmlSerializer = new XmlSerializer(typeof(LocalNotification));
            using (var stringReader = new StringReader(notificationString))
            {
                var notification = (LocalNotification)xmlSerializer.Deserialize(stringReader);
                return notification;
            }
        }
    }

I am usign DependencyService to achieve this (my assembly is defined on the scope of my namespace but I havent included it for showing the problem)
Any help please?

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    Try to refer to this documentation about how to implement location notifications on Android:
    https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/local-notifications#create-the-android-interface-implementation
    We need to create channel after api 26 for your notifications:

    void CreateNotificationChannel()
    {
        manager = (NotificationManager)AndroidApp.Context.GetSystemService(AndroidApp.NotificationService);
    
        if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
        {
            var channelNameJava = new Java.Lang.String(channelName);
            var channel = new NotificationChannel(channelId, channelNameJava, NotificationImportance.Default)
            {
                Description = channelDescription
            };
            manager.CreateNotificationChannel(channel);
        }
    
        channelInitialized = true;
    }
    

    I created a sample for displaying notifications with alert manager based on the code you posted above. you could see the attachment for the specific code.

  • AndresQuiValAndresQuiVal Member ✭✭
    edited December 2019

    @LandLu sorry, I still have the same error even using your sample, exact the same (I am in API23, android 6.0):
    Severity Code Description Project File Line Suppression State
    Error Failed to create JavaTypeInfo for class: Android.Support.V4.View.Accessibility.AccessibilityManagerCompat/ITouchExplorationStateChangeListenerImplementor due to MAX_PATH: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\andre\OneDrive\Escritorio\LocalNotificationSample\LocalNotificationSample\LocalNotificationSample.Android\obj\Debug\90\android\src\mono\android\support\v4\view\accessibility\AccessibilityManagerCompat_TouchExplorationStateChangeListenerImplementor.java'.
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
    at System.IO.File.InternalDelete(String path, Boolean checkHost)
    at System.IO.File.Delete(String path)
    at Xamarin.Android.Tools.Files.CopyIfStreamChanged(Stream stream, String destination)
    at Xamarin.Android.Tasks.Generator.CreateJavaSources(TaskLoggingHelper log, IEnumerable`1 javaTypes, String outputPath, String applicationJavaClass, String androidSdkPlatform, Boolean useSharedRuntime, Boolean generateOnCreateOverrides, Boolean hasExportReference) LocalNotificationSample.Android

  • LandLuLandLu Member, Xamarin Team Xamurai

    This is caused by a MAX_PATH issue on Windows. I noticed the file is located in the C:\Users\andre\OneDrive\Escritorio.... Try to place the root folder of my sample directly in the **C:** to shorten the directory path. And remove the unnecessary parent directory path like: \LocalNotificationSample\LocalNotificationSample\. Finally, delete the bin/obj folders before building the project.
    You could also follow this thread to modify the Android .csproj:
    https://stackoverflow.com/a/56244187/8354952

Sign In or Register to comment.