06 November, 2010

Tivo Series 2 Downloader

I've recently came across a utility that downloads videos from my series-2 Tivo DVR. The conversion can then be done via TivoDecode.

http://tivodownloader.sourceforge.net/

Cheers.

10 October, 2010

Hola Android -- Stage 4

Let's expand on our user interface example by incorporating an 'icon menu' on the main activity. This menu will be activated upon pressing the 'menu button'.

Unlike the incorporation of previous menus, this addition will take place exclusively in the main activity.

We start by defining the menu items in a resource layout XML file as follows:

user@River:~/HolaAndroid$ cat -n res/layout/iconmenu.xml
1    <?xml version="1.0" encoding="utf-8"?>
2    <menu xmlns:android="http://schemas.android.com/apk/res/android">
3        <item android:id="@+id/config"
4              android:title="Config" />
5        <item android:id="@+id/quit"
6              android:title="Quit" />
7    </menu>
8
user@River:~/HolaAndroid$


Next, we modify our HolaAndroid.java source to include the rendering of the menu upon pressing the menu button. We're making use of the Toast utilities to demonstrate the button press. Specifically, lines 13-14 and 57-99 were introduced to get our desired behavior.


user@River:~/HolaAndroid$ cat -n src/com/example/holaandroid/HolaAndroid.java
    1 package com.example.holaandroid;
    2 
    3 import android.app.Activity;
    4 import android.os.Bundle;
    5 import android.widget.Button;
    6 import android.view.View;
    7 import android.view.View.OnClickListener;
    8 import android.util.Log;
    9 import android.content.Intent;
   10 import android.view.Menu;
   11 import android.view.MenuItem;
   12 import android.view.MenuInflater;
   13 import android.widget.Toast;
   14 import android.view.Gravity;
   15 
   16 
   17 public class HolaAndroid extends Activity
   18 {
   19     private static final String ClassName = "HolaAndroid";
   20     private Button b1_;
   21     private Button b2_;
   22 
   23     /** Called when the activity is first created. */
   24     @Override
   25     public void onCreate(Bundle savedInstanceState)
   26     {
   27         final String MethodName = "onStart";
   28 
   29         super.onCreate(savedInstanceState);
   30         setContentView(R.layout.main);
   31 
   32         b1_ = (Button)this.findViewById(R.id.button1);
   33         b1_.setOnClickListener(new OnClickListener() {
   34                 public void onClick (View v){
   35                   Log.d(ClassName+"::"+MethodName, "entry");
   36                   finish();
   37                 }
   38             });
   39         b2_ = (Button)this.findViewById(R.id.button2);
   40         b2_.setOnClickListener(new OnClickListener() {
   41                 public void onClick (View v){
   42                   Log.d(ClassName+"::"+MethodName, "entry");
   43                   createMenu2();
   44                   Log.d(ClassName+"::"+MethodName, "entry");
   45                 }
   46             });
   47     }
   48     private static final int ACTIVITY_CREATE=0;
   49     private void createMenu2() {
   50       final String MethodName = "createMenu2";
   51       Log.d(ClassName+"::"+MethodName, "entry");
   52       Intent i = new Intent(this, Menu2.class);
   53       startActivityForResult(i, ACTIVITY_CREATE);
   54       Log.d(ClassName+"::"+MethodName, "exit");
   55     }
   56 
   57     @Override
   58     public boolean onCreateOptionsMenu(Menu menu)
   59     {
   60         final String MethodName = "onCreateOptionsMenu";
   61         Log.d(ClassName+"::"+MethodName, "entry");
   62         MenuInflater inflater = getMenuInflater();
   63         inflater.inflate(R.layout.iconmenu, menu);
   64         Log.d(ClassName+"::"+MethodName, "exit");
   65         return true;
   66     }
   67 
   68     @Override
   69     public boolean onOptionsItemSelected(MenuItem item)
   70     {
   71         final String MethodName = "onOptionsItemSelected";
   72         Log.d(ClassName+"::"+MethodName, "entry");
   73         boolean retVal=false;
   74         switch (item.getItemId()) {
   75           case R.id.config:
   76               retVal=true;
   77               showMsg("Config Select");
   78             break;
   79           case R.id.quit:
   80               retVal=true;
   81               showMsg("Quit Select");
   82               finish();
   83             break;
   84         default:
   85           retVal=super.onOptionsItemSelected(item);
   86         }
   87         Log.d(ClassName+"::"+MethodName, "exit");
   88         return retVal;
   89     }
   90 
   91     private void showMsg(String msg) {
   92       final String MethodName = "showMsg";
   93       Log.d(ClassName+"::"+MethodName, "entry");
   94       Toast toast = Toast.makeText(this, msg, Toast.LENGTH_LONG);
   95       toast.setGravity(Gravity.CENTER, toast.getXOffset() / 2, toast.getYOffset() / 2);
   96       toast.show();
   97       Log.d(ClassName+"::"+MethodName, "exit");
   98     }
   99 
  100 }
user@River:~/HolaAndroid$


Make it, and run it and you'll get the following result.




07 October, 2010

Hola Android -- Stage 3

So far, we've created the equivalent of a 'Hello World' application, extended the UI to include a menu button, and bound an action with the pressing of the menu button.

Let's expand our example to include a sub-menu system. First, add the additional menu button to the res/layout/main.xml file as follows:


