Android 學習筆記整理2 2011.4.2

下面是我對Android application層進一步學習的一些筆記(linux 環境),轉載時請註明出處 http://blog.csdn.net/zyc13701469860

 

1.創建帶有sdcard的模擬器

在Eclipse下可以直接創建模擬器,並讓其支持sdcard.但是這種用這種方法創建的sdcard有一個很大的缺點,就是一旦你改變模擬器的參數,那麼這個sdcard就會被清空。也就是說之前push到sdcard裏面的東西全都沒有了。

所以我們要先創建一個sdcard的鏡像文件(.iso),這個鏡像文件可以作爲多個模擬器的sdcard,但是在一個模擬器使用時,該sdcard會被上鎖,其他的模擬器無法訪問。

終端創建sdcard命令

$mksdcard 1024MB sdcard.iso

終端啓動模擬器並附帶剛纔創建的sdcard

$emulator -avd avdname -sdcard sdcard.iso

也可以在Eclipse下通過加載sdcard.iso的方式創建sdcard.

 

emulator指令的參數選項還非常的多,您可以運行emulator -help獲得更多的參數功能

如-partition-size 128 設置模擬器的內存爲128M

 

2.關於R.java文件無法自動生成的解決辦法

在用Eclipse的時候,有時會發現R.java文件無法自動生成。遇到這種請況,你需要check:

2.1.在xml文件中,每一個佈局,控件定義的是否正確。有時雖然Eclipse不報錯,比如你爲控件設置了該控件沒有的屬性(語法沒有任何問題),那麼在解析xml文件時就會出錯。

2.2.要注意xml文件名只能爲小寫字母和數字,否則就會報文件名不符合正則表達式的錯誤。所以要根據控制檯打出的信息來找出錯誤的原因。

 

3.關於在Eclipse中工程內的文件都編譯正確,但是在工程文件夾上有錯誤標識的解決方法

 

很簡單,選擇菜單項的project ->clean,再重新編譯即可。

 

4.Android UI的更新

如果我們需要對UI進行更新,不能採用如下方法:

 

Timer timer = new Timer();  

TimerTask task = new TimerTask(){  

 public void run() {  

           changeCurrentTime();//update the TextView 

      }  

 };

timer.schedule(task, 0, 1000);

因爲Android 線程的安全機制,不允許UI線程在子線程中執行,即UI線程只能在主線程執行。原因是如果子線程需要耗費大量時間,比如下載文件,那麼主線程就因爲超時而down掉。所以要使用Handler類來實現主線程和子線程的通信:

Handler handler = new Handler(){
  public void handleMessage(Message msg) {
      switch (msg.what) {
       case 0:
       changeCurrentTime();
       break;
       }
   }
}

class audioTimerTask extends TimerTask{
  @Override
    public void run() {
        handler.sendEmptyMessage(0);
    }
}

 


Time timer = new Timer();
timer.schedule(new audioTimerTask(), 0, 1000);

 

5.關於Android MediaPlayer

最近,我主要在研究MediaPlayer,並製作了一個demo.

