Search This Blog

Tuesday, January 24, 2012

Debugging and Publishing the Blinker App


For entertainment I decided to publish a real app to the marketplace.  I wanted to see what it was like, if there were any unknown obstacles, and see if anyone used my app.   I started with my hello world blinking LED app and polished it up into something marginally useful to others.   Easiest next step was an app to completely control the LED flashlight, blink, pattern setting, speed setting, strobe light, maybe dimming.   It would be useful as a toy and as an emergency signalling device, a strobe light for video, whatever.  Here was my starting goal list of functionality:

  • Flashlight
  • Blinking light
  • Party Strobe Light
  • Warning Hazard Light
  • S.O.S. signaler 
  • Custom LED pattern modulator (for hobby use to transmit data)

I signed up for the Android market as a developer.  Google "android developer", follow the links and fill out the forms.  Done.  That cost $25. Also signed up for the Amazon market so I can publish to the Kindle.  Signed up for  https://developer.amazon.com/help/faq.html#KindleFire.  Have to watch out, amazon costs $99/year after the first year, so this may not last as a hobby.  The first year is free however.  Amazon is stricter, we will see if my hobby app can get through.  I may use ads just so I can see how that works.  I expect that I'll earn up to $1 based on my experience with the web.   No pipe dreams of wealth with this one.

To publish I felt I had to have an app that was useful, with a clean GUI, and minimal bugs.  I didn't even look to see how many other apps were there that did the same thing, that would be too depressing.   This is a hobby project so I have to let myself get excited by the creation.  Until you have worked something through to the level that others can use it, you don't learn all the lessons.

This turned out to be a trickier app than you might think.  The trouble is, you need processing power to blink the light, but you don't want to tie up the GUI thread with marking time or the phone appears hung.   So I had to learn about child processes and about other events that happen on the phone platform like randomly hitting the home or back keys, screen rotation, keyboard opening, etc that your app and it's child process have to deal with.  Asynctask would run amok if not managed well.

There is a lot of "artwork" to building an app.  You need an icon, button layouts, backgrounds, etc that make it look professional.  I probably spent as much time with this as making the code.

Implemented a GUI, in the process learned how to used radio buttons and toggle switches.   Tossed in the basic blinking functionality and then entered the "development loop" of adding functionality, debugging glitches, crossing off items on the list and adding more items as ideas, issues, etc emerge.

This would be my PCR list if this were done at work.  Since coding is not a spectator sport, I'll not write the running blog for this development as I do with hardware.  For anyone starting out, this is a simple and productive way to work on a complex task.  You make a working list of all the things to do.  Then you pick one and do it.  If anything new comes up while you are working on that task, just add it to the list and don't stress about it.  When you finish a task, mark it done, smile, and pick another task, either easy or hard depending on how much time you have and how deeply you can think at that time.  If you stumble across information for a task while working on another one, don't switch gears, just drop some notes in the list and keep rolling.  Eventually everything on the list is done or you decide you don't need to do it.

PCR working list
  • DONE - lay out GUI and hook up buttons
  • DONE - Disable editing pattern on the presets, custom field allows editing 
  • DONE - custom has no pattern, starts with whatever is there
  • DONE - Enforce hardware has a camera flash before downloading
    • Looks like i just need the uses-feature line in my manifest
    • <uses-permission android:name="android.permission.CAMERA" />
       <uses-feature android:name="android.hardware.camera" />
  • DONE remove extra permissions
  • DONE - on off button out of sync if exit and come back, need to check isOn at start
  • REJECTED - Remember the settings from use to use - Not doing, it causes too much trouble
  • DONE - Add the blink rate variable, auto set it for preset
  • DONE - Add the rate slider and figure out how to control it
  • DONE Force the screen to be vertical only because buttons go off the screen in horiz
    • Add android:screenOrientation="portrait" to the element in the manifest 
  • DONE - Set up blinking loop for any length pattern
  • DONE - Debug the thread start and stop and not lock up phone while blinking
  • DONE - Now I have to cancel the task when the user wants to stop the blinking
  • DONE - Sort out glitches with on/off toggle switch
  • DONE - If user exits without turning off blinking, it never stops - put a variable in the while loop of the child thread that kills it on exit.  
  • DONE - Add the information screen pop up text window
    • Toast is a function for doing this sort of thing
  • DONE - Add an epilepsy warning about strobe light 10Hz for less than 30 sec
  • DONE - longer text descriptions for choices on screen
  • FUTURE - Investigate brightness.   Possibly write a PWM loop to dim the LED.  Add a brightness control.
  • DONE - Make an icon - more on this below, it was a doozy
  • FUTURE - Investigate running strobe at the same time as the video recorder, either by backing out or by invoking it for strobe video.  This is an enhancement, probably for a later release, this causes all sorts of problems because the child blinking thread runs amok if I leave it going when I exit the app.  I'd need to call the camera from within my app.  Too much function for now. 
  • FUTURE - Button list is getting too long.  Can I enable scrolling for small screens?  
    • Looks like ScrollView does this, have to set up a frame
    • for now i'll leave it portrait only
  • DONE - Divide by zero on rate setting
  • Check frequency on the scope to see if it is accurate
  • DONE See if there are any color or style easy things to make it look better or different
  • DONE - Downrev app requirement to 8 (2.2) to include more devices
  • DONE!  Eliminate errror when user exits with the light still on, coming from onDestroy or figure out how to kill the child thread without any blood or warning messages.  This was a tricky one.  super.onDestroy() cleaned it up.  not really sure what this does, but it worked.
  • DONE - Screen rotation and opening keyboard is hosing the application by restarting the thread
  • DONE - Move the on button to the bottom
  • FUTURE - Look into how to make a separate horizontal layout
  • DONE - Solid pattern has some flicker - maybe make an override to skip the loop and turn it on straight - was due to double starting the thread
  • DONE - Custom pattern entry has stopped working - resent pattern to buffer when toggle pushed
  • DONE - Getting some new random crashes with monkey button pushes, possibly from spawning duplicate threads, seems to happen when going to a shorter string from a longer one.  Added the thread kill variable to the blinking loop, shuts down faster now.  Very stable.
  • DONE - maybe a cool chip photo for a background?
  • add some instructions on pattern setting in the information toast popup
  • DONE - add some info - mostly unsupported but adfree notes
  • DONE - Get the rep rate slider range and values to be realistic
    • rework here caused some divide by zero problems.  need to clean up the values of the timer and Hz and protect against out of range settings
  • DONE - Stretch the stobe light duty cycle and run it faster
  • DONE - Make the menu text a bit bigger
  • DONE - Bring down the contrast on the background picture to make it more readable
  • DONE - Simple Downrev of code level in manifest won't work, because package in source is 2.3.3.   Either change it back to 10 or figure out how to change the target in the source
  • DONE - some nasty bugs with crazy precsion being displayed from the rate calculation.  cleaned up
  • DONE - fast strobe lights you see an occasional hiccup, probably because the phone interrupted the thread and stole some milliseconds.  
