Xamarin.Android notification with custom controls does not work in API26 - c#

I have a notification that shows a button to start a timer. This button works fine on API25, but with API26 and greater, the button does nothing.
I have already set up a notification channel. The notification itself shows up correctly, so I don't think it's a channel issue.
Here I add the play/pause intent
var playPauseIntent = new Intent("com.example.example.timer");
var timerNotificationIntentValue = this.GetTimerNotificationIntentValue(timerAction);
playPauseIntent.PutExtra("timerNotification", timerNotificationIntentValue);
const int playPauseIntentId = 0;
var playPausePendingIntent = PendingIntent.GetBroadcast(this.context, playPauseIntentId, playPauseIntent, PendingIntentFlags.UpdateCurrent);
contentView.SetOnClickPendingIntent(Resource.Id.btn_start_pause, playPausePendingIntent);
And this is how I create the notification
var channelId = "11e9a3a1-aebf-425d-a9e8-fcc2fb139664";
var channelName = "General";
NotificationChannel channel;
channel = notificationManager.GetNotificationChannel(channelName);
if (channel == null)
{
channel = new NotificationChannel(channelId, channelName, NotificationImportance.Max);
channel.LockscreenVisibility = NotificationVisibility.Public;
notificationManager.CreateNotificationChannel(channel);
}
channel?.Dispose();
Notification.DecoratedCustomViewStyle notificationStyle = new Notification.DecoratedCustomViewStyle();
notification = new Notification.Builder(this.context, "11e9a3a1-aebf-425d-a9e8-fcc2fb139664")
.SetSmallIcon(Resource.Drawable.ic_logo)
.SetStyle(notificationStyle)
.SetCustomContentView(contentView)
.Build();
Then I just notify
notification.Flags |= NotificationFlags.OngoingEvent;
notificationManager.Notify("1", notification);
When tapping on the button, nothing happens on API26.
Something I notice, is that on API25, when I tap the button, I get to the BroadcastReceiver, whereas on API26 I don't

Changed this
var playPauseIntent = new Intent("com.example.example.timer");
to
var playPauseIntent = new Intent(this.context, typeof(MyNotificationBroadcastReceiver));
and now it seems to be working OK.

Related

How to dynamically Configure different "SubscriptionProperties" for Azure ServiceSub Subscription in C#

I'm trying to configure Azure ServiceBus Topic Subscription dynamically(using C#) with all of its properties which we can set up using Azure Portal.
I have tried the below code, but it's giving me an "object reference error" for SubscriptionProperties while setting up its values.
static SubscriptionProperties subscriptionProperties;
static async Task Main(string[] args)
{
adminClient = new ServiceBusAdministrationClient(connectionString);
client = new ServiceBusClient(connectionString);
subscriptionProperties.AutoDeleteOnIdle = TimeSpan.FromDays(14);
subscriptionProperties.DefaultMessageTimeToLive = TimeSpan.FromDays(14);
subscriptionProperties.TopicName = topicName;
subscriptionProperties.SubscriptionName = subscriptionName;
subscriptionProperties.MaxDeliveryCount = 3;
subscriptionProperties.LockDuration = TimeSpan.FromSeconds(5.00);
subscriptionProperties.DeadLetteringOnMessageExpiration = true;
subscriptionProperties.EnableDeadLetteringOnFilterEvaluationExceptions = true;
Console.WriteLine($"Creating the subscription {subscriptionName} with a correlation filter");
if (!await adminClient.SubscriptionExistsAsync(topicName, subscriptionName))
{
await adminClient.CreateSubscriptionAsync(
new CreateSubscriptionOptions(subscriptionProperties),
new CreateRuleOptions(subscriptionFilterName, new CorrelationRuleFilter() { Subject = correlationFilterValue }));
}
}
Let me know if this is the correct way of setting the property values for "SubscriptionProperties" class or how can I do so?
I was able to fix this issue by following this link https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/servicebus/Azure.Messaging.ServiceBus/samples/Sample07_CrudOperations.md#create-a-topic-and-subscription
var client = new ServiceBusAdministrationClient(connectionString);
string subscriptionName = "<subscription_name>";
var subscriptionOptions = new CreateSubscriptionOptions(topicName, subscriptionName)
{
AutoDeleteOnIdle = TimeSpan.FromDays(7),
DefaultMessageTimeToLive = TimeSpan.FromDays(2),
EnableBatchedOperations = true,
UserMetadata = "some metadata"
};
SubscriptionProperties createdSubscription = await client.CreateSubscriptionAsync(subscriptionOptions);
This might be helpful for other readers as well as having similar doubuts.

