Tuesday, 29 September 2009

Android Developers Blog: Now available: Android 1.6 NDK

Android Developers Blog: Now available: Android 1.6 NDK

Android 1.6 NDK, release 1 is available for download from the Android developer site.

To recap, the NDK is a companion to the SDK that provides tools to generate and embed native ARM machine code within your application packages. This native code has the same restrictions as the VM code, but can execute certain operations much more rapidly. This is useful if you're doing heavy computations, digital processing, or even porting existing code bases written in C or C++.

Android AnalogClock

It's very easy to add a Analog Clock in Android, Just add the code of AnalogClock in main.xml.



AnalogClock is a widget to display an analogic clock with two hands for hours and minutes.

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"
android:text="@string/hello"
/>
<AnalogClock
android:id="@+id/myAnalogClock"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>


</LinearLayout>

Wednesday, 23 September 2009

AndroidSpeech: Android can speech!

A new feature, Text-To-Speech (TTS), have been introduced in version 1.6 of the Android platform. Also known as 'speech synthesis', TTS enables Android device to 'speak' text of different languages.

it's a very simple code to make Android speech. It can speech only.

Create a Android Application, with Target platform 1.6, API Level 4. Modify the code as following.

AndroidSpeech.java
package com.exercise.AndroidSpeech;

import android.app.Activity;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;

public class AndroidSpeech extends Activity implements OnInitListener{

TextToSpeech myTTS;

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

myTTS = new TextToSpeech(this, this);
}

@Override
public void onInit(int status) {
// TODO Auto-generated method stub

String myText1 = "Hello Android!";
String myText2 = "I can speech.";
myTTS.speak(myText1, TextToSpeech.QUEUE_FLUSH, null);
myTTS.speak(myText2, TextToSpeech.QUEUE_ADD, null);
}

@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
myTTS.shutdown();
}
}




For more details of Android Text-To-Speech, refer to:
Android Developers Blog: An introduction to Text-To-Speech in Android: "We've introduced a new feature in version 1.6 of the Android platform: Text-To-Speech (TTS). Also known as 'speech synthesis', TTS enables your Android device to 'speak' text of different languages."

Eclipse Day at the Googleplex: Developing for Android with Eclipse

Xavier Ducrohet (Google)
Abstract:

Eclipse is the recommended way to develop applications for Android. The Android SDK comes with an official set of Eclipse plug-ins called the Android Development Tools (ADT). ADT provides features such as custom builders, advanced editors for Android XML files, debugging on emulators and devices, and on-device testing.

This talk will show how to use ADT alongside the Android SDK to create, debug, profile and publish Android applications.

Total running time 56:11 minutes

This video was recorded at Eclipse Day at the Googleplex.

Source>>





Tuesday, 22 September 2009

AndroidBrowser, with visible/gone URL bar

Personally, I don't like the UI in the previous exercise, which start another activity to enter URL, and passed back to open the URL. Here, I implement a URL bar, using TableLayout with visibility. It can be set between visible and gone(hide) by click on the "URL bar" option on the Menu. Such that user can enter URL on the same screen of the browser, and hide it if more room for display is wanted.



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"
>
<TableLayout
android:id="@+id/UrlEntry"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:shrinkColumns="0"
android:visibility="gone"
>
<TableRow>
<EditText
android:id="@+id/goUrl"
android:text="http://"
/>
<Button
android:id="@+id/goUrlButton"
android:text="GO"
/>
</TableRow>
</TableLayout>
<WebView android:id="@+id/mybrowser"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>

main.xml can be downloaded here.

strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, AndroidBrowser!</string>
<string name="app_name">Android Browser</string>

<string name="str_about_message">Android Browser</string>

<string name="str_exit_message">Exit?</string>
<string name="str_ok">OK</string>
<string name="str_no">No</string>
<string name="str_URL">URL:</string>

