Taco Interactive Daydream

Earlier On

There were couple of programming environments I used during the 80s. Atari BASIC, Commodore 128 BASIC, Commodore 64 BASIC were common. There were also the weird assemblers that I first typed out of Ahoy! magazine, and then used to validate other programs that were just long lists of hex values. And then there was a curious program called Garry Kitchen's Gamemaker.

This was a very early approach to making programming a visual experience. It was used to make simple games utilizing a limited yet versatile set of tools. There a number of similar types of applications that are currently gaining popularity. The programs that Gamemaker created were large and sometimes buggy, but it was fun and very easy to use.

This daydream that I've created reminds me of these old silly programs. Touch on the taco to increment the counter and reset the position of the taco. That's it. Just a minor distraction while your phone is charging. If you choose not to interact with it, you'll just see tacos drifting through the sky. That's a great thing to see any day.

The Project

The code is very similar to the Elusive Red Dot daydream. Instead of having one ImageView, I used four and each has its own animator. I also added a ClickListener to the taco, which then increments a counter and resets the position.

Download

This daydream is available on GooglePlay and can be installed through the website or via the Play Store app on your phone or tablet.

Get it on Google Play

ElusiveDot

If you own a cat, you probably own a laser pointer. Endless entertainment can be found by watching your cat chase around a speck of light.

Now you can experience laser pointer excitement every time you charge your Android phone.

Android Daydreams

Daydreams are basically screensavers that run while your phone is charging. They provide a bit of visual entertainment while your phone is idle.

Code

AnimatorListenerAdapter

    private final AnimatorListener mAnimListener = new AnimatorListenerAdapter() {

        @Override
        public void onAnimationEnd(Animator animation) {
            // Start animation again
            try {
                elusiveDotAnimation();
            } catch(Exception e) {
                Log.e(TAG, e.getMessage());
            }
        }

    };

onAttachedToWindow

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();

        //read preferences
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        boolean prefInteractive = prefs.getBoolean(getString(R.string.pref_dream_interactive_key), false);
        boolean prefFullscreen = prefs.getBoolean(getString(R.string.pref_dream_fullscreen_key), false);

        // set screen preferences
        setInteractive(prefInteractive);
        setFullscreen(prefFullscreen);

        // Set the content view, just like you would with an Activity.
        setContentView(R.layout.dot_daydream);

        //red_dot
        mImageView = (ImageView)findViewById(R.id.dream_image);
        mImageView.setImageResource(R.drawable.reddot);
    }

elusiveDotAnimation

    private void elusiveDotAnimation() {
        // Refresh Size of Window
        getWindowManager().getDefaultDisplay().getSize(mPointSize);

        final int windowWidth = mPointSize.x;
        final int windowHeight = mPointSize.y;

        // Move ImageView to random y value
        mImageView.setTranslationX(mLastX);
        mImageView.setTranslationY(mLastY);

        //get new random positions
        int xRange = windowWidth - mImageView.getWidth();
        int yRange = windowHeight - mImageView.getHeight();
        mLastX = randInt(0, xRange);
        mLastY = randInt(0, yRange);

        // Create an Animator and keep a reference to it
        int randDuration = randInt(200, 1500);
        mAnimator = mImageView.animate()
                .translationX(mLastX)
                .translationY(mLastY)
                .setDuration(randDuration)
                .setListener(mAnimListener)
                .setInterpolator(sInterpolator);

        // Start the animation
        mAnimator.start();
    }

Download

Get it on Google Play

Screensaver Revival

Screensaver Projects

In the 1990s, my father obtained an Apple Mac 8100/80 for his screenprinting business. Compared to the Windows Pcs of the time, the thing was an absolute beast. Photoshop and Illustrator will still unknown to Windows users, knowing only of PaintshopPro and CorelDraw.

With this computing power, came opportunities for fun. Third party control panels were the source of all kinds of absurd desktop distractions. In my opinion, the most entertaining of these was the AfterDark series of screensavers. They were fairly expensive but damn were they ever entertaining.

Back in the 1990s, I created a number of little applications and screensaver hacks. I've decided to revisit them, and port some of them to Android.

Android Daydreams

The Android platform has a number of under-utilized features, some. One of these is the Daydream functionality, which is located under your Display Settings. In essence, a Daydream or DreamService is a screensaver. They can vary in complexity and even allow for some levels of user interaction. They're most practical to use while charging so that they don't chew up your battery.

From DOS To Android

The first place I decided to start wasn't an actual screensaver, it was a simple DOS application that I wrote in Pascal called “Bob's” Aphorisms. All it did was read a text file and output a random line from it. It was designed to display while starting up, adding a line to the AUTOEXEC.BAT.

At the core of the application was a text file. I didn't actually create this file, it was assembled by another developer who created a 68K series Macintosh version, who went by the name Dad.

The Tools

I wish I still had the Pascal source to post here. On Ubuntu, I used Android Studio for development. I've used Eclipse in the past and in college but I really like the simplified approach to this specialized IDE.

AndroidStudio also has a simple template to create a basic Daydream. This was an excellent starting point.

Application Pieces

MainActivity.java

This is just the default activity, with the default name. Presently, it only contains a button to update the settings.

//set button handler

        //set button handler
        Button btnOpenSettings = (Button)findViewById(R.id.btnOpenSettings);
        btnOpenSettings.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {

                startActivityForResult(new Intent(Settings.ACTION_DREAM_SETTINGS), 0);
            }
        });