Automatically video play in chat bot emulator

I am Adding a videos card to my chat bot.
var resultMessage = context.MakeMessage();
var bytes = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath("~/Videos/Cute.mp4"));
string videoData = Convert.ToBase64String(bytes);
resultMessage.AttachmentLayout = AttachmentLayoutTypes.Carousel;
resultMessage.Attachments = new List<Microsoft.Bot.Connector.Attachment>();
VideoCard vc = new VideoCard()
{
// Title = $"hi",
// Subtitle = Address,
Media = new List<MediaUrl>()
{
new MediaUrl()
{
// Url = "https://i1.wp.com/thefreshimages.com/wp-content/uploads/2017/12/lord-shiva-hd-images.jpg?resize=3840%2C2160&ssl=1"
Url = "data:video/mp4;base64,"+ videoData
},
}
};
resultMessage.Attachments.Add(vc.ToAttachment());
await context.PostAsync(resultMessage);
It will play When user click the play button .But I want to play automatically.
Says here that Autostart property is true by default, so it should start playing automatically. You could try setting it to true and see if it works.
VideoCard vc = new VideoCard()
{
Media = new List<MediaUrl>()
{
new MediaUrl()
{
// Url = "https://i1.wp.com/thefreshimages.com/wp-content/uploads/2017/12/lord-shiva-hd-images.jpg?resize=3840%2C2160&ssl=1"
Url = "data:video/mp4;base64,"+ videoData
}
},
Autostart = true
};

Microsoft Bot Framework : SigninCard not showing in telegram

I tried create Telegram bot client with Microsoft Bot Framework, when I create signincard with this framework, signincard created successfully and I can see buttons in Microsoft Bot Emulator but when I publish to server and test it with Telegram, signincard not showing in bot, please tell me how to fix it.
code :
Activity reply = null;
ConnectorClient connector = new ConnectorClient(new Uri(activity.ServiceUrl), "", "");
if (activity.Type == ActivityTypes.Message)
{
if (activity.Text == "/start")
{
reply = activity.CreateReply($"Welcome, please select an option");
reply.Recipient = activity.From;
reply.Type = ActivityTypes.Message;
reply.Attachments = new List<Attachment>();
List<CardAction> cardButtons = new List<CardAction>();
var helpAction = new CardAction()
{
Image = "",
Title = "Get Menu",
Type = "imBack",
Value = "help"
};
var contactAction = new CardAction()
{
Image = "",
Title = "Contact Us",
Type = "imBack",
Value = "contact"
};
cardButtons.Add(helpAction);
cardButtons.Add(contactAction);
var sc = new SigninCard()
{
Buttons = cardButtons,
Text = ""
};
Attachment attach = sc.ToAttachment();
reply.Attachments.Add(attach);
}
else
{
}
}
await connector.Conversations.ReplyToActivityAsync(reply);
sorry for bad english.
I think sign-in card type must be "signin", and the value should be url instead of string
working code:
replyActivity.Attachments = new List<Attachment>();
var cardButtons = new List<CardAction>();
var plButton = new CardAction
{
Value = auth.SessionUrl,
Type = "signin",
Title = "Connect"
};
cardButtons.Add(plButton);
var plCard = new SigninCard("You need to authorize to use Quick Book feature", cardButtons);
var plAttachment = plCard.ToAttachment();
replyActivity.Attachments.Add(plAttachment);
replyActivity.Text = "Should go to conversation, sign-in card";
screenshot:

