I'm developing a C# WinForms app, using the UWP API. I'm attempting to read notifications programatically, and I have succeeded so far. However, whenever I call AppInfo from the UserNotification class, I get a NotImplementedException, no matter what property I read from AppInfo.
Does anyone have any suggestions?
I have only been able to find 1 answer to this question and it's not very useful, and also a few years old. This is a major roadblock in my project, any help is massively appreciated!
Thank you in advance.
EDIT
Here's my code.
try {
this.source = notification.AppInfo.DisplayInfo.DisplayName;
} catch(NotImplementedException e) {
this.source = "Unspecified";
}
NotificationBinding binding = notification.Notification.Visual.GetBinding(KnownNotificationBindings.ToastGeneric);
if (binding != null) {
Console.WriteLine(binding.GetTextElements()[1]);
this.title = binding.GetTextElements().FirstOrDefault()?.Text;
this.body = string.Join("\n", binding.GetTextElements().Skip(1).Select(t => t.Text));
}
Init();
I'm using the code from the examples in the docs.
UWP AppInfo throws NotImplementedException
Based on the exception message, it looks like notification.AppInfo.DisplayInfo has not
been implemented for WinForm platform. For this scenario, we have a workaround for getting AppInfo with [AppDiagnosticInfo][1] api. Please refer the following code
var list = await AppDiagnosticInfo.RequestInfoAsync();
var currentPackage = list.Where(o => o.AppInfo.PackageFamilyName == Package.Current.Id.FamilyName).FirstOrDefault();
if (currentPackage != null)
{
AppInfo currentAppInfo = currentPackage.AppInfo;
var display = currentAppInfo.DisplayInfo;
}
private async Task<AppDisplayInfo> GetDisplayInfo()
{
var list = await AppDiagnosticInfo.RequestInfoAsync();
var currentPackage = list.FirstOrDefault(o => o.AppInfo.PackageFamilyName == Package.Current.Id.FamilyName);
if (currentPackage != null)
{
var currentAppInfo = currentPackage.AppInfo;
var display = currentAppInfo.DisplayInfo;
return display;
}
return null;
}
Related
So I'm working in Silverlight right now unfortunately for the first time. I'm decently familiar with callbacks, but I'm not entirely sure how to convert this method to be synchronous to perform logic on the order data.
I've been frequently told that making this synchronous was ill-advised, but my goal is to check if certain fields have been modified in the XAML UI and are different from what exists in the database. Then prompt for a reason for the change. If there is a better way to go about this, I'd love to know.
I'm in Silverlight 5 with .Net Framework 4.0 in VS 2013
Thank you! Here's the async order provider:
public void GetOrder(string ordNumber, Action<Func<OrderLoadResults>> callback)
{
String exStr = String.Format("{0}.{1}() --> received an empty value for",
this.GetType().Name,
MethodBase.GetCurrentMethod().Name);
if (ordNumber == null)
{
throw new ArgumentNullException("ordNumber", exStr);
}
if (callback == null)
{
throw new ArgumentNullException("callback", exStr);
}
IOrderServiceAsync channel = CreateChannel();
AsyncCallback asyncCallback = ar => GetOrderCallback(callback, ar);
channel.BeginGetOrderByOrdNumber(ordNumber, asyncCallback.ThreadSafe(), channel);
}
And here's what I'm doing with it:
public List<ATMModifiedFieldModel> CheckForATMModifiedFields()
{
if (!_order.Stops.Items.Any(x => x.ModelState == ModelState.Modified))
{
return null;
}
List<StopModel> oldStop = new List<StopModel>();
Provider.OrderProvider orderProvider = new Provider.OrderProvider();
//Looking to convert this method to sync to pull the order info out to compare against
//orderProvider.GetOrder(_order.Item.OrdHdrNumber.ToString(),getResult => OnGetOrderComplete(getResult));
List<ATMModifiedFieldModel> modifiedFields = new List<ATMModifiedFieldModel>();
foreach (StopModel stop in _order.Stops.Items)
{
if (stop.ModelState == ModelState.Modified)
{
foreach (string ATMFieldName in Enum.GetNames(typeof(ATMFields)))
{
string beforeValue = "before value"; //Should check the value in the database
string afterValue = stop.GetType().GetProperty(ATMFieldName).GetValue(stop, null).ToString();
if (beforeValue != afterValue)
{
modifiedFields.Add(new ATMModifiedFieldModel(ATMFieldName, beforeValue, afterValue, stop.StpNumber, "Stop"));
}
}
}
}
return modifiedFields;
}
I have a probably simple question for every pro coder:
I would like to write an iOS app with xamarin in C# that prints html to a receipt printer. For that I would like to adapt the default Cutterbeavior of the receipt printer.
i have this Code which works perfect for me:
var printer = UIPrintInteractionController.SharedPrintController;
printer.ShowsPageRange = true;
printer.ShowsNumberOfCopies = true;
printer.ShowsPaperSelectionForLoadedPapers = true;
var page = #"<!DOCTYPE html><style></style><html><head><meta charset='UTF-8'><title>Title</title></head><body>Text to print</body></html>";
var textFormatter = new UIMarkupTextPrintFormatter(page);
printer.PrintFormatter = textFormatter;
printer.Present(true, (handler, completed, err) =>
{
if (!completed && err != null)
{
Console.WriteLine("error");
}
});
and now i would like to customize this property:
printer.ChooseCutterBehavior
Unfortunately, the documenation does not help me any further:
https://developer.xamarin.com/api/property/UIKit.UIPrintInteractionController.ChooseCutterBehavior/
How can I set the property ChooseCutterBehavior? Unfortunately, I can not continue at this point and I am grateful for any hint!
Thanks!
In your IUIPrintInteractionControllerDelegate implementation, add the optional printInteractionController:chooseCutterBehavior: method.
This method may be called by the printer driver and will give the available (UIPrinterCutterBehavior) behaviors that this printer supports. You return one of the supported behaviors based upon your requirements.
public class MyPrintInteractionControllerDelegate : NSObject, IUIPrintInteractionControllerDelegate
{
[Export("printInteractionController:chooseCutterBehavior:")]
public UIPrinterCutterBehavior ChooseCutterBehavior(UIPrintInteractionController printInteractionController, NSNumber[] availableBehaviors)
{
// What does this printer support?
foreach (var whatsAvailable in availableBehaviors)
{
var nameofEnum = Enum.GetName(typeof(UIPrinterCutterBehavior), whatsAvailable.Int16Value);
Console.WriteLine($"AvailableBehavior : {nameofEnum}");
}
// If the printer supports CutAfterEachJob, use it, otherwise use the whatever the printer default is.
if (availableBehaviors.Contains((int)UIPrinterCutterBehavior.CutAfterEachJob))
return UIPrinterCutterBehavior.CutAfterEachJob;
else
return UIPrinterCutterBehavior.PrinterDefault;
}
//~~~ other delegate methods ~~~
}
Now assign the delegate (IUIPrintInteractionControllerDelegate) to your UIPrintInteractionController.SharedPrintController instance:
var printer = UIPrintInteractionController.SharedPrintController;
printer.Delegate = new MyPrintInteractionControllerDelegate();
I have created an app with in app purchase and tested it with CurrentAppSimulator and works fine but when i create the package for app it fails
This is my code for which i am creating package
public async System.Threading.Tasks.Task InAppInit()
{
var listing = await CurrentApp.LoadListingInformationAsync();
// Delux Unlock - Durable
var unlockFeatureDelux = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "deluxe" && p.Value.ProductType == ProductType.Durable);
isDeluxPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureDelux.Value.ProductId].IsActive;
deluxProductID = unlockFeatureDelux.Value.ProductId;
// Standard Unlock - Durable
var unlockFeatureStandard = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "standard" && p.Value.ProductType == ProductType.Durable);
isStarndardPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureStandard.Value.ProductId].IsActive;
standardProductID = unlockFeatureStandard.Value.ProductId;
}
I am calling this method OnLaunched in App.xaml.cs
Based on our discussion here is what I would do:
The LoadListingInformationAsync method uses internet and if the user does not have an internet connection then it will throw an exception. So I suggest to wrap this whole stuff into a try/ctach block
As we see the ProductListings does not contain any item. I don't know how this list is populated, but as long as your app is not in the store I would not be surprised when that list is empty (Maybe someone can help out here... but i did not find anything regarding this in the docs). So for this I would just simply check if the feature you need is in the list... With this your package will pass the test you mentioned and you can upload it. If the list is also empty when the package is installed via the store, then something with the IAP setting is wrong (but that is related to the store..)
And a general comment: Obviously this code is not complete... You need some code for purchasing the IAPs and here we only get the Ids.. (But I think you only pasted the relevant part anyway.)
So all this in code:
public async System.Threading.Tasks.Task InAppInit()
{
try
{
var listing = await CurrentApp.LoadListingInformationAsync();
if (listing.ProductListings.ContainsKey("deluxe"))
{
// Delux Unlock - Durable
var unlockFeatureDelux = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "deluxe" && p.Value.ProductType == ProductType.Durable);
isDeluxPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureDelux.Value.ProductId].IsActive;
deluxProductID = unlockFeatureDelux.Value.ProductId;
}
else
{
//There is no deluxe IAP defined... so something with your IAP stuff is wrong...
}
if (listing.ProductListings.ContainsKey("standard"))
{
// Standard Unlock - Durable
var unlockFeatureStandard = listing.ProductListings.FirstOrDefault(p => p.Value.ProductId == "standard" && p.Value.ProductType == ProductType.Durable);
isStarndardPurchased = CurrentApp.LicenseInformation.ProductLicenses[unlockFeatureStandard.Value.ProductId].IsActive;
standardProductID = unlockFeatureStandard.Value.ProductId;
}
else
{
//same as for Delux
}
}
catch
{
//Show this on the UI...
}
}
I want to get the name of a place (similar to Foursquare or Google Maps) from my current location using Maps API in Windows Phone 8. I can already get my current location using the code from this tutorial.
Can anybody help me?
You can use the ReverseGeocodeQuery class.
var rgc = new ReverseGeocodeQuery();
rgc.QueryCompleted += rgc_QueryCompleted;
rgc.GeoCoordinate = myGeoCoord; //or create new gc with your current lat/lon info
rgc.QueryAsync();
You can then get the data from within your rgc_QueryCompleted event handler using the Result property of the event args passed in.
If #keyboardP answer wasn't sufficient enough, here's (hopefully) working example to get the information about your location. There's no "name" property you could look up, at least not from the API's side.
public async Task<MapLocation> ReverseGeocodeAsync(GeoCoordinate location)
{
var query = new ReverseGeocodeQuery { GeoCoordinate = location };
if (!query.IsBusy)
{
var mapLocations = await query.ExecuteAsync();
return mapLocations.FirstOrDefault();
}
return null;
}
For this to work you'll need to add the following extension method for async query (from compiledexperience.com blog)
public static class GeoQueryExtensions
{
public static Task<T> ExecuteAsync<T>(this Query<T> query)
{
var taskSource = new TaskCompletionSource<T>();
EventHandler<QueryCompletedEventArgs<T>> handler = null;
handler = (sender, args) =>
{
query.QueryCompleted -= handler;
if (args.Cancelled)
taskSource.SetCanceled();
else if (args.Error != null)
taskSource.SetException(args.Error);
else
taskSource.SetResult(args.Result);
};
query.QueryCompleted += handler;
query.QueryAsync();
return taskSource.Task;
}
}
I'm trying to test the Internet connection in Windows8 from my C# application. I have a variable of type Boolean that returns me the connection status. When the boolean is true: do nothing. When the boolean becomes false, load my "NetworkDisconection" page. However, when I debug this line:
if (this.Frame != null)
I get an exception:
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
Yeah, this method is on a different thread. How can I resolve this?
private bool bConection;
public HUB()
{
this.InitializeComponent();
bConection = NetworkInformation.GetInternetConnectionProfile()!= null;
NetworkInformation.NetworkStatusChanged += NetworkInformation_NetworkStatusChanged;
}
void NetworkInformation_NetworkStatusChanged(object sender)
{
if (NetworkInformation.GetInternetConnectionProfile() == null)
{
if (bConection == false)
{
bConection = true;
}
}
else
{
if (bConection == true)
{
bConection = false;
if (this.Frame != null)
{
Frame.Navigate(typeof(NetworkDisconection));
}
}
}
}
Use the following code and it should fix your problem...
Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
if (this.Frame != null)
{
Frame.Navigate(typeof(NetworkDisconection));
}
});
You should be able to acquire the Dispatcher directly since it looks like your code is in the code-behind of a XAML page (reference to this.Frame).
Tons of good info can be found in the C# Win8 Dev Forums. Search for Dispatcher and you will find several discussions on it. As always, check out GenApp for other great resources.
The NetworkInformation.NetworkStatusChanged event is raised on a non-UI thread. Similar to WinForms and WPF, you are still limited to accessing controls on the UI thread.
To get around this aspect, you'll have to invoke the UI thread similar to how you would on WinForms or WPF using this.Invoke/this.Dispatcher.Invoke.
At first you may try to use Window.Current.Dispatcher.RunAsync() but you will notice that Window.Current is always null here.
Instead, you should use CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync() in the Windows.ApplicationModel.Core namespace. Yeah, that's quite a mouthful for sure so I recommend this helper method in App.cs.
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
public static IAsyncAction ExecuteOnUIThread(DispatchedHandler action)
{
var priority = CoreDispatcherPriority.High;
var dispatcher = CoreApplication.MainView.CoreWindow.Dispatcher;
return dispatcher.RunAsync(priority, action);
}
I would also recommend this helper method too:
public static bool CheckInternetAccess()
{
var profile = NetworkInformation.GetInternetConnectionProfile();
if (profile == null) return false;
var connectivityLevel = profile.GetNetworkConnectivityLevel();
return connectivityLevel.HasFlag(NetworkConnectivityLevel.InternetAccess);
}
And finally:
async void NetworkInformation_NetworkStatusChanged(object sender)
{
var isConnected = CheckInternetAccess();
await ExecuteOnUIThread(() =>
{
if (!isConnected && this.Frame != null)
this.Frame.Navigate(typeof(ConnectionLostPage));
});
}