user@River:~/HolaAndroid$ cat -n res/layout/main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<Button android:id="@+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Menu1" />
<Button android:id="@+id/button2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="Menu2" />
</LinearLayout>


Rebuilding and running and you'll get twin menu buttons, the first bound to quitting the application, the second unbound to any action.













Next, we need to bind the pressing of button 2 to an action, namely the creation and rendering of another submenu.

Let's contain the behaviors of the second menu button to a newly defined class, as follows:

user@River:~/HolaAndroid$ cat src/com/example/holaandroid/Menu2.java
package com.example.holaandroid;

import com.example.holaandroid.R;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class Menu2 extends Activity {
private Button addButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu2);
addButton = (Button)this.findViewById(R.id.m2_button1);
}
}


Easy thing to forget, but now that we're introducing a new Activity you must define it in the manifest (line 14).

$ user@River:~HolaAndroid$ cat AndroidManifest.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="com.example.holaandroid"
4 android:versionCode="1"
5 android:versionName="1.0">
6 <application android:label="@string/app_name">
7 <activity android:name=".HolaAndroid"
8 android:label="@string/app_name">
9 <intent-filter>
10 <action android:name="android.intent.action.MAIN" />
11 <category android:name="android.intent.category.LAUNCHER" />
12 </intent-filter>
13 </activity>
14 <activity android:name=".Menu2"/>
15 </application>
16 </manifest>


Since we're referencing a button in our source code, we need to have it defined in our layout xml. Create a new XML file which defines our button as follows:

user@River:~/HolaAndroid$ cat res/layout/menu2.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button android:text="M2.Button1"
android:id="@+id/m2_button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom ="true"/>
</LinearLayout>



The final main class follows, the updates include importing the newly relevant packages, creating a createMenu2() method and assigning the main menu button click to the generation of the submenu (lines 9-12, 18, 36-43 & 45-52).


user@River:~/HolaAndroid$ cat -n src/com/example/holaandroid/HolaAndroid.java
1 package com.example.holaandroid;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.widget.Button;
6 import android.view.View;
7 import android.view.View.OnClickListener;
8 import android.util.Log;
9 import android.content.Intent;
10 import android.view.Menu;
11 import android.view.MenuItem;
12 import android.view.MenuInflater;
13
14 public class HolaAndroid extends Activity
15 {
16 private static final String ClassName = "HolaAndroid";
17 private Button b1_;
18 private Button b2_;
19
20 /** Called when the activity is first created. */
21 @Override
22 public void onCreate(Bundle savedInstanceState)
23 {
24 final String MethodName = "onStart";
25
26 super.onCreate(savedInstanceState);
27 setContentView(R.layout.main);
28
29 b1_ = (Button)this.findViewById(R.id.button1);
30 b1_.setOnClickListener(new OnClickListener() {
31 public void onClick (View v){
32 Log.d(ClassName+"::"+MethodName, "entry");
33 finish();
34 }
35 });
36 b2_ = (Button)this.findViewById(R.id.button2);
37 b2_.setOnClickListener(new OnClickListener() {
38 public void onClick (View v){
39 Log.d(ClassName+"::"+MethodName, "entry");
40 createMenu2();
41 Log.d(ClassName+"::"+MethodName, "entry");
42 }
43 });
44 }
45 private static final int ACTIVITY_CREATE=0;
46 private void createMenu2() {
47 final String MethodName = "createMenu2";
48 Log.d(ClassName+"::"+MethodName, "entry");
49 Intent i = new Intent(this, Menu2.class);
50 startActivityForResult(i, ACTIVITY_CREATE);
51 Log.d(ClassName+"::"+MethodName, "exit");
52 }
53
54 }



While you're still in a similar predicament as our previous post, namely a submenu button with no action defined, you can navigate to/from the submenu using the main button and the back keypad button.

Cheers.

05 October, 2010

Hola Android -- Stage 2

Ok, so you've got your first Android application that prints 'Hello World'; nothing to write home about.

Let's expand on it a bit and make use of some of the User Interface capabilities. First though, let's remove the printing of 'Hello World'.

If you search the code you'll find no reference to our elusive string, instead it's hiding in the resources layout definition file res/layout/main.xml.

user@River:~/HolaAndroid$ cat -n res/layout/main.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7 <TextView
8 android:layout_width="fill_parent"
9 android:layout_height="wrap_content"
10 android:text="Hello World, HolaAndroid"
11 />
12 </LinearLayout>
13
user@River:~/HolaAndroid$


Removing line 10 and you'll now have an application that renders a blank screen. Rebuild and re-run and you'll get:

