Tuesday, 23 December 2014

Checking entitlements of iOS app bundle using codesign

I had a problem arise today - it became clear that a production iOS app wasn't requesting push notification permission from users. I went through some tagged releases and tested locally with Xcode, repeatedly installing and uninstalling and changing the date on my phone, and every time I was correctly asked for push permissions when expected.

So my attention turned to the production app and its permissions/entitlements. There was clearly nothing wrong with the code, but perhaps it hadn't been signed properly?

In Xcode's Organizer there is no way (as far as I can tell) to recover the ipa file that was submitted to Apple using the 'Submit' button, so instead I went to the App Store on my mac and downloaded the live production app. In Finder, I changed the .ipa file to a .zip, and opened up the package contents. In the 'payload' directory is the app file. With this, I checked the entitlements like so:
codesign -d --entitlements :- "Payload/YourApp.app"
The response showed that there were no APS entitlements. I compared it to a known working .app file, and the following entry was missing:
<key>aps-environment</key>
It seems that at some point the app was submitted with the wrong Distribution Profile. If it only it wasn't Christmas holidays at iTuneConnect!

Friday, 19 December 2014

Xamarin Android back button event during ActionMode

When a user presses the back button during an ActionMode, OnBackPressed() doesn't get called, s0 how to do we intercept this event if we need to do something?

Like this:
 public override bool DispatchKeyEvent(KeyEvent keyevent)
        {
            if (_contextualActionBar != null && ItemsInEditMode.Any())
            {
                if (keyevent.KeyCode == KeyEvent.KeyCodeFromString("KEYCODE_BACK") && keyevent.Action == KeyEventActions.Up)
                {
                    DeselectallItems(_listOfItems);
                    KillActionBar();
                    return true;
                }
            }
            return base.DispatchKeyEvent(keyevent);
        }

Thursday, 18 December 2014

Screenshot complete listview in Xamarin Android

Today I needed to turn a complete listview into an image, including the below-the-fold content that was yet to be rendered. I found some Java code on SO and ported it to C#. It works a treat:
public static Bitmap GetWholeListViewItemsToBitmap(ListView listview, HistoryAdapter adapter)
        {

            int itemscount = adapter.Count;
            int allitemsheight = 0;
            var bmps = new List();

            for (int i = 0; i < itemscount; i++)
            {

                View childView = adapter.GetView(i, null, listview);
                childView.Measure(View.MeasureSpec.MakeMeasureSpec(listview.Width, MeasureSpecMode.Exactly),
                        View.MeasureSpec.MakeMeasureSpec(0, MeasureSpecMode.Unspecified));

                childView.Layout(0, 0, childView.MeasuredWidth, childView.MeasuredHeight);
                childView.DrawingCacheEnabled = true;
                childView.BuildDrawingCache();
                bmps.Add(childView.GetDrawingCache(true));
                allitemsheight += childView.MeasuredHeight;
            }

            Bitmap bigbitmap = Bitmap.CreateBitmap(listview.MeasuredWidth, allitemsheight, Bitmap.Config.Argb8888);
            Canvas bigcanvas = new Canvas(bigbitmap);

            Paint paint = new Paint();
            int iHeight = 0;

            for (int i = 0; i < bmps.Count; i++)
            {
                Bitmap bmp = bmps[i];
                bigcanvas.DrawBitmap(bmp, 0, iHeight, paint);
                iHeight += bmp.Height;

                bmp.Recycle();
            }

            return bigbitmap;
        }

Tuesday, 16 December 2014

Intent.FLAG_ACTIVITY_NEW_TASK in Xamarin C# Android

While trying to StartActivity from a list adapter I got this warning:
Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
The way to overcome this in Java:
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
The not-so-well-documented way to acheive this using Xamarin:
intent.SetFlags(ActivityFlags.NewTask);

Tuesday, 9 December 2014

Converting from dips to pixels

Useful bit of C# Xamarin code for converting from dips to pixels:
            var dpValue = 10; // value in dips
            var d = AppContext.Resources.DisplayMetrics.Density;
            var pixValue = (int)(dpValue * d); // value in pixels