Now I'm pretty happy with the app.  It's stable and it does what it is supposed to do.  I can't crash it by pushing buttons on the phone, opening the keyboard, changing settings like crazy, etc.  I'm going to try to push it to the android market now.


Requirements enforced by the Android Market server:
  1. Your application must be signed with a cryptographic private key whose validity period ends after 22 October 2033.
  2. Your application must define both an android:versionCode and an android:versionName attribute in the <manifest> element of its manifest file. The server uses the android:versionCode as the basis for identifying the application internally and handling updates, and it displays the android:versionName to users as the application's version.
  3. Your application must define both an android:icon and an android:label attribute in the <application> element of its manifest file.

Got the versionCode and versionName.  Now the icon.  Wow.  A lot of artwork to do.
http://developer.android.com/guide/practices/ui_guidelines/icon_design_launcher.html#icons_in_market
https://support.google.com/androidmarket/developer/bin/answer.py?hl=en&answer=1078870

You have to make an icon of several different resolutions.  I tried scaling a jpg photo and shapes in GIMP and it didn't work well at all.  At low resolution and on the phone screen it looked really ragged and unprofessional.   I was using GIMP and the image scaling function and saving at the lower resolutions.   Finally I tried a simple drawing with some texture in power point.  Then I scaled the picture in power point and copied it into the GIMP drawing, over and over again for each resolution.  That worked pretty well and it looks good.  On the phone screen it stands out like a little hazard flasher auto button.


Collected a couple screen shots that are required,  by doing an alt printscreen of the emulator and pasting it into gimp.



Now to figure out how to sign the app.  Found a couple links
http://developer.android.com/guide/publishing/app-signing.html
This seems like a weird and mysterious process.

However it looks like Eclipse  File->Export to an android app presents a form to fill out to make the keystore.   I made a separate directory for this since I had no idea what I was supposed to do.   It seemed to work without doing all the command line stuff.

I walked through the android developer upload page.  I had to scale my screenshots with gimp to 480x854 get them accepted.    A bit of fiddling with the pictures and up it went!

Here is a link to my app list, I will try installing it from the market and see if it works.

Available in Android Market

I published the app and it showed up on a web search the next morning.  I dont know how long it actually took since I went to bed, but it wasn't instant.  Must have been more than an hour.

I cant find the app on the android market from my phone.   When i went to the web link above from my phone, it said my phone WAS NOT COMPATIBLE!  Whaa?  I developed it on that phone.  Something is wrong with my app requirement settings.

Google made a page for the app.  It says I need Android 2.3.7 to install!!! how did that happen?  It looks like since I picked "10" as the build level, it set the requirements to the highest rev that is release 10, which is 2.3.7 not 2.3.3.

https://market.android.com/details?id=sifish.android.blinky&feature=search_result#?t=W251bGwsMSwyLDEsInNpZmlzaC5hbmRyb2lkLmJsaW5reSJd

I went back to downrev the build of the application to 2.1 in eclipse.  That should cover the vast majority of devices.  Right click on project name, Build Path->Configure Build Path->Android and the list of Project Build Targets shows up.  Change the check mark to a lower rev.  Took a while to dig that out of the GUI, but once I found it, it was easy.

Next I had trouble with the keystore, it refused to export the application again.  It turned out there were some errors in the layout.xml file, the "match_parent" keyword didn't work in Android 2.1 and had to be changed to fill_parent.  Once that was cleared up, i could re-export the app.

Discovered I forgot to update the version number when I went to publish.  Had to export again.   After that I still couldn't see the new rev in the app market.   Turns out I had to activate the new release, and de-activate the old one due to the conflict in Android rev support.  

Arrrgh.  Still can't download the app to my phone.  After about an hour, the new rev showed up when doing a web search for the the app.  But I can't see if from the phone and the label says the app is incompatible with my Motorola Droid 2 GLobal.   Whaaa?