user@River:~/HolaAndroid$ vi res/layout/main.xml
user@River:~/HolaAndroid$ make
ant debug
Buildfile: build.xml
[setup] Android SDK Tools Revision 6
[setup] Project Target: Android 1.5
[setup] API level: 3
[setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
[setup] Importing rules file: platforms/android-3/ant/ant_rules_r2.xml

-compile-tested-if-test:

-dirs:
[echo] Creating output directories if needed...

-resource-src:
[echo] Generating R.java / Manifest.java from the resources...

-aidl:
[echo] Compiling aidl files into Java classes...

compile:
[javac] Compiling 1 source file to /home/user/HolaAndroid/bin/classes

-dex:
[echo] Converting compiled files and external libraries into /home/user/HolaAndroid/bin/classes.dex...

-package-resources:
[echo] Packaging resources
[aaptexec] Creating full resource package...

-package-debug-sign:
[apkbuilder] Creating HolaAndroid-debug-unaligned.apk and signing it with a debug key...
[apkbuilder] Using keystore: /home/user/.android/debug.keystore

debug:
[echo] Running zip align on final apk...
[echo] Debug Package: /home/user/HolaAndroid/bin/HolaAndroid-debug.apk

BUILD SUCCESSFUL
Total time: 1 second
user@River:~/HolaAndroid$ make run
adb install -r ./bin/HolaAndroid-debug.apk
97 KB/s (4342 bytes in 0.043s)
pkg: /data/local/tmp/HolaAndroid-debug.apk
Success
adb shell am start -a android.intent.action.HolaAndroid -n com.example.holaandroid/com.example.holaandroid.HolaAndroid
Starting: Intent { act=android.intent.action.HolaAndroid cmp=com.example.holaandroid/.HolaAndroid }
user@River:~/HolaAndroid$















Now, you can play with your screen design by editing the res/layout/main.xml file. Note below we've added lines 11-15 to add a button to the main window.

user@River:~/HolaAndroid$ cat -n res/layout/main.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:orientation="vertical"
4 android:layout_width="fill_parent"
5 android:layout_height="fill_parent"
6 >
7 <TextView
8 android:layout_width="fill_parent"
9 android:layout_height="wrap_content"
10 />
11 <Button android:id="@+id/button1"
12 android:layout_width="fill_parent"
13 android:layout_height="wrap_content"
14 android:layout_alignParentBottom="true"
15 android:text="Menu1" />
16 </LinearLayout>
user@River:~/HolaAndroid$


Rebuild and run and you'll get:



Alas, while you've created a button, the button has no action associated with it. Press it as you'd like you'll never get it to do anything.

So, let's make it do something. In order to tie your newly created button to an action you'll need to edit the src/com/example/holaandroid/HolaAndroid.java source. We'll add a button member, or attribute, and assign an action method to be called on the button click.

Below is our modified source code:

user@River:~/HolaAndroid$ cat -n src/com/example/holaandroid/HolaAndroid.java
1 package com.example.holaandroid;
2
3 import android.app.Activity;
4 import android.os.Bundle;
5 import android.widget.Button;
6 import android.view.View;
7 import android.view.View.OnClickListener;
8 import android.util.Log;
9
10 public class HolaAndroid extends Activity
11 {
12 private static final String ClassName = "HolaAndroid";
13 private Button b1_;
14
15 /** Called when the activity is first created. */
16 @Override
17 public void onCreate(Bundle savedInstanceState)
18 {
19 final String MethodName = "onStart";
20
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.main);
23
24 b1_ = (Button)this.findViewById(R.id.button1);
25 b1_.setOnClickListener(new OnClickListener() {
26 public void onClick (View v){
27 Log.d(ClassName+"::"+MethodName, "entry");
28 }
29 });
30 }
31 }
user@River:~/HolaAndroid$



Now, if you're running the debugger you'll notice upon button click the debugger will receive a 'D/HolaAndroid::onStart( 1525): entry' message. To make our action a bit more obvious, follow line 27 with:

..
..
25 b1_.setOnClickListener(new OnClickListener() {
26 public void onClick (View v){
27 Log.d(ClassName+"::"+MethodName, "entry");
28 finish();
29 }
30 });
..
..

Now, your application will terminate when you press the button.

03 October, 2010

Hola Android -- Stage 1

I've begun my upward journey developing Android applications for my Samsung Galaxy phone. My intention is to review some of what I've learned and follow on with posts as I learn more. I'll skip the development setup as I've documented that in previous posts.

As with every good Computer Science example, we'll begin with the infamous 'hello world'.

Our target, a simple application that prints 'hello world' to the screen. Slowly I intend on building on it with no clear final destination than playing with features as they present themselves.

Assuming you've got your Android development environment properly set up we embark by creating a new project:

user@River:~$ ./android-sdk-linux_86/tools/android create project --package com.example.holaandroid --activity HolaAndroid --target 2 --path ~/HolaAndroidCreated project directory: /home/user/HolaAndroid
Created directory /home/user/HolaAndroid/src/com/example/holaandroid
Added file /home/user/HolaAndroid/src/com/example/holaandroid/HolaAndroid.java
Created directory /home/user/HolaAndroid/res
Created directory /home/user/HolaAndroid/bin
Created directory /home/user/HolaAndroid/libs
Created directory /home/user/HolaAndroid/res/values
Added file /home/user/HolaAndroid/res/values/strings.xml
Created directory /home/user/HolaAndroid/res/layout
Added file /home/user/HolaAndroid/res/layout/main.xml
Added file /home/user/HolaAndroid/AndroidManifest.xml
Added file /home/user/HolaAndroid/build.xml
user@River:~$


Now we've got a nice clean project directory structure that looks like the following:

user@River:~$ cd HolaAndroid/
user@River:~/HolaAndroid$ find .
.
./build.xml
./bin
./default.properties
./libs
./build.properties
./AndroidManifest.xml
./local.properties
./res
./res/values
./res/values/strings.xml
./res/layout
./res/layout/main.xml
./src
./src/com
./src/com/example
./src/com/example/holaandroid
./src/com/example/holaandroid/HolaAndroid.java
user@River:~/HolaAndroid$


