Friday, September 25, 2015

App a Day 9: OneTable using ContentProvider

Classes Used: ContentProvider, Uri.

Once again, refactoring the very first day's app. this time using a ContentProvider. The way I understand it a ContentProvider is an added layer of abstraction onto the app's persistent storage. So the rest of my app has no clue that SQLite is the underlying database. A big help in this one was the Sunshine app from Udacity's Android course.

Thursday, September 24, 2015

App a Day 8: Map

Classes Used: FragmentActivity, SupportMapFragment, GoogleMap, LocationListener, LocationManager, Location.

This took all of like 10 minutes to make and was directly following this tutorial. That's encouraging, I think I'll make more map apps now.

App A Day 7: Diet Plan

Classes Used: Intent, ListActivity, SQLiteDatabase, Cursor, SimpleCursorAdapter, AlertDialog, SQLiteOpenHelper.

My first practical app. It is a diet plan for a workout program. All the information is hard coded and inserted into the database when first created. This one uses three tables and joins two. It simply uses a ListActivity and SimpleCursorAdapter. When an item is clicked it opens a second activity called IngredientsActivity. This is also a ListActivity, the only difference is items need to be long clicked and then a dialog is opened with alternate foods. Look at this activity at your own risk, it's a little messy, but I'm glad it worked out.

Wednesday, September 23, 2015

App a Day 6: OneTable with Parse

Classes Used: Parse, ParseObject, ParseQueryAdapter, AlertDialog, ListView

Identical to the app I made on day 1 except with a parse back end instead of a SQLiteDatabase. I was a little frustrated by things at times especially because a friend was singing it's praises, how it was so easy to use, painless to set up, etc.. It wasn't. First I was impeded by gradle problems and then a not so intuitive local data store. I could only EITHER get it to work in local data or remote. So I chose remote, Eventually deciding what was required to have both simultaneously was an unnecessary extra complex problem.

This tutorial should get anyone wanting to do the same on the right track

Sunday, September 20, 2015

App a Day 5: Timer

Classes Used: Timer, TimerTask, Calendar, Handler.

I needed a really simple app for this day and this was much simpler than I thought it ever would be. This straightforward tutorial shows all the basics. The app simply starts a timer which runs a task. The timer runs in the background, but then sends a runnable back to the UI thread every second to update the timer display with the current count. In this one I didn't use a layout xml file because it was complicating things for when I wanted to swap out the buttons. I suppose better way would just be to have the button use one onClickListener a which would determine if I'm starting or stopping, but I didn't think of that then.

Friday, September 18, 2015

App a Day 4: Dice

Classes used: GridView, BaseAdapter, PreferenceActivity, Intent.

This one was a hair ripper. This isn't even true to my original concept and I came up with it for day 2. As you know I worked out only ONE die. However it's close enough.

It's basically what you get from this guide on GridViews, plus the roll button and a PreferencesActivity so I can alter the number of dice.

To get a PreferencesActivity started via the action menu bar I needed a menu layout and a preferences screen layout. I'll leave out the menu xml since it's auto-generated every time you start an android project.

And that other part that auto-generated by Android Studio every time I start a project? That's where the intent goes to open SettingsActivity

Go to the repo and look at the settings activity. It's simply an activity which overrides onCreate which is going to take the xml file above and make a preference screen with it. But it is also an OnPreferenceChangeListener so when things get changed it tells itself (really) to update the preference summary to the new value. I'll use the listener again in the adapter.

Finally I need an adapter. Adapters are objects that manage data or objects for views that display repetitive structured information, so in this case a GridView. The GridView displays some data in the same way over and over again in specific pattern but the data changes with each grid cell. The adapter is going to make sure the right data get to the right cell.

This adapter is an extension of BaseAdapter. Basically the GridView, as it attempts to draw itself, tells the adapter, "Give me what I need to draw for cell 0." By calling the adapter's getView method and passing the position number to it. I override the getView method so it returns an ImageView with the correct configuration and image. In this case an ImageView displaying the face of a die.