Configure kafka-net to stop sending latest messages

I'm using kafka 0.8.1.1 on a Red Hat VM with kafka-net plugin. How can I configure my consumer to stop receiving earlier messages from kafka?
My consumer code:
var options = new KafkaOptions(new Uri("tcp://199.53.249.150:9092"), new Uri("tcp://199.53.249.151:9092"));
Stopwatch sp = new Stopwatch();
var router = new BrokerRouter(options);
var consumer = new Consumer(new ConsumerOptions("Test", router));
ThreadStart start2 = () =>
{
while (true)
{
sp.Start();
foreach (var message in consumer.Consume())
{
if (MessageDecoderReceiver.MessageBase(message.Value) != null)
{
PrintMessage(MessageDecoderReceiver.MessageBase(message.Value).ToString());
}
else
{
Console.WriteLine(message.Value);
}
}
sp.Stop();
}
};
var thread2 = new Thread(start2);
thread2.Start();
The Consumer in Kafka-net does not currently auto track the offsets being consumed. You will have to implement the offset tracking manually.
To Store the offset in kafka version 0.8.1:
var commit = new OffsetCommitRequest
{
ConsumerGroup = consumerGroup,
OffsetCommits = new List<OffsetCommit>
{
new OffsetCommit
{
PartitionId = partitionId,
Topic = IntegrationConfig.IntegrationTopic,
Offset = offset,
Metadata = metadata
}
}
};
var commitResponse = conn.Connection.SendAsync(commit).Result.FirstOrDefault();
To set the consumer to start importing at a specific offset point:
var offsets = consumer.GetTopicOffsetAsync(IntegrationConfig.IntegrationTopic).Result
.Select(x => new OffsetPosition(x.PartitionId, x.Offsets.Max())).ToArray();
var consumer = new Consumer(new ConsumerOptions(IntegrationConfig.IntegrationTopic, router), offsets);
Note the above code will set the consumer to start consuming at the very end of the log, effectively only receiving new messages.

Background task is skipping schedule, updating every 60 min sometimes

