2010年3月18日 星期四

Save a File

public class ReadFile extends Activity implements View.OnClickListener {

private static final String TAG = "ReadFileActivity";

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

Button readButton = (Button) findViewById(R.id.button1);
readButton.setOnClickListener(this);

Button clearButton = (Button) findViewById(R.id.clearbutton);
clearButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
TextView textArea = (TextView) findViewById(R.id.filecontent);
textArea.setText("");
}
});
}

public void onClick(View arg0) {
doReadFromFile(this);
}

private void doReadFromFile(Context context) {
InputStream istream = null;
BufferedReader br = null;
String fileContent = "", line="";

try {
istream = (InputStream) context.getResources().openRawResource(R.raw.mytext);
br = new BufferedReader(new InputStreamReader(istream));

while ( (line = br.readLine()) != null) {
fileContent += line + "\n";
}

br.close();
istream.close();
} catch (Exception e){
Log.e(TAG, "Found exception when reading file: " + e);
}
Log.i(TAG, "file content = " + fileContent );

TextView showContent = (TextView) findViewById(R.id.filecontent);
showContent.setText(fileContent);
}

}

SQLite Database Example

DBExample.java
public class DBExample extends Activity implements View.OnClickListener {

private TextView textArea1;
private EditText field1;
private EditText field2;

public static String newline = System.getProperty("line.separator");

private SQLiteDatabase db;
private static final String TAG = "DBExample";
private static final String DBNAME = "sample1";
private static final String TABLE1NAME = "table1";

private static final String CREATE_TABLE1 = "create table if not exists "
+ " table1 (id integer primary key autoincrement, "
+ " text1 text not null, text2 text not null);";

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

field1 = (EditText) findViewById(R.id.field1);
field2 = (EditText) findViewById(R.id.field2);

Button saveButton = (Button) findViewById(R.id.button1);
saveButton.setOnClickListener(this);

Button deleteButton = (Button) findViewById(R.id.delbutton);
deleteButton.setOnClickListener( new View.OnClickListener() {
public void onClick(View v) {
deleteAllRows();
}
});

Button showAllButton = (Button) findViewById(R.id.showallbutton);
showAllButton.setOnClickListener( new View.OnClickListener() {
public void onClick(View v) {
showAllValues();
}
});

textArea1 = (TextView) findViewById(R.id.textarea1);

openDatabase();
//insertRow("hello1", "db1");
}

private void openDatabase() {
try {
db = openOrCreateDatabase(DBNAME, MODE_WORLD_WRITEABLE, null);
db.execSQL(CREATE_TABLE1);
}
catch (Exception e){
Log.i(TAG, "Error opening DB or creating new DB. " + e);
}
}

private boolean insertRow(String value1, String value2) {
ContentValues values = new ContentValues();
values.put("text1", value1);
values.put("text2", value2);
return (db.insert(TABLE1NAME, null, values) > 0);
}


private boolean deleteAllRows() {
textArea1.setText("Deleted All Values in Table: "+TABLE1NAME);
return (db.delete(TABLE1NAME, "id>=0", null) > 0);
}


public List getItems() {
ArrayList dbRows = new ArrayList();
try {
Cursor c = db.query(TABLE1NAME, new String[] { "id", "text1", "text2" }, null,
null, null, null, null);

int numRows = c.getCount();
c.moveToFirst();

for (int i = 0; i < numRows; ++i) {
Table1Items item = new Table1Items();
item.id = c.getLong(0);
item.text1 = c.getString(1);
item.text2 = c.getString(2);
dbRows.add(item);
c.moveToNext();
}
} catch (Exception e) {
Log.e(TAG, "Error in getting items from db: " + e);
}
return dbRows;
}


/*
*
* clicked on button "Insert Values"
*
*/
public void onClick(View arg0) {
textArea1.setText("");
insertRow(field1.getText().toString(), field2.getText().toString());
textArea1.append("inserted: "+field1.getText() + ", " + field2.getText().toString());
field1.setText("");
field2.setText("");
}

