2011年2月9日 星期三

Android - 儲存偏好設定(Preference)

1. 此範例是利用SharedPreferences來儲存使用者在某個程式內的偏好設定。

2. MainActivity.java
package org.me.android_preference;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {
    private EditText nameEditText;
    private Button saveButton;
    private Button restoreButton;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        nameEditText = (EditText) findViewById(R.id.nameEditText);
        saveButton = (Button) findViewById(R.id.saveButton);
        restoreButton = (Button) findViewById(R.id.restoreButton);
        saveButton.setOnClickListener(saveClickListener);
        restoreButton.setOnClickListener(restoreClickListener);
    }

    //按下Save按鈕
    private Button.OnClickListener saveClickListener = new Button.OnClickListener() {

        public void onClick(View arg0) {
            //取得SharedPreference設定("Preference"為設定檔的名稱)
            SharedPreferences settings = getSharedPreferences("Preference", 0);
            //置入name屬性的字串
            settings.edit().putString("name", nameEditText.getText().toString()).commit();
        }
    };

    //按下Restore按鈕
    private Button.OnClickListener restoreClickListener = new Button.OnClickListener() {

        public void onClick(View arg0) {
            //取得SharedPreference設定("Preference"為設定檔的名稱)
            SharedPreferences settings = getSharedPreferences("Preference", 0);
            //取出name屬性的字串
            String name = settings.getString("name", "");
            nameEditText.setText(name);
        }
    };
}


3. main.xml(Layout)
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
android:id="@+id/widget0"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<TextView
android:id="@+id/nameView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Name:"
android:layout_x="22px"
android:layout_y="34px"
>
</TextView>
<EditText
android:id="@+id/nameEditText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_x="90px"
android:layout_y="20px"
>
</EditText>
<Button
android:id="@+id/saveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save"
android:layout_x="20px"
android:layout_y="86px"
>
</Button>
<Button
android:id="@+id/restoreButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Restore"
android:layout_x="98px"
android:layout_y="84px"
>
</Button>
</AbsoluteLayout>


4. 執行之後的畫面。(按下Store將Name的值儲存在偏好設定,按下Restore會將儲存在偏好設定的值取回)

2011年2月8日 星期二

Android WIFI控制(開啟、關閉)

1. WIFI的控制,主要是透過WifiManager來管理WIFI。

2.WifiManagerExample.java
package tw.nicky.WifiManagerExample;
import android.app.Activity;
import android.content.Context;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class WifiManagerExample extends Activity {
 private WifiManager wiFiManager;
 private Button turnOnWifiButn;
 private Button turnOffWifiButn;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  // 取得WifiManager
  wiFiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
  turnOnWifiButn = (Button) findViewById(R.id.turnOnWifiButn);
  turnOffWifiButn = (Button) findViewById(R.id.turnOffWifiButn);

  // 開啟wifi
  turnOnWifiButn.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    //若wifi狀態為關閉則將它開啟
    if (!wiFiManager.isWifiEnabled()) {
     wiFiManager.setWifiEnabled(true);
    }
   }
  });

  // 關閉wifi
  turnOffWifiButn.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    //若wifi狀態為開啟則將它關閉
    if (wiFiManager.isWifiEnabled()) {
     wiFiManager.setWifiEnabled(false);
    }
   }
  });
 }
}

3. main.xml(Layout)
<?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="開啟Wifi" 
android:id="@+id/turnOnWifiButn" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content">
</Button>

<Button 
android:text="關閉Wifi" 
android:id="@+id/turnOffWifiButn" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content">
</Button>
</LinearLayout>
4. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="tw.nicky.WifiManagerExample"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".WifiManagerExample"
                  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-permission android:name="android.permission.CHANGE_WIFI_STATE"></uses-permission>
    <uses-permission android:name="android.permission.WAKE_LOCK"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"></uses-permission>
</manifest> 


5. 執行畫面

2011年2月6日 星期日

Android - 錄音(MediaRecorder)

1. 要進行錄音需先取得錄音的權限,加上需將錄音檔寫到記憶卡,因此需在AndroidManifest.xml允許存取android.permission.RECORD_AUDIO及android.permission.WRITE_EXTERNAL_STORAGE這二個權限。

2.MediaRecorderExample.java
package tw.nicky;
import java.io.File;
import java.io.IOException;
import android.app.Activity;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.widget.Button;

public class MediaRecorderExample extends Activity {
 private Button recordButn;
 private Button stopButn;
 private MediaRecorder mediaRecorder = null;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  recordButn = (Button) findViewById(R.id.recordButn);
  stopButn = (Button) findViewById(R.id.stopButn);