<string name="str_URLbar">URL bar</string>
<string name="str_About">About</string>
<string name="str_Exit">Exit</string>
<string name="str_Backward"><<</string>
<string name="str_Reload">Reload</string>
<string name="str_Forward">>></string>

</resources>

strings.xml can be downloaded here.

package com.exercise.AndroidBrowser;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TableLayout;

public class AndroidBrowser extends Activity {

final int MENU_VISIBILITY = 0;
final int MENU_ABOUT = 1;
final int MENU_EXIT = 2;
final int MENU_BACKFORD = 3;
final int MENU_RELOAD = 4;
final int MENU_FORWARD = 5;

WebView myBrowser;
TableLayout myUrlBar;
EditText gotoUrl;
Button myUrlButton;

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

String myURL = "http://www.google.com";
myBrowser=(WebView)findViewById(R.id.mybrowser);

myUrlBar = (TableLayout)findViewById(R.id.UrlEntry);
gotoUrl = (EditText)findViewById(R.id.goUrl);
myUrlButton = (Button)findViewById(R.id.goUrlButton);
myUrlButton.setOnClickListener(myUrlButtonOnClickListener);

/*By default Javascript is turned off,
* it can be enabled by this line.
*/
myBrowser.getSettings().setJavaScriptEnabled(true);
myBrowser.setWebViewClient(new WebViewClient());

myBrowser.loadUrl(myURL);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(0, MENU_VISIBILITY, 0, R.string.str_URLbar);
menu.add(0, MENU_ABOUT, 0, R.string.str_About);
menu.add(0, MENU_EXIT, 0, R.string.str_Exit);
menu.add(0, MENU_BACKFORD, 0, R.string.str_Backward);
menu.add(0, MENU_RELOAD, 0, R.string.str_Reload);
menu.add(0, MENU_FORWARD, 0, R.string.str_Forward);

return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
super.onOptionsItemSelected(item);

switch(item.getItemId())
{
case MENU_VISIBILITY:
ToggleGotoVisibility();
break;
case MENU_ABOUT:
openAboutDialog();
break;
case MENU_EXIT:
openExitDialog();
break;
case MENU_BACKFORD:
if(myBrowser.canGoBack())
myBrowser.goBack();
break;
case MENU_RELOAD:
myBrowser.reload();
break;
case MENU_FORWARD:
if(myBrowser.canGoForward())
myBrowser.goForward();
break;
}
return true;
}

void ToggleGotoVisibility()
{
if (myUrlBar.getVisibility() == View.GONE)
{
myUrlBar.setVisibility(View.VISIBLE);
}
else
{
myUrlBar.setVisibility(View.GONE);
}
}

private void openAboutDialog()
{
new AlertDialog.Builder(this)
.setTitle(R.string.str_About)
.setMessage(R.string.str_about_message)
.setPositiveButton(R.string.str_ok,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialoginterface, int i)
{}
})
.show();
}

private void openExitDialog()
{
new AlertDialog.Builder(this)
.setTitle(R.string.str_Exit)
.setMessage(R.string.str_exit_message)
.setNegativeButton(R.string.str_no,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialoginterface, int i)
{}
})
.setPositiveButton(R.string.str_ok,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialoginterface, int i)
{ finish();
}
})
.show();
}

private Button.OnClickListener myUrlButtonOnClickListener
= new Button.OnClickListener()
{

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
myBrowser.loadUrl(gotoUrl.getText().toString());
}

};

}

AndroidBrowser.java can be downloaded here.

Remember to delete the files gotopanel.xml and AndroidBrowserGoto.java. And also remove "activity android:name=".AndroidBrowserGoto" from AndroidManifest.xml to resume original.

The whole project can be downloaded here.

Previous articale >> AndroidBrowser, with simple navigating functions

Sunday, 20 September 2009

AndroidBrowser, with simple navigating functions

It's the second version of the dummy AndroidBrowser; with some improvement, add some navigating functions, such as Goto URL, Forward, Backward and Reload, and also About Me and Exit.