private void showAllValues() {
textArea1.setText("");
ArrayList tableItems = (ArrayList) getItems();
for (Iterator it = tableItems.iterator(); it.hasNext(); ) {
Table1Items item = it.next();
textArea1.append(item.toString() + newline);
}
}

}

Contacts如何選擇聯繫人的頭像

程序要求:如何從相冊的列表中選擇頭象,並將其裁剪
步驟如下:
1、觸發一個單擊事件,在單擊時間中發送一個 Intent
Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
intent.setType("image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 96);
intent.putExtra("outputY", 96);
try {
intent.putExtra("return-data", true);//將是否有結果返回的標誌位改為true
startActivityForResult(intent, PHOTO_PICKED_WITH_DATA);
} catch (ActivityNotFoundException e) {
new AlertDialog.Builder(EditContactActivity.this)
.setTitle(R.string.errorDialogTitle)
.setMessage(R.string.photoPickerNotFoundText)
.setPositiveButton(android.R.string.ok, null)
.show();
}
2、重寫onActivityResult方法:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
switch (requestCode) {
case PHOTO_PICKED_WITH_DATA: {
final Bundle extras = data.getExtras();
if (extras != null) {
Bitmap photo = extras.getParcelable("data");
mPhoto = photo;
mPhotoChanged = true;
mPhotoImageView.setImageBitmap(photo);
setPhotoPresent(true);
}
break;
}
}
}
3、顯示圖片列表的Activity需要滿足:
A. 將顯示的結果保存
Intent result = new Intent(null, img.fullSizeImageUri());
if (myExtras != null && myExtras.getString("return-data") != null) {
Bitmap bitmap = img.fullSizeBitmap(1000);
if (bitmap != null)
result.putExtra("data", bitmap);
}
setResult(RESULT_OK, result);
finish();
B、設置android:name="android.intent.action.GET_CONTENT"
android:configChanges="orientation|keyboardHidden"
android:icon="@drawable/ic_launcher_gallery">
...












...

多語系模式開發

Android 多語系模式開發
Android 多語系的開發方式
1. 先將程式中的語系文字抽出至 res/values 中
2. 複製 res/values 的資料後, 重新貼上並修改成該語系所對應的目錄
3. 開啟新產生的目錄裡頭的檔案後, 將其文字內容改成該語系即可
4. 原 res/values 的目錄可以保留著, 若是系統找不到對應的語系時, 預設會讀取 res/values 目錄
5. 開發完成後, 只要變更手機裡頭的區域設定 (Local setting) 即可變更成該語系
6. 也可以在 onCreate() 中加入底下程式碼來測試不同的語系介面
Resources res = getResources();
Configuration conf = res.getConfiguration();
conf.locale = Locale.TRADITIONAL_CHINESE;//中文
DisplayMetrics dm = res.getDisplayMetrics();
res.updateConfiguration(conf, dm);
支援的語系目錄檔名對應如下:
繁體中文: values-zh-rTW
簡體中文: values-zh-rCN
日文: values-ja
英文: values-en
美式英文: values-en-rUS
英式英文: values-en-rUK

取得手機屏幕大小

Android基礎教程(四)之取得手機屏幕大小DisplayMetrics的應用

大家好,我們這一節要講的內容是Android如何取得手機屏幕大小的例子.本節主要用了三個對象TextView ,Button ,以及DisplayMetrics ,其中Displaymetrics 是取得手機屏幕大小的關鍵類,這個例子非常的簡單,當我們點擊按鈕,觸發事件,在TextView 裡顯示手機屏幕的寬高分辨率.

其中我們在res->layout->values->string.xml增加了兩行如下(黑體)


Hello World, DisplayMetricsDemo!
DisplayMetricsDemo
手機分辨率為:
按我獲分辨率

而佈局文件main.xml代碼如下:

android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:id="@+id/textview1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/resolution"
/>
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/pressme"
/>

