Saturday, November 7, 2015

REST API WEEK! App a Day 22: Reddit Images

I'm not sure if this one is really accessing an API, technically. Though it does request subreddits in JSON in order to display thumbnails of images which doesn't require any authentication.

REST API WEEK! App a Day 21: Goodreads Authors

Classes Used: Service, AbstractThreadedSyncAdapter, XmlPullParser, ContentProvider, ContentResolver SQLiteOpenHelper, Handler, ContentObserver.

I've always wanted to play with the Goodreads API. So here's my first attempt. Responses are in XML only, unfortunately. This makes a request for the books (reviews) in my favorites shelf and lists the authors. Very simple in theory. I was going to do more but I ran out of time.

I finally made some templates files for a SQLite Database, but without any of the provider's URI constants. Just copy the gist code below into a file template.

Friday, November 6, 2015

REST API WEEK! App a Day 20: Facebook Likes

Uses Classes: FacebookSdk, LoginButton, FacebookCallback, AsyncTask, Thread, BaseAdapter, GraphRequest, JSONObject, JSONArray.

This uses the Facebook Graph API and SDK to display the first page of the user's likes.

Wednesday, November 4, 2015

REST API WEEK! App a Day 19: Weather Map

Classes Used: ContentProvider, ContentResolver, Service, AbstractThreadedSyncAdapter, GoogleMap, Handler

I think I need to learn a lot in regards to what is possible using data that is already out there. So I'm going to make this REST API week. I'll use different API's in all of my dailies.
This one uses Using it's cities in cycle feature it grabs current temperatures for 10 cities near your current GPS location and displays the markers on the map.

Friday, October 23, 2015

App a Day 18: Todo with DatePicker

Classes Used: DatePicker, Preference, PreferenceActivity, CheckBoxPreference, SharedPreferences, Preference Manager, OnPreferenceChangeListener, OnPreferenceClickListener

I fought with this one for a good while. I'll say if you're starting a new project it's probably a good idea to store dates as string. If you are storing them as integer's just remember that SQLite assumes your time is in the format epoch time in SECONDs. Not milliseconds, even though an integer in SQLite is 64 bits, same as java's long. Okay just remember that.

Saturday, October 17, 2015

App a Day 16: Coursera Android Concurrency Assignment 1

Day 16 is unconventional, I'm going through Coursera's online class called: "Programming Mobile Services for Android Handheld Systems: Concurrency." This is the first assignment from that course. The assignment is to implement a couple of predefined Threads and Runnables and use a java semaphore. The UI and the app structure already existed. Here's the unfinished source.

Thursday, October 15, 2015

App a Day 15: OneTableApp with Parse Login

As when you're doing anything simple in android simply combining yesterday's app with the previous OneTableApp using parse was 'anything other than simple. More build.gradle problems (remove "compile fileTree(dir: 'libs', include: ['*.jar'])"). Parse's signUpInBackground wasn't even running the SignUpCallback's done method (Restart your emulator). And somehow one of my AppCompatActivity wasn't using an AppCompat theme (check all of your styles.xml files, all of them).

Wednesday, October 14, 2015

App a Day 14: Simple Login w/ Parse

Uses Classes: ParseUser, ParseObject, Intent.

This app demonstrates a simple log in, log out, and sign up UI for parse. I started with the Login template from android studio, but I think things would have been simpler if I had just started from scratch and followed the parse guide.

Sunday, October 11, 2015

App a Day 13: Todo

Uses Classes: ListActivity, SQLiteOpenHelper, SQLiteDatabase, CursorAdapter, PreferenceActivity

I finally decided to make this staple app way later than I should have. There really isn't anything new in this app just reenforcing things I've already learned. I did make some effort to at least write down steps to implement the common patterns in this app that I would use again.

  • Local SQLiteDatabase for persistent storage
    1. Define one or more Contract classes. You could do one Contract for a number of tables or one contract for every table. It's up to you how you organize it. You just need to know where things are.
    2. Define a static Entry class, which implements BaseColumns, for every table you will use in your database.
    3. Extend SQLiteOpenHelper and override onCreate and onUpgrade methods and define a constructor. The onCreate method will call db.execSQL on a string containing your create table query.
    4. Define static CRUD methods for each action you'll be taking on the database. Make these methods of the Contract class so you can access them from anywhere (Activity, Adapter, etc.)
  • ListView with CursorAdapter
    1. Create a ListView with android:id="@android/id:list" in your main activities layout.
    2. Create a layout file layout/list_item_layout.xml.
    3. Extend CursorAdapter in a new class defining a constructor and overriding the newView and bindView methods. In new view inflate R.layout.list_item_layout and return it.
    4. Optionally, create a static private class called ViewHolder. In here define public field variables for each of the views in your list item's layout. Define a constructor that requires a view as a parameter and using that view's findViewById method assign your field variables to these views for easy access later. In your overridden newView method you instantiate a ViewHolder and call setTag on the view which you return. When you implement bindView call getTag on the view and cast it to the ViewHolder type to access the view identifiers.

Friday, October 9, 2015

App a Day 12: InsideArea

Uses Classes: LocationListener, GoogleMap, Polygon, LatLng.

Today's app returns to google maps to determine if the gps location is in a given boundary. It implements a ray casting algorithm to determine if a point is within a polygon. I would have expected this to be built into the google maps API's library, but all of the solutions I found to do this suggest there is not. However, implementing the algorithm isn't very complex.

Thursday, October 8, 2015

App a Day 11: Checklist

Classes Used: AsyncTask, ArrayAdapter, ListActivity.

This one was much more problematic than I had anticipated. I will probably revisit this one soon.

Tuesday, October 6, 2015

App a Day 10: Camera

Uses Classes: Camera, SurfaceView, SurfaceHolder.Callback, CameraPreview.

I hadn't intended to take a week off, but I stayed with my parents before my sisters wedding and it was pretty difficult to not get involved in wedding preparations.

So I have a lot of running to do. But here's another simple app. I simply followed this guide omitting the video stuff and filling it in with a fix.

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.