OHMS BLOG

Wednesday, 14 March, 2012

technology

How do I reference TrustedInstaller?

I was editing some ACLs on my Windows box the other day, and I wanted to assign ownership of a directory to TrustedInstaller. The trouble was that I couldn't figure out how to specify the TrustedInstaller user into the security editor. After scouring several blog posts I finally found the answer. Here it is for posterity:

NT SERVICE\TrustedInstaller

Wednesday, 8 February, 2012

code

Announcing Audio Auto-adjust

As I've been chronicling in my Adventures in Android series, I've been working on an Android app. I'm pleased to announce that today I have published Audio Auto-adjust 1.0.0 to the Android Market. I'd like to take this opportunity to provide a brief overview of what Audio Auto-adjust is and how to use it.

While there are numerous volume control apps already on the Android Market, I wrote this app to because I had some very specific needs that I wanted to address. I wanted an app that didn't leave services constantly running in the background, yet I wanted an app that would be responsive to system actions. In particular, I wanted to be able to save my audio settings as presets, and then associate those presets with actions.

The Main Activity



Here is the main activity as it appears in the portrait orientation. As you can see, the various audio streams are easily adjusted by moving the slider controls.




The toolbar across the top provides three widgets. The first button on the left toggles silent mode. The next button saves the current volume configuration to a preset. The third widget is a dropdown that displays the currently active preset (if any) and allows you to switch to a different preset. This widget is only enabled when there are two or more presets that have been saved.

Notice that some of the streams are identified by hyperlinks. Those hyperlinks lead to context menus for additional configuration settings that are permitted for the selected audio stream.

To access Audio Auto-adjust's advanced features, select your phone's menu button to activate the main menu. Note that the Edit Presets and Actions options are only available if you have already saved at least one preset.



Edit Presets Activity



This activity lists all the presets that have been saved in Audio Auto-adjust. In this example I have saved two presets, "Foo" and "Max." Touching one of those presets will command Audio Auto-adjust to switch to that preset. Long-pressing a preset, however, raises a context menu that allows you to modify that preset. For example, long-pressing the "Foo" preset presents this menu:



Actions Activity

The most powerful feature of Audio Auto-adjust is the ability to associate presets with system actions. My personal use case for this was when I enter my car and my phone connects to my vehicle's hands-free system via Bluetooth. Upon receiving notification that my phone has connected to my car, Audio Auto-adjust will automatically switch to an associated preset.

NOTE: In order to configure Bluetooth events, you must enable Bluetooth on your phone before entering the "Configure Actions" activity.



Each row in this activity lists a system action that may be associated with a preset. Actions containing "(None)" are simply ignored by Audio Auto-adjust. To associate an action with a preset, select the action's corresponding dropdown, and then choose a preset from the list.

A Note About Precedence

The order of the listed system actions in the "Configure Actions" activity affects the precedence of those actions. Entries that are located higher on the list are given a higher precedence by Audio Auto-adjust. If more than one system event is activated at the same time, the action with the highest precedence is the one that will be activated by Audio Auto-adjust.

Precedence may be adjusted by placing your finger on the grip on the left side of the row, and then dragging it up or down to your desired position.

Settings Activity

I've tried to ensure that each preference in the settings activity contains a useful summary. Here's a brief overview that goes into a bit further detail:

  • Volume Control Stream: Chooses which audio stream will be adjusted by your phone's hardware volume controls. Note that this setting only applies when Audio Auto-adjust is running in the foreground.
  • Background Notification: When enabled, Audio Auto-adjust will post a notification whenever it switches presets while running in the background.
  • Play Sounds: When adjusting volume settings, play sounds to illustrate the loudness of the setting.
  • Tie Ring Volume: When set, hide the controls for the Notification audio stream. Instead, the Ring audio stream will control both itself and the Notification stream.


In Conclusion

My goal with Audio Auto-adjust was to make a volume control app that fulfilled my needs. I hope that is as useful to others as it is to me. In the future I plan to expand the app with additional features, so please stay tuned!

Wednesday, 2 November, 2011

code

Adventures in Android, Part IV: Vertical SeekBars

One user interface element that I wanted to include in my activities was a vertically-oriented SeekBar. While Android has provided View.setRotation() since API level 11, since I am targeting API level 7 I do not have that functionality available to me. I knew that this could probably be achievable by manually applying a transformation matrix to a View, but I had no idea how difficult it would end up being. I attempted numerous different approaches in an effort to achieve my desired results. Much to my frustration, I kept finding limitations in the APIs that made every option either unfeasible or difficult.

  1. My first attempt was to try something subclassing SeekBar similarly to this StackOverflow post. It overrides View.onDraw() and applies a transformation to the Canvas. It also sends fake size dimensions up to the SeekBar superclass and provides a custom View.onTouchEvent() handler. My concerns were as follows:
    • A custom event handler must call SeekBar.setProgress() to update the SeekBar's state. Since this is being done programmatically, any listeners will be told that this change did not come from the user, even though indirectly it actually did.
    • This custom event handler did not (and cannot) propagate touch events up to the SeekBar in a way that it will be able to redraw itself during the touch event. In particular, the SeekBar thumb was not being highlighted while the view was being touched.

  2. Figure 1: SeekBar with thumb drawn at incorrect location
    My second attempt was an extension to the first. Instead of completely overriding onTouchEvent(), I decided to use onTouchEvent() to perturb the touch coordinates of the provided MotionEvent, then call up into the superclass. While this fixed the issues from the first option, it still didn't look right.
    • Notice that in Figure 1, the SeekBar's progress indicator is at 100%, yet the thumb is located near the bottom. It turns out that the SeekBar's drawing code calls getWidth() to figure out where to position the thumb. Since the SeekBar is now in a vertical orientation, it should be using the height instead of the width.
  3. Finally we reach the third, definitive option: I wrote a derivative of ViewGroup called RotatedLayout that does a perfect transformation of the child View. From the child's perspective, it is operating using its regular orientation. The RotatedLayout class transforms coordinates for drawing, measuring, layout, invalidation, touch events and key events between its parent and its child. This allows me to provide my users with a pixel-perfect vertical SeekBar!
    • It was annoying to deal with invalidation; Android goes to great lengths to prevent you from tinkering with it. I had no choice, however: any invalidation rectangles generated by the SeekBar need to be transformed from the SeekBar's coordinate system to the parent view's coordinates. Figure 2 illustrates what happens if invalidation isn't transformed: Only a small region of pixels at the top of the SeekBar are redrawn. This happens because that small region happens to be exactly the same height as the underlying horizontal SeekBar. Figure 3 overlays a horizontal SeekBar with the misdrawn vertical SeekBar to illustrate.

Figure 2: Vertical SeekBar with no invalidation transformation

Figure 3: Invalidated region from Figure 2 overlaid with horizontal SeekBar

Figure 4: Vertical SeekBars in Audio Auto-adjust.
Are you interested in what RotatedLayout can do for your app? Drop me a line: ohmsblog at teamohms dot org

Release 7.0; Copyright © 1996-2011 Aaron Klotz. All Rights Reserved.