Since I don't utilize the Eclipse development environment (personal choice) I authored a Makefile to ease some of the routine tasks.

user@River:~/HolaAndroid$ cat Makefile
all:
ant debug

setup:
emulator -avd myAvd &
xterm -e "adb logcat" &

run:
adb install -r ./bin/HolaAndroid-debug.apk
adb shell am start -a android.intent.action.HolaAndroid -n com.example.holaandroid/com.example.holaandroid.HolaAndroid

clean:
adb shell rm data/app/com.example.holaandroid.apk
ant clean
user@River:~/HolaAndroid$


Attempting to build the application by issuing a 'make' command and you'll be met with success.

user@River:~/HolaAndroid$ make
ant debug
Buildfile: build.xml
[setup] Android SDK Tools Revision 6
[setup] Project Target: Android 1.5
[setup] API level: 3
[setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
[setup] Importing rules file: platforms/android-3/ant/ant_rules_r2.xml

-compile-tested-if-test:

-dirs:
[echo] Creating output directories if needed...
[mkdir] Created dir: /home/user/HolaAndroid/gen
[mkdir] Created dir: /home/user/HolaAndroid/bin
[mkdir] Created dir: /home/user/HolaAndroid/bin/classes

-resource-src:
[echo] Generating R.java / Manifest.java from the resources...

-aidl:
[echo] Compiling aidl files into Java classes...

compile:
[javac] Compiling 2 source files to /home/user/HolaAndroid/bin/classes

-dex:
[echo] Converting compiled files and external libraries into /home/user/HolaAndroid/bin/classes.dex...

-package-resources:
[echo] Packaging resources
[aaptexec] Creating full resource package...

-package-debug-sign:
[apkbuilder] Creating HolaAndroid-debug-unaligned.apk and signing it with a debug key...
[apkbuilder] Using keystore: /home/user/.android/debug.keystore

debug:
[echo] Running zip align on final apk...
[echo] Debug Package: /home/user/HolaAndroid/bin/HolaAndroid-debug.apk

BUILD SUCCESSFUL
Total time: 2 seconds


Running it and you'll get

user@River:~/HolaAndroid$ make run
adb install -r ./bin/HolaAndroid-debug.apk
99 KB/s (4385 bytes in 0.043s)
pkg: /data/local/tmp/HolaAndroid-debug.apk
Success
adb shell am start -a android.intent.action.HolaAndroid -n com.example.holaandroid/com.example.holaandroid.HolaAndroid
Starting: Intent { act=android.intent.action.HolaAndroid cmp=com.example.holaandroid/.HolaAndroid }
user@River:~/HolaAndroid$




Just about every Android introduction tutorial demonstrates this, but now you've got another.

Cheers.

14 September, 2010

Journey of Android Development -- Installed on Phone

After 'cutting my teeth' with the emulator I embarked on installing my simple app on my phone.

A couple setup steps that are worth mentioning for my Samsung Galaxy.

First, you need to enable the USB debugging on the phone. This is done by enabling Settings->Applications->Development->USB debugging

By default, the usb connection is only accessible by the root user. You can leave it in this mode, but the consequence is that you'll have to start the adb server as root to attain the permissions to connect to the phone.

$ sudo adb kill-server
$ sudo adb start-server


After you've done this you'll be able to list and connect to the phone as a general user.

$ adb devices
List of devices attached
T9592dbc8xxx device


Now, you're able to connect to your phone in the same manner as the emulator.

Cheers.

13 September, 2010

Journey of Android Development -- First Emulator App

Still trying to get the feel for the development environment. Much of this is likely fully integrated with Eclipse, but Eclipse is historically a resource hog. 'sides, I more of a command line kinda guy.

I authored my very first application that entails multiple buttons and debug logging. The app simply creates three buttons, registers a click handler for each and demonstrates the ability to log to the adb logfile stream.

Feel free to download it here.


You may also find the Makefile useful, which supports:
1) setting up the environment (ie. starting AVD and logcat utility)
2) rebuilding the project
3) reinstalling and remotely starting the app on the emulator
4) cleanup

The project assumes you've greated an AVD called myAVD.

Cheers.

12 September, 2010

Journey of Android Development -- Running Apps vi Adb Command Line

Ok, so you're developing the next killer app for Android. If you're anything like me, and pray you aren't, you may find you want to start your app from your development machine via the emulator.

I posted how you can install, reinstall, and uninstall your app in previous posts. This post builds on that.

Issuing an 'adb shell' command essentially executes a shell command on the emulator. If you issue a command you'll execute the command rather than enter an interactive shell.

The Activity/Intent Manager/Messenger tool allows you to start your activity through the adb command line.

The trick is to define the command arguments properly, which is done by pulling relevant information from your AndroidManifest.xml file. You need to specify the proper action and component in your command line, extracted from your Android Manifest.

Given the following AndroidManifest.xml file:

user@debian:~/Buttons$ cat -n AndroidManifest.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3 package="com.example.buttons"
4 android:versionCode="1"
5 android:versionName="1.0">
6 <application android:label="@string/app_name">
7 <activity android:name=".Buttons"
8 android:label="@string/app_name">
9 <intent-filter>
10 <action android:name="android.intent.action.MAIN" />
11 <category android:name="android.intent.category.LAUNCHER" />
12 </intent-filter>
13 </activity>
14 </application>
15 </manifest>


