如何使用Local Notifications / Notification.Builder

时间:2018-05-22 23:36:51

标签: android xamarin xamarin.forms notifications xamarin.android

我正在尝试在显示本地通知时在Android平台上播放自定义声音,下面的代码基于Xamarin Local Notification Documentation,但是某些我被唠叨的字段已经过时/弃用。

特别是 SetSound

然而,我尝试使用SetSound,希望它仍然可以工作,即使已弃用。但我不知道如何引用Android / Xamarin' Asset'中的mp3文件。我在Android / Xamarin' Resources / raw'中的文件夹或副本夹。

/资产内容具有构建操作AndroidAsset

/ Resources / raw contents有构建动作AndroidResource

这条线是令我头痛的原因......

.SetSound(Android.Net.Uri.Parse(" android.resource://MyAssemblyName.Droid/Assets/filename"));

也尝试了

.SetSound(Android.Net.Uri.Parse(" android.resource://MyAssemblyName.Resources/raw/filename"));

Q1)使用Assets或Resources文件夹正确播放自定义通知声音需要做什么?

Q2)因为SetSound已被弃用,我打算做什么呢?

我已经作弊,部分成功,我有一个播放声音的Xamarin插件,它引用了便携式类库(PCL)中的相同文件,并且该机制可以工作(当未注释时),但仅当应用程序在前景。

如果我刷到“杀死”,似乎我的预定本地通知不会触发。应用程序,即使应用程序不会因为我有一个持久的通知阻止应用程序关闭(直到将来的某个时间发布持续通知,可能会在几分钟后)。

问题3)一旦用户滑动应用程序,为什么不会触发计划的本地通知,即使持久系统通知让应用程序保持运行?以下是如何设置持久性通知的方法。如果不是这个问题,我可能会通过上面详述的黑客来播放来自PCL的声音。

        var activity = new Intent(Android.App.Application.Context, typeof(MainActivity));
        var pIntent = PendingIntent.GetActivity(this, 0, activity, 0);

        var notification = new Notification.Builder(this)
            .SetContentTitle("Persistent Notification Test")
            .SetContentText("This is always running to ensure that you are safe.")
            .SetSmallIcon(Resource.Drawable.icon)
            .SetOngoing(true)
            .SetDefaults(0) // no sounds
            .SetContentIntent(pIntent)
            .Build();

        // Enlist this instance of the service as a foreground service
        StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);

对于那些感兴趣的人,注释掉的行

// PlatformDifferences.PlaySound(soundFilename, Logger);

调用此方法使用SimpleAudioPlayer插件

    public virtual void PlaySound(string soundFilenameExcludingPath, Logger logger) {
        var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;

        Stream audioStream = assembly.GetManifestResourceStream("<my-pcl-assembly-name>.Sounds." + soundFilenameExcludingPath);
            if (audioStream != null)
            {
                logger.Log(this, "playing sound:" + soundFilenameExcludingPath);
                var player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
                player.Load(audioStream);
                player.Play();
            }
            else
            {
                logger.Log(this, "failed - playing sound:" + soundFilenameExcludingPath);
            }
    }

这是一个显示我的项目结构的屏幕截图

Screenshot of resource and asset folder with code snippet

以下是我想要显示通知时调用的方法,无论是因为我想要预定的本地通知,还是因为我已收到推送通知并希望向我们显示详细信息用户。

    private async Task DisplayLocalNotification(String title, String message, String soundFilename)
    {

        Logger.Log(this, "DisplayLocalNotification title:" + title + " message:" + message);

        // Ensure the main activity is lauched when the app is started.
        Intent secondIntent = new Intent(Android.App.Application.Context, typeof(MainActivity));

        Notification.BigTextStyle textStyle = new Notification.BigTextStyle();
        textStyle.BigText(message);
        int length = message.Length;
        if (length > 80)
        {
            length = 80;
        }
        textStyle.SetSummaryText(message.Substring(0, length));

        const int pendingIntentId = 0;
        PendingIntent pendingEventForMainActivity =
            PendingIntent.GetActivity(Android.App.Application.Context, pendingIntentId, secondIntent, PendingIntentFlags.OneShot);

        Notification.Builder builder = new Notification.Builder(Android.App.Application.Context)
            .SetContentTitle(title)
            .SetContentText(message)
            .SetAutoCancel(true)
            .SetContentIntent(pendingEventForMainActivity)
            //.SetWhen () // - Now
            .SetSmallIcon(Resource.Drawable.icon)
            .SetVisibility(NotificationVisibility.Public) 
            .SetCategory(Notification.CategoryEvent)
            .SetStyle(textStyle)
            //.SetSound(Asset);?? What import?
            //.SetSound(RingtoneManager.) ?? Looks like it's a fixed list of alert sounds
            .SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate) // << DEPRECATD
            .SetSound(Android.Net.Uri.Parse("android.resource://My-Assembly.Droid/Assets/" + soundFilename)); // << DEPECATD

        // Hack - Works (if in foreground, but no if swipe-to-kill)...
        // PlatformDifferences.PlaySound(soundFilename, Logger);

        // Example: .SetSound(Uri.Parse("android.resource://" + this.PackageName + "/Raw/" + Resource.Raw.woop));

        if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
        {
            builder.SetSmallIcon(Resource.Drawable.icon);// Resource.Drawable.icon_transparent);
        }
        else
        {
            builder.SetSmallIcon(Resource.Drawable.icon);
        }

        // Create a task stack builder to manage the back stack:
        TaskStackBuilder stackBuilder = TaskStackBuilder.Create(Android.App.Application.Context);

        // Add all parents of SecondActivity to the stack: 
        stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(MainActivity)));

        // Push the intent that starts SecondActivity onto the stack:
        stackBuilder.AddNextIntent(secondIntent);

        // Build the notification:
        Notification androidNotification = builder.Build();

        NotificationManager notificationManager =
            Android.App.Application.Context.GetSystemService(Android.Content.Context.NotificationService) as NotificationManager;

        // Publish the notification:
        int notificationId = await StorageService.increment(Constants.STORAGE_KEY_NOTIFICATION_COUNTER);
        notificationManager.Notify(notificationId, androidNotification);

        Console.Out.WriteLine("DisplayLocalNotification title:" + title + " message:" + message + " published as id:" + notificationId + "?");

    }

1 个答案:

答案 0 :(得分:0)

请参阅@SushiHangover的评论

  

您的屏幕截图显示的是API-27设备以及targetSdkVersion   设置好了,你需要使用NotificationChannels(你会的   需要if / else测试API级别,如我的链接示例所示)。我有   看到很多不同类型的通知失败就不同了   (API-26 +)设备,甚至模拟器中的通知都表现出来   不使用NotificationChannels时会有所不同。