Another important part for this implementation is the array that the adapter uses called mArray. This is not a standard feature of BaseAdapter, but necessary for this case. I made the adapter into a listener for preference changes. Every time the preference for dice count is changed I reset the array to one of the new size filled with all -1.

Finally back in the MainActivity class whenever you roll the dice, change the array in adapter to the new number. I do this by making it public but you could also use getItem if you're using a reference to an actual object. When the number's changed call mAdapter.notifyDataSetChanged and that will call getView again and redraw the views, thus setting them to the correct face image.

I hope this was educational. Good night.

Thursday, September 17, 2015

App a Day 3: Morse Code Translator

Uses Classes: Handler, Thread, Message

This was a great exercise in concurrent communication. I highly recommend anyone learning to write this app in this way. I was getting frustrated that none of my previous apps used concurrency so I thought this project was perfect for that.

To my knowledge this program was a common assignment for SJSU's mobile development course.

A great resource for handlers was this video:

First I need a Runnable class. This is Translator which extends Runnable. The constructor parameters take a string and my Handler. The Handler is going to transfer messages from the Translator thread to the UI thread. A Runnable starts at the overridden run method. This calls translate. I've omitted translate from the gist, but it loops through the letters of missive, then loops through each letter's corresponding code array of DOT's DASH's and OFF's. At each iteration of the code array (and spaces in between) call blink.

Blink is where the Handler sends messages to the UI thread. Obtain a Message and set arg1 to white or black and arg2 to the character we are currently translating. Call Handler.sendMessage and then sleep.

When sendMessage is called the Handler calls handleMessage over on the UI thread. It sets the color and displays the letter by what the message just delivered via the Handler. To start everything in motion, make a Thread object that references the Translator and then call start on that thread.

Wednesday, September 16, 2015

App a Day 2: Die

Die displays one ImageView in the middle of the screen showing the face of a die. Clicking on it randomly shows one of the 6 faces of the die and plays a sound.

Here is free clip art of dice:

And here is the sound I used:

As for code resources, if you look at the code for the below example's from Coursera's Android course from University of Maryland you'll see some close similarities:

App a Day Challenge - Day 1: One Table

I'm starting an App a Day challenge. And I'm starting it today. The challenge ends when I get a job.

The Rules

The App a Day Challenge must result in one mobile app, which performs its intended function, posted to my github page once per day, 5 days a week. For my purposes the 5 days will be Tuesday through Saturday.

The app must compile, must perform its intended function without crashing, and it must be posted by midnight or 11:59 PM for the day it is made. I will be making changes to existing apps as some dailies but I will try to ensure that the added feature is not trivial.

A missed day will result in punishment; until better punishment is decided on, I will jog 5 kilometers. Every 2 failures will increase the punishment by 1 kilometer.

This does not mean that I will be starting and ending an app in one day. If I'm going to be able to do this I will need to make sure more complex apps get more time.

Day 1: OneTable

Click here for code.
In this app I just wanted to learn the basics of using a SQLite Database for persistent storage. It falls just short of doing something useful, allowing a user to keep short simple notes and displaying them in a list ordered newest to oldest. Each list item has a delete button.

If I had more time I'd obviously clean up the looks. I also wanted to make the list items more compact and then expand when focused.

I should be able to save a lot of time on future projects by starting with copies of the Contract, Helper, and Adapter classes and modifying those.

I used a lot of code and concepts from this Android training page on SQLite and from this code from the one of Udacity's Android courses.

So first I needed to define the database. This is done in the Contract and Helper classes.

Create an instance of the Helper. Also create an instance of the adapter. The Adapter simply extends cursor adapter and overrides newView and bindView.

After this part I defined functions that insert and query the database following almost exactly the related sections in the aforementioned Android training documentation regarding SQLite. You may have noticed the call to getLogTimes() which is just what they have there. It returns the cursor from SQLiteDatabase.query(). Whenever you run this function, take the cursor and put it into the swapCursor function of the adapter: mAdapter.swapCursor(getLogTimes(db)). This will update the list view with the new stuff.

I'm writing a shitty blog post so I'm going to come back and make this better another day. But for now, day one complete.