Maybe it has something to do with my hardware permissions.  The FLASHLIGHT permission seemed odd, although it works when directly installing.  On the android dev site it seems to be
android.hardware.camera.flash
http://developer.android.com/guide/topics/manifest/uses-feature-element.html
This page showed some different syntax
http://www.linuxforu.com/2011/10/android-app-development-part-5-hardware-and-sensors/

Still going nuts.    Can't get the app to show up on the market as compatible with ANY phones.   This post had some more ideas.   This is something stupid but I don't know what it is yet.
http://stackoverflow.com/questions/5053507/my-android-app-shows-as-this-item-is-not-compatible-with-your-device  After days of fiddling I thought I finally figured out the problem.  It was the  android:screenOrientation="portrait"  line in the manifest http://forums.whirlpool.net.au/archive/1771380.  There is some bug in the compatibility that makes the market think that phones with ONLY portrait mode can use the app.   Lame.   However that STILL didn't get me past the FLASHLIGHT filter. 

The only thing i can seem to publish is a version with the FLASHLIGHT permission stripped out.  making the app totally useless.   So I have an app that works great on my phone, but I can't seem to publish it.  FAIL.   I'm going to put this on the back burner and move on to another app, since this ceases to be fun.

Update!!!!! HOoRAYYYYYYY!  W000T!  By giving up for a day and working on something else I thought of something else to try.  Not only did I have a permission line, i had the line in my manifest that says <uses-feature android:name="android.hardware.FLASHLIGHT" />.   I deleted that, to see if the android market added it back in, and it didn't!  Plus the app still works fine.  Now I show on the dev console as being compatible with 945 devices.  Hooray again, i finally can publish the app.

Amazon app store rejected my app, said that the light didn't turn on.   Lies!   However it is on market now.

In the process of looking for my app in the store, I saw that there are probably 1000 apps to do similar tasks.   So many in fact that I have to search for pub:Siliconfish to even find it amongst the clutter.  I didn't see one exactly the same, and the world probably doesn't need this app.  However I had fun, and I learned a lot, so the project is still a success.    On to bigger fish!




Saturday, January 7, 2012

Android java app - Blinking camera flash LED

I'm developing hardware control applications for the Android phone platform to replicate functionality I've previously used in gadgets for the Arduino.

Finally I achieved my goal of replicating the very first "I'm Alive!" hardware test on a new platform.  Whenever you make a new gadget, the first program you run blinks a light to show health.

I was able to get the LED used for the camera flash to blink!  Hooray!   In my earlier post I found the code and permissions needed to turn it on and off with a button press.   Then I had to find a suitable system clock to use to time the blinking, but got sidetracked generating audio tones.  So finally I put the two together and here is how I did it using the Android SDK in Eclipse.  This technique is limited to <500Hz because the system clock is milliseconds.   The next step will be to find a method to access a faster clock.  However if the goal is communicate to humans or slow serial interface, this might be good enough.