最後是我們主類DisplaymetricsDemo.java,代碼如下:
package com.android.test;
import android.app.Activity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class DisplayMetricsDemo extends Activity {

private TextView textview1;
private Button button1;
//獲取手機屏幕分辨率的類
private DisplayMetrics dm;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

//獲取佈局中TextView,Button對像
textview1 = (TextView)findViewById(R.id.textview1);
button1 = (Button)findViewById(R.id.button1);

//增加button事件響應

button1.setonClickListener(new Button.onClickListener(){
public void onClick(View v)
{
dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
//獲得手機的寬帶和高度像素單位為px
String str = "手機屏幕分辨率為:" + dm.widthPixels
+" * "+dm.heightPixels;
textview1.setText(str);
}
});

}
}

Android數據存取之Databases

在Android平台上可以操作數據庫,這是第一次接觸Android時的驚豔之一。在Android平台上,綁定了SQLite數據庫,這個數據庫系統也是極具性格的,它的最大的應用場景是嵌入式系統,進一步瞭解可以參看這裡。
如果有JDBC的經驗,那麼在這裡會容易的多。Android中操作數據庫首先要通過一個 類:android.database.sqlite.SQLiteOpenHelper。它封裝了如何打開一個數據庫,其中當然也包含如果數據庫不存在 就創建這樣的邏輯。看一個例子:

pubilc class DatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "com.roiding.simple.note";
private static final int DATABASE_VERSION = 1;
private static final String NOTES_TABLE_NAME = "notes";
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + NOTES_TABLE_NAME
+ " (id integer primary key autoincrement, name text);");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS notes");
onCreate(db);
}
}
這裡面,如下的語句需要解釋:
super(context, DATABASE_NAME, null, DATABASE_VERSION)
數據庫連接的初始化,中間的那個null,是一個CursorFactory參數,沒有仔細研究這個參數,暫時置空吧。
public void onCreate(SQLiteDatabase db)
這裡面的onCreate是指數據庫onCreate時,而不是DatabaseHelper的onCreate。也就是說,如果已經指定 database已經存在,那麼在重新運行程序的時候,就不會執行這個方法了。要不然,豈不是每次重新啟動程序都要重新創建一次數據庫了!在這個方法中,完成了數據庫的創建工作。也就是那個execSQL()方法。
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
在程序的開發維護過程中,數據庫的結構可能會有變化,那麼這個方法就有用處了。在DatabaseHelper這個對象一創建時,就已經把參數 DATABASE_VERSION傳入,這樣,如果Android發現此版本與現有版本不一致,就會調用這個onUpgrate方法。於是,可以在這裡面實現一些數據的upgrade工作,比如說創建一個臨時表,將數據由臨時表中轉到新的表結構中。需要注意的是,這裡面的onUpgrade是在版本不一致時調用,也就是說不管當前需要的版本高於現有版本還是低於現有版本,都會出發這個方法,類似的這種情況,就需要對oldVersion和 newVersion進行判斷之後再決定使用什麼策略來更新數據。
在Android中,數據庫存放在 /data/data/PACKAGE_NAME/databases 目錄下。
接下來就可以使用這個Helper來操作數據庫了,操作數據庫也就無非是增、刪、改、查。先看一個增的例子:

public static void insert(Context context, String s) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);
String table = "notes";
String nullColumnHack = "id";
ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");
long id = mOpenHelper.getReadableDatabase().insert(table,
nullColumnHack, values);
mOpenHelper.getReadableDatabase().close();
}
DatabaseHelper mOpenHelper = new DatabaseHelper(context);
如果和JDBC例子的話,這一步貌似就像是獲得了一個Statement,用它就可以操作數據庫了。
ContentValues values = new ContentValues();
Android在向數據庫中插入數據的時候,要求數據存放到ContentValues中,這裡面的ContentValues其實就是一個 Map,Key值是字段名稱,Value值是字段的值。這樣,也許你會發現一個問題,那數據類型怎麼辦?其實在SQLite數據庫中就是沒有數據類型的, 一切都是字符串。
mOpenHelper.getReadableDatabase().insert(table,nullColumnHack, values);
將數據入庫,注意這裡面有一個nullColumnHack,看文檔是和所有字段都是空的記錄有關係,我沒有去實驗他具體的效果,只是隨便給他一個字段名稱。
再看一個查的例子:

public static void select(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);
String table = "notes";
String[] columns = new String[] { "id", "name" };
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String groupBy = null;
String having = null;
String orderBy = "id desc";
String limit = "1";
Cursor c = mOpenHelper.getReadableDatabase().query(table,
columns, selection, selectionArgs, groupBy, having, orderBy, limit);
c.moveToFirst();
for (int i = 0; i < c.getCount(); i++) {
String s = c.getString(1);
c.moveToNext();
}
c.close();
mOpenHelper.getReadableDatabase().close();
}
DatabaseHelper mOpenHelper = new DatabaseHelper(context);
於前文中的相同
mOpenHelper.getReadableDatabase().query();
通過mOpenHelper.getReadableDatabase(),會得到一個SQLiteDatabase類型的只讀的數據庫連接,在這裡直接調用了他的query方法。這個query方法相對複雜,因為他將一個完整的SQL語句拆成了若幹個部分:
table:表名。相當於SQL的from後面的部分。那如果是多表聯合查詢怎麼辦?那就用逗號將兩個表名分開,拼成一個字符串作為table的值。
columns:要查詢出來的列名。相當於SQL的select後面的部分。
selection:查詢條件,相當於SQL的where後面的部分,在這個語句中允許使用「?」,也就是說這個用法和JDBC中的 PreparedStatement的用法相似。
selectionArgs:對應於selection的值,selection有幾個問號,這裡就得用幾個值。兩者必須一致,否則就會有異常。
groupBy:相當於SQL的group by後面的部分
having:相當於SQL的having後面的部分
orderBy:相當於SQL的order by後面的部分,如果是倒序,或者是聯合排序,可以寫成類似這樣:String orderBy = 「id desc, name」;
limit:指定結果集的大小,它和Mysql的limit用法不太一樣,mysql可以指定從多少行開始之後取多少條,例如「limit 100,10」,但是這裡只支持一個數值。
c.moveToFirst();
這一句也比較重要,如果讀取數據之前,沒有這一句,會有異常。
c.getString(1);
與JDBC一致了,Android不支持按字段名來取值,只能用序號。
再看一個刪除和修改的例子:

public static void delete(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);
String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;
mOpenHelper.getWritableDatabase().delete(table, whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}
有了上面的基礎這裡就容易理解了,這裡的whereClause相當於前面的selection,whereArgs相當於前面的 selectionArgs。

public static void update(Context context) {
DatabaseHelper mOpenHelper = new DatabaseHelper(context);
String table = "notes";
String selection = "id>? and name<>?";
String[] selectionArgs = new String[] { "0", "roiding.com" };
String whereClause = selection;
String[] whereArgs = selectionArgs;
ContentValues values = new ContentValues();
values.put("name", "www.roiding.com");
mOpenHelper.getWritableDatabase().update(table, values,
whereClause, whereArgs);
mOpenHelper.getWritableDatabase().close();
}
這個update的用法,綜合select和delete就可以理解。
注意:
Cursor和Databases要及時關閉,不然也會有異常。
getWritableDatabase()和getReadableDatabase()在當前的Android版本中貌似可以通用,像上面的 insert,用的就是getReadableDatabase。
在真實的應用中,會對上面這些基本操作做更高一級的抽象和封裝,使之更容易使用。在select時,除了用上述的方法,將分段的SQL語句傳進去之外,Android還支持一種方法:使用SQLiteQueryBuilder。如果使用的是上述的分段SQL語句的方法,在Android的內部實現中,也是先將分段的SQL使用SQLiteQueryBuilder的靜態方法來生成一個真正的SQL的,而且,我沒有看出來使用 SQLiteQueryBuilder的優勢

Android判斷sd卡是否可寫