- Enable my own browser to handle our own URL loading

If you run implemented and ran the AndroidBrowser in the previous article, you can note that the control will be passed to Android default Browser when any links is clicked. In order to make the new links is opened by our own browser, setWebViewClient() have to be called after the browser initiated.

myBrowser.setWebViewClient(new WebViewClient());

* Refer to Android's Hello, WebView example, there is another implementation with little bit difference.

- Remove TextView in main.xml to make more room for the browser.

- Override onCreateOptionsMenu() to add menu for various navigating functions

- Override onOptionsItemSelected(), and the corespond methods to handle the actual operation when the navigating functions selected.

- Implement a AndroidBrowserGoto.java class to handle Goto URL entry, it communicate with the main class, AndroidBrowser, by means of Intent and Bundle.

When GOTO menu item selected, control will be passed to AndroidBrowserGoto.java; after user input the URL and click OK, control and the target URL will be passed back to AndroidBrowser.java. So we start AndroidBrowserGoto.java using startActivityForResult(), instead of startActivity(). And also, we have to Override onActivityResult() to handle the returned data.

main.xml, layout used by AndroidBrowser.java
<?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"
>
<WebView android:id="@+id/mybrowser"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>


gotopanel.xml, layout used by AndroidBrowserGoto.java.
<?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:id="@+id/mybrowser"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Enter the URL:"
/>
<EditText
android:id="@+id/gotourl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="http://"
/>
<Button
android:id="@+id/gotoButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK"
/>
<Button
android:id="@+id/cancelgotoButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="CANCEL"
/>
</LinearLayout>


strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, AndroidBrowser!</string>
<string name="app_name">Android Browser</string>

<string name="str_about_message">Android Browser</string>

<string name="str_exit_message">Exit?</string>
<string name="str_ok">OK</string>
<string name="str_no">No</string>
<string name="str_URL">URL:</string>

<string name="str_Goto">Go to</string>
<string name="str_About">About</string>
<string name="str_Exit">Exit</string>
<string name="str_Backward"><<</string>
<string name="str_Reload">Reload</string>
<string name="str_Forward">>></string>
</resources>


AndroidBrowser.java
package com.exercise.AndroidBrowser;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class AndroidBrowser extends Activity {

final int MENU_GOTO = 0;
final int MENU_ABOUT = 1;
final int MENU_EXIT = 2;
final int MENU_BACKFORD = 3;
final int MENU_RELOAD = 4;
final int MENU_FORWARD = 5;

WebView myBrowser;

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

String myURL = "http://android-er.blogspot.com";
myBrowser=(WebView)findViewById(R.id.mybrowser);

/*By default Javascript is turned off,
* it can be enabled by this line.
*/
myBrowser.getSettings().setJavaScriptEnabled(true);
myBrowser.setWebViewClient(new WebViewClient());

myBrowser.loadUrl(myURL);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO Auto-generated method stub
menu.add(0, MENU_GOTO, 0, R.string.str_Goto);
menu.add(0, MENU_ABOUT, 0, R.string.str_About);
menu.add(0, MENU_EXIT, 0, R.string.str_Exit);
menu.add(0, MENU_BACKFORD, 0, R.string.str_Backward);
menu.add(0, MENU_RELOAD, 0, R.string.str_Reload);
menu.add(0, MENU_FORWARD, 0, R.string.str_Forward);

return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
super.onOptionsItemSelected(item);

switch(item.getItemId())
{
case MENU_GOTO:
openGotoDialog();
break;
case MENU_ABOUT:
openAboutDialog();
break;
case MENU_EXIT:
openExitDialog();
break;
case MENU_BACKFORD:
if(myBrowser.canGoBack())
myBrowser.goBack();
break;
case MENU_RELOAD:
myBrowser.reload();
break;
case MENU_FORWARD:
if(myBrowser.canGoForward())
myBrowser.goForward();
break;
}
return true;
}