5.1MediaPlayer的生命週期(這裏引用了http://blog.csdn.net/ddna/archive/2010/01/11/5178864.aspx

 

MediaPlayer的狀態轉換圖也表徵了它的生命週期,搞清楚這個圖可以幫助我們在使用MediaPlayer時考慮情況更周全,寫出的代碼也更具健壯性。

 


 

這張狀態轉換圖清晰的描述了MediaPlayer的各個狀態,也列舉了主要的方法的調用時序,每種方法只能在一些特定的狀態下使用,如果使用時MediaPlayer的狀態不正確則會引發IllegalStateException異常

 

Idle 狀態:當使用new()方法創建一個MediaPlayer對象或者調用了其reset()方法時,該MediaPlayer對象處於idle狀態。這兩種方法的一個重要差別就是:如果在這個狀態下調用了getDuration()等方法(相當於調用時機不正確),通過reset()方法進入idle狀態的話會觸發OnErrorListener.onError(),並且MediaPlayer會進入Error狀態;如果是新創建的MediaPlayer對象,則並不會觸發onError(),也不會進入Error狀態。

 

End 狀態:通過release()方法可以進入End狀態,只要MediaPlayer對象不再被使用,就應當儘快將其通過release()方法釋放掉,以釋放相關的軟硬件組件資源,這其中有些資源是隻有一份的(相當於臨界資源)。如果MediaPlayer對象進入了End狀態,則不會在進入任何其他狀態了。

 

Initialized 狀態:這個狀態比較簡單,MediaPlayer調用setDataSource()方法就進入Initialized狀態,表示此時要播放的文件已經設置好了。

 

Prepared 狀態:初始化完成之後還需要通過調用prepare()prepareAsync()方法,這兩個方法一個是同步的一個是異步的,只有進入Prepared狀態,才表明MediaPlayer到目前爲止都沒有錯誤,可以進行文件播放。

 

Preparing 狀態:這個狀態比較好理解,主要是和prepareAsync()配合,如果異步準備完成,會觸發OnPreparedListener.onPrepared(),進而進入Prepared狀態。

 

Started 狀態:顯然,MediaPlayer一旦準備好,就可以調用start()方法,這樣MediaPlayer就處於Started狀態,這表明MediaPlayer正在播放文件過程中。可以使用isPlaying()測試MediaPlayer是否處於了Started狀態。如果播放完畢,而又設置了循環播放,則MediaPlayer仍然會處於Started狀態,類似的,如果在該狀態下MediaPlayer調用了seekTo()或者start()方法均可以讓MediaPlayer停留在Started狀態。

 

Paused 狀態:Started狀態下MediaPlayer調用pause()方法可以暫停MediaPlayer,從而進入Paused狀態,MediaPlayer暫停後再次調用start()則可以繼續MediaPlayer的播放,轉到Started狀態,暫停狀態時可以調用seekTo()方法,這是不會改變狀態的。

 

Stop 狀態:Started或者Paused狀態下均可調用stop()停止MediaPlayer,而處於Stop狀態的MediaPlayer要想重新播放,需要通過prepareAsync()prepare()回到先前的Prepared狀態重新開始纔可以。

 

PlaybackCompleted狀態:文件正常播放完畢,而又沒有設置循環播放的話就進入該狀態,並會觸發OnCompletionListeneronCompletion()方法。此時可以調用start()方法重新從頭播放文件,也可以stop()停止MediaPlayer,或者也可以seekTo()來重新定位播放位置。

 

Error狀態:如果由於某種原因MediaPlayer出現了錯誤,會觸發OnErrorListener.onError()事件,此時MediaPlayer即進入Error狀態,及時捕捉並妥善處理這些錯誤是很重要的,可以幫助我們及時釋放相關的軟硬件資源,也可以改善用戶體驗。通過setOnErrorListener(android.media.MediaPlayer.OnErrorListener)可以設置該監聽器。如果MediaPlayer進入了Error狀態,可以通過調用reset()來恢復,使得MediaPlayer重新返回到Idle狀態。

 

 

 

5.2製作一個MediaPlayer播放器

這是我做的一個PPT,全英文的~下面我把主要的步驟和方法貼了出來。我的demo在Android3.0模擬器上可以順利運行.

 

5.2.1How to use MediaPlayer to play an audio

 

1.Create a MediaPlayer object

MediaPlayer mp = new MediaPlayer();

 

2.There are two mainly ways to set the data source. 

2.1Play a resource file. You can create a folder named “raw” under folder “res”.Then put you media file in it.

mp.create(this,R.raw.xxx);

 

Note:Use this method don't need perpare().

 

3. Finally,you can play your media file.

mp.start();

 

You also can use MediaPlayer.OnPreparedListener interface when play a stream file.

public void onPrepared(MediaPlayer mp) {

    mp.start();

}

 

And you need register at first.

mp.set.OnPreparedListener(this);

 

When the MediaPlayer is not used,we should release it's software and hardware resource by the method of release() as soon as possible.

 

if(mp != null){

mp.stop();

mp.release();

mp = null;

}

 

5.2.2  Play a video on SurfaceView

 

1.Define a SurfaceView in your xml file.

 

2.Get the SurfaceView

SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.xxx);

 