in AndroidManifest.xml you need (you may not need them all, didn't test that)

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.FLASHLIGHT"/>
    <uses-permission android:name="android.permission.HARDWARE_TEST"></uses-permission>

The code I wrote looks like this (copied out the relevant bits from a larger program so hopefully I didn't leave out something critical).  This code was placed in a callback from a button press.  The actual flashing is just done with the for loops, but the rest starts it in another thread so the phone is locked up while this is running.  You don't have to do this but you might frustrate a user if you don't.  I tried it first without the additional thread.   The full app is here, but the relevant bits are below  http://code.google.com/p/arduino-java-xyzcnc/downloads/detail?name=Siliconfish%20Blink.zip&can=2&q=#makechanges
  
    //variables for light blinking
    private final int blinkrate_ms = 100;
    private long nextblink = blinkrate_ms;
        
            //blink the light
            // Use a new thread to flash as this can take a while
                final Thread thread = new Thread(new Runnable() {
                    public void run() {
                        handler.post(new Runnable() {


                            public void run() {                              
                                // loop to flash the camera LED
                                for(int q = 0; q<10; q++)  {
                            nextblink = SystemClock.elapsedRealtime() + blinkrate_ms;
                            while (SystemClock.elapsedRealtime()<nextblink) {
                            setOn(true, null);
                            }
                            nextblink = SystemClock.elapsedRealtime() + blinkrate_ms;
                            while (SystemClock.elapsedRealtime()<nextblink) {
                            setOn(false, null);
                            }
                            } //for
                                
                            }
                        });
                    } 
                }); //thread
                thread.start();
           
                  
It required these functions which turn on and off the LED
     
    // code largely copied from   http://www.java2s.com/Open-Source/Android/Tools/quick-settings/com/bwx/bequick/flashlight/Droid22Flashlight.java.htm
    // Controls the camera flash LED
    
    private Object mManager;


    public boolean isOn(Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method getFlashlightEnabledMethod = manager.getClass()
                        .getMethod("getFlashlightEnabled");
                return (Boolean) getFlashlightEnabledMethod
                        .invoke(manager);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
        return false;
    }


    public void setOn(boolean on, Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method setFlashlightEnabledMethod = manager.getClass()
                        .getMethod("setFlashlightEnabled",
                                boolean.class);
                setFlashlightEnabledMethod.invoke(manager, on);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
    }


    private Object getManager() {
        if (mManager == null) {
            try {
                Class<?> managerClass = Class
                        .forName("android.os.ServiceManager");
                Method methodGetService = managerClass.getMethod(
                        "getService", String.class);
                IBinder hardwareService = (IBinder) methodGetService
                        .invoke(managerClass, "hardware");


                Class<?> stubClass = Class
                        .forName("android.os.IHardwareService$Stub");
                Method asInterfaceMethod = stubClass.getMethod(
                        "asInterface", IBinder.class);
                mManager = asInterfaceMethod.invoke(stubClass,
                        hardwareService);
            } catch (Exception e) {
                Log.e(TAG, "", e);
            }
        }
        return mManager;
    }

Saturday, December 31, 2011

Android app continued v: time, tones, and GUI

As stated in the previous couple of posts, I want to take advantage of the android phone/tablet platform to do a lot of the cool widgets I've build with Arduino, etc.   I've been making the first baby steps to creating an application and learning to interact with the phone hardware.   So far I've installed all the software, drivers, etc and successfully uploaded an app to my phone.  (see previous posts)  Then I upgraded my app to control the camera flash LED in response to a button press.  Now the goal is to learn about the Android system clock and what precise time keeping functions are available.  To do much useful with the Android I need to be able to perform functions like the Arduino delay() and pwm timers.  Once that is licked I can use the LED to send a serial stream of data which is my eventual goal.

I'm going to start with the app in my previous post and try to add timebase functions.  I'll put that on the scope and see how accurate it is.    I'll also try generating precise tones and measuring them.

Found this useful page on android system clock
http://developer.android.com/reference/android/os/SystemClock.html

This is a little trickier than it might seem, because I need to use a handler rather than tying up the phone 100% in a timing loop waiting for an event.  But for now we need to get a clock running.

http://stackoverflow.com/questions/526524/android-get-time-of-chronometer-widget
This page had an example of accessing a chronometer that I was able to integrate to make a time base
However I did not need all the functionality in this example.  just mChronometer.start, stop and setBase.   Added buttons to start, stop and clear the timer.    I get an output readout of ms, which is useful, but limits my maximum frequency to 1/2ms = 500Hz for a string of 101010 at this rate.  Boo,  Not good enough for most serial transmission applications.

Went off to try audio tone generation.  Found some examples of playing tones, this was the best, incorporated this code that used the audio sample rate to set a tone frequency
http://stackoverflow.com/questions/2413426/playing-an-arbitrary-tone-with-android
I thought this might lead me to a faster timebase to use, but it turns out this sets a sample rate on the audio player as the timebase, it doesn't use the system clock. I'll put this on the scope and see how accurate it is.

Having an annoying problem that the emulator sound doesn't play, but my phone's does!
Went to Run->configurations and added -useaudio in the command line options field.
Didn't work.  I'm not going to figure out this issue right now.  I'll have to use the real phone for development for the moment.   The computer audio is windows-fied.


Took a side trip and polished my app for a couple hours, working around making the image change when buttons were pressed so that I could learn to control what was on the screen and make GUIs.
http://developer.android.com/guide/topics/graphics/2d-graphics.html  was a good example.  Now I have a GUI with buttons, checkboxes, a picture that changes in response to button pushes, a timer, data entry, the camera LED turns on and off and a beep is played if a box is checked.  Basically a starting point for many apps.  I piled in every function I could think of.




Using an audio jack cable connected to the phone, I measured the frequency of the beep on the oscilloscope, it was about 1 / 2.3ms = 434.78Hz.   Probably was really the 440Hz that was programmed by private final double freqOfTone = 440; // hz.   I just couldn't measure it more accurately.

Next I set the frequency to 5000 Hz, knowing that the audio sample rate is 8000 Hz, so I am above Nyquist and the waveform is going to be distorted and aliased.  The frequency is wrong because of the aliasing.  Here is what it looked like:

I'll need to see if I can up the sample rate to 16000.  Wow, that sounds a lot better.  Much purer tone.  Here is 5Khz at 16KHz sample.
Now here is 5kHz at 32kHz sample rate.  Now we are in business.  This tone sounds pure and the amplitude isn't getting modulated by much as it beats against the sample frequency.


So where are we?   I'm up and comfortable with creating apps, having fun, although I'm sure I'd make a programmer cringe with my code.    The system clock is in milliseconds, and is too slow to be very useful for applications other than human interface.    The audio playback is pretty good up to 5kHz, I didn't push the audio sample rate up higher, but I imagine it won't go much past 44KHz (CD quality).    Next I'm going to have to dive deeper in the hardware to realize my goal of high frequency LED modulation.

Meanwhile I'll post my relevant code at the end of this post and perhaps look into joining the app store as a distribution method.  It is also posted here:
http://code.google.com/p/arduino-java-xyzcnc/downloads/detail?name=Siliconfish%20Blink.zip&can=2&q=#makechanges

Activity.java


package com.example.android.skeletonapp;

import android.app.Activity;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Chronometer;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import java.lang.reflect.Method;
import java.lang.Object;
import android.content.Context;
import android.util.Log;

/**
 * This class provides a basic demonstration of how to write an Android
 * activity. Inside of its window, it places a single view: an EditText that
 * displays and edits some internal text.
 */
public class SkeletonActivity extends Activity {
 
// sets up menu items for the pop up menu
    static final private int BACK_ID = Menu.FIRST;
    static final private int CLEAR_ID = Menu.FIRST + 1;
    static final private int BEEP_ID = Menu.FIRST + 2;
    static final private int NOFLASH_ID = Menu.FIRST + 3;

    // sets up the objects that are on the screen
    private EditText mEditor;
    private ImageView mImage;
    private TextView mTextView;
    private CheckBox mCheckBox;
    private EditText mFreq;
    Chronometer mChronometer;
 
    // name for the exception debug log
    private static final String TAG = "sifish.blink";
     
    // variables for tone generation
    private final int duration = 3; // seconds
    private final int sampleRate = 32000;
    private final int numSamples = duration * sampleRate;
    private double sample[] = new double[numSamples];
    private double infreqOfTone = 440.0; // hz
    private byte generatedSnd[] = new byte[2 * numSamples];
    Handler handler = new Handler();
 
    public SkeletonActivity() {
    }

    /** Called with the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Inflate our UI from its XML layout description.
        setContentView(R.layout.skeleton_activity);

        // Find the objects inside the screen layout xml, because we
        // want to do various programmatic things with them.
        mEditor = (EditText) findViewById(R.id.editor);
        mImage = (ImageView ) findViewById(R.id.imageView1);
        mChronometer = (Chronometer ) findViewById (R.id.chronometer1);
        mTextView = (TextView) findViewById (R.id.TextView1);
        mCheckBox = (CheckBox) findViewById (R.id.checkBox1);
        mFreq = (EditText) findViewById(R.id.editFreq);
 

        // Hook up button presses to the appropriate event handler.
        ((Button) findViewById(R.id.back)).setOnClickListener(mBackListener);
        ((Button) findViewById(R.id.clear)).setOnClickListener(mClearListener);
        ((Button) findViewById(R.id.flash)).setOnClickListener(mFlashListener);
        ((Button) findViewById(R.id.noflash)).setOnClickListener(mNoFlashListener);
     
        // Do initial setups
        mEditor.setText("Hello from Siliconfish!");
        mImage.setImageDrawable(getWallpaper());
        mFreq.setText(Double.toString(infreqOfTone));
     
        mChronometer.setBase(SystemClock.elapsedRealtime());
        mChronometer.stop();
        mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
        genTone(infreqOfTone);  //make sure the tone exists
    }

    /**
     * Called when the activity is about to start interacting with the user.
     */
    @Override
    protected void onResume() {
        super.onResume();
    }

    /**
     * Called when your activity's options menu needs to be created.
     */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);

        // We are going to create two menus. Note that we assign them
        // unique integer IDs, labels from our string resources, and
        // given them shortcuts.
        menu.add(0, BACK_ID, 0, R.string.back).setShortcut('0', 'b');
        menu.add(0, CLEAR_ID, 0, R.string.clear).setShortcut('1', 'c');
        menu.add(0, BEEP_ID, 0, R.string.beep).setShortcut('2', 'b');
        menu.add(0, NOFLASH_ID, 0, R.string.noflash).setShortcut('3', 'x');

        return true;
    }

    /**
     * Called right before your activity's option menu is displayed.
     */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        // Before showing the menu, we need to decide whether the clear
        // item is enabled depending on whether there is text to clear.
        menu.findItem(CLEAR_ID).setVisible(mEditor.getText().length() > 0);

        return true;
    }

    /**
     * Called when a menu item is selected.
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case BACK_ID:
            finish();
            return true;
        case CLEAR_ID:
            mEditor.setText("");
            return true;
        case BEEP_ID:
            mEditor.setText("! BEEP !");
                     
         // Play a sound Use a new thread as this can take a while
            final Thread thread = new Thread(new Runnable() {
                public void run() {
                    genTone(infreqOfTone);
                    handler.post(new Runnable() {

                        public void run() {
                            playSound();
                        }
                    });
                }
            });
            thread.start();
         
         
            return true;
        case NOFLASH_ID:
            mEditor.setText("MENU - NO FLASH");
            setOn(false, null);
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A call-back for when the user presses the back button.
     */
    OnClickListener mBackListener = new OnClickListener() {
        public void onClick(View v) {
            finish();
        }
    };

    /**
     * A call-back for when the user presses the clear button.
     */
    OnClickListener mClearListener = new OnClickListener() {
        public void onClick(View v) {
        mEditor.setText("");
        mChronometer.setBase(SystemClock.elapsedRealtime());
        mImage.setImageDrawable(getWallpaper());
        mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
        }
    };
 
    /**
     * A call-back for when the user presses the flash button.
     */
    OnClickListener mFlashListener = new OnClickListener() {
        public void onClick(View v) {
        setOn(true, null);
        mChronometer.start();
            mEditor.setText("*FLASH*");  
            mImage.setImageResource(R.drawable.scifiarmy_small);
            mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
            if(mCheckBox.isChecked() ) {
            //get the value entered by the user
            try {
            infreqOfTone = Double.parseDouble(mFreq.getText().toString());
            } catch(NumberFormatException nfe) {
            infreqOfTone = 440.0;
            Log.e(TAG, "bad frequency input", nfe);
            }
            mEditor.setText(Double.toString(infreqOfTone));
           
        // Play a sound Use a new thread as this can take a while
           final Thread thread = new Thread(new Runnable() {
               public void run() {
                   genTone(infreqOfTone);
                   handler.post(new Runnable() {

                       public void run() {
                           try {
                        playSound();
                           }
                           catch (Exception e) {
                            Log.e(TAG, "playSound problem", e);
                         
                           }
                       }
                   });
               }
           });
         
           thread.start();
                     
         
            } //if checked
        }
    };
    /**
     * A call-back for when the user presses the no flash button.
     */
    OnClickListener mNoFlashListener = new OnClickListener() {
        public void onClick(View v) {
        setOn(false, null);
        mChronometer.stop();
            mEditor.setText("It is DARK");
            mImage.setImageResource(R.drawable.thorsmall);
            mTextView.setText(Long.toString(SystemClock.elapsedRealtime() - mChronometer.getBase()));
        }
    };
 
     
    // code largely copied from   http://www.java2s.com/Open-Source/Android/Tools/quick-settings/com/bwx/bequick/flashlight/Droid22Flashlight.java.htm
    // Controls the camera flash LED
 
    private Object mManager;

    public boolean isOn(Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method getFlashlightEnabledMethod = manager.getClass()
                        .getMethod("getFlashlightEnabled");
                return (Boolean) getFlashlightEnabledMethod
                        .invoke(manager);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
        return false;
    }

    public void setOn(boolean on, Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method setFlashlightEnabledMethod = manager.getClass()
                        .getMethod("setFlashlightEnabled",
                                boolean.class);
                setFlashlightEnabledMethod.invoke(manager, on);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
    }

    private Object getManager() {
        if (mManager == null) {
            try {
                Class<?> managerClass = Class
                        .forName("android.os.ServiceManager");
                Method methodGetService = managerClass.getMethod(
                        "getService", String.class);
                IBinder hardwareService = (IBinder) methodGetService
                        .invoke(managerClass, "hardware");

                Class<?> stubClass = Class
                        .forName("android.os.IHardwareService$Stub");
                Method asInterfaceMethod = stubClass.getMethod(
                        "asInterface", IBinder.class);
                mManager = asInterfaceMethod.invoke(stubClass,
                        hardwareService);
            } catch (Exception e) {
                Log.e(TAG, "", e);
            }
        }
        return mManager;
    }
   
    // http://stackoverflow.com/questions/2413426/playing-an-arbitrary-tone-with-android
    // functions for tone generation
    void genTone(double freqOfTone){
        // fill out the array
        for (int i = 0; i < numSamples; ++i) {
            sample[i] = Math.sin(2 * Math.PI * i / (sampleRate/freqOfTone));
        }

        // convert to 16 bit pcm sound array
        // assumes the sample buffer is normalised.
        int idx = 0;
        for (double dVal : sample) {
            // scale to maximum amplitude
            short val = (short) ((dVal * 32767));
            // in 16 bit wav PCM, first byte is the low order byte
            generatedSnd[idx++] = (byte) (val & 0x00ff);
            generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);

        }
    }

    void playSound(){
        final AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRate, AudioFormat.CHANNEL_CONFIGURATION_MONO,
                AudioFormat.ENCODING_PCM_16BIT, numSamples,
                AudioTrack.MODE_STATIC);
        audioTrack.write(generatedSnd, 0, generatedSnd.length);
        audioTrack.play();
    }
 
}

