2011年4月15日 星期五

Battery資訊

Battery資訊
利用BroadcastReceiverIntentFilter物件偵測Battery資訊
    public void onCreate() {
        .......
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(mBroadcastReceiver, filter);
    }

    public void onDestroy() {
        .............
        unregisterReceiver(mBroadcastReceiver);
    }

    private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                // status
                switch (intent.getIntExtra("status", 0)) {
                case BatteryManager.BATTERY_STATUS_UNKNOWN:
                    statusString = "unknown";
                    break; 
                case BatteryManager.BATTERY_STATUS_CHARGING:
                    statusString = "charging";
                    break; 
                case BatteryManager.BATTERY_STATUS_DISCHARGING:
                    statusString = "discharging";
                    break;
                case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
                    statusString = "not charging";
                    break;
                case BatteryManager.BATTERY_STATUS_FULL:
                    statusString = "full";
                    break;
                default:
                    statusString = "unknown";
                    break;
                }
                // health
                switch (intent.getIntExtra("health", 0)) {
                case BatteryManager.BATTERY_HEALTH_UNKNOWN:
                    healthString = "unknown";
                    break;
                case BatteryManager.BATTERY_HEALTH_GOOD:
                    healthString = "good";
                    break;
                case BatteryManager.BATTERY_HEALTH_OVERHEAT:
                    healthString = "over heat";
                    break;
                case BatteryManager.BATTERY_HEALTH_DEAD:
                    healthString = "dead";
                    break;
                case BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE:
                    healthString = "over voltage";
                    break;
                case BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE:
                    healthString = "unspecified failure";
                    break;
                default:
                    healthString = "unknown";
                    break;
                }
                // plugged
                switch (intent.getIntExtra("plugged", 0)) {
                case BatteryManager.BATTERY_PLUGGED_AC:
                    acString = "plugged ac";
                    break;
                case BatteryManager.BATTERY_PLUGGED_USB:
                    acString = "plugged usb";
                    break;
                default :
                    acString = "disconnect";
                    break;
                }
                // others
                boolean present = intent.getBooleanExtra("present", false);
                int level = intent.getIntExtra("level", 0);
                int scale = intent.getIntExtra("scale", 0);
                int icon_small = intent.getIntExtra("icon-small", 0);
                int voltage = intent.getIntExtra("voltage", 0);
                int temperature = intent.getIntExtra("temperature", 0);
                String technology = intent.getStringExtra("technology");
            }
        }
    };

MediaPlayer物件

MediaPlayer物件
Audio Play
    使用MediaPlayer物件撥放聲音,可以從不同的來源設定,其使用的方式也不相同。
    1. 本地端(包含在APK裡的檔案)
        private MediaPlayer mediaPlayer = null;

        // Start Play Audio
        private OnClickListener start = new OnClickListener() {
            public void onClick(View v) {
                // 直接從本地端讀取音源檔
                mediaPlayer = MediaPlayer.create(AudioPlay.this, R.raw.test);
                try {
                    mediaPlayer.start();
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                }
                btn_start.setEnabled(false);
                btn_stop.setEnabled(true);
            }
        };

        // Stop Play Audio
        private OnClickListener stop = new OnClickListener() {
            public void onClick(View v) {
                mediaPlayer.stop();
                // 結束時把控制全釋放,避免占用資源
                mediaPlayer.release();
                mediaPlayer = null;
                btn_start.setEnabled(true);
                btn_stop.setEnabled(false);
            }
        };

        // 銷毀,當不正常結束的情形發生時的處理動作
        public void onDestroy() {
            super.onDestroy();
            // 避免物件為"空"時,使用屬性發生錯誤
            if (mediaPlayer != null) {
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }

    2. 外部裝置或路徑
        // Use sd card resource
        bplay.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                try {
                    mp.setDataSource("/sdcard/Christina - Fighter.mp3");
                    mp.prepare();
                    mp.start();
                    bmsg.setText("Playing...");
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });

Video Play
撥放影音需用到SurfaceView物件
    main.xml    <SurfaceView
        android:id="@+id/surface"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_gravity="center"/>

    Xxx.java
    private MediaPlayer mMediaPlayer;
    private SurfaceView mPreview;
    private SurfaceHolder holder;

    // 初始化,並設定holder
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        mPreview = (SurfaceView) findViewById(R.id.surface);
        holder = mPreview.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

    }

    // 初始化及設定MediaPlayer物件
    private void playVideo() {
        doCleanUp();
        try {
            path = "/sdcard/test.mp4";
            // Create a new media player and set the listeners
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setDataSource(path);
            mMediaPlayer.setDisplay(holder);
            mMediaPlayer.prepare();
            mMediaPlayer.setOnBufferingUpdateListener(this);
            mMediaPlayer.setOnCompletionListener(this);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnVideoSizeChangedListener(this);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        }
        catch (Exception e) {
        }
    }

    // Called to update status in buffering a media stream(非必要)
    public void onBufferingUpdate(MediaPlayer arg0, int percent) { }

    // 當影片播放結束,進入onCompletion狀態(非必要)
    // 若是要重複播放,可以參考下列流程控制
    // 或是在playVideo加入"mMediaPlayer.setLooping(true)"
    public void onCompletion(MediaPlayer arg0) {
        mMediaPlayer.stop();
        try {
            mMediaPlayer.prepare();
        }
        catch (IllegalStateException e) { }
        catch (IOException e) { }
        mMediaPlayer.start();
    }

    // 讀取影片畫面大小
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
        if (width == 0 || height == 0) {
            return;
        }
        mIsVideoSizeKnown = true;
        mVideoWidth = width;
        mVideoHeight = height;
        if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
            startVideoPlayback();
        }
    }

    // 準備狀態
    public void onPrepared(MediaPlayer mediaplayer) {
        mIsVideoReadyToBePlayed = true;
        if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
            startVideoPlayback();
        }
    }

    // for "SurfaceHolder.Callback" use
    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k) { }
    public void surfaceDestroyed(SurfaceHolder surfaceholder) { }
    public void surfaceCreated(SurfaceHolder holder) {
        playVideo();
    }

    protected void onDestroy() {
        super.onDestroy();
        releaseMediaPlayer();
        doCleanUp();
    }

    private void releaseMediaPlayer() {
        if (mMediaPlayer != null) {
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    private void doCleanUp() {
        mVideoWidth = 0;
        mVideoHeight = 0;
        mIsVideoReadyToBePlayed = false;
        mIsVideoSizeKnown = false;
    }

    // strat to play
    private void startVideoPlayback() {
        holder.setFixedSize(mVideoWidth, mVideoHeight);
        mMediaPlayer.start();
    }

KeyEven接收

KeyEven接收
擷取按Key的動作

    public boolean dispatchKeyEvent(KeyEvent event) {
        switch (event.getKeyCode()){
        case KeyEvent.KEYCODE_MENU:
            break;
        case KeyEvent.KEYCODE_BACK:
            break;
        case KeyEvent.KEYCODE_VOLUME_UP:
            break;
        case KeyEvent.KEYCODE_VOLUME_DOWN:
            break;
        default:
            break;
        }
    }

// 目前"POWER"及"HOME"還不清楚要怎麼做
// Android OS限制?

AudioManager物件

AudioManager物件
下面介紹一些音量管理器的功能

取得音量控制器
    AudioManager audioManager =
        (AudioManager)getSystemService(Context.AUDIO_SERVICE);

目前音量
    current_volume.setText(
        String.valueOf(audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)));

正常模式
    mode1.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
        }
    });

震動模式
    mode2.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
        }
    });

靜音模式
    mode3.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
        }
    });

增大音量
    volume_add.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            audioManager.setStreamVolume(
                AudioManager.STREAM_MUSIC,
                audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)+1,0);
        }
    });

減少音量
    volume_dec.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            audioManager.setStreamVolume(
                AudioManager.STREAM_MUSIC,
                audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)-1,0);
        }
    });

2011年4月13日 星期三

LinearLayout版面配置

LinearLayout版面配置
線性佈局版面配置,每一行只放一個物件,依方向可分為垂直及水平方向

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"    >
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"   
        android:layout_height="fill_parent"
        <!-- 切割視窗的屬性 -->
        android:layout_weight="1">
        <SurfaceView
            android:layout_width="wrap_content"   
            android:layout_height="wrap_content"   
            android:layout_gravity="center"/>
    </LinearLayout>
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"   
        android:layout_height="fill_parent"
        android:layout_weight="1">   
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Run Time"/>
       <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Stop!!"/>
    </LinearLayout>
</LinearLayout>

假設一個Layout裡包含了2個LinearLayout,分別是LinearLayout_A和LinearLayout_B
當android:layout_weight的屬性分別設定為(3,2)時
LinearLayout_A會占全部畫面的2/(3+2)
LinearLayout_B會占全部畫面的3/(3+2)

2011年4月12日 星期二

EditText物件

