The June
PyGameSF meet up will be at the Sycip conference room on the fourth floor of the
main San Francisco public library beside
civic center BART. The library closes at 8pm so we will reconvene to
frjtz on hayes street for dinner/drinks afterwords.This month’s presentations are:
- Casey Duncan: “Grease: it’s a game framework, no it’s a game engine, no it’s a framework for making game engines; and now it’s more than just vaporware!” Grease is an open-source project for rapid Python game development. Casey is going to give a little guided tour of the not-just-sci-fi-anymore Grease API and talk a bit about future directions. He is also going to talk about using Sphinx to document Grease, and how you can, and should, use it to document your own projects and ideas.
- Al Sweigart : “Invent Your Own Computer Games with Python.” Al’s presentation will cover his book which teaches kids (and adult beginners) how to program by making computer games. Al will talk about the methodology his book uses, things he’s learned about teaching programming and games, and about how games can bring more people into software development. The book is under a Creative Commons license and is available for free at http://inventwithpython.com. The book is also for sale in print on Amazon.com.
The May
PyGameSF meet up will be at the Sycip conference room on the fourth floor of the
main San Francisco public library beside
civic center BART. The library closes at 8pm so we will reconvene to
frjtz on hayes street for dinner/drinks afterwords.This month’s presentations are:
- Dan Grover : Audio on the iPhone/iPad. produce visually striking results. Dan (guy behind shovebox, etude, simplechord and phonefinger) will give an overview of the audio APIs available on the iPhone OS.
- Warren Stringer: Ontological synesthesia – performing visual music on the iPad. Warren Stringer will be showing Tr3, a platform for creating real time ontologies. Warren will be using Tr3 and OSC to create a visual music performance, using two iPads, projector, one iPhone, and one iPod touch. Anyone with OSC music controllers are welcome to join in. More information can be found here.
One of the killer features of
Android smartphones is the ability for applications to grab your location and provide tailored service based on it. Implementing such location services on the
Android platform is pretty easy but doing it in such a way so as to not unnecessarily drain your battery can be a little tricky. I just added a location utility called
GeoUtil which does just this to my
crossfit workout tracking application. The following is an explanation of this utility and how to integrate it into your
Android activity and if you so wish add location information to your notes using the
Snaptic API.
| 01 | |
| 02 | //Add the following member variables to your activity class |
| 03 | private LocationManager mLocationManager; |
| 04 | private GeoUtil mGeoUtil; |
| 05 | private static final int LOCATION_UPDATE_INTERVAL_MILLIS = 5000; |
| 06 | private static final float LOCATION_UPDATE_DISTANCE_METERS = 10; |
| 07 | private Location externalLocation = null; |
| 08 | |
| 09 | |
| 10 | //Add the following code to your activity onPause, onResume, onCreate |
| 11 | |
| 12 | @Override |
| 13 | protected void onPause() { |
| 14 | mLocationManager.removeUpdates(mGeoUtil); |
| 15 | super.onPause(); |
| 16 | } |
| 17 | |
| 18 | @Override |
| 19 | protected void onResume() { |
| 20 | super.onResume(); |
| 21 | if (externalLocation == null) { |
| 22 | // Register for location updates |
| 23 | mLocationManager.requestLocationUpdates( |
| 24 | LocationManager.NETWORK_PROVIDER, |
| 25 | LOCATION_UPDATE_INTERVAL_MILLIS, |
| 26 | LOCATION_UPDATE_DISTANCE_METERS, mGeoUtil); |
| 27 | mLocationManager.requestLocationUpdates( |
| 28 | LocationManager.GPS_PROVIDER, |
| 29 | LOCATION_UPDATE_INTERVAL_MILLIS, |
| 30 | LOCATION_UPDATE_DISTANCE_METERS, mGeoUtil); |
| 31 | } else { |
| 32 | mLocationManager.removeUpdates(mGeoUtil); |
| 33 | } |
| 34 | } |
| 35 | |
| 36 | @Override |
| 37 | protected void onCreate(Bundle savedInstanceState) { |
| 38 | mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); |
| 39 | mGeoUtil = new GeoUtil(getApplicationContext()); |
| 40 | } |
| 41 | |
| 42 | //Now when you want to add location information to a note do the following |
| 43 | if(mGeoUtil.hasLocation()) {//Create a note |
| 44 | SnapticNote note = new SnapticNote(); |
| 45 | Location location = new Location(mGeoUtil.getLocation()); |
| 46 | note.latitude =location.getLatitude(); |
| 47 | note.longitude = location.getLongitude(); |
| 48 | note.text = "Post note with location information"; |
| 49 | int returnCode = mApi.addNote(note); |
| 50 | if(DEBUG)Log.d(LOGCATNAME, "Print out note lat: " + note.latitude+ " note long: " + note.longitude ); |
| 51 | } else { |
| 52 | if(DEBUG)Log.d(LOGCATNAME, "No location available"); |
| 53 | Toast.makeText(getApplicationContext(), |
| 54 | "No location available", |
| 55 | Toast.LENGTH_LONG).show(); |
| 56 | } |
| 57 | |
| 58 | //Also make sure you have the following permissions in your applications manifest |
| 59 | android.permission.INTERNET |
| 60 | android.permission.ACCESS_FINE_LOCATION |
| 61 | android.permission.ACCESS_COARSE_LOCATION |
| 62 | |
Lets review whats going on in the above code and talk about what
GeoUtil actually does. mLocationManager is the system
LocationManager service. Our
GeoUtil class is the update-handler class for location updates sent out by the
LocationManager service, it is a sub class of
LocationListener. We indicate that we want location updates and designate that these updates shall be handled by mGeoUtil. The requestLocationUpdates() call to the
LocationManager service dicates how often we will get updates on the location (those parameters have direct impact on battery drain, so they've been picked for a reasonable use-case tradeoff). In the above example we ask for updates no closer than 5 seconds apart (they can come longer apart, if the system decides to) and we also put a 10m change radius on the updates, anything less than that will be filtered out and no messages sent.
I just added a function to search for a given string in your
snaptic.com notes to our
android-lib. This function returns a list of all notes containing that given string. In the following example I search for all notes containing the workout tag.
| 01 | |
| 02 | ArrayList<SnapticNote> notes = new ArrayList<SnapticNote>(); |
| 03 | int getNotesReturnCode = mApi.searchNotes("#Workout", notes); |
| 04 | |
| 05 | //Only proceed if notes were fetched |
| 06 | if(getNotesReturnCode == SnapticAPI.RESULT_OK){ |
| 07 | //Search for notes containing descriptions of exercises |
| 08 | for(SnapticNote n : notes){ |
| 09 | if(DEBUG)Log.d(LOGCATNAME, "Note: " + n.summary); |
| 10 | } |
| 11 | } |
| 12 | |
A number of users have emailed me requesting an
android example with a simple username/password screen and an accompanying flow for signing into a
Snaptic account. I have updated
my example crossfit tracking app to provide just such an example. After syncing the latest changes from
github, simply load it onto your phone and hit the menu button, you will see two buttons, sync (which currently does nothing) and settings which will take you to the sign in screen.
Most of the sign in form magic takes place in SigninActivity.java. The menu code is inflated from an xml file and most of the code which drives it can be found in the functions
onCreateOptionsMenu and onOptionsItemSelected in WorkOutEditor.java.
A few people have emailed me asking how to append an image to a note created using the
Snaptic API. In this post I will expand on t
he example in my previous post and show you how to append an image loaded from your
Android phone’s
SD card.
| 01 | |
| 02 | String LOGNAME = "HELLO_SNAPTIC"; |
| 03 | Boolean DEBUG = true; |
| 04 | |
| 05 | String mUsername = ""; |
| 06 | String mPassword = ""; |
| 07 | SnapticAPI mApi = new SnapticAPI(mUsername, mPassword); |
| 08 | |
| 09 | //To post a note |
| 10 | |
| 11 | //Create a note |
| 12 | SnapticNote note = new SnapticNote(); |
| 13 | |
| 14 | //Set the attributes you cate about |
| 15 | note.text = "Post this note now and add an image to it later"; |
| 16 | int returnCode = mApi.addNote(note); |
| 17 | |
| 18 | if(returnCode != SnapticAPI.RESULT_OK){ |
| 19 | //Log Error |
| 20 | if(DEBUG)Log.d(LOGNAME, "Notes Error: " + SnapticAPI.resultToString(returnCode)); |
| 21 | }else |
| 22 | { |
| 23 | //Printe the note id which gets set when you post the note |
| 24 | if(DEBUG)Log.d(LOGNAME, "Snaptic id of note: " + note.id); |
| 25 | } |
| 26 | |
| 27 | //Append a picture from your SD card to the note you just posted. The note.id, is set when you post note. |
| 28 | |
| 29 | // Make sure SD card is present/mounted |
| 30 | if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { |
| 31 | // Point to your ".jpg" located at top level of SD card |
| 32 | File imageFile = new |
| 33 | File(Environment.getExternalStorageDirectory() + File.separator + |
| 34 | "death-star-transformer.jpg"); |
| 35 | |
| 36 | // check if imageFile is valid |
| 37 | if (imageFile != null && imageFile.exists() && imageFile.canRead()) { |
| 38 | |
| 39 | // Image is valid so Upload. |
| 40 | returnCode = mApi.addImage(note.id, imageFile); |
| 41 | |
| 42 | if(returnCode != SnapticAPI.RESULT_OK){ |
| 43 | //Log Error |
| 44 | if(DEBUG)Log.d(LOGNAME, "Notes Error: " + SnapticAPI.resultToString(returnCode)); |
| 45 | } |
| 46 | }else { |
| 47 | if(DEBUG)Log.d(LOGNAME, "Something happened openening file from SD Path: " + Environment.getExternalStorageDirectory() ); |
| 48 | } |
| 49 | } |
| 50 | |
| 51 | //Grab all notes from the account. |
| 52 | |
| 53 | //Create an array list to hold notes |
| 54 | ArrayList<SnapticNote> notes = new ArrayList<SnapticNote>(); |
| 55 | |
| 56 | //Call get notes |
| 57 | returnCode = mApi.getNotes(notes); |
| 58 | |
| 59 | if(returnCode != SnapticAPI.RESULT_OK){ |
| 60 | //Log error |
| 61 | if(DEBUG)Log.d(LOGNAME, "Notes Error: " + SnapticAPI.resultToString(returnCode)); |
| 62 | } |
| 63 | |
| 64 | //Iterate over notes and do what you want with the note attributes |
| 65 | for(SnapticNote n : notes){ |
| 66 | if(DEBUG)Log.d(LOGNAME, "Note text" + n.text); |
| 67 | } |
| 68 | |
As part of the
Snaptic Move Your App! Developer Challenge you are required to use the
Snaptic API to create an
Android app which encourages and tracks physical movement. Currently their are two ways to do this: Either by using
intents to save data via
3banana notes or by including the
Snaptic android-lib in your project.
The advantage of the first approach is that you have to do a minimum amount of work to push/pull notes and accompanying information from the
Snaptic backend. The disadvantage is that you now have a dependency on
3banana notes which must be installed in order for you to access any stored information. Integrating using the
Snaptic android-lib gets rid of this dependency and allows you to communicate directly with the backend. For instructions on how to integrate with
3banana notes using
intents go
here, the rest of this article will cover how to integrate using the
Snaptic android-lib.
The following is a little cooking demo which will show you how to create a basic app which can post and fetch notes from a
Snaptic account.
- Download the Snaptic android-lib project from git hub.
- Create a new Android project using the instructions outlined in the following hello world tutorial.
- Copy the src for com.android.http.multipart and com.snaptic.api into your project from Snaptic android-lib.
- Add the commons-codec-1.4.jar to your project (included in the android-lib lib directory), see this tutorial for instructions on how to add libraries with eclipse.
- Add the internet permission to your Hello World manifest xml file, for details on how to do this see here.
- Now add the following to your HelloAndroid activity in order to be able to post/get notes:
| 01 | |
| 02 | String LOGNAME = "HELLO_SNAPTIC"; |
| 03 | Boolean DEBUG = true; |
| 04 | String mUsername = "";//Add your username here |
| 05 | String mPassword = "";//Add your password here |
| 06 | SnapticAPI mApi = new SnapticAPI(mUsername, mPassword); |
| 07 | |
| 08 | //To post a note |
| 09 | |
| 10 | //Create a note |
| 11 | SnapticNote note = new SnapticNote(); |
| 12 | |
| 13 | //Set the attributes you cate about |
| 14 | note.text = "Post this notes"; |
| 15 | int returnCode = mApi.addNote(note); |
| 16 | |
| 17 | if(returnCode != SnapticAPI.RESULT_OK){ |
| 18 | //Log Error |
| 19 | if(DEBUG)Log.d(LOGNAME, "Notes Error: " + SnapticAPI.resultToString(returnCode)); |
| 20 | } |
| 21 | |
| 22 | //Grab all notes from the account. |
| 23 | |
| 24 | //Create an array list to hold notes |
| 25 | ArrayList<SnapticNote> notes = new ArrayList<SnapticNote>(); |
| 26 | |
| 27 | //Call get notes |
| 28 | returnCode = mApi.getNotes(notes); |
| 29 | |
| 30 | if(returnCode != SnapticAPI.RESULT_OK){ |
| 31 | //Log error |
| 32 | if(DEBUG)Log.d(LOGNAME, "Notes Error: " + SnapticAPI.resultToString(returnCode)); |
| 33 | } |
| 34 | |
| 35 | //Iterate over notes and do what you want with the note attributes |
| 36 | for(SnapticNote n : notes){ |
| 37 | if(DEBUG)Log.d(LOGNAME, "Note text" + n.text); |
| 38 | } |
| 39 | |
For a more advanced example app which uses the
Snaptic android-lib checkout the
open source crossfit tracking app I wrote
here. Also the javadocs for the
Snaptic android-lib can be found
here.
The March
PyGameSF meet up will be at the Sycip conference room on the fourth floor of the
main San Francisco public library beside
civic center BART. The library closes at 8pm so we will reconvene to
frjtz on hayes street for dinner/drinks afterwords.This month’s presentations are:
- Patrick Stinson: Embedding Python as a Realtime Audio Scripting Engine. Topics will include separation and communication between the application and scripting engine, why Python is “safe” for audio work including empirical performance metrics, and caveats related to multithreaded processing as performance requirements increase. I will share my experiences using the standard CPython implementation to research and develop a state-of-the-art scripting engine for the Play professional sampling engine (http://www.soundsonline.com).
- Shandy Brown : Structuring Your Game’s Code. One approach to designing video games with a focus on rapid development and networked multiplayer capabilities. Shandy Brown will highlight key ideas in his tutorial. Fundamental topics such as event-based design, defining your game model, and separating the model and the view will be covered.
Say you have a list and you want to create a dictionary such that the contents of the list become the keys of the dictionary. This is how you would do it:
| 1 | #Example, key = file name in list, value = path+filename |
| 2 | import os |
| 3 | path = os.path.abspath(os.path.dirname(__file__)) |
| 4 | mylist = ['harry.png', 'andy.png', 'dan.png'] |
| 5 | aDict = dict([(fn, os.path.join(path, fn)) for fn in mylist]) |