Thursday, December 29, 2011

Android application - A GUI turning on the flash

In this post the goal is to just to build a GUI with buttons that turn on and off the camera flash.  

The way I see it, there are generally two things for a hardware guy to do with an android platform.
  1. Use it as the human interface device to control something else.  Normally through USB, Bluetooth, 3G, etc.  Human pushes buttons, app sends commands to an Android.
  2. Use it as the brain for a micro controller like application, such as the portable computer for a robot.  Then use it's compute power, sensors, and network interface ability to talk to a remote user.
I'll be exploring the second type of application.  In that case I have to get the Android to talk to the outside world and control things.  It's ability to do that is somewhat limited.  It has a screen where it can display lights, patterns, etc.  It has a couple LEDs, most notably the camera flash LED.   There is a headphone jack that can be used to create waveforms up to maybe 20kHz, and finally a USB jack.   

What I'm eventually going to attempt to do is flash the LED in some sort of modulated fashion that an Arduino or other serial device can recognize and respond to.  I could use the USB port, but that requires a lot of code writing on the Arduino to decode.  Using only the LED I can send binary codes directly to the serial interface of the Arduino, with only a photo transistor for hardware.   I believe the phone may already have a light sensor because it dims the screen in response to ambient light, so communication could be two way.

Once I get the flash working, I will explore how precise the timing of the flashing can be, and what frequency I can modulate data onto it.   There are many other possibilities that I will share once I learn what the capabilities are.