private void openGotoDialog()
{
Intent intent = new Intent();
intent.setClass(AndroidBrowser.this, AndroidBrowserGoto.class);

startActivityForResult(intent, 0);

}

private void openAboutDialog()
{
new AlertDialog.Builder(this)
.setTitle(R.string.str_About)
.setMessage(R.string.str_about_message)
.setPositiveButton(R.string.str_ok,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialoginterface,
int i)
{}
})
.show();
}

private void openExitDialog()
{
new AlertDialog.Builder(this)
.setTitle(R.string.str_Exit)
.setMessage(R.string.str_exit_message)
.setNegativeButton(R.string.str_no,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialoginterface, int i)
{}
})
.setPositiveButton(R.string.str_ok,
new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialoginterface,
int i)
{ finish();
}
})
.show();
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {

// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
if (requestCode==0)
{
switch (resultCode)
{ case RESULT_OK:
String gotourl = data.getStringExtra("url");
myBrowser.loadUrl(gotourl);
break;
case RESULT_CANCELED:
break;

}

}
}
}


AndroidBrowserGoto.java
package com.exercise.AndroidBrowser;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class AndroidBrowserGoto extends Activity {

Button gotoButton, cancelButton;
EditText gotoURL;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.gotopanel);

gotoURL = (EditText) findViewById(R.id.gotourl);
gotoButton = (Button) findViewById(R.id.gotoButton);
gotoButton.setOnClickListener(gotoOnClickListener);
cancelButton = (Button) findViewById(R.id.cancelgotoButton);
cancelButton.setOnClickListener(cancelgotoOnClickListener);
}

private Button.OnClickListener gotoOnClickListener = new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent = new Intent();
Bundle bundle = new Bundle();

//bundle.putString("url", "http://www.google.com/");
String targetURL = gotoURL.getText().toString();
bundle.putString("url", targetURL);
intent.putExtras(bundle);
setResult(RESULT_OK, intent);
finish();
}
};
private Button.OnClickListener cancelgotoOnClickListener
= new Button.OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
setResult(RESULT_CANCELED);
finish();
}
};
}


Finally, add in AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidBrowser"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidBrowser"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".AndroidBrowserGoto"></activity>

</application>
<uses-sdk android:minSdkVersion="3" />

</manifest>


The whole project can be downloaded here.

Previous articale >> AndroidBrowser, implement a Android Browser using WebView
Next article >> AndroidBrowser, with visible/gone URL bar

Saturday, 19 September 2009

AndroidBrowser, implement a Android Browser using WebView

Webkit, the Android build-in web browser can be embedded in Android Application easily, just include WebView in the layout, main.xml.



Create a New Android Application:
- Project Name: AndroidBrowser
- Application Name: Android Browser
- Package Name: com.exercise.AndroidBrowser
- Create Activity: AndroidBrowser
- Min SDK Version: 3

Modify main.xml to have a WebView:
<?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"
android:text="@string/hello"
/>
<WebView android:id="@+id/mybrowser"
android:layout_width="fill_parent"

android:layout_height="fill_parent"

/>

</LinearLayout>


Modify AndroidBrowser.java
package com.exercise.AndroidBrowser;

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

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

String myURL = "http://android-er.blogspot.com";
WebView myBrowser=(WebView)findViewById(R.id.mybrowser);

/*By default Javascript is turned off,

* it can be enabled by this line.

*/

myBrowser.getSettings().setJavaScriptEnabled(true);

myBrowser.loadUrl(myURL);

}
}


You also have make change on AndroidManifest.xml, so your application can access internet:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.exercise.AndroidBrowser"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".AndroidBrowser"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

</application>
<uses-sdk android:minSdkVersion="3" />

</manifest>


Next article >>
- AndroidBrowser, with simple navigating functions
- Load local HTML webpage inside APK



TinyTSS -- All your iphone restores are belong to you

TinyTSS is a small java app that acts as your very own signature service.