The action is defined in line 10, the component defined as lines 3+7 respectively.

You can start the 'Buttons' activity by specifying the following command:

adb shell am start -a android.intent.action.MAIN -n com.example.buttons/com.example.buttons.Buttons

11 September, 2010

Journey of Android Development -- Install/Reinstall/Uninstall Apps

As I've mentioned in previous posts, I'm starting along a journey of developing applications for the Android phone. I figure I'll likely post some of my findings along the way for your amusement.

The first thing I was kinda surprised at was the fact that the Android Emulators are persistent, meaning that if you install an application it persists through emulator power cycle. Sure, sure it's certainly understandable that they are attempting to emulate a true phone which persists through power cycle but I was surprised this was the default behavior.

The relevance is that in the fashion of incremental development you'll find yourself coding a little, testing a little,... That manner requires you to install your app numerous times for testing. You'll quickly find that you need to uninstall the previous version to install the latest.

You install your app by applying a command similar to the following:

user@debian:~/Buttons$ adb -s emulator-5554 install ./bin/Buttons-debug.apk
98 KB/s (4384 bytes in 0.043s)
pkg: /data/local/tmp/Buttons-debug.apk
Success


An attempt to reinstall will fail due to the application already existing.

user@debian:~/Buttons$ adb -s emulator-5554 install ./bin/Buttons-debug.apk
98 KB/s (4384 bytes in 0.043s)
pkg: /data/local/tmp/Buttons-debug.apk
Failure [INSTALL_FAILED_ALREADY_EXISTS]


You can remedy that by forcing an overwrite.

user@debian:~/Buttons$ adb -s emulator-5554 install -r ./bin/Buttons-debug.apk
95 KB/s (4384 bytes in 0.044s)
pkg: /data/local/tmp/Buttons-debug.apk
Success


Alternatively, you can remove the application explicitly

user@debian:~/Buttons$ adb shell rm data/app/com.example.buttons.apk

08 September, 2010

Installing Windows XP Unattended with VirtualBox

If you're like me you find that you may wish to experiment with clean installations of WinXp VMs from time to time. Sometimes you wish to modify the VM settings that must be assigned prior to OS installation. Sometimes you just want a clean slate to start from. And other times you've got nothing else to do and "God help you" you just plain love installing operating systems in your spare time. Well, if any of this is true and you'd like to know how to install without baby-sitting this post is for you.

The overall intent is that you can install Xp unattended if you properly populate an answer file on a floppy disk. The installation pulls the specifications from the answer file (winnt.sif).

Step 1 – Creating a Virtual Floppy Disk
user@xion:~$ dd bs=512 count=2880 if=/dev/zero of=~/.VirtualBox/HardDisks/floppy01.img
user@xion:~$ /sbin/mkfs.msdos ~/.VirtualBox/HardDisks/floppy01.img
You may need to install dosfstools package.

http://untitledfinale.wordpress.com/2007/10/09/create-mount-and-copy-floppy-disks-images-under-linux/

Step 2 – Create the Virtual Machine
user@xion:~$ VBoxManage createvm --name AutoInstallXp --register --ostype "WindowsXP"

user@xion:~$ VBoxManage modifyvm AutoInstallXp --memory 1024 --vram 16 --boot1 dvd --boot2 floppy --boot3 disk


Step 3 – Create Hard Drive
user@xion:~$ VBoxManage createhd --filename AutoInstallXp.vdi --size 10240
user@xion:~$ VBoxManage openmedium disk AutoInstallXp.vdi

Step 4 – Attach Hard Disk
user@xion:~$ VBoxManage storagectl AutoInstallXp --add ide --name "Storage Controller"

user@xion:~$ VBoxManage storageattach AutoInstallXp --storagectl "Storage Controller" --port 0 --device 0 --type hdd --medium AutoInstallXp.vdi

user@xion:~$ VBoxManage storageattach AutoInstallXp --storagectl "Storage Controller" --port 0 --device 1 --type dvddrive --medium HardDisks/WinXpInstall.iso

Step 5 – Add Floppy Disk
user@xion:~$ VBoxManage storagectl AutoInstallXp --add floppy --name "Floppy Controller"

user@xion:~$ VBoxManage storageattach AutoInstallXp --storagectl "Floppy Controller" --port 0 --device 0 --type fdd --medium ~/.VirtualBox/HardDisks/floppy01.img

Step 6 – Populate Unattended Answer File
Copy the example answer file to the floppy image and update the ProductKey field value. This can be done by mounting the floppy image as root and copying the contents as follows:
# mount -o loop .VirtualBox/HardDisks/floppy01.img /mnt
# cp winnt.sif /mnt
# cat /tmp/winnt.sif
;SetupMgrTag
[Data]
AutoPartition=1
MsDosInitiated="0"
UnattendedInstall="Yes"
AutomaticUpdates="Yes"

[Unattended]
UnattendMode=FullUnattended
OemSkipEula=Yes
OemPreinstall=No
TargetPath=\WINDOWS
Repartition=Yes
UnattendSwitch=Yes
AutoActivate=Yes

[GuiUnattended]
AdminPassword=*
EncryptedAdminPassword=NO
OEMSkipRegional=1
TimeZone=20
OemSkipWelcome=1