  //錄音
  recordButn.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
    //設定錄音檔名
    String fileName = "record.amr";
    try {
     File SDCardpath = Environment.getExternalStorageDirectory();
                    File myDataPath = new File( SDCardpath.getAbsolutePath() + "/download" );
                    if( !myDataPath.exists() ) myDataPath.mkdirs();
     File recodeFile = new File(SDCardpath.getAbsolutePath() + "/download/"+fileName);
     
     mediaRecorder = new MediaRecorder();

     //設定音源
     mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
     //設定輸出檔案的格式
     mediaRecorder
       .setOutputFormat(MediaRecorder.OutputFormat.RAW_AMR);
     //設定編碼格式
     mediaRecorder
       .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
     //設定錄音檔位置
     mediaRecorder
       .setOutputFile(recodeFile.getAbsolutePath());

     mediaRecorder.prepare();

     //開始錄音
     mediaRecorder.start();
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  });

  //停止錄音
  stopButn.setOnClickListener(new View.OnClickListener() {
   public void onClick(View v) {
    if(mediaRecorder != null) {
     mediaRecorder.stop();
     mediaRecorder.release();
     mediaRecorder = null;
    }
   }
  });

 }
}
3. main.xml(Layout)
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
android:id="@+id/widget0"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<Button
android:id="@+id/recordButn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="錄音"
android:layout_x="68px"
android:layout_y="44px"
>
</Button>
<Button
android:id="@+id/stopButn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止"
android:layout_x="170px"
android:layout_y="43px"
>
</Button>
</AbsoluteLayout>

4. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="tw.nicky"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".MediaRecorderExample"
                  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-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.RECORD_AUDIO"></uses-permission>
</manifest> 


5. 執行畫面

2011年1月21日 星期五

Android - 讀取手機電話簿(PhoneBook)

1. 此範例是自動填入文字(AutoCompleteTextView)功能來搜尋電話簿內的聯絡人姓名。

2. 由於我們需取得目前手機的電話簿,因此必需在AndroidManifest.xml內新增一個讀取電話簿的權限。

3. MainActivity.java
package org.me.android_phonebook;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.Contacts;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;

public class MainActivity extends Activity {
    private AutoCompleteTextView autoComplete;

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        autoComplete = (AutoCompleteTextView) findViewById(R.id.autoComplete);
        //設定自動填入的文字內容
        ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item,getContactsName());
        autoComplete.setAdapter(adapter);
    }

    //取得所有聯絡人姓名
    public String[] getContactsName() {
        //取得內容解析器
        ContentResolver contentResolver = this.getContentResolver();
        //設定你要從電話簿取出的欄位
        String[] projection = new String[]{Contacts.People.NAME,Contacts.People.NUMBER};
        //取得所有聯絡人
        Cursor cursor = contentResolver.query(Contacts.People.CONTENT_URI, projection, null, null, Contacts.People.DEFAULT_SORT_ORDER);
        String[] contactsName = new String[cursor.getCount()];
        for (int i = 0; i < cursor.getCount(); i++) {
            //移到指定位置
            cursor.moveToPosition(i);
            //取得第一個欄位
            contactsName[i] = cursor.getString(0);
        }
        return contactsName;
    }
}
4. AndroidManifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="org.me.android_phonebook">
    <application>
         <activity android:name=".MainActivity" android:label="PhoneBook">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
</manifest>
5. main.xml(Layout)
<?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">" 
    <AutoCompleteTextView
        android:id="@+id/autoComplete"
        android:layout_width="fill_parent"
        android:layout_height="50px">
    </AutoCompleteTextView>
</LinearLayout>
6. 執行之後的畫面。

2011年1月19日 星期三

Android - 通話狀態(PhoneState)

1. 利用繼承PhoneStateListener來實作當通話狀態為閒置、接起或響起時我們所要做的動作。

2. 由於我們需取得目前手機的通話狀態,因此必需在AndroidManifest.xml內新增一個讀取通話狀態的權限。

3. MainActivity.java
package org.me.android_callstate;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        //電話狀態的Listener
        MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener();
        //取得TelephonyManager
        TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
        //將電話狀態的Listener加到取得TelephonyManager
        telephonyManager.listen(myPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

    public class MyPhoneStateListener extends PhoneStateListener {
        @Override
        public void onCallStateChanged(int state, String phoneNumber) {
            switch (state) {
                //電話狀態是閒置的
                case TelephonyManager.CALL_STATE_IDLE:
                    break;
                //電話狀態是接起的
                case TelephonyManager.CALL_STATE_OFFHOOK:
                    Toast.makeText(MainActivity.this, "正接起電話…", Toast.LENGTH_LONG).show();
                    break;
                //電話狀態是響起的
                case TelephonyManager.CALL_STATE_RINGING:
                    Toast.makeText(MainActivity.this, phoneNumber + "正打電話來…", Toast.LENGTH_LONG).show();
                    break;
                default:
                    break;
            }
        }
    }
}


