July 11, 2014

 

WP8 - some troubles report

While releasing first commercial app for WP8 I had experienced following effects.

1. Beta app updates very unstable. Frequently the description is new, but xap itself is of previous version. I don't know workaround. Usually publish new version. You have to check version carefully on every launch.

2. If you have crashes (unhandled exceptions), these stack traces will be in dashboard only 4 (yes, four) days after exception happened. After all, not every crash is reported. Workaround: I ended up writing my own unhandled exception handler which sends reports to my own sever.

3. IAP logics is not so simple as it may be thought of when you use consumable products with your own server check. There's one pitfall: you must call CurrentApp.RequestProductPurchaseAsync() only from UI thread (or you will have and unhandled exception!), while LicenseInformation.IsActive IAP license testing calls must not be called from UI according to MSDN. So it seems good idea on "buy" click to show some "please wait" indicator and continue to work in new thread. But when time comes to make a purchase method call you don't have Dispatcher.Invoke() for synchronously executing in UI thread (I mean wait for result). Also, you have to deliver exceptions from UI thread to your own thread. Here's the way:

          //not UI thread. something like "new Thread(delegate(){ ...following code... }).Start();"
          AutoResetEvent waitHandle = new AutoResetEvent(false);
          Dispatcher.BeginInvoke(async () =>
          {
            try{
              await CurrentApp.RequestProductPurchaseAsync(productListing.ProductId, false);
            }
            catch (Exception e) {
              purchaseEx = e;
              log(print(e)); 
            }
            waitHandle.Set();
          });
          waitHandle.WaitOne();
Or course you have to handle exceptions from separate UI thread, otherwise you will have unhandled exception and crash.

4. RequestProductPurchaseAsync() leads to ProductLicense.IsActive = true. But nobody knows when. MSDN says ""

5. When user press Cancel (or Back button) during system purchase confirmation, CurrentApp.RequestProductPurchaseAsync() throws an exception. This is undocumented behaviour, so you have to catch general Exception (I've seen System.Runtime.InteropServices.COMException at 8.0, but nobody guarantees 8.1 have same). By the way, catching general Exception is called "no-go" by Microsoft. Very nice.

Actually, I did not found good code sample of working IAP for consumable and self-checking. I'm going to publish my code when I test it fully. See next post.

Labels: , , , , , , ,

June 29, 2014

 

Some WP8 in app purchase errors

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
this means you call CurrentApp.RequestProductPurchaseAsync not from UI thread

error code 805a0194
(in a dialog) means that you need to publish your app (maybe in beta) via Store before you can test purchases.

Labels: , , , , , , ,

June 28, 2014

 

windows phone LINQ "already exists" issue on empty table

Update this happens not only when you have the only primary key field. Even when primary key is autogen, this exception happens when you put same value as you deleted previously in same DataContext session. I don't have workaround yet. Do you?

LINQ to SQL has strange effects when you try to reuse DataContext (re-creating of DataContext after every update/delete operation has different bad effect).

For example if your sole field is actually your primary key (it is unique at any moment and not null) and you delete it and in the same DataContext session insert same value, you will have InvalidOperationException. In my case the table is even empty!

  [Table(Name = "Receipts")]
  public class Receipt : PropertyChangedBase
  {
    protected String _s;
    public Receipt() { }
    public Receipt(String s) { _s = s; }

    [Column(IsPrimaryKey = false, CanBeNull = false, AutoSync = AutoSync.Always)]
    public String s
It seems that after delete you have to recreate DataContext. Will try this strategy.

Labels: , , , , , , ,

This page is powered by Blogger. Isn't yours?