[UserData]
ProductKey=XXXXX-XXXXX-XXXXX-XXXXX-XXXXX
FullName="personal"
OrgName="nona ur business"
ComputerName=WinXp

[GuiRunOnce]
; Command0=%SystemRoot%\system32\cmd.exe

[Identification]
JoinWorkgroup=WORKGROUP

[Networking]
InstallDefaultComponents=Yes

[Display]
BitsPerPel=8
XResolution=1024
YResolution=768
Flags=0
AutoConfirm=1


Step 7 – Add CDRom
user@xion:~$ dd if=/dev/sr0 of=~/.VirtualBox/HardDisks/WinXpInstall.iso
user@xion:~$ VBoxManage openmedium dvd WinXpInstall.iso
user@xion:~$ VBoxManage storageattach AutoInstallXp --storagectl "Storage Controller" --port 0 --device 1 --type dvddrive --medium HardDisks/WinXpInstall.iso

Step 8 – Start the VM
user@xion:~$ VBoxManage startvm AutoInstallXp

05 September, 2010

Stitching Mpeg Videos Together

Start with a video stream captured from your good 'ole television and you'll likely wanna remove the commercials. This act essentially requires you to split the video, less the commercials, into segments and them stitching them back together.

Relatively easy, break into video segments (minus the commercials)


$ ffmpeg -i Desktop/Futureweapons\ -\ \'\'Maximum\ Impact\'\'\ \(Recorded\ May\ 4\,\ 2006\,\ DSC\).mpg -ss 0 -t 10 /var/tmp/out1.mpg
$ ffmpeg -i Desktop/Futureweapons\ -\ \'\'Maximum\ Impact\'\'\ \(Recorded\ May\ 4\,\ 2006\,\ DSC\).mpg -ss 10 -t 10 /var/tmp/out2.mpg


Now stitch them together, using the 'cat' utility:

$ cat /var/tmp/out1.mpg /var/tmp/out2.mpg > /var/tmp/out.mpg


Simple.

01 September, 2010

Android Development Setup -- Debian 5.0 Amd64

I've touted in previous posts that I've recently got a Samsung Galaxy phone, equipped with Android 2.1. The decision was pretty easy as I wanted an Android-based phone to develop applications for.

I'm embarking on establishing the development environment and thought it would be useful to record the steps.

I'm starting with a fresh installation of Debian 5.0 as a VirtualBox Guest. Before we delve into the Android setup I first installed the VirtualBox Additions to get better control of my mouse and keyboard. While not required directly by the Android development they're useful, but only applicable if you're running VirtualBox.

VirtualBox Additions Installation

# apt-get install gcc linux-headers-`uname -r` build-essential


Then select Devices->Install VirtualBox Additions to mount the disc image.

I've always had trouble running the installation script directly from the disc, so I have had to introduce an incremental step of copying to the file system before running.

# cp /media/cdrom0/VBoxLinuxAdditions-amd64.run /tmp
# /tmp/VBoxLinuxAdditions-amd64.run


Then reboot the system for the additions to take effect.

Now the preliminaries are complete, let's get to installing the Android development environment.

Install Sun Java
Update you're repository to utilize the non-free Sun packages.

# echo "deb http://ftp.de.debian.org/debian/ lenny main contrib non-free" >> /etc/apt/sources.list
# apt-get update
# apt-get install sun-java6-jdk sun-java6-jre


Since I'm running an AMD64 kernel I need to install the 32-bit libaries.

# apt-get install ia32-libs


Lastly, you need to ensure you're running the Sun Java utilities and not the Gcc versions. To ensure this, remove any unnecessary Gcc Java packages and ensure the symbolic links for the relevant Java utilities are pointing to the Sun packages.

# apt-get remove gcj-jdk
# update-alternatives --config javac
# update-alternatives --config java

On each of the update-alternatives ensure the selection is pointed toward the .../java-6-sun/... version. This killed me in my first attempt as the symbolic reference for the 'java' utility was pointing to '/usr/lib/jvm/java-gcj/jre/bin/java' and bad things happened (e.g. Null References when installing Android targets). Moral of the story, "check this".

Android SDK installation
Alright, we're ready to install the SDK having set up the Java environment.

Notice I'm running as a general user and will be installing in my home directory.


$ wget http://dl.google.com/android/android-sdk_r06-linux_86.tgz
$ tar -xvf ./android-sdk_r06-linux_86.tgz


Next, install the platforms by issuing the following command and selecting "SDK Platform Android 2.1 API 7, revision 1' (in my case anyway as my Galaxy is a Android 2.1 based). Then select the 'install' button. Then, exit as we'll proceed on with the command line.

user@debian:~$ ./android-sdk-linux_86/tools/android update sdk


You'll next need to create an Android Virtual Device. Note, the target 6 specifies an Android 2.1 target, applicable for my phone.

$ ./android-sdk-linux_86/tools/android create avd --target 6 --name myAvd



Create a new Android project by issuing the following command:

$ $ ./android-sdk-linux_86/tools/android create project --package com.example.helloandroid --activity HelloAndroid --target 2 --path ~/HelloAndroid


You'll find the example primed with a main routine:

user@debian:~$ cat /home/user/HelloAndroid/src/com/example/helloandroid/HelloAndroid.java
package com.example.helloandroid;

import android.app.Activity;
import android.os.Bundle;

public class HelloAndroid extends Activity
{
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}



Now you're ready to compile this no-op application and run in the emulator.