When iTunes verifies your restore for your 3gs phone, it 'phones home' to see if you are allowed to restore to the version you are requesting. With TinyTSS + the shsh blob file(s) you obtained with Umbrella, you will be able to restore to the version of those shsh files forever!

People may wonder why I did this when Saurik is already doing the same thing. I'll explain my philosophy. I admire Saurik for what he has done and I thank him for pointing me in this direction. I simply think that I would rather have my shsh blobs on my personal machine AND on his server for safe keeping. This way if something happens to cydia, I can still restore my phone to the version I want to restore to.

Plus I have the peace of mind knowing that my files are safely in my possession. I don't have to worry that some catastrophic event could render my downgrades impossible.

So use cydia's shsh storage feature! But use Umbrella and TinyTSS if you are a power user that wants control over your own ecid shsh files and want to be able to use your own machine for restores.

I've fixed a bug that I introduced accidentally. I had forgotten to add a library or two to the Manifest so it wasn't able to run from the jar.

UPDATE: I've revamped the readme file. It should be a bit more informative. Also removed an error on JRE 1.5 on Leopard

UPDATE: You can follow me on twitter: notcom

Download Umbrella and TinyTSS together:

If you need an md5 checker I like: Nirsoft's MD5 Checker

I've gotten quite a few questions about donations. I'll accept donations but I want it clear that I did this for fun.
If you really want to donate you can contact me at xsemaphorex (the symbol for the word "at") gmail (the dot symbol) com.

Thursday, 17 September 2009

AndroidInfo to retrieve various system info. for Android Phone

Expend from previous exercises, AndroidInfo is a integrated application to retrieve various Android information, such as OS Version, System Information, CPU Information, Screen Resolution, Memory, Disk Space.













OS: Ubuntu 9.04
Java: Sun JDK 6
Eclipse version: 3.5 Galileo
Android SDK: Android 1.6 SDK r1

Fill in the project details with the following values:

* Project name: AndroidInfo
* Application name: Hello World, AndroidInfo!
* Package name: com.exercise.AndroidInfo
* Create Activity: AndroidInfo
* Min SDK Version: 4 (using Android 1.5 SDK for trial)

It contents one main class to handle the selection of function (AndroidInfo.java), and six class for each function (AndroidInfoOSVersion.java, AndroidInfoSys.java, AndroidInfoCpu.java, AndroidInfoScreen.java, AndroidInfoMemory.java, and AndroidInfoDisk.java).
It can be download here and extract to the folder /AndroidInfo/src/com/exercise/AndroidInfo/

Two layout files, main.xml for AndroidInfo.java, and panel.xml shared by all other classes.
Download here and extract to the folder /AndroidInfo/res/layout/

also remember to include the added classes in AndroidManifest.xml
Download here and replace the original AndroidManifest.xml.

Or, The whole project can be downloaded here.
This blog exists solely to publicize the MD5 for the tool that I wrote for obtaining and saving your iPhone 3.1 shsh blobs. The tool simply performs the same challenge request that itunes does during an iphone 3gs restore. The difference is that I save the results in a single shsh file. This file will give you the ability, when used in conjunction to another tool I have, to restore back to 3.1 indefinitely -- Provided you stay at itunes 9.

UPDATE: I would recommend grabbing your shsh files again but even if you don't it doesn't matter. When TinyTSS is released, it will handle the 3 shsh files. Keep checking back for the TinyTSS release!

Since I released the source I expect some vultures to try and profit off of this. I expressly forbid it. Nothing I did was profound but I release the code under GPL.

NOTE: I have combined Umbrella and TinyTSS into a single download!

You can download it from the link posted in the TinyTSS release post!


If you need an md5 checker I like: Nirsoft's MD5 Checker

Have fun. And please beware of imposters. CHECK THE MD5/SHA1 OF THE ARCHIVE!

Note: If you have saurik's server in your /etc/hosts or %WINDOWS%/system32/drivers/etc/hosts file you will need to remove it as I do _NOT_ want people spamming his servers unnecessarily.