4. AndroidManifest.xml
<?xml version="1.0" encoding="UTF-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="org.me.android_callstate">
    <application>
         <activity android:name=".MainActivity" android:label="MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
</manifest>


4. 執行之後的畫面。

2011年1月16日 星期日

Android - 畫廊(Gallery)

1. 使用Gallery Widget來達到畫廊的效果。

2. 需建立一個繼承BaseAdapter的物件來放置你要呈現的圖片。

3. MainActivity.java
package org.me.android_gallery;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Gallery;
import android.widget.Toast;

public class MainActivity extends Activity {
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        Gallery gallery = (Gallery) findViewById(R.id.gallery);
        ImageAdapter imageAdapter = new ImageAdapter(this);
        //設定圖片來源
        Integer[] mImageIds = {
            R.drawable.android_logo,
            R.drawable.androids,
            R.drawable.cupcake_2009,
            R.drawable.donut_2009,
            R.drawable.eclair_2009
        };
        //設定圖片的位置
        imageAdapter.setmImageIds(mImageIds);
        //圖片高度
        imageAdapter.setHeight(100);
        //圖片寬度
        imageAdapter.setWidth(200);
        gallery.setAdapter(imageAdapter);
        gallery.setOnItemClickListener(new OnItemClickListener(){
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                Toast.makeText(MainActivity.this, "您選的是第"+position+"張圖", Toast.LENGTH_LONG).show();
            }
        });
    }
}

4. ImageAdapter.java
package org.me.android_gallery;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;

public class ImageAdapter extends BaseAdapter {
    private Context mContext;
    private Integer width;
    private Integer height;
    private Integer[] mImageIds;

    public ImageAdapter(Context c) {
        mContext = c;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ImageView imageView = new ImageView(mContext);
        //設定圖片來源
        imageView.setImageResource(mImageIds[position]);
        //設定圖片的寬、高
        imageView.setLayoutParams(new Gallery.LayoutParams(width, height));
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        return imageView;
    }

    public Integer getHeight() {
        return height;
    }

    public void setHeight(Integer height) {
        this.height = height;
    }

    public Integer[] getmImageIds() {
        return mImageIds;
    }

    public void setmImageIds(Integer[] mImageIds) {
        this.mImageIds = mImageIds;
    }

    public Integer getWidth() {
        return width;
    }

    public void setWidth(Integer width) {
        this.width = width;
    }

    public int getCount() {
        return mImageIds.length;
    }

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

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


5. main.xml(Layout)
<?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">
    <Gallery
        android:id="@+id/gallery"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </Gallery>
</LinearLayout>


4. 執行之後的畫面。

2011年1月15日 星期六

Android - 計時器(Timer)

1. 由於若不是Main Thread則無法去變更畫面的Widget內容,需透過android.os.Handler來達到此效果。

2. MainActivity.java
package org.me.android_timer;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;

public class MainActivity extends Activity {
    private Long startTime;
    private Handler handler = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //取得目前時間
        startTime = System.currentTimeMillis();
        //設定定時要執行的方法
        handler.removeCallbacks(updateTimer);
        //設定Delay的時間
        handler.postDelayed(updateTimer, 1000);
    }

    //固定要執行的方法
    private Runnable updateTimer = new Runnable() {
        public void run() {
            final TextView time = (TextView) findViewById(R.id.timer);
            Long spentTime = System.currentTimeMillis() - startTime;
            //計算目前已過分鐘數
            Long minius = (spentTime/1000)/60;
            //計算目前已過秒數
            Long seconds = (spentTime/1000) % 60;
            time.setText(minius+":"+seconds);
            handler.postDelayed(this, 1000);
        }
    };
}


3. main.xml(Layout)
<?xml version="1.0" encoding="utf-8"?>
<AbsoluteLayout
    android:id="@+id/widget0"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"
    >
    <TextView
        android:id="@+id/timer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0:0"
        android:textSize="70sp"
        android:layout_x="90px"
        android:layout_y="160px"
        >
    </TextView>
</AbsoluteLayout>


4. 執行之後的畫面。