This is the point I realized that Android development requires Ant, so I installed the package.


# apt-get install ant


You'll see that a build.xml file exists, the source for the Ant build.

user@debian:~$ cd /home/user/HelloAndroid/
user@debian:~/HelloAndroid$ ls
AndroidManifest.xml build.xml local.properties
bin default.properties res
build.properties libs src


Build the target by issuing 'ant debug' from the project directory.

user@debian:~/HelloAndroid$ pwd
/home/user/HelloAndroid
user@debian:~/HelloAndroid$ ant debug


The result is an *.apk file in the bin directory; this is the executable you'll be running in the emulator.

Running in the Emulator
You're last steps are to start the AVD and install the application within it.

Start the AVD by issuing the android tool, selecting the AVD, and clicking on the start button. In a few seconds you should get a virtual phone presented on the screen.

$ /home/user/android-sdk-linux_86/tools/android


In another window/terminal, you can list the available devices by issuing the following command. You should be met with a list that includes the AVD you just started.

$ /home/user/android-sdk-linux_86/tools/adb devices


Almost there; final steps are to install your app and run it.

user@debian:~/HelloAndroid$ /home/user/android-sdk-linux_86/tools/adb -s emulator-5554 install ./bin/HelloAndroid-debug.apk


Running the application just like you would on your phone, navigate to the applications and click on it.
























As you can see, you get a 'Hello World, HelloAndroid' on the screen. Not too exciting. If you're interested, and you should be, you'll find the text reference in the ~/HelloAndroid/res/layout/main.xml file.

Keep your stick on the ice.

Ellusive 'Error: java.lang.NullPointerException' for Android Development Installation

I just spent some time debugging why my android development setup was failing on Debian 5.0

I repeatedly got a "XML verification failed for https://dl-ssl.google.com/android/repository/repository.xml.Error: java.lang.NullPointerException" error.

After navigating to the referenced web site and confirmed it wasn't a web site mis-reference I consulted Google.

A couple forums elluded to updating the SDK and Java, but neither was the case for me. My problem was I failed to configure the Sun packages as the default java compiler. This is done by:

debian:/root# update-alternatives --config java

