There are multiple explanations for how to use IDisposable. I get it now, so here goes:
public class Connection : IDisposable
{
public IntPtr buffer; // Unmanaged resource (memory buffer)
public SafeHandle resource; // Managed resource that implements IDisposable
private bool disposed;
public Connection()
{
buffer = ... // allocates memory
resource = new SafeHandle( ... ) // allocates some managed resource that we assume allocates an unmanaged resource, but we don't care
}
~ Connection()
{
Dispose(false);
}
public void StartConnection()
{
if (disposed) throw new ObjectDisposedException();
... // implementation
}
public void Dispose()
{
// NOTE: If you think multiple threads could try to Dispose your object
// consider locking this section as well. DON'T do this in the Dispose(bool)
// function, as locks are unsafe at finalization time (and there is only one
// finalizer thread)
Dispose(true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
// No need to repeat the frees
if (!disposed)
{
// Release ALL unmanaged resources here so that it's ALWAYS done!
Release(buffer);
if (disposing)
{
// If the caller has explicitly called the Dispose() method, call Dispose() on managed objects early.
// By early, I mean that we TRUST disposable managed objects to do the same thing we are above for UNMANAGED resources
resource.Dispose(); // Note that we don't have to check if it's NULL first because this will never execute in the Finalized state
}
}
}
}
The complex bit here is the trust that all IDisposable objects behave like this. Basically, an object should never let itself leak an unmanaged resource. Thus, it frees unmanaged resources both when Dispose() is called and on from the Finalizer.
Today, I’m launching my very first app under the Cryclops name. It’s called RingPack, and is currently available on the Android market in beta testing.
The idea started with a very simple desire. I get a lot of texts/notifications, and usually whatever ringtone I choose for my text ringtone (the Default Notification Ringtone in Android), I grow to hate after a while. It starts with loving the new tone, and being impressed with it for a few weeks, but then — just like a hit song on the radio — the repetition finally gets to me and I can’t stand it anymore.
RingPack started as a solution to this annoyance. I thought it would be kind of fun to not know what sound your phone was going to make next. Obviously, I want my actual ringtone (the one people get when they call me), to remain the same, otherwise I wouldn’t know what was ringing. But the text notification had some room to wiggle. So I came up with 3 main ideas I wanted to accomplish:
The first idea was to have the app shuffle around different, yet similar sounds. For instance, it would shuffle your tone between all known guitar chords in the key G. This way, you’d still be expecting the correct pitch, but you wouldn’t know the exact mood of whatever chord was coming.
Then I thought about theming. I loved Ocarina of Time as a kid, and wouldn’t it be cool to have a themed set of notification tones, all from the same game. That way, instead of just recognizing it by key, I would recognize it by association.
Lastly, I remembered my girlfriend, who always has the same exact song snippet as her text tone. “Still D.R.E.” That gets stuck in your head all day. Wouldn’t it be cool if your phone could progress through the song as you get texts?
So I thought I’d pack together ringtones in “packs” and make an app to manage them.
Long story short, after a month of development I’m proud to release the beta version of RingPack. I think you’ll like the UI, especially the implementation of custom QuickActions based on this tutorial. The app is based around a Service, to swap out tones in the background, and BroadcastReceivers, to tell the Service when it needs to make a change.
I ran into some limitations on my “perfect” idea of an implementation simply due to constraints in the Android framework. For instance, the only notification I can listen for is incoming SMS’s. Things like incoming Google Talk and Voice messages simply don’t seem to be a thing that I can detect. To compensate for this, I’ve given the user the option of listening for time ticks instead. You can have your tone rotate on either 1 minute or 5 minute intervals. In the future, I’ll probably give the user more options (perhaps once daily, weekly, after every phone call).
Features include:
Intuitive UI
(2×1) Widget
Shuffle, Lock, and Rotation preferences
Easy on the battery background service
Extend-able packs! (I’ll post more on how you can make your own packs soon)
I’m allowing Android 1.6 and up to install it, although users who are below Android 2.0 might experience some issues with the background service. Android 1.6 has some issues with restarting the service. I’ve done my best to try to fix those issues for now, but as I’m testing on 2.2, I can’t confirm for sure.
Known bugs:
The 1.6 thing
Playing mp3 ringtones very quickly (using the widget) will result in the mp3 decoder becoming overloaded and Android will panic and reset the Default Notification Ringtone to it’s most basic one. If this happens to you, simply open RingPack, select the “None” pack, then your desired pack and it will return to normal. I’m working on this. It seems ogg files may be a better choice.
After a restart, RingPack can take up to 1 minute to restate itself.
Sometime the interface is slow to respond. I’ve not been so good about breaking into Threads. This is my first priority to fix.
If the app Force Closes on you (which I’ve done my best to stop. In fact in the last week of testing, I haven’t hit any), it has the potential to leave a orphan entry in your MediaStore library. It’s not harmful, but if you’d like to clean it up, I recommended using the ever popular ringdroid. Just open it, click Menu>Show All Audio>Search for “ringpack”. If there’s an entry there, longpress it to delete it and you’re all cleaned up. There is a special case where the Service manages to delete the file, but misses the MediaStore library entry. Ringdroid will tell you that it couldn’t delete the file in this case, but it lies. The entry will have been removed from your library. I’ll definitely be implementing my own fix for this type of thing soon, but for now this works.
Lastly, screenshots can be found on the official RingPack page. Look there in the future for more goodies.