private static boolean checkFsWritable() {
// Create a temporary file to see whether a volume is really writeable.
// It's important not to put it in the root directory which may have a
// limit on the number of files.
String directoryName =
Environment.getExternalStorageDirectory().toString() + "/DCIM";//External.getExternalStorageDirectory() 返回存儲卡位置的名稱
File directory = new File(directoryName);
if (!directory.isDirectory()) {
if (!directory.mkdirs()) {
return false;
}
}
File f = new File(directoryName, ".probe");
try {
// Remove stale file if any
if (f.exists()) {
f.delete();
}
if (!f.createNewFile()) {
return false;
}
f.delete();
return true;
} catch (IOException ex) {
return false;
}
}

處理各種觸摸事件

Android裡有兩個類
android.view.GestureDetector
android.view.GestureDetector.SimpleOnGestureListener


1)
新建一個類繼承SimpleOnGestureListener,HahaGestureDetectorListener
可以實現以下event事件。

boolean onDoubleTap(MotionEvent e)
解釋:雙擊的第二下Touch down時觸發

boolean onDoubleTapEvent(MotionEvent e)
解釋:雙擊的第二下Touch down和up都會觸發,可用e.getAction()區分。

boolean onDown(MotionEvent e)
解釋:Touch down時觸發

boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
解釋:Touch了滑動一點距離後,up時觸發。

void onLongPress(MotionEvent e)
解釋:Touch了不移動一直Touch down時觸發

boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
解釋:Touch了滑動時觸發。

void onShowPress(MotionEvent e)
解釋:Touch了還沒有滑動時觸發
(與onDown,onLongPress比較
onDown只要Touch down一定立刻觸發。

而Touchdown後過一會沒有滑動先觸發onShowPress再是onLongPress。

所以Touchdown後一直不滑動,onDown->onShowPress->onLongPress這個順序觸發。


boolean onSingleTapConfirmed(MotionEvent e)
boolean onSingleTapUp(MotionEvent e)
解釋:上面這兩個函數都是在touch down後又沒有滑動(onScroll),又沒有長按(onLongPress),然後Touchup時觸發。

點擊一下非常快的(不滑動)Touchup:
onDown->onSingleTapUp->onSingleTapConfirmed

點擊一下稍微慢點的(不滑動)Touchup:
onDown->onShowPress->onSingleTapUp->onSingleTapConfirmed


2)在view的新建一個GestureDetector的對象。
構造函數裡
gestureDetector = new GestureDetector(new HahaGestureDetectorListener());

然後在View的onTouchEvent裡以下這樣用,就可以在剛才1)弄的事件裡寫自己的代碼了。
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
}

換頁範例


http://docs.google.com/leaf?id=0B2ZDespdKH31YmFkMDM1MGQtYjU2YS00YWVkLThlMmItNGM0NWI5OWRmYWUz&hl=zh_TW

2010年3月17日 星期三

Jollen 的 Android 教學,#18: 佈景(Theme)初體驗

Jollen 的 Android 教學,#18: 佈景(Theme)初體驗

Jollen 的 Android 教學,#9: 啟動 Service - startService()

Jollen 的 Android 教學,#9: 啟動 Service - startService()

Jollen 的 Android 教學,#7: 如何讓文字並排顯示 - TableLayout

Jollen 的 Android 教學,#7: 如何讓文字並排顯示 - TableLayout

Jollen 的 Android 教學,#2: 「Hello Moko」 - Activity 與 View 的關係

Jollen 的 Android 教學,#2: 「Hello Moko」 - Activity 與 View 的關係

Jollen 的 Android 教學,#20: 如何設計一個小型的App Widget?

Jollen 的 Android 教學,#20: 如何設計一個小型的App Widget?

android -- widget example @ Should I be :: 痞客邦 PIXNET ::

android -- widget example @ Should I be :: 痞客邦 PIXNET ::

自已寫的取得天氣範例

http://docs.google.com/a/xn--sx5a.co.cc/leaf?id=0B2ZDespdKH31Mzc1NWFmYTAtMTkwNy00ZDYxLTllYzUtYjQ0ZDRiMWI4OGI4&hl=en

如何部署自己開發的應用程式呢??


環境說明編輯區段


Android 裝置:Android Dev Phone 1


大綱


安裝 USB driver 及取的台灣天氣


  1. 首先必須下載 SDK 與 usb_driver。
  2. 安裝完 SDK 與 usb_driver