There are 3 alternatives which provide `java'.

Selection Alternative
-----------------------------------------------
1 /usr/bin/gij-4.3
*+ 2 /usr/lib/jvm/java-gcj/jre/bin/java
3 /usr/lib/jvm/java-6-sun/jre/bin/java

Press enter to keep the default[*], or type selection number: 3
Using '/usr/lib/jvm/java-6-sun/jre/bin/java' to provide 'java'.



Next issue a SDK update by issuing the 'android update sdk' command and install the targets.

The symptom of this issue was an unpopulated target list (e.g. 'android list targets' resulting in no targets available).

Kudos.

18 August, 2010

New Phone

Well ladies (and gentlmen),
I've moved into the 21st century and replaced my old cell phone with a smart phone. Really wasn't too much of a question when selecting as my criteria was an Android-based phone. Settled in on the Samsung Galaxy and couldn't be much happier. The only issue I've noticed is the wireless doesn't work for 802.11N and haven't had a chance to get it to connect to our wireless router at home.

Anyway....I figured I'd play with converting videos for the phone, the intent of this post. As always, FFMpeg is our tool:


$ ffmpeg -i ./Tosh-001.mpg -s qcif -vcodec h263 -ac 1 -ar 8000 -r 25 -ab 12.2k -y outputfile.3gp


Mount the phone, copy in the output file, unmount and play through the gallery. Easy-peezy.

16 July, 2010

Easing System Setup with Debian Packages

Seems like every 6 months or so I feel like reinstalling Linux on my workstation. Not because I need to, but more because I want to.

Seems as my interests wander I find the need to install loads of packages for temporary tasks, once accomplished I want to remove them. Unfortunately, I don't keep track of the packages and as a result start a-fresh periodically.

I do it often enough that it doesn't take too much time. Much of it is just the identification and reinstallation of packages I regularly use.

Authoring a system installation package that identifies all my essential packages as a dependency seems as it would minimize this effort dramatically. Since packages can define dependencies and installing it can auto-resolve and install the required dependencies seems like if we authored a faux package with dependencies on the packages I want installed we'd be right on mark.

Let's start;

Start by creating a directory.

$ mkdir ~/myPackage


Next, create the necessary control file which will identify the dependencies.

$ mkdir ~/myPackage/DEBIAN
$ edit ~/myPackage/DEBIAN/control

Populate ~/myPackage/DEBIAN/control with the following:
Package: MyPackage
Version: 1.0
Section: web
Priority: optional
Architecture: all
Essential: no
Depends: gnuplot, tcl
Pre-Depends: gnuplot
Recommends:
Suggests:
Installed-Size: 1024
Maintainer: Joe Brockmeier [jzb@dissociatedpress.net]
Conflicts: wile-e-coyote
Replaces: sam-sheepdog
Provides: acme
Description: The description can contain free-form text
describing the function of the program, what
kind of features it has, and so on.

Pay special attention to the Depends: field, it's populated with tcl and gnuplot. That means, when we install this package we ask that these dependencies are installed as well.

Next, create the package by executing the following command:

$ dpkg -b ~/myPackage /tmp/myPackage.deb


All set, now just install the package as root and you'll achieve an indirect installation of the dependencies.


# gdebi /tmp/myPackage.deb


Cheers.

24 May, 2010

WindowsXp Search Command Line

I've recently needed to search a suite of Windows Xp machines in search of files with particular extensions. Since I intended on piping the results to a text file for review Windows Explorer wouldn't suit my needs. The 'find' command wasn't the proper tool for the job either as it is used for finding text strings in files.

I found good-ole 'dir' was the man for the job.


c:\ dir c:\ *.exe /s


This command will recursively search from C: for files matching '*.exe'.

That'll do donkey, that'll do.

06 May, 2010

Installing WindowMaker on Debian

Real short, but it took me a bit of searching to find how to replace Gnome as my window manager.

Start by installing the WindowMaker package:

# apt-get install wmaker


Next, as the user that you wish to run WindowMaker as the window manager:

$ echo "exec wmaker" >> ~/.xsession
$ echo "exec wmaker" >> ~/.xinitrc


Log off, then back on for it to take effect.

Cheers.

05 May, 2010

Querying WinXp Process Information

Deep down I've always been a Unix guy. I've grown to love the types of utilities and applications authored for Unix-like systems. Generally, they adopt flexibility that many UI-based operating environments lack. Case in point, the batch command syntax is far superior to any Windoze has or likely will offer and as a result I often struggle to find similar features available when I am working in Windows. I recently learned something I felt was worth sharing.

The 'top' utility offers just about all you would require in monitoring your system performance. While task manager in Windows offers similar information I'd never found a means to pipe the output to a file for parsing and analysis. Today I found such a mechanism.

The 'wmic' utility available on multiple forms of Windows stands for 'Windows Management Instrumentation Command' and can offer similar information (and in some cases more info) than the equivalent use of 'top'. While you can initiate queries beyond processes I'm interested in process and memory utilization at this time.

Initiating the command:

wmic process get WorkingSetSize,Caption /format:csv >> c:\resources.log

Will query the memory utilization and name of all the processes currently running on the system, format into a comma-separated vector and append to the specified file. Wrap this fella in a loop, place in your start-up folder and you've got the makings of monitoring your system through initialization.

Boo-yah.

16 April, 2010

Iso Magic

I find that over the past couple weeks I've had to generate, burn, and examine ISO images to support releasing our software product on external media. I thought it useful to share some useful mechanisms.

If you have a directory structure that you want bundled into a ISO image, issue the command:

mkisofs -o MyImage.iso -J dirName


To burn the image onto a DVD/CDROM use the following command:

cdrecord -v dev=X,X,X MyImage.iso

where X,X,X is determined by issuing the command:

cdrecord --scanbus

and selecting the appropriate device

You can examine the contents of an ISO image by mounting loopback as follows:

mount -o loop MyIsoImage.iso /mnt/iso


Issuing a 'find /mnt/iso' will show the contents of the image.

27 March, 2010

A Duck Of A Different Feather

Microsoft has been known to do things a bit different from the norm. Sometimes for no reason, sometimes to set themselves apart, sometimes because they're simply idiots.

Case in point, Windows Seven now has a "Performance Information and Tools" that'll rate the performance of your system compared to a benchmark. Below is the benchmark for my puny Acer Aspire one:




A scale from 1.0 .. 7.9......WTF?

04 January, 2010

Mplayer + FFMpeg + /dev/video

I've recently published posts for capturing video from a QuickCam Express using FFMpeg. I also posted how to play live video with MPlayer. That covers storing video or playing live video. Playing or storing video with a camera source seems mutually exclusive.

That said, what if you want to store and play live video simultaneously?

Playing live video while storing the incoming video is do-able using these tools and a first-in-first-out (FIFO).

The trick is to recognize that FFMpeg can support converting a single input file into multiple output files. For instance, you can convert a source video file into two output files as follows:


$ ffmpeg -i source.avi /tmp/output.avi /tmp/output.mpg


This command will take the source file source.avi and generate twin output files /tmp/output.avi and /tmp/output.mpg converting them simultaneously.

Similarly, you can use a video device /dev/video rather than an input video file and generate twin output files by using a similar command:


$ ffmpeg -r 15 -s 352x288 -f video4linux -i /dev/video0 /tmp/output.avi /tmp/output.mpg


While cool and closer, attempting to play the file will eventually reach the file end and terminate. Instead, by using a FIFO as an output file and using this FIFO as the input to Mplayer you've accomplished your goal.


$ mkfifo /tmp/vidPipe
$ ffmpeg -y -f video4linux -r 15 -s 352x288 -i /dev/video0 -f avi -vcodec msmpeg4 /tmp/vidPipe /tmp/output.avi


In another terminal window play the fifo with Mplayer using the following command:

$ mplayer /tmp/vidPipe


I love it when a plan comes together.

03 January, 2010

Playing QuickCam Video Stream with Mplayer

I've been toying with developing a Tk UI for multiple video sources, something like a video surveillance or situational awareness console.

I've made some notable progress embedding mplayer into multiple UI frames using precollected video source files and next needed to integration a 'live' video stream. That required determining the 'secret sauce' of arguments to get mplayer to recognize my QuickCam Express webcam....don't laugh, I've had it for years.

For those of you that are interested, the secret sauce is:

$ mplayer -fps 20 -tv driver=v4l:width=352:height=288:device=/dev/video0:outfmt=bgr24 tv://


Cheers.