EditText物件
編輯文字,用於資料輸入時使用
    edittext.setOnKeyListener(new OnKeyListener() {
       
public boolean onKey(View v, int keyCode, KeyEvent event) {
           
// 當按下"Enter Key"時
           
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
               
(keyCode == KeyEvent.KEYCODE_ENTER)) {
                Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
               
return true;
           
}
           
return false;
       
}
    });

    // 在虛擬鍵盤按下"ENTER"後,隱藏虛擬鍵盤
    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        if (event != null&& (event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
            InputMethodManager in =
                (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            in.hideSoftInputFromWindow(
                v.getApplicationWindowToken(),
                InputMethodManager.HIDE_NOT_ALWAYS);
        }
        return true;
    }

2011年4月11日 星期一

ListView物件

ListView物件
表單,用於顯示複數以上的物件。
常見的應用例如"檔案管理","系統功能選項"。

一般的做法
    // layout裡為一個TextView
    adapter = new ArrayAdapter<String>(this, R.layout.device_name);
   
    ListView lv= (ListView) findViewById(R.id.list);
    // 此行程式碼會將list的資料更新
    lv.setAdapter(adapter);
    lv.setOnItemClickListener(select);
   
    // 在ListView裡加入項目
    adapter.add("item1");
    adapter.add("item2");
    adapter.add("item3");
    ........

    private OnItemClickListener select= new OnItemClickListener() {
        public void onItemClick(AdapterView<?> av, View v, int pos, long arg3) {
       
        }
    };

另一種方法,用SimpleAdapter
    public void onCreate(Bundle savedInstanceState) {
        ..........
        listview = (ListView)findViewById(R.id.list);
        listview.setOnItemClickListener(listen_click);
        update_list();
        ...........
    }
   
    private void update_list() {
        SimpleAdapter adapter = new SimpleAdapter(this, getData(), R.layout.listitem,
            new String[]{"info","img"}, new int[]{R.id.info,R.id.img}); 
            listview.setAdapter(adapter);
    }

    private List<Map<String, Object>> getData() {
        int i;
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> map;
       
        map = new HashMap<String, Object>();
        map.put("info", "name"); 
        map.put("img", R.drawable.back);
        list.add(map);
       
        return list;
    }
   
    private OnItemClickListener listen_click = new OnItemClickListener() {
        public void onItemClick(AdapterView<?> arg0, View v, int position, long id) {
       
        }
   };

SharedPreferences物件


SharedPreferences物件
偏好設定SharedPreferences可用來紀錄資料
在Activity重新啟動後,可回復關閉前資訊 
通常在"onPasue"寫入參數,在"onRseume"讀取參數

寫入參數
    SharedPreferences settings = getSharedPreferences ("DATA", 0);
    SharedPreferences.Editor PE = settings.edit();
    PE.putString("data_str", "hello");
    PE.putInt("date_int", 100);
    PE.commit();


    or

    SharedPreferences settings = getSharedPreferences ("DATA", 0);
    settings.edit()
        .putString("data_str", "hello");
        .putInt("date_int", 100);
        .commit();

讀取參數
    SharedPreferences settings = getSharedPreferences("DATA", 0);
    // 如果讀不到值,就會回傳後面設定的參數
    String str = settings.getString("data_str", "null");
    int i = settings.getInt("date_int", 0);

Menu物件

Menu物件
選單,通常用於修改AP設定使用的物件
簡易的做法
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        menu.add(0, ITEM1, 0, "item1");
        menu.add(0, ITEM2, 0, "item2");
        return true;
    }

    public boolean onOptionsItemSelected(MenuItem item) {
        super.onOptionsItemSelected(item);
        switch(item.getItemId()){
            case ITEM1:
                break;
            case ITEM2:
                break;
        }
        return true;
    }

使用resource
在res下新增menu的資料夾,加入xml檔
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
       
<item android:id="@+id/new_game"
                
android:icon="@drawable/ic_new_game"
                
android:title="@string/new_game" />
       
<item android:id="@+id/help"
                 
android:icon="@drawable/ic_help"
                
android:title="@string/help" />
    </menu>

然後在.java加入
    public boolean onCreateOptionsMenu(Menu menu) {
       
MenuInflater inflater = getMenuInflater();
        inflater
.inflate(R.menu.game_menu, menu);
       
return true;
    }


    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
       
case R.id.new_game:
            //newGame
();
           
break;
       
case R.id.help:
            //showHelp
();
           
break;
       
default:
           
return super.onOptionsItemSelected(item);

            break;
       
}

        return true;
    }


其他作法可參照官方網站
Dev Guide - Framework Topics - User Interface - Creating Menus

Toast & Log物件

Toast & Log物件
Toast主要用於顯示通知訊息
Log主要是提供給debug的編寫者使用

    Toast用法
    Toast.makeText(Sample.this, "serivce destroy", Toast.LENGTH_LONG).show();
    (LENGTH_LONG - 顯示時間長短)

    Log用法
    Log.d("TAG", "message");
   
    Log.v (VERBOSE) 詳細訊息
    Log.d (DEBUG) 除錯訊息
    Log.i (INFO) 通知訊息
    Log.w (WARN) 警告訊息
    Log.e (ERROR) 錯誤訊息