I'm about to loose it soon... I have two apps with working background tasks that are updating the live tile. The data for the live tile is downloaded, parsed and then an image is created dynamically and used as the background for the live tile.
Everything is working just fine for a day or two, but then the updating starts behaving very strange. The first one-two days both live tiles for my apps are updating every 28 minutes like clockwork. But then they start skipping updates. Often app A then updates when app B doesn't update the live tile so that they are not updating at the same time and only once an hour. To put it simple they are way off schedule.
This is really frustrating since I need to be able to rely on the tiles beeing updated every 30 minutes (if I have enough battery, good reception and so on).
I would really appreciate if someone could help me out and maybe take a look at my code to see if there might be something messing up the update interval (like not calling NotifyComplete correctly). I have removed some code and and tried to simplify it. Please ask if you need anything else to understand this.
I have been trying to fix this for the last two months, trying different phones and going throughmy code very carefully.
Your help is more appreciated than you can ever know.
Thanks in advance.
My OnInvoke function:
Timer t = null;
ShellToast toast = new ShellToast();
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(strUrlHBH));
request.Accept = "*/*";
request.AllowAutoRedirect = true;
// disable caching.
request.Headers["Cache-Control"] = "no-cache";
request.Headers["Pragma"] = "no-cache";
t = new Timer(
state =>
{
if (string.Compare(state.ToString(), id, StringComparison.InvariantCultureIgnoreCase) == 0)
{
//logger.Write("Timeout reached for connection [{0}], aborting download.", id);
runNotifyComplete = false;
NotifyComplete();
request.Abort();
t.Dispose();
}
},
id,
timeout,
0);
request.BeginGetResponse(
r =>
{
try
{
if (t != null)
{
t.Dispose();
}
var httpRequest = (HttpWebRequest)r.AsyncState;
var httpResponse = (HttpWebResponse)httpRequest.EndGetResponse(r);
using (var reader = new StreamReader(httpResponse.GetResponseStream()))
{
var response = reader.ReadToEnd();
Deployment.Current.Dispatcher.BeginInvoke(new Action(() =>
{
try
{
//Parse the result
if (boolResult) //If we have a result
{
Grid grid = new Grid();
StackPanel sp = new StackPanel();
sp.Height = 173;
sp.Width = 173;
//StreamResourceInfo info = Application.GetResourceStream(new Uri("Pin-to-start2.png", UriKind.Relative));
if ((bool)settings["LiveTileMetro"] == true)
{
// create source bitmap for Image control (image is assumed to be alread 173x173)
/*WriteableBitmap wbmp2 = new WriteableBitmap(1, 1);
wbmp2.SetSource(info.Stream);
Image img = new Image();
img.Source = wbmp2;
// add Image to Grid
grid.Children.Add(img);
strBackBackground = "Pin-to-start2.png";
}
else
{*/
sp.Background = (SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"];
//sp.Background.Opacity = 0.0;
strBackBackground = "";
}
StreamResourceInfo info;
//GC.Collect();
info = Application.GetResourceStream(new Uri("/MyApp;component/images/Icons/livetile/livetile.png", UriKind.Relative));
WriteableBitmap wbmp3 = new WriteableBitmap(1, 1);
try
{
wbmp3.SetSource(info.Stream);
}
catch
{
}
Image img3 = new Image();
img3.Source = wbmp3;
// add Image to Grid
img3.Width = 173;
img3.Height = 173;
img3.Margin = new Thickness { Left = 0, Bottom = 0, Right = 0, Top = 0 };
TextBlock txtTemperature = new TextBlock();
TextBlock txtTemperatureRing = new TextBlock();
txtTemperature.Foreground = new SolidColorBrush(Colors.White);
txtTemperature.Text = strTemp;
txtTemperature.TextAlignment = TextAlignment.Right;
txtTemperatureRing.Style = (Style)Application.Current.Resources["PhoneTextTitle3Style"];
txtTemperatureRing.FontFamily = new FontFamily("Segoe WP Light");
txtTemperatureRing.FontSize = 40;
txtTemperatureRing.Foreground = new SolidColorBrush(Colors.White);
txtTemperatureRing.Text = "°";
txtTemperatureRing.TextAlignment = TextAlignment.Right;
txtTemperature.FontFamily = new FontFamily("Segoe WP Light");
txtTemperature.FontSize = 60;
txtTemperature.Margin = new Thickness { Left = 0, Bottom = 0, Right = 0, Top = -75 };
txtTemperature.Height = 80;
txtTemperature.Width = 145;
txtTemperatureRing.Margin = new Thickness { Left = 128, Bottom = 0, Right = 0, Top = -97 };
txtTemperatureRing.Height = 50;
txtTemperatureRing.Width = 39;
sp.Children.Add(img3);
sp.Children.Add(txtTemperature);
sp.Children.Add(txtTemperatureRing);
//call measure, arrange and updatelayout to prepare for rendering
sp.Measure(new Size(173, 173));
sp.Arrange(new Rect(0, 0, 173, 173));
sp.UpdateLayout();
grid.Children.Add(sp);
WriteableBitmap wbmp = new WriteableBitmap(173, 173);
wbmp.Render(grid, null);
wbmp.Invalidate();
//write image to isolated storage
string sIsoStorePath = #"\Shared\ShellContent\tile.png";
using (IsolatedStorageFile appStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
//ensure directory exists
String sDirectory = System.IO.Path.GetDirectoryName(sIsoStorePath);
if (!appStorage.DirectoryExists(sDirectory))
{
appStorage.CreateDirectory(sDirectory);
}
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(sIsoStorePath, System.IO.FileMode.Create, appStorage))
{
wbmp.SaveJpeg(stream, 173, 173, 0, 100);
}
}
/// If application uses both PeriodicTask and ResourceIntensiveTask
//ShellTile TileToFind = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("TileID=2"));
ShellTile TileToFind = ShellTile.ActiveTiles.First();
//test if Tile was created
if (TileToFind != null)
{
StandardTileData NewTileData = new StandardTileData
{
BackgroundImage = new Uri("isostore:Shared/ShellContent/tile.png", UriKind.Absolute),
Title = strTitle,
Count = null,
BackTitle = (string)settings["SelectedCityName"],
BackBackgroundImage = new Uri(strBackBackground, UriKind.Relative),
BackContent = strWind + Environment.NewLine + strPrecipitation
};
//ShellTile.Create(new Uri("/MainPage.xaml?TileID=2", UriKind.Relative), NewTileData);
TileToFind.Update(NewTileData);
}
}
if (runNotifyComplete == true)
{
runNotifyComplete = false;
NotifyComplete();
}
}//If matches.count
}
catch
{
if (runNotifyComplete == true)
{
runNotifyComplete = false;
NotifyComplete();
}
}
finally
{
if (runNotifyComplete == true)
{
runNotifyComplete = false;
NotifyComplete();
}
}
}));
}
if (runNotifyComplete == true)
{
runNotifyComplete = false;
NotifyComplete();
}
}
catch
{
// error handling.
if (runNotifyComplete == true)
{
runNotifyComplete = false;
NotifyComplete();
}
}
finally
{
}
},
request);
}
catch
{
if (runNotifyComplete == true)
{
runNotifyComplete = false;
NotifyComplete();
}
}
finally
{
}
EDIT 1: Here is the code for initializing the background task
MessageBox.Show(MyResources.LiveTileToggleMsgBoxText, "Live tile", MessageBoxButton.OK);
//start background agent
PeriodicTask periodicTask = new PeriodicTask("AppPeriodicAgent0440");
periodicTask.Description = "Periodic task for APP that updates the LiveTile .";
periodicTask.ExpirationTime = System.DateTime.Now.AddDays(14);
// If the agent is already registered with the system,
if (ScheduledActionService.Find(periodicTask.Name) != null)
{
ScheduledActionService.Remove("AppPeriodicAgent0440");
}
try
{
//only can be called when application is running in foreground
ScheduledActionService.Add(periodicTask);
}
catch
{
}
EDIT 2:
This code is run everytime I exit the application in order to keep the background task alive. I put it in OnNavigatedFrom to avoid slowing down the start up of the app
//start background agent
PeriodicTask periodicTask = new PeriodicTask("AppPeriodicAgent0440");
periodicTask.Description = "Periodic task for APP that updates the LiveTile.";
periodicTask.ExpirationTime = System.DateTime.Now.AddDays(14);
// If the agent is already registered with the system,
if (ScheduledActionService.Find(periodicTask.Name) != null)
{
ScheduledActionService.Remove("AppPeriodicAgent0440");
}
//only can be called when application is running in foreground
ScheduledActionService.Add(periodicTask);
If you read the Background Agents overview
http://msdn.microsoft.com/en-us/library/hh202942(v=vs.92).aspx you'll see that it details several scenarios where you schedule won't be followed. For example:
Battery Saver mode is an option that the user can enable on the device
to indicate that battery life should be prioritized. If this mode is
enabled, periodic agents may not run, even if the interval has elapsed
There is no guarantee that the scheduled task will run on the expected schedule. It even has a +/- 10 minute clause in the execution timeschedule.
From your question there is no information about how you're recording other events/tasks that may be happenening on the device at the time you're expecting a schedule to run.
In that you have no logging of errors, timeouts or checking of the LastExitReason of the task there could be all sorts of reasons for the behaviour you're seeing.
If I had to guess where the issue is, based on the information you have provided, I'd presume the problem is with the web request (either the network or the server) and an error in the request causes the UI to not be updated.
There is no way to guarantee that the tile will update on a predictable schedule. If you must absolutely have this updated for your circumstances/requirements then this platform isn't going to be able to provide that guarantee.
If you need multiple tiles to be kept in sync I'd approach this by having all the tiles updated by the same process.
This way, even if there is an inconsistency in the updating of the tiles from a time perspective they'll be in sync with each other.

Categories