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时考虑情况更周全,写出的代码也更具健壮性。

Android 学习笔记整理2 2011.4.2_第1张图片

 


 

这张状态转换图清晰的描述了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
Android 学习笔记整理2 2011.4.2_第2张图片

 

 

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 这里就不贴了~

 

你可能感兴趣的:(Android 学习笔记整理2 2011.4.2)