PS. umbrella64 REQUIRES that you have a 64bit jvm installed... dont use it if you have no idea what that means.

After much weeping and wailing and gnashing-of-teeth: The 3gs' chipid is 0x8920

Wednesday, 16 September 2009

CKEditor 3 - Rich Text Editor


Ajax Logo

This is an older post on Ajaxian, but it is new to me and well worth a look. FCKEditor has been around a long time. Its a Javascript based full featured rich text editor. Well it has been updated and renamed to CKEditor 3. Lots of new features including improved performance and a new UI. In addition, it is know accessible and includes full screen reader support.


I highly recommend checking out the demo. A lot of flexibility has been added. Very cool stuff.

An Argument for Web Applications

Ajax Logo

Ajaxian has this story on why a developer has given up on desktop apps in favor a a Web version. Definitely makes a lot of good points.

Upgrade Android SDK 1.5 to 1.6

Android SDK 1.6 is just released and available to be download.

The procedure to Install Android SDK 1.6 on Eclipse 3.5 Galileo is same as previouse version.

If you have installed Android SDK 1.5 with Eclipse already, here is the procedure to upgrade from Android 1.5 to 1.6.

Download Android 1.6 SDK, Release 1 -
from http://developer.android.com/sdk/1.6_r1/index.html, extract to any location you want.

Update your path if the SDK location changed.

Update Eclipse ADT Plugin -

Start Eclipse, Click Help >> Check For Updates.


Enable Android DDMS and Android Development Tools, click Next, then Next again to confirm.


Accept the Terms and click Finish.


And wait for Update finished, and restart Eclipse.

Update your Eclipse SDK Preferences (If your Android SDK 1.6 location changed) -

In Eclipse, ckeck Windows >> preference


Highlight Android, and Browse to the location of your SDK. Click Apply, and wait for a moment, the list of SDK will be displayed, click OK.


Create a new AVD for Android 1.6 if you want -

In Eclipse, click Window >> Android SDK and AVD Manager


Click New, Enter Name and select Target..., Create AVD.


That's!





After upgraded, you have to set your Build Path again as described in Install Android SDK on Eclipse 3.5 Galileo.

Right click you project, Build Path>>Configure Build Path...
Enable Android 1.x and click OK.

Tuesday, 15 September 2009

Android Developers Blog: Android 1.6 SDK is here

Android Developers Blog: Android 1.6 SDK is here


Android 1.6 SDK is available for download. Android 1.6, which is based on the donut branch from the Android Open Source Project, introduces a number of new features and technologies. With support for CDMA and additional screen sizes, your apps can be deployed on even more mobile networks and devices. You will have access to new technologies, including framework-level support for additional screen resolutions, like QVGA and WVGA, new telephony APIs to support CDMA, gesture APIs, a text-to-speech engine, and the ability to integrate with Quick Search Box. What's new in Android 1.6 provides a more complete overview of this platform update.

Source: Android Developers Blog: Android 1.6 SDK is here


Android 1.6 Official Video

Tuesday, 8 September 2009

Bigger Fonts for Yahoo Mail

Just wanted to give a shout out to the developers at Yahoo! mail. They increased the size of the fonts in the "new" mail interface. Yays!!!! Trying to read mail with the 8pt fonts on a 23" screen really wasn't much fun. Definitely glad I upgraded to the new UI and premium service now.

Monday, 7 September 2009

Read Android CPU info

Android CPU info. can be retrieved by reading of "/proc/cpuinfo". So, it's just a very little bit of modification on Read Android OS version.



Create a new Android Application, with the Activity named AndroidCPUinfoActivity. Modify the main.xml and AndroidCPUinfoActivity.java:

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"
android:gravity="center_horizontal"
android:text="android-er.blogspot.com"
android:autoLink="web"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Android CPU Info.:"
/>
<TextView
android:id="@+id/CPUinfo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>

Download main.xml.