First I want to use the camera flash LED, Some links I found

Stole code here, I pretty much copied out the setOn() functions verbatim and assigned them to my buttons
http://www.java2s.com/Open-Source/Android/Tools/quick-settings/com/bwx/bequick/flashlight/Droid22Flashlight.java.htm

This is the juicy bits, the rest is all the buttons and GUI that evolved from the skeleton app


// code largely copied from   http://www.java2s.com/Open-Source/Android/Tools/quick-settings/com/bwx/bequick/flashlight/Droid22Flashlight.java.htm
 
    private Object mManager;
    public boolean isOn(Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method getFlashlightEnabledMethod = manager.getClass()
                        .getMethod("getFlashlightEnabled");
                return (Boolean) getFlashlightEnabledMethod
                        .invoke(manager);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
        return false;
    }
    public void setOn(boolean on, Context context) {
        try {
            Object manager = getManager();
            if (manager != null) {
                Method setFlashlightEnabledMethod = manager.getClass()
                        .getMethod("setFlashlightEnabled",
                                boolean.class);
                setFlashlightEnabledMethod.invoke(manager, on);
            }
        } catch (Exception e) {
            Log.e(TAG, "", e);
        }
    }
    private Object getManager() {
        if (mManager == null) {
            try {
                Class<?> managerClass = Class
                        .forName("android.os.ServiceManager");
                Method methodGetService = managerClass.getMethod(
                        "getService", String.class);
                IBinder hardwareService = (IBinder) methodGetService
                        .invoke(managerClass, "hardware");
                Class<?> stubClass = Class
                        .forName("android.os.IHardwareService$Stub");
                Method asInterfaceMethod = stubClass.getMethod(
                        "asInterface", IBinder.class);
                mManager = asInterfaceMethod.invoke(stubClass,
                        hardwareService);
            } catch (Exception e) {
                Log.e(TAG, "", e);
            }
        }
        return mManager;
    }






