i am triyng to add in-app purchase option for my application.
i can purchase product correctly but when i purchase and navigate to other page and back to purchase page i can still purchase same product again. and when i purchase another product, my older purchased product become unpurchased.
here is my codes:
Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
LicenseChangedEventHandler licenseChangeHandler = null;
public SatinAlma()
{
this.InitializeComponent();
}
private async Task LoadInAppPurchaseProxyFileAsync()
{
StorageFolder proxyDataFolder = await Package.Current.InstalledLocation.GetFolderAsync("Data");
StorageFile proxyFile = await proxyDataFolder.GetFileAsync("in-app-purchase.xml");
licenseChangeHandler = new LicenseChangedEventHandler(InAppPurchaseRefreshScenario);
CurrentAppSimulator.LicenseInformation.LicenseChanged += licenseChangeHandler;
await CurrentAppSimulator.ReloadSimulatorAsync(proxyFile);
try
{
ListingInformation listing = await CurrentAppSimulator.LoadListingInformationAsync();
var PurchasePzl9 = listing.ProductListings["puzzle9"];
var PurchasePzl16 = listing.ProductListings["puzzle16"];
var PurchasePzl25 = listing.ProductListings["puzzle25"];
var PurchaseYardimseverlik = listing.ProductListings["yardimseverlik"];
var PurchaseTumpaket = listing.ProductListings["tumpaket"];
}
catch (Exception)
{
OAL_toast.showToast("LoadListingInformationAsync API call failed\n");
}
}
///////**i insert and delete this part nothing changed
//protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
//{
// if (licenseChangeHandler != null)
// {
// CurrentAppSimulator.LicenseInformation.LicenseChanged -= licenseChangeHandler;
// }
// base.OnNavigatingFrom(e);
//}
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
await LoadInAppPurchaseProxyFileAsync();
}
private void InAppPurchaseRefreshScenario()
{
}
private async void purchaseProduct()
{
LicenseInformation licenseInformation = CurrentAppSimulator.LicenseInformation;
if (!licenseInformation.ProductLicenses[stringPurchaseProduct].IsActive)
{
try
{
await CurrentAppSimulator.RequestProductPurchaseAsync(stringPurchaseProduct);
if (licenseInformation.ProductLicenses[stringPurchaseProduct].IsActive)
{
OAL_toast.showToast(stringPurchaseProduct + " purchased.");
this.Frame.Navigate(typeof(MainPage));
}
else
{
//OptimeAnimationLib.MsgBox(stringPurchaseProduct + " was not purchased.");
OAL_toast.showToast(stringPurchaseProduct + " was not purchased.");
}
}
catch (Exception)
{
OAL_toast.showToast("Unable to buy " + stringPurchaseProduct);
}
}
else
{
OAL_toast.showToast("you already own " + stringPurchaseProduct);
}
}
private void IMG_puzzle9_PointerReleased(object sender, PointerRoutedEventArgs e)
{
LicenseInformation licenseInformation = CurrentAppSimulator.LicenseInformation;
var productLicense = licenseInformation.ProductLicenses["puzzle9"];
if (productLicense.IsActive)
{
OAL_toast.showToast("you already own Puzzle 9.");
}
else
{
stringPurchaseProduct = "puzzle9";
purchaseProduct();
}
}
thanks, sorry for my english
It looks like you're reloading your Store simulator XML file every time you navigate, which will reset any Store activity you've done previously. Change your code so that you load the XML only when the app starts, and then you should see the Store state maintain itself across navigations. Note also that when you restart the app you'll be reloading the XML and thus reset the state.
Related
I have a function called getMessages that can be called by a Button click (using the RelayCommand trigger) or that is called in a timer every 15s.
The desired behavior is:
webservice > deserialize answer > system notification > updatelistview > insert localDB
But when the function is called by the timer the updatelistview is not done. Why does this happen if the function is the same and works perfectly in the button command?
CODE:
// Get messages for the logged in user
public async void getMessages()
{
try
{
List<FriendGetMessage> msg = new List<FriendGetMessage>();
var response = await CommunicationWebServices.GetCHAT("users/" + au.idUser + "/get", au.token);
if (response.StatusCode == HttpStatusCode.OK) // If there are messages for me.
{
var aux = await response.Content.ReadAsStringAsync();
IEnumerable<FriendGetMessage> result = JsonConvert.DeserializeObject<IEnumerable<FriendGetMessage>>(aux);
if (result != null)
{
foreach (var m in result)
{
msg.Add(m);
}
//MsgList=msg;
foreach (var f in Friends)
{
if (f.msg == null || f.msg.Count() == 0)
{
f.msg = new ObservableCollection<Messages>();
}
foreach (var mess in msg)
{
if (mess.idUser == f.idUser)
{
Messages mm = new Messages();
mm.received = mess.message;
mm.timestamp = "Received " + mess.serverTimestamp;
mm.align = "Right";
// Add to the friend list.
f.msg.Add(mm);
// Add to Local DB
InsertMessage(null, au.idUser.ToString(), f.idUser, mess.message, mess.serverTimestamp);
var notification = new System.Windows.Forms.NotifyIcon()
{
Visible = true,
Icon = System.Drawing.SystemIcons.Information,
BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info,
BalloonTipTitle = "New Message from " + f.name,
BalloonTipText = "Message: " + mess.message,
};
// Display for 5 seconds.
notification.ShowBalloonTip(5);
// The notification should be disposed when you don't need it anymore,
// but doing so will immediately close the balloon if it's visible.
notification.Dispose();
}
}
}
counterChat = 1; // resets the counter
}
}
else {
counterChat = counterChat * 2;
}
//var sql = "select * from chat";
//var respo = GetFromDatabase(sql);
OnPropertyChanged("Friends");
}
catch (Exception e)
{
MessageBox.Show("GetMessages: " + e);
Debug.WriteLine("{0} Exception caught.", e);
}
}
CODE TIMER:
public void chatUpdate()
{
_timerChat = new DispatcherTimer(DispatcherPriority.Render);
_timerChat.Interval = TimeSpan.FromSeconds(15);
_timerChat.Tick += new EventHandler(timerchat_Tick);
_timerChat.Start();
}
public void timerchat_Tick(object sender, EventArgs e)
{
if (counterChat != incChat)
{
incChat++;
}
else
{
getMessages();
OnPropertyChanged("Friends");
incChat = 0;
}
}
ADDED - I've also tried this and didn't worked (it seems that is some kind of concurrency problem to the ObservableCollection called Friends (is a friendslist) each friend has an ObservableCollection of messages (is a chat))
public void chatUpdate()
{
_timerChat = new DispatcherTimer(DispatcherPriority.Render);
_timerChat.Interval = TimeSpan.FromSeconds(15);
_timerChat.Tick += new EventHandler(timerchat_Tick);
_timerChat.Start();
}
public async void timerchat_Tick(object sender, EventArgs e)
{
if (counterChat != incChat)
{
incChat++;
}
else
{
Application.Current.Dispatcher.Invoke((Action)async delegate { await getMessages(); });
incChat = 0;
}
}
Best regards,
I think you need to make the timer handler be an async method as follows:
public async void timerchat_Tick(object sender, EventArgs e)
{
if (counterChat != incChat)
{
incChat++;
}
else
{
await getMessages();
OnPropertyChanged("Friends");
incChat = 0;
}
}
This way OnPropertyChanged("Friends") is guaranteed to fire after the work in getMessages is done.
The methods need to change to:
DispatcherTimer _timerChat = new DispatcherTimer(DispatcherPriority.Render);
_timerChat.Interval = TimeSpan.FromSeconds(15);
_timerChat.Tick += new EventHandler(timerchat_Tick);
_timerChat.Start();
public async void timerchat_Tick(object sender, EventArgs e)
{
//...
await getMessages();
//...
}
public async Task getMessages()
{
try
{
// ... your code here
string result = await response.Content.ReadAsStringAsync();
// .... rest of your code
}
catch (Exception e)
{
MessageBox.Show("GetMessages: " + e);
}
}
It is solved. The problem was in my ViewModels I was opening multiple threads and sometimes the right one would update the UI and sometimes no.
Thanks for all the answers.
I want to make an ap that turn on the flash when i press the On button, and turn off when I press the Off Button. This is my code :
protected AudioVideoCaptureDevice Device { get; set; }
private async void Button_Click_TurnOn(object sender, RoutedEventArgs e)
{
var sensorLocation = CameraSensorLocation.Back;
try
{
// get the AudioViceoCaptureDevice
var avDevice = await AudioVideoCaptureDevice.OpenAsync(sensorLocation,
AudioVideoCaptureDevice.GetAvailableCaptureResolutions(sensorLocation).First());
// turn flashlight on
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchMode);
if (supportedCameraModes.ToList().Contains((UInt32)VideoTorchMode.On))
{
avDevice.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.On);
// set flash power to maxinum
avDevice.SetProperty(KnownCameraAudioVideoProperties.VideoTorchPower,
AudioVideoCaptureDevice.GetSupportedPropertyRange(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchPower).Max);
}
else
{
//ShowWhiteScreenInsteadOfCameraTorch();
}
}
catch (Exception ex)
{
// Flashlight isn't supported on this device, instead show a White Screen as the flash light
// ShowWhiteScreenInsteadOfCameraTorch();
}
}
private void Button_Click_TurnOff(object sender, RoutedEventArgs e)
{
var sensorLocation = CameraSensorLocation.Back;
try
{
// turn flashlight on
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(sensorLocation, KnownCameraAudioVideoProperties.VideoTorchMode);
if (this.Device != null && supportedCameraModes.ToList().Contains((UInt32)VideoTorchMode.Off))
{
this.Device.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, VideoTorchMode.Off);
}
else
{
//turnWhiteScreen(false);
}
}
catch (Exception ex)
{
// Flashlight isn't supported on this device, instead show a White Screen as the flash light
//turnWhiteScreen(false);
}
}
I copied it from another question at stackoverflow, but I dont know why this code doesnt work for me. Tested on Lumia 820.
Please help me, thank you very much :)
async private void FlashlightOn_Click(object sender, RoutedEventArgs e)
{
// turn flashlight on
CameraSensorLocation location = CameraSensorLocation.Back;
if (this.audioCaptureDevice == null)
{
audioCaptureDevice = await AudioVideoCaptureDevice.OpenAsync(location,
AudioVideoCaptureDevice.GetAvailableCaptureResolutions(location).First());
}
FlashOn(location, VideoTorchMode.On);
}
private void FlashlightOff_Click(object sender, RoutedEventAgrs e)
{
// turn flashlight off
var sensorLocation = CameraSensorLocation.Back;
FlashOn(sensorLocation, VideoTorchMode.Off);
}
public bool FlashOn(CameraSensorLocation location, VideoTorchMode mode)
{
// turn flashlight on/off
var supportedCameraModes = AudioVideoCaptureDevice
.GetSupportedPropertyValues(location, KnownCameraAudioVideoProperties.VideoTorchMode);
if ((audioCaptureDevice != null) && (supportedCameraModes.ToList().Contains((UInt32)mode)))
{
audioCaptureDevice.SetProperty(KnownCameraAudioVideoProperties.VideoTorchMode, mode);
return true;
}
return false;
}
I have a problem with my async method in WPF application. I want to implement asynch await pattern in my WPF application to retain form responsiveness when querying database with EntityFramework. I did everything as described in microsoft examples but it doesn't return control flow to the application as example applications do.
Here is my button click code:
private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
var loggedIn = await _gluUserRepository.LoginAsync(LoginTextBox.Text, PasswordTextBox.Text);
Switcher.Switch(new Loader());
if (loggedIn)
{
UserName = LoginTextBox.Text;
Switcher.Switch(new Blank());
}
else
{
UserName = String.Empty;
MessageBox.Show("Błędny login lub hasło. Spróbuj ponownie.");
Switcher.Switch(new Login());
}
}
Here is my LoginAsync method:
public async Task<bool> LoginAsync(string login, string password)
{
string hashedPassword = PasswordHasher.Hash(password);
var user = await _dbContext.Users.FirstOrDefaultAsync(x => x.UserName == login);
if (user != null && user.Password == hashedPassword)
return true;
return false;
}
I've seen the same usage of async/await in Microsoft example applications, however, their WPF apps return control to Window handle, i.e. I can move window around when in my app that is impossible.
What I want to achieve is using async/await pattern with WPF application to retain responsiveness of application. I want to display loading circle when querying database and return to method when querying has been completed.
Anyone has an idea what am I doing wrong?
If I understand correctly
Switcher.Switch(new Loader());
is what shows the 'loading circle'.
You need to call it before you await the login. As it is now, your handler does everything else after LoginAsync returns.
You may also want to look at ReactiveUI. It provides a useful framework solving your problem.
It's hard to make guesses, but try changing the beginning of your LoginButton_Click code to start the task and await for its result later, like this:
private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
var loggedInTask = _gluUserRepository.LoginAsync(LoginTextBox.Text, PasswordTextBox.Text);
MessageBox.Show("before await");
var loggedIn = await loggedInTask;
MessageBox.Show("after await");
// ...
}
You should be seeing two message boxes, one after another, both of them should be responsive, i.e. moveable and click-able. If you do see such behaviour, then the problem is most likely with your Switcher.Switch and has nothing to do with asynchronous methods of EntityFramework.
I've found solution. Though I don't know why it actually works. But it doesn't block UI thread. I don't think it's thread safe too, you should we weary.
private async void LoginButton_Click(object sender, RoutedEventArgs e)
{
var loginTask = userRepository.LoginAsync(LoginTextBox.Text, PasswordTextBox.Password);
controller.DisplayPageLoader();
DbUser loginResult = await loginTask;
if (loginResult != null)
{
controller.DisplayPageNewMeal();
controller.SetLoggedUser(loginResult);
}
else
{
MessageBox.Show("Błędny login lub hasło. Spróbuj ponownie.");
controller.DisplayPageLogin();
}
}
and then in repository
public Task<DbUser> LoginAsync(string login, string password)
{
return Task.Run<DbUser>( () => Login(login, password));
}
private DbUser Login(string login, string password)
{
try
{
string hashedPassword = PasswordHasher.Hash(password);
var user = _dbContext.Users.FirstOrDefaultAsync(x => x.UserName == login);
if (user.Result != null && user.Result.Password == hashedPassword)
return user.Result;
return null;
}
catch(Exception ex)
{
_logger.Error("Blad logowania uzytkownika", ex);
return null;
}
}
i have main form with async load method :
private async void MainMenu_Load(object sender, EventArgs e)
{
await _connection.Start();
await _myHub.Invoke("Join");
_myHub.On("recieved", data =>
{
var obj = JsonConvert.DeserializeObject(data);
messagewindows = new SendMessage(User, obj.Sender);
if ((obj.Reciever == User ) )
{
messagewindows. txtHistory.Text += obj.Sender + " :" + obj.text + Environment.NewLine;
messagewindows.Show();
}
});
}
i show second form for show message but form hang crash app :
private async void SendMessage_Load(object sender, EventArgs e)
{
Text = Reciever;
await _connection.Start();
await _myHub.Invoke("Join");
_myHub.On("recieved", data =>
{
var obj = JsonConvert.DeserializeObject<MessageSent>(data);
if ((obj.Reciever == Sender || obj.Sender == Sender) && (obj.Sender == Reciever || obj.Reciever == Reciever))
{
txtHistory.Text += obj.Sender + " :" + obj.text + Environment.NewLine;
txtHistory.SelectionStart = txtHistory.Text.Length;
txtHistory.ScrollToCaret();
}
});
}
i try whithout success to delete a file in my local storage. Exactly, i took a photo and i want to delete it later with a button for exemple. But when i click on the button, the app bugs and i have : "access denied".
I sude a simple Delet.Async() after i get the file in a StorageFile.
private async void delete_click(object sender, RoutedEventArgs e)
{
StorageFile filed = await ApplicationData.Current.LocalFolder.GetFileAsync("myImg.jpg");
if (filed != null)
{
await filed.DeleteAsync();
}
}
Try the code below to see if it works for you.
private async void takephoto_click(object sender, RoutedEventArgs e)
{
var ui = new CameraCaptureUI();
ui.PhotoSettings.CroppedAspectRatio = new Size(4, 3);
var file = await ui.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (file != null)
{
// store the file
var myFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("myImg.jpg");
await file.MoveAndReplaceAsync(myFile);
// display the file
var bitmap = new BitmapImage();
bitmap.SetSource(await file.OpenAsync(FileAccessMode.Read));
Photo.Source = bitmap;
}
}
private async void delete_click(object sender, RoutedEventArgs e)
{
StorageFile filed = await ApplicationData.Current.LocalFolder.GetFileAsync("myImg.jpg");
if (filed != null)
{
await filed.DeleteAsync();
}
StorageFile filefound = await ApplicationData.Current.LocalFolder.GetFileAsync("myImg.jpg");
if (filefound != null)
{
// do something here
}
}
i am having same problem in deleting file from local storage. there are many files stored in the local storage with different names so how to delete other files. in the above case you have hard coded the file name to delete.
StorageFile filefound = await ApplicationData.Current.LocalFolder.GetFileAsync("myImg.jpg");
instead of myImg.jpg user want to delte other file then how user will delete
/// <summary>
/// Delete the indicated application file
/// </summary>
/// <param name="strFilePathName">The file path name to delete</param>
/// <returns>True, if successful; else false</returns>
public async static Task<bool> DeleteAppFile(string strFilePathName)
{
try
{
StorageFile fDelete = null;
if (!strFilePathName.Equals(""))
{
fDelete = await ApplicationData.Current.LocalFolder.GetFileAsync(strFilePathName);
if (fDelete != null)
{
try
{
await fDelete.DeleteAsync();
}
catch (Exception ex)
{
AFFECTS.App.ShowMessage(true, "Error", "DeleteAppFile {" + strFilePathName + "}", ex.Message);
return false;
}
return true;
}
}
else
AFFECTS.App.ShowMessage(true, "Error", "DeleteAppFile", "File path name is empty.");
}
catch (Exception ex)
{
AFFECTS.App.ShowMessage(true, "Error", "DeleteAppFile {" + strFilePathName + "}", ex.Message);
}
return false;
}
I have this and this only saves the last folder used when the user closes the application and re-opens it.
private void btnBrowse_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Reload();
fbFolderBrowser.SelectedPath = AppVars.LastSelectedFolder;
if (fbFolderBrowser.ShowDialog() == DialogResult.OK)
{
Properties.Settings.Default.LastSelectedFolder = fbFolderBrowser.SelectedPath.ToString();
Properties.Settings.Default.Save();
}
}
Every time the user selects a folder, I want to save that path. Then, when he clicks the browse button again, I want the default path to be his last selection.
The above is not working. It only saves the last path selected and goes back to it only if I restart the app. How would I go about saving the last path in the same app session?
You need to reload the settings:
Properties.Settings.Default.Reload();
Note that this only works when not running in Debug mode (AFAIK).
I'm gonna post my code here, because none of the answers I had seen addressed all the issues. This will save the location and re-load the settings for a file Browse dialog (file and folder browse dialogs are slightly different when getting path)... the answers above seem to be for the session only(?). Updated with new method to avoid config settings be lost with an update of clickonce app...
Code:
public class ConfigSettingsDictionary
{
public Dictionary<String, String> ConfigSettings = new Dictionary<String, String>();
}
ConfigSettingsDictionary MyConfigurationSettings = new ConfigSettingsDictionary();
private void SaveConfig()
{
using (System.IO.StreamWriter sw = new System.IO.StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\YOUR_APP_NAME_PLUS_UNIQUE_VALUE.config"))
{
foreach (var pair in MyConfigurationSettings.ConfigSettings)
{
sw.WriteLine(pair.Key + "=" + pair.Value);
}
}
}
private void LoadConfig()
{
if (System.IO.File.Exists(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\YOUR_APP_NAME_PLUS_UNIQUE_VALUE.config"))
{
var settingdata = System.IO.File.ReadAllLines(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\YOUR_APP_NAME_PLUS_UNIQUE_VALUE.config");
for (var i = 0; i < settingdata.Length; i++)
{
var setting = settingdata[i];
var sidx = setting.IndexOf("=");
if (sidx >= 0)
{
var skey = setting.Substring(0, sidx);
var svalue = setting.Substring(sidx + 1);
if (!MyConfigurationSettings.ConfigSettings.ContainsKey(skey))
{
MyConfigurationSettings.ConfigSettings.Add(skey, svalue);
}
}
}
}
}
private void UpdateConfig(Dictionary<String, String> keyvaluepairs)
{
foreach (var pair in keyvaluepairs)
{
if (!MyConfigurationSettings.ConfigSettings.ContainsKey(pair.Key))
{
MyConfigurationSettings.ConfigSettings.Add(pair.Key, pair.Value);
}
else
{
MyConfigurationSettings.ConfigSettings[pair.Key] = pair.Value;
}
}
}
then I use it like this (this saves the folder chosen in a file browse dialog and also the file chosen):
string lastused = "";
if (MyConfigurationSettings.ConfigSettings.ContainsKey("openFileDialog2_last_used"))
{
MyConfigurationSettings.ConfigSettings.TryGetValue("openFileDialog2_last_used", out lastused);
}
if (lastused != "")
{
openFileDialog2.InitialDirectory = lastused;
}
else
{
openFileDialog2.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
}
string filestring = "";
if (template_filename == "")
{
try
{
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
filestring = openFileDialog2.FileName;
String chosenPath = Path.GetDirectoryName(openFileDialog2.FileName);
Dictionary<String, String> settings_to_save = new Dictionary<String, String>();
settings_to_save.Add("openFileDialog2_last_used", chosenPath);
settings_to_save.Add("openFileDialog2_last_used_template_file", filestring);
UpdateConfig(settings_to_save);
}
else return;
}
catch (Exception ex)
{
MessageBox.Show("There was an error.", "Invalid File", MessageBoxButtons.OK);
return;
}
private void YOURFORMNAME_Load(object sender, EventArgs e)
{
// Load configuration file
LoadConfig();
}
private void YOURFORMNAME_FormClosing(object sender, FormClosingEventArgs e)
{
// Save configuration file
SaveConfig();
}