Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

Wednesday, July 7, 2010

25K !!

Yup, we just hit 25,000 downloads for RipChord over the Fourth of July weekend. Occasionally, I get emails from customers. Here are some highlights:
Thanks for building such an awesome app!!!
This is the ONLY paid AP I have on my phone.
I think it is awesome.
Every now and then as a self taught guitarist I find a teaching tool that helps me expand a great deal... and now I add RipChord to that list.
People on the Android Market seem to like it too:
This AP is ridiculously awesome!
Love it!
Tuba
Great UI. Love it
Awesome
Tuba? Anyway...
Notice the recurrence of the word "awesome"? Me too! I remember thinking "Maybe if I give the company a name that complements itself, people will agree..." Turns out, it worked!
While I'm all buttered up from your compliments, I have some news for you. A new app is coming. RipChord is for the rhythm guitarist in you. Now it's almost time to take the lead...

Wednesday, March 24, 2010

Free Android App A Day

Have you been to Free Android App A Day yet? They feature a single free Android app a day. Today, they're featuring RipChord, with bar codes to scan and take your Android phone straight to it (and RipChord Deluxe) in the Android Market!

Wednesday, December 9, 2009

Android on a Blackberry !?!

I was looking over the Flurry data from RipChord, and found something fascinating: 2 people that are running RipChord are doing it on a Blackberry 8230! Also, it looks like there are some people out there that have Android versions 2.0.1 and 2.1 already.

All About RipChord

Now that RipChord has been released, it's a good time to spill the beans on exactly what it does and how it works. I'm going to assume you know about music & chords already.

RipChord is meant to solve one problem - and solve the hell out of it! You've learned all the standard chord forms, but they're meant for standard tuning. If you're in a different tuning, all those chord forms change. RipChord can figure out how to play any chord in any tuning, at any position on the fretboard. But it throws in something extra. It determines every possible way to play that chord, including all inversions (which can be disabled in the Settings screen). For instance, in standard tuning at open position, there are 63 ways to play C Major, but in open C (CGCGCE), there are 141.

Right now, there are 27 chords and 16 tunings supported in RipChord Deluxe. Adding new ones is a quick process on our end, so if ever you need a tuning or chord that's not listed, let us know with an email or a comment, and we'll add it right away.

Currently, there are two versions of RipChord available on the Android Market: RipChord and RipChord Deluxe. RipChord Deluxe has the full set of 27 chords and 16 tunings and costs $1.99. RipChord has 2 chords and 4 tunings and is available for free. I hope that if you try out RipChord and find it useful, you'll upgrade to RipChord Deluxe. That will allow me to add new features that I've been thinking of, such as swipe to play and bookmarking chords.

Friday, December 4, 2009

Creating a boot-loading, always-on service

Let's say you've got an app that you'd like to run in the background. You'd like it to get started as soon as possible, and stay on whenever the device is powered on. It's an achievable goal, with one caveat. After installing the app from the Android Market or wherever, the user will need to run it at least once to give you a chance to execute some code that puts your foot in the door. Of course, once your app starts up, you're free to set up the system to make sure that your code is always running. There are really two parts to the issue: running the service, and turning the service on at startup. For today, let's talk about startup. If you poke around in the Android developer docs enough, you'll probably encounter the BroadcastReceiver class. The OS supports the idea of broadcast events, which can be caught by subclasses of BroadcastReceiver. Setting up that subclass is fairly simple - just extend BroadcastReceiver and override onReceive(), like this:
public class ServiceLauncher extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {

        // Start the service here
        return;
}

}
It's possible for a BroadcastReceiver to pull extra duty by listening for several types of broadcasts. If that's what you want to do, open up the Intent passed to onReceive() and check for the proper Action. Now, that's only half of the story. At this point, we have a class ready and able to listen, but the OS doesn't know that. To make the final connection, we need to add this snippet inside the application tag of AndroidManifest.xml:
<receiver android:enabled="true" android:exported="true" android:name="your.package.ServiceLauncher"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </receiver>
There seems to be a lot going on here, but when you really look at it, it's just an intent and an action, which you've most likely seen before, wrapped in this new receiver tag. All this is really saying is "We've got a class called ServiceLauncher, and it's going to get fired when the system boots." To sum up, there are two small parts, and that's all we need:
  • Create a subclass BroadcastReceiver and override onReceive().
  • Add a receiver tag for your subclass.
I hope this is helpful, and I'd be happy to take requests or questions about particular topics.

Friday, November 27, 2009

RipChord is coming to Android