3.Define a SurfaceHolder in your code.

SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();

 

4.Create a MediaPlayer object and setDataSource() like audio.

 

5.Sets the SurfaceHolder to use for displaying the video portion of the media.
mp.setDisplay(mSurfaceHolder);
6.Make the surface a fixed size,or your video maybe nebulous.
If your video size is 320 * 240 (.mp4),you can set:
mSurfaceHolder.setFixedSize(320, 240);
7.Finally,prepare and start.
5.2.3Make a MediaPlayer by yourself
You can make a MediaPlayer by yourself and run it in android 3.0 simulator.
Create a sdcard for your simulator.
$mksdcard 1024MB sdcard.iso
Command mksdcard is in your AndroidSDK path/tools/
Use sdcard
$emulator -avd avdname -sdcard sdcard.iso
Push your media file to sdcard
$adb push xxx.mp3  /sdcard/
5.2.4My application demo

 

 

5.2.5 Use SeekBar to control the process of media file

 

1.Define a SeekBar in xml file.And get it from code.

android:id="@+id/seekbar"

SeekBar mSeekBar = (SeekBar) findViewById(R.id.seekbar);

 

2.Set the listener of the seekbar

mSeekBar.setOnSeekBarChangeListener(seekBarChangeListener);

 

3.When the seekbar changed,we set the process of the media.

 

We need set the Max of the seekbar.

The max is the time of the media file.(ms)

mSeekBar.setMax(mp.getDuration());

 

private OnSeekBarChangeListener seekBarChangeListener = new OnSeekBarChangeListener(){

......

    public void onStopTrackingTouch(SeekBar seekBar) {

        mp.seekTo(seekBar.getProgress()); 

    }

};

Then the media will play from the process.

 

 

5.2.6 Control the sound volume

 

We can use AudioManager.

AudioManager provides access to volume and ringer mode control.

 

AudioManager mAudioManager =(AudioManager) getSystemService(Context.AUDIO_SERVICE);

 

We can't set the volume arbitrary,because the stream volume of media is STREAM_MUSIC,and the volume is from 0 to 15.

 

int maxVolume = mAudioManager.GetStreamMaxVolume ( AudioManager.STREAM_MUSIC ); //volume is 15

 

int currentVolume = mAudioManager.GetStreamVolume ( AudioManager.STREAM_MUSIC ); 

 

if(currentVolume < maxVolume){

mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC,            currentVolume + 1, AudioManager.FLAG_SHOW_UI);

}

 

5.2.7 How to get media file information in sdcard
Android system can search the media file in sdcard and save the information to MediaStore.Audio.Media and MediaStore. Video.Media table when system start up,power off or sdcard hot plug.
We can use cursor to query the table and get the media information.
Cursor cursor = this.getContentResolver() .query (MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,  new String[]{MediaStore.Audio.Media.DATA},null,null ,MediaStore.Audio.Media.DATA + " DESC");
It's same as the SQL sentence 
SELECT MediaStore.Audio.Media.DATA 
FROM MediaStore.Audio.Media.EXTERNAL_CONTENT_URI 
ORDER BY MediaStore.Audio.Media.DATA DESC
Get an arraylist to set list adapt.
ArrayList<String> searchList = new ArrayList<String>();
cursor.moveToFirst();    
while(!cursor.isAfterLast()){
searchList.add(cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA)));
cursor.moveToNext();
}
Set the list adapt and notifyDataSetChanged.
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,searchList));
((ArrayAdapter<String>)getListAdapter()).notifyDataSetChanged();
source code 這裏就不貼了~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章