That almost worked right off but I got an error that I needed HARDWARE_TEST or FLASHLIGHT permission was needed.

Found an example of setting permissions here:
http://android.okhelp.cz/turn-screen-on-off-android-sample-code/

Later found that the manifest GUI knows the whole list of permissions, you just click on them.
I have to update the AndroidManifest.xml to add the uses-permission statements
I added HARDWARE_TEST, CAMERA and eventually FLASHLIGHT

Also found that the phone knows what permissions you asked for in the Settings->Applications menu.  Apparently when you load an app this way it doesn't ask if you want to grant permission.  It just takes it.

W00t!  Partial Success!  The flash button on my app now turns on the camera light!   I was missing the FLASHLIGHT permissions in my manifest.  Added an off button too and played around with the GUIs to clean things up.

At this point I have done all the basic GUI things and hardware fundamentals in only a few hours work!   Anyone could do this.  My code is a kluge of the highest order, but I've demonstrated making buttons, menus, displaying text responses, showing a gif, and making the hardware do something.  Awesome.

Here is the emulator running the app, taking a picture of the phone isn't worth the effort.   I showed that in my last post, and because my phone is my camera, it involves borrowing wifey's phone.    Too bad the emulator doesn't have the flashlight.   


Next step is to explore flashing the light like a strobe, and learning what timing sources are available!






Wednesday, December 28, 2011

Getting started developing apps on Android smartphones


The smartphone is microcontroller with a bunch of juicy built in hardware, so I should be able to replicate a lot of my Arduino projects on the Android platform.    The goal of this post is to make a "Hello World" on my actual phone in my actual hand.  From there I will move on to controlling hardware in later posts. This should serve as a good way to control and interact with the widgets I build.

The future is that we will all carry a device to interface to the world.  I'm going to have to get on board.    If I succeed maybe this will encourage other hardware heads to try writing apps.  Or this will sedate me into a coma in which case my blog will stop.

I have an Android phone, because I have one, and all the Android software is free and the market is open source.    My love is for electronics and hardware, not software, and I'm never going to go full hog as a software app developer.  It's just too boring.  Also, judging from the number of apps out there, it is hard to do something everyone else already hasn't done. However I have an idea for an app that I haven't seen anyone else do yet.  That may be because the hardware can't hack it.   I'll find out.   That is for later, for now, make the phone do something.  Anything.

I attempted this once before and crashed and burned with the versions I used and had lots of mysterious errors.   Here we go again, this time I'm not trying to outsmart the default installs.  The issue I had before is that books and web sites are out of date on the releases and the buttons they describe are never as they say they are.  It takes a bit of  translation and imagination to follow instructions.

Found the basics of what to do
http://www.talkandroid.com/guides/developer/android-sdk-install-guide/#.Tvn9ttRSTU8
Of course the android.com site had the same basic info
http://developer.android.com/sdk/installing.html

Side note ... found another development program I may try that may save some code writing.  Just noting it for later.  http://www.appinventorbeta.com/about/.  I didn't try it.

Download and install the developer software
As of 12/27/2011, these were the versions I used:

Decided to use Eclipse 64 bit, downloaded here:
http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/indigo/SR1/eclipse-java-indigo-SR1-win32-x86_64.zip
Downloaded, unzipped the files and clicked on "eclipse.exe", it complains it needs Java.

Downloaded Java SE 7u2 JDK here, Windows x64
http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u2-download-1377129.html
clicked on the file and installed the development kit.
Started Eclipse again, no errors this time!

Downloaded the SDK here using the windows installer link
http://developer.android.com/sdk/index.html
It found Java and did the default install, SD manager popped up and I installed everything that looked relevant.
Making note of the install directory
C:\Program Files (x86)\Android\android-sdk

In order to install the Android development tools (ADT)
Started Eclipse -> Help -> Install Software,
Clicked on Available software sites link
Add this (from the instructions)
     https://dl-ssl.google.com/android/eclipse/
Click on it, close the sites list and wait for the list to load
check the box for "Developer Tools",  in the list (Expand and you see android) then Next
Restarted Eclipse as required




Next set up the launch configuration to say what device I'm emulating.  
I'm using a Motorola Droid2 global with the gingerbread 2.3.3 update, full specs are here:
480 x 854 pixels
Went  to the Window->AVD Manager and made a moto droid 2 target using the specs, filled out form an hit Create AVD
Shouldn't have put in an 8Gb SD card, that took forever to create.  Oh well.
In EclipseRun->Run Configurations Select Android Application from the list and press the cleverly disguised New button in the upper leftBrowse for your recently created projectEnter a name for the configuration.  I chose "moto droid2"Poked around on the Target tab , hit Run