Something new is brewing at Awesome Unlimited. It's a chord dictionary with something no other one has - multiple tunings. But what makes RipChord really special is that it finds every conceivable way to play a chord. Want to play Am7 at the first fret in dropped D tuning? There are 111 ways to do it, including inversions. So far, it's got 22 chord types, and 13 tunings, with more being added all the time. Here's a sneak peek at the main interface:
Watch this space and Android Market for a release very soon!

Friday, March 27, 2009

Dynamic Code Loading

I've been looking for a way to upgrade an Android application without any interaction with the user, and pushed through several options. Along the way, I found a few dusty corners of Android which I think are worth mentioning.
The first thing I wanted to try is just remotely installing an application - download it from some server, and then install it. Long story short: can't be done. Applications don't have the security permissions to install other applications. Certainly, that's a good thing, and it was a relief to see that it isn't so easy.
So then I thought "Why not just use a framework that dynamically loads some class files and executes them on some standard interface, such as Runnable. As I expected, I wasn't the first to think this. It turns out that some really sharp guys got it running for Apache Felix, which is a framework that does basically what I'm looking to do. But the trick is, they did it with 0.9 of the SDK. When Google put out 1.0, they changed some permissions so that it would no longer work. The in's and out's of this are interesting, so let's delve a little deeper.
As you may know, Android uses a custom VM called dalvik to run Java. Why? Maybe just to circumvent Sun, but my guess is they have some other trick up their sleeves. Dalvik doesn't use standard Java .class files, but instead uses .dex files - a format that has yet to be finalized (They're still fiddling with the opcodes). With an ordinary JVM, a developer could download a jar, unpack it, and use the classes inside. With dalvik, developers need to re-code their .class files into .dex files before loading them. That gets done by a tool called dx that ships with the Android SDK. So far, so good. Now, standard java class loaders can't handle .dex files, so the use of a different class loader is needed. Here's where it gets problematic. 
First of all, there's no documentation. Up until October, that was no problem. But when Google released SDK 1.0, they locked up some security. Now the undocumented class loader puts the bytes of the unpacked class into a part of the disk that only the system has access to. If an application tries to load a class there, it fails the permissions check. Is there a workaround? Not that I can find or figure out. Luckily, I'm not the only one trying to do this. In fact, Google is going to be officially releasing a dynamic code loading API in Cupcake. Those of you with Macs or Linux boxes can download the source and see it in action. But if you're looking to put something on the Market now that can load code dynamically, I'm afraid you're just out of luck.

Saturday, March 14, 2009

Launch Day!!

After getting some fresh graphics for the Toddler Percentile Calculator, I'm happy to announce that it is now available on the Android Market. The price is $0.99, and like all apps on the Android Market, there's a 24-hour return policy. So give it a try, risk free, and if you don't like it, just return it. Also, I'd love to hear your thoughts about it. Anything missing? Want it to support older kids? Shoot me an email and let me know!

Friday, February 6, 2009

Android 101: Launching dialogs - part 1

Hello!  We're going to talk today about a common task in Android, and user interfaces in general - launching a dialog to retrieve data.  
If we want very simple information, such as an OK/Cancel or Yes/No, we can use AlertDialog.  The code would look like this:
new AlertDialog.Builder(this)
     .setMessage("Should I buy a new cell phone?")
     .setPositiveButton("Yes", myClickListener)
     .setNegativeButton("No", myClickListener)
     .show();
It often makes more sense to implement OnClickListener in the class that's launching the dialog so that the data is sent to the object that launched the dialog.  Here's how that generally looks:
public class MyDialog extends Activity implements OnClickListener{
...
public void foo()
{
 new AlertDialog.Builder(this)
      .setMessage("Should I buy a new cell phone?")
      .setPositiveButton("Yes", (OnClickListener)this)
      .setNegativeButton("No", (OnClickListener)this)
      .show();
}
@Override
public void onClick(DialogInterface dialog, int which) {
// "which" contains the result of the alert dialog
}
}
Execution passes from foo() to the AlertDialog.  When the user presses "Yes" or "No", the dialog is closed and onClick() is called.  From there, we can update object members and take other actions based on the results of the dialog.  It's a pretty straightforward mechanism once you watch it work, and it's a useful way to keep from writing tons of tiny classes that are tightly coupled.
Part two will talk about how to return multiple variables from a dialog using Bundle and Intent.

Sunday, February 1, 2009

Flarb!

I'm happy to announce that we've got a new contract with Flarb LLC. We'll be porting Flarb's upcoming iPhone/iPod Touch release of Rune Stone Reader to the Android. Stay tuned for further details, but you can expect to see it on the Android Market this quarter.

Wednesday, November 5, 2008

Toddler Percentile Calculator v1.0a

Here's a screen of our first software release, exclusively for Android:
This small app can calculate percentiles of weight and height for any child 72 months (6 years) or younger. It accepts both English and Metric units. Stay tuned for details on how to download!