設定 Android Dev Phone 1 可接受 USB 安裝 Application


  1. 設定 Android Dev Phone 1 可以從外部安裝 Application。
    在「桌面」按下「MENU」>「Setting」>「Application
    get-screenshot-12.png get-screenshot-13.png
    將「Unknow sources」打勾,同時會有警告訊息,按下「OK」即完成設定
    local-install-001.png local-install-002.png



  1. 在電腦上開啟「命令提示字元」,「開始」>「執行」>「cmd
    local-install-003.png

    local-install-004.png
  2. 確定 Android Dev Phone 1 已經使用 USB 與電腦連結
  3. 接下來先切換到「SDK」資料夾的「tools」,利用以下指令

    1. adb install D:\*.apk

    畫面會出現「Success」表示安裝成功



Android 上網程式設計 簡單範例

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

public class ex002 extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
WebView webView = new WebView(this);
webView.loadUrl("http://www.just.edu.tw/");
setContentView(webView);
//setContentView(R.layout.main);
}
}

1.Android 中所採用的瀏覽器是 WebKit,要控置瀏覽器很簡單,只要 import android.webkit.WebView 後,呼叫 loadUrl() 函數載入網頁即可。
2.在sdk-0.9_beta版後,對網路控管提升,因此模擬器需增添在網路、藍牙、相機等等的使用許可授權後才可正常使用。
3.作法:在androidmanifest.xml裡,加入以下程式碼

開始

  1. 設置環境
    • Windows XP with SP3
    • 下載相關開發軟體
        • Java 開發環境,前天我下載的版本是 JDK 6 Update 13 (jdk-6u13-windows-i586-p.exe)
          • Android 1.5 SDK, Release 1 (android-sdk-windows-1.5_r1.zip)
            • 這是寫程式免費 IDE 編輯器,但我完全沒用過 orz
            • 我選擇的是 Eclipse IDE for Java Developers (eclipse-java-ganymede-SR2-win32.zip)
            • 初步軟體設置
              • 安裝 JDK
                • 點一點就搞定,安裝完後請設定環境變數,以方便 cmd mode 下使用。
                • 安裝 Andorid SDK
                  • 解壓縮就行!假設解壓縮在 C:\ ,搭配預設目錄名即為 C:\android-sdk-windows-1.5_r1
                  • 安裝 Eclipse
                    • 解壓縮就行!假設解壓縮在 C:\ ,搭配預設目錄名即為 C:\eclipse
                    • 設定環境變數
                      • [我的電腦] 按右鍵切換 -> [內容] -> [進階] -> [環境變數] -> 使用者變數 新增/編輯 PATH 變數 -> C:\bin;C:\Program Files\Java\jre6\bin;C:\android-sdk-windows-1.5_r1\tools;
                      • 使用 Eclipse 與其環境設置
                        • 點選 C:\eclipse\eclipse.exe 開啟該軟體
                        • 第一個碰到的視窗是詢問 Workspace ,若沒特別想設定的,預設即可。若覺得以後被問很麻煩,可以再勾選下面的選項 Use this as the default and do not ask again
                        • 下載 Android Development Tools plugin (ADT)
                          • [Help] -> [Software Updates] -> [Available Software] -> [Add Site] -> Location 填寫 http://dl-ssl.google.com/android/eclipse/site.xml
                          • 我碰到一個錯誤訊息 No repository found at https://dl-ssl.google.com/android/eclipse/ ,仔細一看有一處是 http://dl-ssl.google.com/android/eclipse/site.xml ,就使用這個吧(暫時忽略這個錯誤XD),勾選此項並 Install !經過一陣子後,Eclipse 會要求重新啟動此軟體。(安裝了 Android DDMS & Android Development Tools )
                          • 設定 Android SDK 位置,讓 Eclipse 能夠找到它
                            • [Window] -> [Preferences] -> 點選左邊 Android 項目 -> 使用 Browse 選擇與設定 SDK Location ,設定完選 Apply 跟 OK 吧
                            •