Aphorism.java

 

“An aphorism is a terse saying, expressing a general truth, principle, or astute observation, and spoken or written in a laconic (concise) and memorable form.”

-- http://en.wikipedia.org/wiki/Aphorism

 

As usual in object oriented programming, I needed to create an object to represent the aphorism.

 

public class Aphorism {
    private long aphorismId;
    private String title;

    public Aphorism() {
    }

    public Aphorism(String title) {
        this.title = title;
    }

    public Aphorism(long aphorismId, String title) {
        this.aphorismId = aphorismId;
        this.title = title;
    }

    public long getAphorismId() {
        return aphorismId;
    }

    public void setAphorismId(long aphorismId) {
        this.aphorismId = aphorismId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

}

 

ReadData.java

 

This helped to create an ArrayList of Aphorisms. I used the exact same file as the Pascal application. After reading up on where to put resources, I decided that /res/raw was a pretty good location. Using openRawResource() I was able to open the file without much messing around. I then used a BufferedReader to iterate through the text file.

 

public class ReadDataFile {
    public static ArrayList<Aphorism> ReadFile(Context ctx) {
        InputStream inputStream = ctx.getResources().openRawResource(R.raw.aphorism);
        ArrayList<Aphorism> aphorisms = new ArrayList<Aphorism>();

        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));

        try {
            String line = "";
            int lineNum = 1;
            do {
                line = reader.readLine();
                Aphorism item = new Aphorism(lineNum, line);
                aphorisms.add(item);

                lineNum++;
            } while (line != null);

            inputStream.close();
            reader.close();
       } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return aphorisms;
    }
}

AphorismDaydreamService.java

 

Letting AndroidStudio create this for you will get you going quickly. You can create a simple scrolling TextView that displays a preset message. I changed the direction it was scrolling, adjusted the width dynamically and read a random entry from the database. I kept about half of the code that was automatically created.

 

    private void startTextViewScrollAnimation() {
        String aphorismText = getTextFromPreferences();
        Aphorism aphorism = new Aphorism();

        try {
            db.open();
            Cursor c = db.fetchRandomAphorism();
            c.moveToFirst();

            //set aphorism text
            String title = c.getString(c.getColumnIndex("title"));
            if(title != "") {
                aphorismText = title;
            }
            db.close();
        } catch(SQLException sqlEx) {
            Log.e(TAG, sqlEx.getMessage());
        } catch(Exception ex) {
            Log.e(TAG, ex.getMessage());
        }

        mDreamTextView = (TextView) findViewById(R.id.dream_text);
        mDreamTextView.setText(aphorismText);

        mDreamTextView.measure(0, 0);
        int measuredWidth = mDreamTextView.getMeasuredWidth();

        // Refresh Size of Window
        getWindowManager().getDefaultDisplay().getSize(mPointSize);

        final int windowWidth = mPointSize.x;
        final int windowHeight = mPointSize.y;

        // Move TextView so it's moved all the way to the left
        mDreamTextView.setTranslationX(windowWidth);

        // Move TextView to random y value
        final int yRange = windowHeight - mDreamTextView.getHeight();
        mDreamTextView.setTranslationY(mRandom.nextInt(yRange));

        // Create an Animator and keep a reference to it
        int translationPosition = -1 * (mDreamTextView.getMeasuredWidth() + windowWidth);
        int animateDuration = aphorismText.length() * 100;
        mAnimator = mDreamTextView.animate().translationX(translationPosition)
            .setDuration(animateDuration)
            .setListener(mAnimListener)
            .setInterpolator(sInterpolator);

        // Start the animation
        mAnimator.start();
    }

Download

Get it on Google Play

You can download the Android version from the Play Store, or visit this website. WARNING: THE TEXT FILE CONTAINS LOTS OF OFFENSIVE LANGUAGE. You can still download the DOS version here

Coding in Ubuntu

I tend to make a big deal about opensource. I presented on it at PodCamp London, I develop in Android and PHP using MySQL, Apache and other open tools. I clearly talk about it constantly seeing that a friend from my lodge bought me a Linux Fish car decal. So, obviously my development environment is built on opensource.

What is Oneiric Ocelot?

Each version of Ubuntu gets better and better. I wouldn't put it on par with latest offerings from Apple and Microsoft but it's pretty damn close. While at first I resisted Ubuntu's switch to Unity, I recently decided to embrace it. Personally, my experience with the upgrade didn't have the best results and others have reported the same, so be wary. So, I backed up my files and formatted my Ubuntu partition (I still keep the VistaHome partition that came with the PC, just in case). I haven't had Ubuntu upgrade problems in years, and hopefully this doesn't happen again.

Web Development Server

A few steps need to be taken to set up your Ubuntu machine for web development. You need to install apache2, mysql and php.

Website Development Tools

Geany is my top choice for php and other web development. It provides tab-based documents and syntax-highlighting.

For MySQL development, I use the MySQL Query Browser and MySQL Administrator GUI apps, which can be easily installed via the Software Center. Personally, I prefer these two separate tools over MySQL Workbench. However, if you prefer Workbench, you can download it here.

Android Development

Eclipse has become the preferred tool for Android development. Google provides very straightforward instructions on how to set up the development environment. The key here is to resist installing Eclipse from a repository; instead, download Eclipse Classic directly from the Eclipse website.