AndroidCPUinfoActivity.java
package com.exercise.AndroidCPUinfo;

import java.io.IOException;
import java.io.InputStream;

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

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

TextView CPUinfo = (TextView) findViewById(R.id.CPUinfo);
CPUinfo.setText(ReadCPUinfo());

}

private String ReadCPUinfo()
{
ProcessBuilder cmd;
String result="";

try{
String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
cmd = new ProcessBuilder(args);

Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while(in.read(re) != -1){
System.out.println(new String(re));
result = result + new String(re);
}
in.close();
} catch(IOException ex){
ex.printStackTrace();
}
return result;
}
}

Download AndroidCPUinfoActivity.java.

Sunday, 6 September 2009

Read Android system info., using System.getProperty

It's another exercise to read Android system information, using system provided method getProperty.



Create a new Android Application, with the Activity named AndroidSYSinfoActivity. Modify the main.xml and AndroidSYSinfoActivity.java:
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"
android:gravity="center_horizontal"
android:text="android-er.blogspot.com"
android:autoLink="web"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Android System:"
/>
<TextView
android:id="@+id/SYSinfo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>

Download main.xml.

AndroidSYSinfoActivity.java
package com.exercise.AndroidSYSinfo;

import com.exercise.AndroidSYSinfo.R;

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

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


TextView SYSinfo = (TextView) findViewById(R.id.SYSinfo);
SYSinfo.setText(ReadSYSinfo());
}

private static StringBuffer SYSinfoBuffer;

private String ReadSYSinfo()
{
SYSinfoBuffer = new StringBuffer();

getProperty("os.name", "os.name", SYSinfoBuffer);
getProperty("os.version", "os.version", SYSinfoBuffer);

getProperty("java.vendor.url", "java.vendor.url", SYSinfoBuffer);
getProperty("java.version", "java.version", SYSinfoBuffer);
getProperty("java.class.path", "java.class.path", SYSinfoBuffer);
getProperty("java.class.version", "java.class.version", SYSinfoBuffer);
getProperty("java.vendor", "java.vendor", SYSinfoBuffer);
getProperty("java.home", "java.home", SYSinfoBuffer);

getProperty("user.name", "user.name", SYSinfoBuffer);
getProperty("user.home", "user.home", SYSinfoBuffer);
getProperty("user.dir", "user.dir", SYSinfoBuffer);

return SYSinfoBuffer.toString();
}

private void getProperty(String desc, String property, StringBuffer tBuffer)
{
tBuffer.append(desc);
tBuffer.append(" : ");
tBuffer.append(System.getProperty(property));
tBuffer.append("\n");
}
}

Download AndroidSYSinfoActivity.java.

Saturday, 5 September 2009

Read Android OS version

In this exercise, read Android OS version, using ProcessBuilder to Creates operating system processes.



Create a operating system processes, "/system/bin/cat", to retrieve "/proc/version".

If your system is running in Linux, you can try to type the command below in Terminal.
$ cat /proc/version



Actually, this exercise perform the same operation.

Create a new Android Application, with the Activity named AndroidOSinfoActivity. Modify the main.xml and AndroidOSinfoActivity.java:
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"
android:gravity="center_horizontal"
android:text="android-er.blogspot.com"
android:autoLink="web"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Android OS:"
/>
<TextView
android:id="@+id/OSinfo"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>

Download main.xml.

AndroidOSinfoActivity.java
package com.exercise.AndroidOSinfo;

import java.io.IOException;
import java.io.InputStream;

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

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

TextView OSinfo = (TextView) findViewById(R.id.OSinfo);
OSinfo.setText(ReadOSinfo());

}

private String ReadOSinfo()
{
ProcessBuilder cmd;
String result="";

try{
String[] args = {"/system/bin/cat", "/proc/version"};
cmd = new ProcessBuilder(args);

Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while(in.read(re) != -1){
System.out.println(new String(re));
result = result + new String(re);
}
in.close();
} catch(IOException ex){
ex.printStackTrace();
}
return result;
}
}