Created project from "SkeletonApp" sample project
File->Create Project->Android Application
Then Run.  Boom.   Error.
"Your project contains errors"  R cannot be resolved to a variable.  
What is going on?
Found this
Wasn't the problem.  Looked some more.

I did everything on this page, and after the last one, my Hello Android project finally ran.  W00t!
I reordered the build path under Project Properties so that gen was above source.  Geez, that was the answer.


Ran the emulator and ran an app
Hit Run.  The emulator pops up, says Android for a while, and then eventually launches the sample app.  Whew.


I edited the java variables to change Hello to Siliconfish, renamed it Siliconfish App and ran it again.  Success.  If only a tiny one.   Here you see the text changed, and the application name is Siliconfish app on both the app and the menu screen.   I'm in business!







Get the Hardware set up to use the real phone


Now the next step is to upload it to the phone and prove I can write a app.  Back to some web surfing.

1) Set up the phone for development mode
http://stackoverflow.com/questions/2664425/how-to-test-my-app-on-my-phone-i-have-eclipse-w-android-plug-in  tells me:
 If you have eclipse with the Android plug-in, all you need to do is go into the settings of the phone (the actual phone in your hand), then applications, then development. Set the Debug mode to on. when you compile the app with eclipse I guess it looks for an actual phone first, if it detects it, then it loads the app on it. If no phone is detected and you have the ADV set up right it loads it there. Easy... 
When you select "run" from eclipse, and you have your droid plugged in, it should give you the option to select which device you want to execute the code on. Double clicking on your droid will automatically install and launch the app. You may need to enable the development settings within the Settings menu though for it to be recognized. To confirm that eclipse (really it's adb) can see your droid, launch a terminal or command prompt and type adb devices while the droid is connected. If it's listed there, you're good to go
Set up the phone for debug as it says, Still didn't work.  No sign that eclipse can see my phone plugged in via the usb cable.  I can see the phone's disk from the computer but maybe I have USB in the wrong mode. Figuring out that next.

2) Install the development USB driver on your Windows computer
More surfing...
http://developer.android.com/guide/developing/device.html
I think need to install the windows adb driver for my phone on my computer.  You need a special USB driver for developers.
http://developer.motorola.com/docstools/USB_Drivers/
Clicked on Handset USB Driver for Windows 64 bit, had to register and all that junk
Downloaded, installed  Motorola Mobile Drivers Installation 5.2.0
Rebooted

3) Verify that you can see the phone from the computer
Reading the http://developer.android.com/guide/developing/device.html site again, I got some more info on how to run "adb devices".
You can verify that your device is connected by executing adb devices from your SDK platform-tools/ directory. If connected, you'll see the device name listed as a "device."
Turns out you run this in a command window on the windows box, after you cd over to the directory where the android sdk is installed.  Ran it there.  Duh.   Here you see the command running for me.  

4) Set Eclipse to target the phone as an option
Looks like it sees the phone!  I can turn of the emulator and the other long number device stays.
However I still don't get the option to Run the program on the real device.  Turns out I had to go back to the Run->Configurations and set the target to "Manual" instead of automatic.  Now that the driver is installed I get the choice to run on the phone after I hit Run.

Here is the app running on my phone.  It was a pain to get these photos because I use my phone to take all the pictures in this blog.   So I won't be photographing the phone very much ;-).    You can see the app running with the mysterious "Siliconfish there, you Activity" message.


Here is the app showing up on the menu, in the middle right is "Siliconfish App".


I'll save publishing to the Android market until I have something that is worth sharing.  But here I have shown  how you can make an app for free and put it on your phone in about 6-8 hours of web surfing.  Granted I did not program anything, just changed a word or two in a sample program, but this is sure to impress your friends anyway.   It took me two tries, this was the second.  On the first I never got to the point of launching the emulator because I had so many mysterious errors due to bad versions and botched installations.  Just go with the defaults and you will be fine.

The next post goal will be to develop a "Blink" application that flashes a light on the phone.  Blink is the "Hello World" of the hardware engineer.







Monday, December 26, 2011

Shopping cart locking boots???



Today I was shopping at a grocery store I don't usually go to.  I parked at the far edge of the lot because I had to go to another store first.   When I came out I pushed my cart out to my car, and about 10 yards before I got to my car, I heard a clunk and one of the wheels of my cart wouldn't roll.  The cart was full of groceries and I had to pick up the front of the cart and drag it.  Pretty annoying.  I thought I got something stuck in it until I stopped and bent down to see what was wrong.

I discovered the cart actually had a locking boot!! It had activated because it decided I had taken the cart too far from home.   I looked around to see if there was a radio transmitter in the store or some sort of invisible fence. I saw one of those wire strips embedded in the surface of the road, like a traffic light sensor, running across the parking lot.   Would have been nice if they put it at the edge of the lot instead of halfway across the plaza.

The cart wheel looked about like this picture.




















I found several articles from people who had figured out how to defeat and or trick carts into locking.
Now I have absolutely no interest in stealing a shopping cart, or making other peoples carts lock.  I was just surprised that stores go to such lengths to annoy their customers.  I'm not going to bother building anything to mess with these things, I'm just gonna post some links on how they work and where people have hacked them.   At the very least I learned that it is possible to lift the cart over the metal strip and possibly prevent it from locking next time I go to this store.

Look at these for some fun and subversion: