       
<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Platty Soft &#187; Android</title>
	<atom:link href="http://www.plattysoft.com/category/android-2/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.plattysoft.com</link>
	<description>Android consulting fun and professional.</description>
	<lastBuildDate>Mon, 12 Jan 2026 20:55:39 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=4.1.5</generator>
	<item>
		<title>Book: Mastering Android Game Development</title>
		<link>http://www.plattysoft.com/2015/07/06/book-mastering-android-game-development-2/</link>
		<comments>http://www.plattysoft.com/2015/07/06/book-mastering-android-game-development-2/#comments</comments>
		<pubDate>Mon, 06 Jul 2015 09:33:04 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1103</guid>
		<description><![CDATA[I&#8217;ve been busy the past few months writing a book titled Mastering Android Game Development with focuses on using the Android SDK for building games. The book is now available online. If you are an intermediate-level Android developer who wants &#8230; <a href="http://www.plattysoft.com/2015/07/06/book-mastering-android-game-development-2/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been busy the past few months writing a book titled <a href="https://www.packtpub.com/game-development/mastering-android-game-development" target="_blank">Mastering Android Game Development</a> with focuses on using the Android SDK for building games. The book is now available online.</p>
<p><a href="https://www.packtpub.com/game-development/mastering-android-game-development"><img class="aligncenter wp-image-1107 size-full" src="http://www.plattysoft.com/wp-content/uploads/2015/07/4757_MockupCover_Normal.png" alt="4757_MockupCover_Normal" width="302" height="373" /></a></p>
<p>If you are an intermediate-level Android developer who wants to create highly interactive and amazing games with the Android SDK, then this book is for you.</p>
<p>This book is a progressive, hands-on guide to developing highly interactive and complex Android games from scratch. You will learn all the aspects of developing a game using a space shooter game as the example that will evolve with you through the chapters. You will learn all about frame-by-frame animations and resource animations. You will also create beautiful and responsive menus and dialogs and explore the different options for playing sound effects and music in Android, the basics of creating a particle system, how to configure and use Google Play Game Services on the developer console and port our game to the big screen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2015/07/06/book-mastering-android-game-development-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Snapping items on a horizontal list</title>
		<link>http://www.plattysoft.com/2015/06/16/snapping-items-on-a-horizontal-list/</link>
		<comments>http://www.plattysoft.com/2015/06/16/snapping-items-on-a-horizontal-list/#comments</comments>
		<pubDate>Tue, 16 Jun 2015 13:31:53 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1065</guid>
		<description><![CDATA[The Problem We want to have a horizontal scrolling view that holds several items and that snaps to the selected one once the scroll stops, placing it centered on the screen. Essentially something that works like this: In old versions of Android &#8230; <a href="http://www.plattysoft.com/2015/06/16/snapping-items-on-a-horizontal-list/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<h1>The Problem</h1>
<p>We want to have a horizontal scrolling view that holds several items and that snaps to the selected one once the scroll stops, placing it centered on the screen.</p>
<p>Essentially something that works like this:</p>
<h1><a href="http://www.plattysoft.com/wp-content/uploads/2015/06/ezgif.com-crop.gif"><img class="aligncenter size-full wp-image-1080" src="http://www.plattysoft.com/wp-content/uploads/2015/06/ezgif.com-crop.gif" alt="ezgif.com-crop" width="480" height="255" /></a></h1>
<p>In old versions of Android we had the <a href="http://developer.android.com/reference/android/widget/Gallery.html" target="_blank">Gallery</a> class that allowed us to do something similar, but it has been deprecated. It is also similar to what you can do with a <a href="http://developer.android.com/training/animation/screen-slide.html" target="_blank">ViewPager</a>, but those are normally designed for full width Fragments.</p>
<h1>The Solution (TL;DR)</h1>
<p>What we will do is to listen for the event of scrolling stop on the list. Then we will check which item is currently in the middle of the screen and make the list scroll until it is positioned on the center.</p>
<p>The code for this example is <a href="https://github.com/plattysoft/SnappingList" target="_blank">available on GitHub as the project SnappingList</a></p>
<h1>The detailed solution</h1>
<p>You probably want something more detailed, so let&#8217;s get into it.</p>
<h2>Some considerations</h2>
<p>We are going to use a <a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html" target="_blank">RecyclerView</a> because the <a href="https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener.html" target="_blank">OnScrollListener</a> allows us to know the pixels that have been scrolled, and that is not possible with a standard <a href="http://developer.android.com/reference/android/widget/ListView.html" target="_blank">ListView</a>. Its <a href="http://developer.android.com/reference/android/widget/AbsListView.OnScrollListener.html" target="_blank">OnScrollListener</a> does not provide enough information. Besides, a <em>RecyclerView</em> is more fancy.</p>
<p>We will know the with of the items on the list beforehand. This is very important to be able to calculate the center of the screen and which item is the selected one.</p>
<p>We are going to have two extra items in the list, one at the beginning and one at the end, to be able to position the first and last items centered on the screen. The width of these extra items need to be large enough for it.</p>
<h2>The list items</h2>
<p>As we mentioned, we will have two different items in the list. The normal ones and the ones we will add at the beginning and the end.</p>
<p>The layout for the extra items is defined in the layout file <em>list_item_padding.xml</em> and looks like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;FrameLayout  xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;@dimen/padding_item_width&quot;
    android:layout_height=&quot;match_parent&quot;&gt;
&lt;/FrameLayout&gt;
</pre>
<p>On the other hand, the normal items we are going to use are just a square shape in the background and a number in the center. They are defined in the layout <em>list_item.xml</em> which looks like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;FrameLayout  xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;@dimen/item_width&quot;
    android:background=&quot;@drawable/bgr&quot;
    android:layout_height=&quot;match_parent&quot;&gt;

    &lt;TextView
        style=&quot;@android:style/TextAppearance.DeviceDefault.Large&quot;
        android:id=&quot;@+id/item_text&quot;
        android:layout_gravity=&quot;center&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot; /&gt;

&lt;/FrameLayout&gt;
</pre>
<p>These layouts have the width defined as a dimension. This allows us to tweak it for different screen sizes and also to be able to read the width in code without the need of waiting for the views to be measured. The values we are using for the example are:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;resources&gt;
    &lt;dimen name=&quot;item_width&quot;&gt;200dp&lt;/dimen&gt;
    &lt;dimen name=&quot;padding_item_width&quot;&gt;300dp&lt;/dimen&gt;
&lt;/resources&gt;
</pre>
<h2>The Adapter</h2>
<p>Then, we are going to create an adapter that just adds the two extra items. We call it <em>ExtraItemsAdapter</em> and the code is like this:</p>
<pre class="brush: java; title: ; notranslate">
public class ExtraItemsAdapter
        extends RecyclerView.Adapter&lt;ViewHolder&gt; {

  private static final int VIEW_TYPE_PADDING = 1;
  private static final int VIEW_TYPE_ITEM = 2;

  private final int mNumItems;

  public ExtraItemsAdapter(int numItems) {
    mNumItems = numItems;
  }

  @Override
  public int getItemCount() {
    return mNumItems+2; // We have to add 2 paddings
  }

  @Override
  public int getItemViewType(int position) {
    if (position == 0 || position == getItemCount()-1) {
      return VIEW_TYPE_PADDING;
    }
    return VIEW_TYPE_ITEM;
  }

  @Override
  public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    // create a new view
    if (viewType == VIEW_TYPE_ITEM) {
      View v = LayoutInflater.from(parent.getContext())
        .inflate(R.layout.list_item, parent, false);
      return new ViewHolder(v);
    }
    else {
      View v = LayoutInflater.from(parent.getContext())
        .inflate(R.layout.list_item_padding, parent, false);
      return new ViewHolder(v);
    }
  }

  @Override
  public void onBindViewHolder(ViewHolder holder, int pos) {
    if (getItemViewType(pos) == VIEW_TYPE_ITEM) {
      // We bind the item to the view
      holder.text.setText(String.valueOf(pos));
    }
  }
}
</pre>
<p>The adapter receives a number that says how many elements to display as a parameter of the constructor.When asked for the item count it will return that number+2.</p>
<p>When asked to create a view, it uses the item view type to check if it is either a padding or a normal item.</p>
<p>To use this on a real world example, you should pass a list of items instead of just an integer and do proper binding inside <em>onBindViewHolder.</em></p>
<p><span style="color: #000000; font-weight: bold;">Controlling the RecyclerView</span></p>
<p>Now that the basics are set, we can move into the really interesting part: handling the <em>RecyclerView</em>.</p>
<p>As we mentioned before, the idea is that when the scroll is stopped, we calculate which item is the current position, then, make the list scroll to that position.</p>
<p>To be able to calculate all that, we need some initialization, mainly to know the width of the items (both normal and extra ones) and also the padding needed, which is calculated based on the screen width and the item width.</p>
<p>We also keep track of the current amount of scroll -in pixels- of the <em>RecyclerView</em> in the <em>allPixels</em> variable.</p>
<p>All this can be done inside the <em>onCreate</em> method of the Activity.</p>
<pre class="brush: java; title: ; notranslate">
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
firstItemWidth = getResources().getDimension(R.dimen.padding_item_width);
itemWidth = getResources().getDimension(R.dimen.item_width);
padding = (size.x - itemWidth) / 2;

allPixels = 0;
</pre>
<p>We also need to initialize the <em>RecyclerView</em> by creating and setting a <em>LayoutManager</em>.</p>
<pre class="brush: java; title: ; notranslate">
final RecyclerView items = (RecyclerView) findViewById(R.id.item_list);
LinearLayoutManager itemslayoutManager = new LinearLayoutManager(getApplicationContext());
itemslayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
items.setLayoutManager(itemslayoutManager);
</pre>
<p>Finally, we set the <em>OnScrollListener</em> to the <em>RecyclerView</em>:</p>
<pre class="brush: java; title: ; notranslate">
items.setOnScrollListener(new RecyclerView.OnScrollListener() {

  @Override
  public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
    super.onScrollStateChanged(recyclerView, newState);
    synchronized (this) {
      if (newState == RecyclerView.SCROLL_STATE_IDLE) {
       calculatePositionAndScroll(recyclerView);
      }
    }
  }

  @Override
  public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
    super.onScrolled(recyclerView, dx, dy);
    allPixels += dx;
  }
});

</pre>
<p>This listener does two things:</p>
<ul>
<li>When the scroll stops (the scroll state changes to SCROLL_STATE_IDLE), it calls <em>calculatePositionAndScroll </em>to make the list snap.</li>
<li>When the list scrolls, it updates the value of <em>allPixels</em>.</li>
</ul>
<p>Then we have the utility method <em>calculatePositionAndScroll</em> which is where the action is:</p>
<pre class="brush: java; title: ; notranslate">
private void calculatePositionAndScroll(RecyclerView recyclerView) {
  int expectedPosition = Math.round((allPixels + padding - firstItemWidth) / itemWidth);
  // Special cases for the padding items
  if (expectedPosition == -1) {
    expectedPosition = 0;
  }
  else if (expectedPosition &gt;= recyclerView.getAdapter().getItemCount() - 2) {
    expectedPosition--;
  }
  scrollListToPosition(recyclerView, expectedPosition);
}

private void scrollListToPosition(RecyclerView recyclerView, int expectedPosition) {
  float targetScrollPos = expectedPosition * itemWidth + firstItemWidth - padding;
  float missingPx = targetScrollPos - allPixels;
  if (missingPx != 0) {
    recyclerView.smoothScrollBy((int) missingPx, 0);
  }
}
</pre>
<p>To calculate the position we use the values of <em>allPixels</em>, <em>padding</em>,  <em>firstItemWidth</em> and <em>itemWith</em>. Note that we are rounding the result.</p>
<p>We check for the special cases of the first and last items -the extra ones- and then tell the list to scroll to that position.</p>
<p>Scrolling to the position calculates the point in which the list needs to be positioned for a specific item, subtracts the value of <em>allPixels</em> from it and tells the list to do a smooth scroll.</p>
<p>Finally, we initialize the adapter with the number of items we want to be displayed.</p>
<pre class="brush: java; title: ; notranslate">
ExtraItemsAdapter adapter = new ExtraItemsAdapter(NUM_ITEMS);
items.setAdapter(adapter);
</pre>
<p>While the code works, there are a couple of situations we want to fix to make it nicer.</p>
<h2>Finishing touches</h2>
<p>The first problem is that rotation does not work properly. <em>RecyclerView</em> does remember the state, but the value of <em>allPixels</em> gets reset when the Activity is destroyed. This is very easy to fix, we just need to save and restore it using the methods from the Activity.</p>
<pre class="brush: java; title: ; notranslate">
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
  super.onRestoreInstanceState(savedInstanceState);
  allPixels = savedInstanceState.getFloat(BUNDLE_LIST_PIXELS);
}

@Override
protected void onSaveInstanceState(Bundle outState) {
  super.onSaveInstanceState(outState);
  outState.putFloat(BUNDLE_LIST_PIXELS, allPixels);
}
</pre>
<p>The other finishing touch is to make the list start in a selected position, since now it starts at the beginning of the list, where an extra item is.</p>
<p>If we call <em>calculatePositionAndScroll</em> directly it will create a wrong state where the value of <em>allPixels</em> is incorrect because the view has not been completely measured yet. To fix that we have to call that method once the layout has been completed and we do that via the <a href="http://developer.android.com/reference/android/view/ViewTreeObserver.OnGlobalLayoutListener.html" target="_blank">OnGlobalLayoutListener</a> class.</p>
<pre class="brush: java; title: ; notranslate">
ViewTreeObserver vto = items.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
  @Override
  public void onGlobalLayout() {
    items.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    calculatePositionAndScroll(items);
  }
});
</pre>
<p>I recommend that you place this code inside <em>onResume</em> (as oposed to <em>onCreate</em>)<em> </em>to ensure that it is called after <em>onRestoreInstanceState. A</em>lthough the layout is most likely never completed before <em>onResume</em> is called, the logic of positioning the list to the right position makes more sense inside <em>onResume</em>.</p>
<p><span style="color: #000000; font-weight: bold;">Final considerations</span></p>
<p>There are some considerations for this to be used on real world applications. Nothing major, but still worth commenting:</p>
<ul>
<li>We chose the size of the items for an optimal view on a Nexus 5 in landscape. You should consider <a href="http://developer.android.com/guide/topics/resources/providing-resources.html" target="_blank">qualifying the dimensions based on the screen smallestWidth</a>.</li>
<li>Removing the ViewTreeObserver has two different methods, one that is valid for minSDK &lt; 16 and another one for SDK 16 on. This example only considers minSDK 16.</li>
</ul>
<p>You can see all the code in the <a href="https://github.com/plattysoft/SnappingList" target="_blank">SnappingList project on GitHub</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2015/06/16/snapping-items-on-a-horizontal-list/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Google Developer Expert</title>
		<link>http://www.plattysoft.com/2015/06/05/google-developer-expert/</link>
		<comments>http://www.plattysoft.com/2015/06/05/google-developer-expert/#comments</comments>
		<pubDate>Fri, 05 Jun 2015 09:39:36 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1057</guid>
		<description><![CDATA[I can proudly say that since January, I have become a Google Developer Expert for Android (GDE in short). The first -and at the moment only- one in Ireland. Google Experts are a global network of experienced product strategists, designers, developers &#8230; <a href="http://www.plattysoft.com/2015/06/05/google-developer-expert/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I can proudly say that since January, I have<a href="https://developers.google.com/experts/people/raul-portales" target="_blank"> </a>become a <a href="https://developers.google.com/experts/people/raul-portales" target="_blank">Google Developer Expert for Android</a> (GDE in short). The first -and at the moment only- one in Ireland.</p>
<p>Google Experts are a global network of experienced product strategists, designers, developers and marketing professionals actively supporting developers, startups and companies changing the world through web and mobile applications.</p>
<p>As part of the activities of the GDE program I spent some time at the Office Hours during Google I/O helping people and I also gave a 20 minutes talk in the sandbox about Playful Design (slides coming shortly).</p>
<p><iframe width="584" height="329" src="https://www.youtube.com/embed/37GpI_s8q-8?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2015/06/05/google-developer-expert/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MTG Tracker 6.1 &#8211; Supporting casual formats</title>
		<link>http://www.plattysoft.com/2015/03/20/mtg-tracker-6-1-supporting-casual-formats/</link>
		<comments>http://www.plattysoft.com/2015/03/20/mtg-tracker-6-1-supporting-casual-formats/#comments</comments>
		<pubDate>Fri, 20 Mar 2015 10:56:55 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Magic TG Tracker]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1051</guid>
		<description><![CDATA[We just published version 6.1 of MTG Tracker, and is all about casual formats. We were the first ones to support EDH more than 3 years ago. Long before it got the name changed to Commander. We love casual formats, &#8230; <a href="http://www.plattysoft.com/2015/03/20/mtg-tracker-6-1-supporting-casual-formats/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>We just published version 6.1 of MTG Tracker, and is all about casual formats.</p>
<p><a href="http://www.plattysoft.com/wp-content/uploads/2012/04/get_it_on_play_logo_large.png" target="_blank" rel="http://play.magictgtracker.com"><img class="aligncenter wp-image-219 size-full" src="http://www.plattysoft.com/wp-content/uploads/2012/04/get_it_on_play_logo_large.png" alt="" width="172" height="60" /></a></p>
<p>We were the first ones to support EDH more than 3 years ago. Long before it got the name changed to Commander. We love casual formats, that&#8217;s why It was time to include some other formats that are getting more and more popular lately.</p>
<ul>
<li><strong>Tiny Leaders</strong> is getting steam quickly, it is a smaller Commander mode with cards of converted mana cost of 3 or less, decks of exactly 50 card, 25 life points and no Commander damage. <a href="http://tinyleaders.blogspot.ie/2013/09/introduction-to-format.html" target="_blank">Check it out at the official site</a>.</li>
<li><strong>Pauper</strong> is a format when you can only use commons. Very cheap to build, lots of fun. It has been a format for Magic Online for a while.</li>
<li><strong>Duel Commander</strong> is a modified version of Commander designed to play one-on-one. Different ban list and 35 life. <a href="http://duelcommander.com/" target="_blank">Check the official site for details</a>.</li>
</ul>
<p>These formats have now a slot under the formats section, a deck type that checks for invalid cards and in the case of Tiny Leaders and Duel Commander, a game mode.</p>
<p><img class="aligncenter wp-image-1052 size-large" src="http://www.plattysoft.com/wp-content/uploads/2015/03/device-2015-03-20-104659_framed-606x1024.png" alt="New Formats" width="584" height="987" /></p>
<p>Also, business as usual, the latest set &#8220;Dragons of Tarkir&#8221; has been added to the app. The cards from &#8220;Duel Decks: Elspeth Vs Kiora&#8221; have been also added.</p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2015/03/20/mtg-tracker-6-1-supporting-casual-formats/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MTG Tracker 6.0 &#8211; Material Design</title>
		<link>http://www.plattysoft.com/2015/01/14/mtg-tracker-6-0-material-design/</link>
		<comments>http://www.plattysoft.com/2015/01/14/mtg-tracker-6-0-material-design/#comments</comments>
		<pubDate>Wed, 14 Jan 2015 15:23:44 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Magic TG Tracker]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1030</guid>
		<description><![CDATA[MTG Tracker has been updating a lot, usually UI changes are made gradually, but sometimes they are big. This update is one of the big ones, and I want to take the chance to look back to all the journey. &#8230; <a href="http://www.plattysoft.com/2015/01/14/mtg-tracker-6-0-material-design/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>MTG Tracker has been updating a lot, usually UI changes are made gradually, but sometimes they are big. This update is one of the big ones, and I want to take the chance to look back to all the journey.</p>
<h1>MTG Tracker UI journey</h1>
<p>The app started with a single screen with a life counter for 2 players. Nothing really flashy. New features were added as tabs, Mana Pool, then Stats, then Decks. Tabs were cool on the early days of mobile apps.</p>
<p><img class="aligncenter wp-image-1032 size-medium" src="http://www.plattysoft.com/wp-content/uploads/2015/01/1st_version-201x300.png" alt="1st_version" width="201" height="300" />Then the ActionBar was presented, and with that, MTG Tracker moved to ActionBar + Dashboard. That is the other time the app had a considerable redesign.</p>
<p><a href="http://www.plattysoft.com/wp-content/uploads/2015/01/dashboard_4.2.png"><img class="aligncenter wp-image-1033 size-medium" src="http://www.plattysoft.com/wp-content/uploads/2015/01/dashboard_4.2-180x300.png" alt="dashboard_4.2" width="180" height="300" /></a></p>
<p>Moving forward, and adding features, at some point the app had so many features that a Dashboard was not enough. Also, a new pattern was emerging: Menu Drawers. So, we added one, not a big change, but still important.</p>
<p><a href="http://www.plattysoft.com/wp-content/uploads/2015/01/02_dashboard_with_options.png"><img class="aligncenter size-medium wp-image-1039" src="http://www.plattysoft.com/wp-content/uploads/2015/01/02_dashboard_with_options-180x300.png" alt="02_dashboard_with_options" width="180" height="300" /></a></p>
<h1>MTG Tracker with Material Design</h1>
<p>And with this, we get to Material Design, the big push from Google with Lollipop. We are adopting quite some new patterns. An image is worth a thousand words.</p>
<p><a href="http://www.plattysoft.com/wp-content/uploads/2015/01/material-design_small.png"><img class="aligncenter size-large wp-image-1036" src="http://www.plattysoft.com/wp-content/uploads/2015/01/material-design_small-1024x849.png" alt="material design_small" width="584" height="484" /></a></p>
<h2>Toolbar replaces ActionBar</h2>
<p>The new toolbar has a more obvious drawer icon and the icon is removed from the bar, leaving some space for options and titles. It also has a very nice animation when opening the menu drawer.</p>
<p>There used to be a blue bar under the action bar for extra options on some screens. This is now part of the toolbar, giving am ore consistent look and feel.</p>
<p>Bonus points: Decks also have a <em>Quick Return Header</em> pattern, which hides part of the header when you scroll down and shows it again when you scroll up.</p>
<h2>Floating Action Button</h2>
<p>In most of the screens, there is a floating action button for the most prominent action (like add a new deck or add cards to a deck or a list).</p>
<h2>Popup Menu replaces Quick Action Menu</h2>
<p>The extra options for elements on a list were displayed with a quick action menu, which was cool when we started using it, but now everyone is moving to the popup menu with 3 dots, which is also more clean, so that has changed as well.</p>
<h2>New simpler, cleaner icons</h2>
<p>We also changed the icons of the home screen and the drawer to simpler, more clear versions of them.</p>
<p>Search is now an option on the menu drawer as well as in the main screen. It is much more accessible there than from the icon on the action bar.</p>
<p><a href="http://www.plattysoft.com/wp-content/uploads/2015/01/device-2015-01-12-144523.png"><img class="aligncenter wp-image-1037 size-medium" src="http://www.plattysoft.com/wp-content/uploads/2015/01/device-2015-01-12-144523-169x300.png" alt="device-2015-01-12-144523" width="169" height="300" /></a></p>
<h2>Deck Edit is no more</h2>
<p>Deck edit has disappeared. It was confusing and was not adding much value. The decks can be edited now at any time. As it was for Card Lists and Trades.</p>
<h2>Something else?</h2>
<p>I want to change some other parts of the user flow, but that will have to wait another update. No spoilers on that one.</p>
<p>But of course, there is a bit more:</p>
<ul>
<li>Added cards from Fate Reforged</li>
<li>EDH banned list has been updated.</li>
<li>Fixed a problem when adding the card &#8220;_______&#8221; to a deck or list.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2015/01/14/mtg-tracker-6-0-material-design/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MOGA controllers and Android TV</title>
		<link>http://www.plattysoft.com/2014/12/30/moga-controllers-and-android-tv/</link>
		<comments>http://www.plattysoft.com/2014/12/30/moga-controllers-and-android-tv/#comments</comments>
		<pubDate>Tue, 30 Dec 2014 09:57:59 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Space Cat]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1020</guid>
		<description><![CDATA[I just released SpaceCat HD for Android TV. What it should have been a very simple and straight forward process turned out to give me quite a headache. If you have a game that is gamepad-ready. Chances are that you are &#8230; <a href="http://www.plattysoft.com/2014/12/30/moga-controllers-and-android-tv/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I just released <a href="http://www.plattysoft.com/the-pill-tree/spacecat/">SpaceCat HD</a> for Android TV. What it should have been a very simple and straight forward process turned out to give me quite a headache.</p>
<p>If you have a game that is gamepad-ready. Chances are that you are supporting MOGA controllers, simply because they are one of the best. If that&#8217;s the case you may also have this problem.</p>
<h2>The not-so-obvious problem</h2>
<p>If you want to publish for Android TV, you essentially have to do a few things in your manifest (<a href="https://developer.android.com/training/tv/start/start.html">see the full article on developer.android.com</a>):</p>
<ul>
<li>Declare a TV Activity using an intent filter of the category CATEGORY_LEANBACK_LAUNCHER.</li>
<li>Add a banner to the application (android:banner=&#8221;@drawable/banner&#8221;).</li>
<li>Declare it as a game (android:isGame=&#8221;true&#8221;).</li>
<li>Specify that it knows how to handle controllers.</li>
<li>Specify that touchscreen is not required.</li>
</ul>
<p>All these are very straight forward, but some of them require you to compile with targetSDK=21 (a.k.a. Lollipop) because is when they were introduced.</p>
<p>Another interesting change on Lollipop is the requirement of all service intents to be explicit. Any non-explicit one will throw an exception on runtime. This requirement is triggered when you compile with targetSDK=21.</p>
<p>And, obviously, the MOGA library does use a service with a non-explicit intent.</p>
<h2>The invalid approaches</h2>
<p>The first approach is to compile with a lower targetSDK, but then you can&#8217;t be on Android TV since the required manifest options aren&#8217;t available.</p>
<p>The second approach is to remove MOGA support, but then, the people that has those controllers will stop to have it supported.</p>
<p>The third option is to have multiple apks, one for Android TV with targetSDK=21 and another one for everyone else with a lower targetSDK. This sounds reasonable, but there is no clear way to separate Android TV from the rest and -as I was told by a Google Dev advocate- this was done in purpose.</p>
<p>But hold on, there is one more option, and it is the most obvious one, once you think about it.</p>
<h2>The obvious solution</h2>
<p>You just need to modify the code of the MOGA library to make it be an explicit intent. Except that the library is not open source.</p>
<p>It was pointed out to me by Robert Broglia, developer of Snes9x-EX+, that you could just use a decompiled version of the library, and then modify the init method. <a href="https://github.com/Rakashazi/emu-ex-plus-alpha/blob/master/imagine/src/base/android/java/bda/controller/Controller.java#L152">As you can see on his github project.</a></p>
<p>I&#8217;m really not a fan of having full libraries inside the source code, so I tried to just extend the controller to replace the init method for one using the explicit intent, that would have been a few lines of code, but the class is final.</p>
<p>At the end I created a new Controller that uses the explicit intent (and basically everything else is the same) and placed it under the package com.bda.controller.</p>
<h2>It could have been easier</h2>
<p>All this could have been much easier if</p>
<ul>
<li>MOGA had updated the library</li>
<li>The Controller class wasn&#8217;t final</li>
</ul>
<p>If you have a game that is MOGA-enabled and you want to port it to Android TV, I hope to have saved you some headaches.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2014/12/30/moga-controllers-and-android-tv/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Kendama SpinOff 1.0 Released</title>
		<link>http://www.plattysoft.com/2014/12/17/kendama-spinoff-1-0-released/</link>
		<comments>http://www.plattysoft.com/2014/12/17/kendama-spinoff-1-0-released/#comments</comments>
		<pubDate>Wed, 17 Dec 2014 11:08:25 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1014</guid>
		<description><![CDATA[A while ago, the British Kendama Association released SpinOff, a physical game for kendama that includes several wheels with tricks and even 3 play modes. Now, that game has made it to Android Phones (and to iOS soon), making it &#8230; <a href="http://www.plattysoft.com/2014/12/17/kendama-spinoff-1-0-released/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>A while ago, the British Kendama Association released <a href="http://www.kendama.co.uk/spinoff.html">SpinOff</a>, a physical game for kendama that includes several wheels with tricks and even 3 play modes.</p>
<p>Now, that game has made it to Android Phones (and to iOS soon), making it the second kendama related app of Platty Soft.</p>
<p><a href="http://www.plattysoft.com/wp-content/uploads/2014/12/Screenshot_2014-12-15-16-29-15_framed.png"><img class="aligncenter size-large wp-image-1015" src="http://www.plattysoft.com/wp-content/uploads/2014/12/Screenshot_2014-12-15-16-29-15_framed-605x1024.png" alt="Screenshot_2014-12-15-16-29-15_framed" width="584" height="988" /></a></p>
<p>&nbsp;</p>
<p>So, if you are a Kendama player and are quite bored of same old games, give SpinOff a chance!</p>
<p>Note: You need a real kendama to play this.</p>
<p><a href="https://play.google.com/store/apps/details?id=com.plattysoft.SpinOff" target="_blank"><img class="aligncenter wp-image-219 size-full" src="http://www.plattysoft.com/wp-content/uploads/2012/04/get_it_on_play_logo_large.png" alt="Kendama SpinOff on Google Play" width="172" height="60" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2014/12/17/kendama-spinoff-1-0-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Leonids Lib 1.2 &#8211; Meteor Shower</title>
		<link>http://www.plattysoft.com/2014/11/19/leonids-lib-1-2-meteor-shower/</link>
		<comments>http://www.plattysoft.com/2014/11/19/leonids-lib-1-2-meteor-shower/#comments</comments>
		<pubDate>Wed, 19 Nov 2014 14:59:50 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=1000</guid>
		<description><![CDATA[I just released an update of Leonids Lib. It includes feedback from previous versions both from github and the workshop I gave at GDGFestDublin. Changes From this version on, speed and acceleration are using dips. This makes a lot of &#8230; <a href="http://www.plattysoft.com/2014/11/19/leonids-lib-1-2-meteor-shower/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I just released an update of Leonids Lib. It includes feedback from previous versions both from github and the workshop I gave at GDGFestDublin.</p>
<h2>Changes</h2>
<p>From this version on, <strong>speed and acceleration are using dips</strong>. This makes a lot of sense, since the library should work together with the standard concepts of the Android framework. Animations should me much more consistent among different pixel density screens now.</p>
<p><strong>Previous versions were using pixels, so you may want to review your parameters when you update.</strong></p>
<h2>New Features</h2>
<p>There are some new configuration options:</p>
<ul>
<li><strong>emitWithGravity</strong>: Allows you to emit from a specific side of the View and particles will be emitted along all the edge of the View. i.e. Gravity.BOTTOM will create a rain-like effect. Default is Gravity.CENTER.</li>
<li><strong>updateEmitPoint</strong>: Allows to dynamically change the point of emission for the particle system (useful to follow the touch along the screen)</li>
<li><strong>stopEmitting</strong>: Will stop creating new particles, but the existing ones will keep animating (this is different from cancel, which also stops the already spanned ones)</li>
<li>emit now has methods to emit from a specific point on the screen given x and y instead of from a View.</li>
</ul>
<h2>New Examples</h2>
<p>Also, new examples are being included to showcase the new features:</p>
<ul>
<li><strong>Emit with Gravity</strong>: Simulates a rain-like effect using Gravity.BOTTOM.</li>
<li><strong>Follow touch</strong>: Creates a trail of stars following the touch on the screen.</li>
</ul>
<p><a href="http://www.plattysoft.com/wp-content/uploads/2014/11/libdemo_rain.gif"><img class="aligncenter size-full wp-image-1003" src="http://www.plattysoft.com/wp-content/uploads/2014/11/libdemo_rain.gif" alt="libdemo_rain" width="388" height="690" /></a></p>
<p>You can also check <a href="http://plattysoft.github.io/Leonids/" target="_blank">Leonids Lib github page</a> and/or <a href="https://play.google.com/store/apps/details?id=com.plattysoft.leonids.examples&amp;hl=en" target="_blank">get Leonids Demo from google play</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2014/11/19/leonids-lib-1-2-meteor-shower/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>KendamApp 2.0</title>
		<link>http://www.plattysoft.com/2014/11/14/kendamapp-2-0/</link>
		<comments>http://www.plattysoft.com/2014/11/14/kendamapp-2-0/#comments</comments>
		<pubDate>Fri, 14 Nov 2014 14:17:51 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=982</guid>
		<description><![CDATA[There is a new version of KendamApp &#8211; The Kendama App out there. It includes 32 new videos and my favourite feature so far: Self Certification. Self Certification Until now you could track your accuracy per trick, and then see &#8230; <a href="http://www.plattysoft.com/2014/11/14/kendamapp-2-0/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>There is a new version of <a href="https://play.google.com/store/apps/details?id=net.shalafi.kendroid&amp;hl=en" target="_blank">KendamApp &#8211; The Kendama App</a> out there. It includes <strong>32 new videos</strong> and my favourite feature so far: Self Certification.</p>
<p><a href="https://play.google.com/store/apps/details?id=net.shalafi.kendroid&amp;hl=en" target="_blank"><img class="aligncenter wp-image-219 size-full" src="http://www.plattysoft.com/wp-content/uploads/2012/04/get_it_on_play_logo_large.png" alt="MTG Tracker on Google Play" width="172" height="60" /></a></p>
<h1>Self Certification</h1>
<p>Until now you could track your accuracy per trick, and then see how close you were to pass an exam, but an actual exam&#8230; that is another story.</p>
<p>This new feature allows you to try for a self certification. It tracks all the attempts of all the tricks and it tells you if you passed or not the grading.</p>
<p>As in a real exam, you don&#8217;t have to keep going with a trick after you&#8217;ve completed the required hits, and as in a real exam, you stop as soon as you miss one trick.</p>
<p>It also keeps track of your attempts to the grading. Note that the tricks performed during the self certification are not added to the trick tracking feature, it is a different feature.</p>
<p>An image is worth a thousand words, so here&#8217;s a screenshot of the self certification in action.</p>
<p><img class="aligncenter size-large wp-image-995" src="http://www.plattysoft.com/wp-content/uploads/2014/11/device-2014-11-14-140526_framed-605x1024.png" alt="KendamApp Self Certification" width="584" height="988" /></p>
<p>Happy clicking!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2014/11/14/kendamapp-2-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Accessing expansion patch files bug (and solution)</title>
		<link>http://www.plattysoft.com/2014/11/14/accessing-expansion-patch-files-bug-and-solution/</link>
		<comments>http://www.plattysoft.com/2014/11/14/accessing-expansion-patch-files-bug-and-solution/#comments</comments>
		<pubDate>Fri, 14 Nov 2014 13:18:35 +0000</pubDate>
		<dc:creator><![CDATA[Platty Soft]]></dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://www.plattysoft.com/?p=978</guid>
		<description><![CDATA[You may have used expansion files on Android. They are very handy when your app goes over 50Mb which, for games, happens pretty soon. In my case I have KendamApp &#8211; The Kendama App which has an extensive library of &#8230; <a href="http://www.plattysoft.com/2014/11/14/accessing-expansion-patch-files-bug-and-solution/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>You may have used <a href="http://developer.android.com/google/play/expansion-files.html" target="_blank">expansion files on Android</a>. They are very handy when your app goes over 50Mb which, for games, happens pretty soon. In my case I have <a href="https://play.google.com/store/apps/details?id=net.shalafi.kendroid&amp;hl=en" target="_blank">KendamApp &#8211; The Kendama App </a>which has an extensive library of videos included.</p>
<p>The expansion files are organized on a main and a patch files. Each of them can be up to 2Gb. Since uploading them can be a pain, you can reuse them from one version to the next.</p>
<p>There are 2 libraries provided with android SDK to help managing expansion files:</p>
<ul>
<li><em>downloader_library:</em> Which purpose should be obvious.</li>
<li><em>zip_file:</em> Which is a nice utility to manage expansion files via a content provider. You should be using it if you are using videos.</li>
</ul>
<p>Also, if you are going to use videos, do not compress them when zipping the obb file.</p>
<h1>Updating only with a patch file</h1>
<p>Essentially, if you are going to add a few assets, it is better to use a patch file and reuse the main file. It will save lots of bandwidth and time.</p>
<p>You don&#8217;t have to re-upload the main file and users do not need to re-download it. Everyone wins.</p>
<p>Except that it may not be too straight forward when using the <em>zip_file</em> library.</p>
<h1>The first pitfall (a.k.a. the undocumented feature)</h1>
<p>First thing first, you should know that if you do not add some meta-data to the AndroidManifest, the library is going to look for the versions that match with the version number of the app. I don&#8217;t recall reading this in the documentation. I actually figured it out by reading the code.</p>
<p>So, the content provider on your AndroidManifest should look like this:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;provider android:authorities=&quot;com.plattysoft.zipprovider&quot; android:name=&quot;com.plattysoft.provider.ZipFileContentProvider&quot; &gt;
   &lt;meta-data android:name=&quot;mainVersion&quot; android:value=&quot;17&quot;/&gt;
   &lt;meta-data android:name=&quot;patchVersion&quot; android:value=&quot;18&quot;/&gt;
&lt;/provider&gt;
</pre>
<h1>The second pitfall (a.k.a. the terrible bug)</h1>
<p>Then, I realized that every time I tried to watch one of the new videos the app was crashing. I checked for the main and patch files and they were properly downloaded and inside the obb directory.</p>
<p>Something weird was going on.</p>
<p>Digging with the debugger, I ended up in a function that is supposed to return an string array with the name of the available expansion files based on the version numbers and after checking that the files do exist.</p>
<pre class="brush: java; title: ; notranslate">
static String[] getAPKExpansionFiles(Context ctx, int mainVersion, int patchVersion) {
   String packageName = ctx.getPackageName();
   Vector&lt;String&gt; ret = new Vector&lt;String&gt;();
      if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
         // Build the full path to the app's expansion files
         File root = Environment.getExternalStorageDirectory();
         File expPath = new File(root.toString() + EXP_PATH + packageName);

         // Check that expansion file path exists
         if (expPath.exists()) {
            if ( mainVersion &gt; 0 ) {
               String strMainPath = expPath + File.separator + &quot;main.&quot; + mainVersion + &quot;.&quot; + packageName + &quot;.obb&quot;;
               File main = new File(strMainPath);
               if ( main.isFile() ) {
                  ret.add(strMainPath);
               }
            }
            if ( patchVersion &gt; 0 ) {
               String strPatchPath = expPath + File.separator + &quot;patch.&quot; + mainVersion + &quot;.&quot; + packageName + &quot;.obb&quot;;
               File main = new File(strPatchPath);
               if ( main.isFile() ) {
                  ret.add(strPatchPath);
               }
            }
         }
      }
      String[] retArray = new String[ret.size()];
      ret.toArray(retArray);
      return retArray;
}
</pre>
<p>Except that it was returning a single string and not two. So, paying extra attention I noticed this specific piece of code.</p>
<pre class="brush: java; title: ; notranslate">
if ( patchVersion &gt; 0 ) {
   String strPatchPath = expPath + File.separator + &quot;patch.&quot; + mainVersion + &quot;.&quot; + packageName + &quot;.obb&quot;;
   File main = new File(strPatchPath);
   if ( main.isFile() ) {
      ret.add(strPatchPath);
   }
}
</pre>
<p>Of course it couldn&#8217;t find the patch expansion file, it is constructing the name using the <em>mainVersion</em> number instead of the <em>patchVersion.</em> Event the File variable is called main!</p>
<blockquote><p>Copy and paste is an anti-pattern.</p></blockquote>
<p>I have checked the latest version of this library that comes with the android SDK and the bug is still there. I&#8217;d check where the code is and send a push request. In the meantime, you know what you have to change to fix it.</p>
<h1>Safe scenarios</h1>
<p>You would not encounter this bug if:</p>
<ul>
<li>You are not using the <em>zip_file</em> library.</li>
<li>You are not using a patch file.</li>
<li>Your main and patch files have the same version number (you update both).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.plattysoft.com/2014/11/14/accessing-expansion-patch-files-bug-and-solution/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