Download AndroidOSinfoActivity.java.

It's another exercise to Read Android system info., using System.getProperty.

Friday, 4 September 2009

HelloGallery, get and display the path of selected picture

Further extend from previouse exercise, HelloGallery, read picture files from SD, using File ArrayList, and File type checking for HelloGallery, the path of the selected picture will be displayed using Toast.



It involve little bit modification on onItemClick(AdapterView parent, View v, int position, long id), and also onCreate(Bundle savedInstanceState).


public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

Gallery g = (Gallery) findViewById(R.id.gallery);

final List<String> SD = ReadSDCard();
g.setAdapter(new ImageAdapter(this, SD));

g.setOnItemClickListener(new OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent,
View v, int position, long id) {
Toast.makeText(HelloGallery.this,
(CharSequence)SD.get(position),
Toast.LENGTH_LONG).show();
}
});
}

Wednesday, 2 September 2009

File type checking for HelloGallery

In the previous article, HelloGallery, read picture files from SD, using File ArrayList, the application view all files, no matter what type it is. Here, add a conditional checking for file type, by checking on the extension. Only files with extension jpg, gif and png will be added in the File ArrayList. Such change involve modification of the method ReadSDCard() only.


private List<String> ReadSDCard()
{
List<String> tFileList = new ArrayList<String>();

//It have to be matched with the directory in SDCard
File f = new File("/sdcard/pictures/");

File[] files=f.listFiles();

for(int i=0; i<files.length; i++)
{
File file = files[i];

String curFile=file.getPath();
String ext=curFile.substring(curFile.lastIndexOf(".")+1,
curFile.length()).toLowerCase();
if(ext.equals("jpg")||ext.equals("gif")||ext.equals("png"))
tFileList.add(file.getPath());
}

return tFileList;
}


Next >> HelloGallery, get and display the path of selected picture

Tuesday, 1 September 2009

HelloGallery, read picture files from SD, using File ArrayList

It extend from previous exercise, HelloGallery, using Gallery Widget, but read files from SD instead of R.drawable.



Firstly, you have to Create an SD Card to existing AVD and Copying Files to a Disk Image.

All the xml files are same as previous, just keep it no change.

Modify the HelloGallery.java:

package com.exercise.HelloGallery;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.AdapterView.OnItemClickListener;

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

Gallery g = (Gallery) findViewById(R.id.gallery);
g.setAdapter(new ImageAdapter(this, ReadSDCard()));

g.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View v, int position, long id) {
}
});
}

private List<String> ReadSDCard()
{
List<String> tFileList = new ArrayList<String>();

//It have to be matched with the directory in SDCard
File f = new File("/sdcard/pictures/");

File[] files=f.listFiles();

for(int i=0; i<files.length; i++)
{
File file = files[i];
/*It's assumed that all file in the path
are in supported type*/
tFileList.add(file.getPath());
}

return tFileList;
}

public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
private List<String> FileList;

public ImageAdapter(Context c, List<String> fList) {
mContext = c;
FileList = fList;
TypedArray a = obtainStyledAttributes(R.styleable.Theme);
mGalleryItemBackground = a.getResourceId(
R.styleable.Theme_android_galleryItemBackground,
0);
a.recycle();
}

public int getCount() {
return FileList.size();
}

public Object getItem(int position) {
return position;
}

public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView,
ViewGroup parent) {
ImageView i = new ImageView(mContext);

Bitmap bm = BitmapFactory.decodeFile(
FileList.get(position).toString());
i.setImageBitmap(bm);

i.setLayoutParams(new Gallery.LayoutParams(150, 100));
i.setScaleType(ImageView.ScaleType.FIT_XY);
i.setBackgroundResource(mGalleryItemBackground);

return i;
}
}
}


The source file, HelloGaller.java, can be downloaded here.

Next>>File type checking for HelloGallery

Related:
- HelloGallery, read picture files from SD, display in ImageView.