音乐播放器、视频播放器、录音、照相、闹钟、铃声设计中的各种方法以及例子总结

 

多媒体开发
 Open Core是Android多媒体开发框架的核心。所有Android平台的音频、视频的采集以及播放都是通过它来实现的。它也被称为PV(Packet Video).
 Open Core是一个多媒体框架,从宏观上看主要包含两大方面的内容:
  PVPlayer :提供媒体播放器的功能,完成各种音频(Audio)、视频(Video)流的回放(Playback)功能。
  PVAuthor: 提供媒体流记录的功能,完成各种音频、视频流以及静态图像的捕获功能。
第一部分 MediaPlayer 类
   1.MdiaPlayer类可以用来播放音频,视频和流媒体(所谓流媒体是指采用流式传输的方式在Internet播放的媒体格式。 流媒体又叫流式媒体,它是指商家用一个视频传送服务器
    把节目当成数据包发出,传送到网络上。用户通过解压设备对这些数据进行解压后,节目就会像发送前那样显示出来。)。其也包含了Audio和Video的播放功能。
   2.当一个MediaPlayer对象被创建或调用了reset()方法后,它处于空闲状态,在调用release()方法后,才会结束状态。
   3.MediaPlayer对象在创建时处于空闲状态,如果通过create()方法创建之后便处于准备状态。
   4.为了避免MediaPlayer对象处于无效状态而导致错误,我们可以通过注册setOnErrorListener(android.media.MediaPlayer.OnErrorListener)方法实现OnErrorListener.onError()
    方法来监控这些错误。如果发生了错误,可以使用reset()方法来恢复错误。
   5.任何MediaPlayer对象都必须处于准备状态,然后才能播放。
   6.要开始播放MediaPlayer对象必须要成功调用start()方法。可以通过isPlaying()方法来检测当前是否播放。
   7.新建的MediaPlayer对象在调用getCurrentPositon(),start(),stop()等方法时不会触发OnErrorListener.onError()事件,但如果MediaPlayer对象调用了reset()方法后,再使用这
    些方法则会触发OnErrorListener.onError()事件。
   8.当MediaPlayer对象不再被使用时,最好用release()方法来释放,使其处于结束状态,以免出错。当MediaPlayer对象处于结束状态时,便不能再使用。
    MediaPlayer类常用方法:
     MediaPlayer         构造方法
     create       创建一个要播放的多媒体
     getCurrentPositons     得到当前播放位置
     getDuration      得到文件时间
     getVideoHeight     得到视频的高度
     getVideoWidth     得到视频的宽度
     isLooping      是否循环播放
     isPlaying      是否正在播放
     pause       暂停
     prepare       准备(同步)
     prepareAsync     准备(异步)
     release       释放MediaPlayer对象
     reset       重置MediaPlayer对象
     seekTo       指定播放的位置(毫秒)
     setAudioStreamType    设置流媒体类型
     setDataSource     设置多媒体数据来源
     setDisplay      设置用SurfaceHolder来显示多媒体
     setLooping      设置是否循环播放
     setOnBufferUpdateListener  设置流媒体缓冲监听
     setOnErrorListener    设置错误信息监听
     setOnVideoSizeChangedListener 设置视频尺寸监听
     setScreenOnWhilePlaying   设置是否使用SurfaceHolder来显示
     setVolume      设置音量
     start       开始播放
     stop       停止播放
     
   Android中通过MediaPlayer来播放音乐步骤:
    MediaPlayer mediaplayer = new MediaPlayer();//构建MediaPlayer对象
    mediaplayer.setDataSource(“/sdcard/test.mp3”);//设置文件路径
    mediaplayer.prepare();//准备
    mediaplayer.start();//开始播放
    
第二部分 MediaRecorder类
   MediaRecorder类用来进行媒体采样,包括音频和视频。MediaRecorder作为状态机运行,需要设置不同的参数,如格式。
    MediaRecorder类的常用方法:
     MediaRecorder     构造方法
     getMaxAmplitude    得到目前为止最大的幅度
     prepare      准备录用机
     release      释放MediaRecorder对象
     reset       重置MediaRecorder对象,使其为空闲状态
     setAudioEncoder    设置音频编码
     setAudioSource    设置音频源
     setCamera     设置摄像机
     setMaxDuration    设置最大期限
     setMaxFileSize     设置文件的最大尺寸
     setOnErrorListener    错误监听
     setOutputFile    设置输出文件
     setOutputFormat    设置输出文件的格式
     setPreviewDisplay   设置预览
     setVideoEncoder    设置视频编码
     setVideoFrameRate   设置视频帧的频率
     setVideoSize    设置视频的宽度和高度(分辨率)
     setVideoSource    设置视频源
     start      开始录制
     stop       停止录制
   
   一段简单的录用代码:
    MediaRecorder recorder = new MediaRecorder();
    recorder.setAudioSource(MediaRecorder.AndrioSource.MTC)
    recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_MB);
    recorder.setOutputFile(PATH_NAME);
    recorder.prepare();
    recorder.start();
    //录用中
    recorder.stop();
    recorder.reset();
    recorder.release();
    
第三部分 音乐播放
   法一、播放SD卡上的音乐:
    设置路径为/sdcatd/,所有需要先向SD卡中添加一些音频文件。步骤:启动模拟器---DDMS---File Explorer---向左向右分别是拷贝进,拷贝出指定位置,减号是删出选中文件。
   public class Activity01 extends ListActivity {
    /* 几个操作按钮 */
    private ImageButton mFrontImageButton = null;
    private ImageButton mStopImageButton = null;
    private ImageButton mStartImageButton = null;
    private ImageButton mPauseImageButton = null;
    private ImageButton mNextImageButton = null;
    public MediaPlayer mMediaPlayer  = null;// MediaPlayer对象
    private List<String> mMusicList = new ArrayList<String>();//播放列表
    private int currentListItme = 0;//当前播放歌曲的索引
    private static final String MUSIC_PATH = new String("/sdcard/");//音乐的路径
    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
     musicList();//更新显示播放列表
     mMediaPlayer  = new MediaPlayer();//构建MediaPlayer对象

     mFrontImageButton = (ImageButton) findViewById(R.id.LastImageButton);
     mStopImageButton = (ImageButton) findViewById(R.id.StopImageButton);
     mStartImageButton = (ImageButton) findViewById(R.id.StartImageButton);
     mPauseImageButton = (ImageButton) findViewById(R.id.PauseImageButton);
     mNextImageButton = (ImageButton) findViewById(R.id.NextImageButton);
    
     mStopImageButton.setOnClickListener(new ImageButton.OnClickListener() {//停止按钮
      public void onClick(View v){
       if (mMediaPlayer.isPlaying()){//是否正在播放    
        mMediaPlayer.reset();//首先需调用reset()方法,重置MediaPlayer到初始状态,这是必须的一步。
              作用:如果正在播放一首歌曲,同时又想去改变这个数据源(即启动下一首歌曲),此方法可将任何正在播放的歌曲。
              
       }
      }
     });  
     mStartImageButton.setOnClickListener(new ImageButton.OnClickListener() {//开始按钮
      public void onClick(View v){
       playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
      }
     });   
     mPauseImageButton.setOnClickListener(new ImageButton.OnClickListener(){//暂停
      public void onClick(View view){
       if (mMediaPlayer.isPlaying()){
        mMediaPlayer.pause();//暂停
       }else {
       mMediaPlayer.start();//开始播放
       }
      }
     }); 
     mNextImageButton.setOnClickListener(new ImageButton.OnClickListener(){//下一首
      public void onClick(View arg0){
       nextMusic();
      }
     }); 
     mFrontImageButton.setOnClickListener(new ImageButton.OnClickListener(){//上一首
      public void onClick(View arg0){
       FrontMusic();
      }
     });
    } 
    public boolean onKeyDown(int keyCode, KeyEvent event){
     if ( keyCode ==  KeyEvent.KEYCODE_BACK){
      mMediaPlayer.stop();
      mMediaPlayer.release();
      this.finish();
      return true;
     }
     return super.onKeyDown(keyCode, event);
    }
    protected void onListItemClick(ListView l, View v, int position, long id){ 当我们点击列表时,播放被点击的音乐
     currentListItme = position;
     playMusic(MUSIC_PATH + mMusicList.get(position));
    }
    public void musicList(){//播放列表  
     File home = new File(MUSIC_PATH);//取得指定位置的文件设置显示到播放列表
     if (home.listFiles(new MusicFilter()).length > 0){
      for (File file : home.listFiles(new MusicFilter())){
       mMusicList.add(file.getName());
      }
      ArrayAdapter<String> musicList = new ArrayAdapter<String>(Activity01.this,R.layout.musicitme, mMusicList);
      setListAdapter(musicList);//setListAdapter为装东西用的容器,给listView提供数据的作用
     }
    }
    private void playMusic(String path){
     try{
      //音乐文件播放步骤如下顺序不能乱
      mMediaPlayer.reset();//重置MediaPlayer
      mMediaPlayer.setDataSource(path);//设置要播放的文件的路径
      mMediaPlayer.prepare();//准备播放
      mMediaPlayer.start();//开始播放
      mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {//此处作用可理解为在播放完一首歌后对事件的监听,如下:设置了播放下一首
       public void onCompletion(MediaPlayer arg0){    
        nextMusic();//播放完成一首之后进行下一首
       }
      });
     }catch (IOException e){}
    }
    private void nextMusic(){//下一首
     if (++currentListItme >= mMusicList.size()){
      currentListItme = 0;
     }else{
      playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
     }
    }
    private void FrontMusic(){//上一首
     if (--currentListItme >= 0){
      currentListItme = mMusicList.size();
     }else{
      playMusic(MUSIC_PATH + mMusicList.get(currentListItme));
     }
    }
   }
  
   class MusicFilter implements FilenameFilter{//过滤文件类型 筛选出可以播放的格式
    public boolean accept(File dir, String name){ 
     return (name.endsWith(".mp3"));//这里还可以设置其他格式的音乐文件
    }
   }
   
   musicitem.xml文件
   <?xml version="1.0" encoding="utf-8"?>
    <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/TextView01"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="@string/hello"/>
     
   main.xml文件
   <?xml version="1.0" encoding="utf-8"?>
    <AbsoluteLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
     <ListView
      android:id="@id/android:list"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:layout_weight="1"
      android:drawSelectorOnTop="false"/>
     <ImageButton
      android:id="@+id/LastImageButton"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" 
      android:layout_x="10px"
      android:layout_y="70px"
      android:src="@drawable/last" 
      />
     <ImageButton
      android:id="@+id/StopImageButton"
      android:layout_height="wrap_content" 
      android:layout_width="wrap_content"
      android:layout_x="70px"
      android:layout_y="70px"
      android:src="@drawable/stop"
      /> 
     <ImageButton
      android:id="@+id/StartImageButton"
      android:layout_height="wrap_content" 
      android:layout_width="wrap_content"
      android:layout_x="130px"
      android:layout_y="70px"
      android:src="@drawable/start"
      />
     <ImageButton
      android:id="@+id/PauseImageButton"
      android:layout_height="wrap_content" 
      android:layout_width="wrap_content"
      android:layout_x="190px"
      android:layout_y="70px"
      android:src="@drawable/pause"
      /> 
     <ImageButton
      android:id="@+id/NextImageButton"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_x="250px"
      android:layout_y="70px"
      android:src="@drawable/next" 
      />
    </AbsoluteLayout>
   
   法二:播放res/raw中的音乐
   public class Activity01 extends Activity{
    private ImageButton mStopImageButton;
    private ImageButton mStartImageButton;
    private ImageButton mPauseImageButton;
    private TextView mTextView; 

    private boolean  bIsReleased  = false;
    private boolean  bIsPaused  = false;
    private boolean  bIsPlaying  = false;

    public MediaPlayer mMediaPlayer = new MediaPlayer();  ;
     public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

     mStopImageButton = (ImageButton) findViewById(R.id.StopImageButton);
     mStartImageButton = (ImageButton) findViewById(R.id.StartImageButton);
     mPauseImageButton = (ImageButton) findViewById(R.id.PauseImageButton);  
     mTextView = (TextView) findViewById(R.id.TextView01);   
     mStopImageButton.setOnClickListener(new ImageButton.OnClickListener() {//停止按钮
      public void onClick(View v){
       if (bIsPlaying == true){
        if ( !bIsReleased ){
         mMediaPlayer.stop();
         mMediaPlayer.release();
         bIsReleased = true; 
        }
        bIsPlaying = false;
        mTextView.setText("当前处于停止状态,请按开始进行音乐播放!");
       }
      }
     });   
     mStartImageButton.setOnClickListener(new ImageButton.OnClickListener() {//开始按钮
      public void onClick(View v){
       try{
        if ( !bIsPlaying ){ 
         bIsPlaying = true;
         mMediaPlayer = MediaPlayer.create(Activity01.this, R.raw.test);//使用create方法 装载资源中的音乐。此处还可以用create方法加载一个网络音乐
                         核心代码在下面的法三中。
         bIsReleased = false;
         mMediaPlayer.setLooping(true);//设置是否循环
         try{
          mMediaPlayer.prepare();
         }catch (IllegalStateException e){
          e.printStackTrace();
         }catch (IOException e){
          e.printStackTrace();
         }
         mMediaPlayer.start();
         mTextView.setText("当前正在播放音乐!");
        }
       }catch (IllegalStateException e){
        e.printStackTrace();
       }
       mMediaPlayer.setOnCompletionListener(new OnCompletionListener() {
        public void onCompletion(MediaPlayer arg0){
         mMediaPlayer.release();
        }
       });
      }
     });   
     mPauseImageButton.setOnClickListener(new ImageButton.OnClickListener() {//暂停
      public void onClick(View view){
       if (mMediaPlayer != null){
        if (bIsReleased == false){
         if (bIsPaused == false){
          mMediaPlayer.pause();
          bIsPaused = true;
          bIsPlaying = true;
          mTextView.setText("已经暂停,请再次按暂停按钮回复播放!");
         }else if (bIsPaused == true){
          mMediaPlayer.start();
          bIsPaused = false;
          mTextView.setText("音乐恢复播放!");
         }
        }
       }
      }
     });
     }
     public boolean onKeyDown(int keyCode, KeyEvent event){
      if ( keyCode ==  KeyEvent.KEYCODE_BACK){
       if ( !bIsReleased ){
        mMediaPlayer.stop();
        mMediaPlayer.release();
        bIsReleased = true; 
       }
       this.finish();
       return true;
      }
      return super.onKeyDown(keyCode, event);
     }
   }
   法三:在上例中使用了create方法不仅可以加载程序中的资源的索引,还可以加载一个Uri地址,当然这就说明我们可以播放网络音乐。
    其核心代码如下:
     private MediaPlayer mediaPlayer;
     Uri uri = Uri.parse("http://www.xxxx.com/xxx.mp3");
     mediaPlayer = MediaPlayer.create(this,uri);
     mediaPlayer.start();

第四部分 视频播放 VideoView
   目前Android平台仅支持MP4的H.264、3GP和WMV视频的解析。
   Android中内置的VideoView类可以快速制作一个系统播放器,VideoView主要用来显示一个视频文件其基本用法如下:
    getBufferPercentage                 得到缓冲的百分比
    getCurrentPostion     得到当前播放的位置
    getDuration       得到视频文件的时间
    isPlaying       是否在播放
    pause        暂停
    resolveAdjustedSize     调整视频显示大小
    seekTo        指定播放位置
    setMediaController     设置播放控制器模式(播放进度条)
    setOnCompletionListener    当媒体文件播放完成时触发事件
    setOnErrorListener     错误监听
    setVideoPath      设置视频源路径
    setVideoURI       设置视频源地址
    start        开始播放
    
   方法一:通过系统自带的VideoView播放一个MP4视频文件
    下来实现了播放MP4的播放。首先在布局文件中创建VideoView布局,并创建几个按钮
   main.xml文件
   <?xml version="1.0" encoding="utf-8"?>
    <AbsoluteLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
     <TextView 
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/hello"
     />
     <VideoView
      android:id="@+id/VideoView01"
      android:layout_width="320px"
      android:layout_height="240px"
     />
     <Button
      android:id="@+id/LoadButton"
      android:layout_width="80px"
      android:layout_height="wrap_content"
      android:text="装载"
      android:layout_x="30px"
      android:layout_y="300px"
     /> 
     <Button
      android:id="@+id/PlayButton"
      android:layout_width="80px"
      android:layout_height="wrap_content"
      android:text="播放"
      android:layout_x="120px"
      android:layout_y="300px"
     />
     <Button
      android:id="@+id/PauseButton"
      android:layout_width="80px"
      android:layout_height="wrap_content"
      android:text="暂停"
      android:layout_x="210px"
      android:layout_y="300px"
     />
    </AbsoluteLayout>

   public class Activity01 extends Activity{
    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

     final VideoView videoView = (VideoView) findViewById(R.id.VideoView01);//创建VideoView对象
     /* 操作播放的三个按钮 */
     Button PauseButton = (Button) this.findViewById(R.id.PauseButton);
     Button LoadButton = (Button) this.findViewById(R.id.LoadButton);
     Button PlayButton = (Button) this.findViewById(R.id.PlayButton);
  
     LoadButton.setOnClickListener(new OnClickListener() {//装载按钮事件
      public void onClick(View arg0){
       videoView.setVideoPath("/sdcard/test.mp4");//设置路径
       videoView.setMediaController(new MediaController(Activity01.this));//设置播放进度条
       videoView.requestFocus();//获取焦点
      }
     });
     PlayButton.setOnClickListener(new OnClickListener() {//播放按钮事件
      public void onClick(View arg0){
       videoView.start();//开始播放
      }
     });
     PauseButton.setOnClickListener(new OnClickListener() {//暂停按钮
      public void onClick(View arg0){
       videoView.pause();//暂停
      }
     });
    }
   }
   方法二  自定义一个播放视频的类
    原理:因为ViedoView是继承SurfaceView类的,且实现了MediaController.MediaPlayerControl接口。所以我们同样可以使用SurfaceView类来显示视频
     首先在布局文件中创建一个SurfaceView。因要通过SurfaceHolder来控制SurfaceView,所以要通过getHolder方法来得到SurfaceView的SurfaceHolder对象。
     如下例:
   <?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">
     <SurfaceView
      android:id="@+id/surface"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="center">
     </SurfaceView>
    </LinearLayout>

   public class Activity01 extends Activity implements
                OnBufferingUpdateListener,
                OnCompletionListener,
                MediaPlayer.OnPreparedListener,
                SurfaceHolder.Callback{
    private static final String TAG = "Activity01";
    private int     mVideoWidth;
    private int     mVideoHeight;
    private MediaPlayer   mMediaPlayer;
    private SurfaceView   mPreview;
    private SurfaceHolder  holder;
    private String    path;
    public void onCreate(Bundle icicle){
     super.onCreate(icicle);
     setContentView(R.layout.main);
  
     mPreview = (SurfaceView) findViewById(R.id.surface);//得打SurfaceView对象
     holder = mPreview.getHolder();//得到SurfaceHolder对象
     holder.addCallback(this);//设置回调函数
     holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);//设置风格
    }
    private void playVideo(){
     try{
      path = "/sdcard/test.mp4";//设置MP4路径
      mMediaPlayer = new MediaPlayer();//构建MediaPlayer对象
      mMediaPlayer.setDataSource(path);//设置媒体文件路径
      mMediaPlayer.setDisplay(holder);//设置通过SurfaceView来显示画面
      mMediaPlayer.prepare();//准备
 
      mMediaPlayer.setOnBufferingUpdateListener(this);//设置事件监听
      mMediaPlayer.setOnCompletionListener(this);
      mMediaPlayer.setOnPreparedListener(this);
      mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
     }catch (Exception e){
      Log.e(TAG, "error: " + e.getMessage(), e);
     }
    }
    public void onBufferingUpdate(MediaPlayer arg0, int percent){
     Log.d(TAG, "onBufferingUpdate percent:" + percent);
    }
    public void onCompletion(MediaPlayer arg0){
     Log.d(TAG, "onCompletion called");
    }
    public void onPrepared(MediaPlayer mediaplayer){
     Log.d(TAG, "onPrepared called");
     mVideoWidth = mMediaPlayer.getVideoWidth();
     mVideoHeight = mMediaPlayer.getVideoHeight();
     if (mVideoWidth != 0 && mVideoHeight != 0){
      holder.setFixedSize(mVideoWidth, mVideoHeight);//设置视频的宽度和高度
      mMediaPlayer.start();// 开始播放
     } 
    }
    public void surfaceChanged(SurfaceHolder surfaceholder, int i, int j, int k){//更改时出发的事件
     Log.d(TAG, "surfaceChanged called");
    }
    public void surfaceDestroyed(SurfaceHolder surfaceholder){// 销毁
     Log.d(TAG, "surfaceDestroyed called");
    }
    public void surfaceCreated(SurfaceHolder holder){//当SurfaceHolder创建时触发
     Log.d(TAG, "surfaceCreated called");
     playVideo();
    }
    protected void onDestroy(){//销毁
     super.onDestroy();
     if (mMediaPlayer != null){
      mMediaPlayer.release();//释放资源
      mMediaPlayer = null;
     }
    }
   }
第五部分 录音功能
   录用使用的是MediaRecorder类
   下例中首先在界面上放置一个ListView来显示文件列表,一个开始、一个停止按钮。当点击"开始"按钮后就构建MediaRecorder对象,并设置声音的来源(setAudioSource)、输出文件的格式
   (setOutPutFormat)、音频文件的编码(setAudioEncoder)、输出文件的路径(setOutputFile)等;然后准备开始录音(prepare),开始录音(start)。最后停止录音(stop),然后释放MediaRecorder
   对象(release),完成录音。
   list.xml文件
   <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:
     android="http://schemas.android.com/apk/res/android"
     android:id="@+id/TextView01"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="@string/hello"/>
     
   main.xml文件
   <?xml version="1.0" encoding="utf-8"?>
   <AbsoluteLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <ListView
     android:id="@id/android:list"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:layout_weight="1"
     android:drawSelectorOnTop="false"/>
    <Button
     android:id="@+id/StartButton"
     android:layout_width="80px"
     android:layout_height="wrap_content"
     android:text="开始"
     android:layout_x="70px"
     android:layout_y="100px"
    /> 
    <Button
     android:id="@+id/StopButton"
     android:layout_width="80px"
     android:layout_height="wrap_content"
     android:text="停止"
     android:layout_x="170px"
     android:layout_y="100px"
    />
   </AbsoluteLayout>

   public class Activity01 extends ListActivity{
    private Button   StartButton;
    private Button   StopButton;

    private File   mRecAudioFile;//录制的音频文件
    private File   mRecAudioPath;//SD卡路径
    private MediaRecorder mMediaRecorder;//MediaRecorder对象
    private List<String> mMusicList = new ArrayList<String>();//录音文件列表
    private String   strTempFile = "recaudio_";//零时文件的前缀

    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);

     StartButton = (Button) findViewById(R.id.StartButton);
     StopButton = (Button) findViewById(R.id.StopButton);

     if (Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){//检测是否存在SD卡
      mRecAudioPath = Environment.getExternalStorageDirectory();//通过getExternalStorageDirectory()得到SD卡的路径
      musicList();//更新所有录音文件到List中
     }else{
      Toast.makeText(Activity01.this, "没有SD卡", Toast.LENGTH_LONG).show();
     }
     StartButton.setOnClickListener(new Button.OnClickListener() {//开始按钮事件监听
     @Override
      public void onClick(View arg0){
       try{
        mRecAudioFile = File.createTempFile(strTempFile, ".amr", mRecAudioPath);//创建录音文件
        mMediaRecorder = new MediaRecorder();//实例化MediaRecorder对象
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置麦克风
        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.DEFAULT);//设置输出文件的格式
        mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);//设置音频文件的编码
        mMediaRecorder.setOutputFile(mRecAudioFile.getAbsolutePath());//设置输出文件的路径
        mMediaRecorder.prepare();//准备
        mMediaRecorder.start();//开始
       }catch (IOException e){
        e.printStackTrace();
       }
      }
     });
     StopButton.setOnClickListener(new Button.OnClickListener() {//停止按钮事件监听
     @Override
      public void onClick(View arg0){
       if (mRecAudioFile != null){
    
        mMediaRecorder.stop();//停止录音   
        mMusicList.add(mRecAudioFile.getName());//将录音文件添加到List中
        ArrayAdapter<String> musicList = new ArrayAdapter<String>(Activity01.this, R.layout.list, mMusicList);
        setListAdapter(musicList);
     
        mMediaRecorder.release();//释放MediaRecorder
        mMediaRecorder = null;
       }
      }
     });
    }
    private void playMusic(File file){//播放录音文件
     Intent intent = new Intent();
     intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
     intent.setAction(android.content.Intent.ACTION_VIEW);
     intent.setDataAndType(Uri.fromFile(file), "audio");//设置文件类型
     startActivity(intent);
    }
    protected void onListItemClick(ListView l, View v, int position, long id){//当我们点击列表时,播放被点击的音乐
     File playfile = new File(mRecAudioPath.getAbsolutePath() + File.separator + mMusicList.get(position));//得到被点击的文件
     playMusic(playfile);// 播放
    }
    public void musicList(){//播放列表
     // 取得指定位置的文件设置显示到播放列表
     File home = mRecAudioPath;
     if (home.listFiles(new MusicFilter()).length > 0){
      for (File file : home.listFiles(new MusicFilter())){
       mMusicList.add(file.getName());
      }
      ArrayAdapter<String> musicList = new ArrayAdapter<String>(Activity01.this, R.layout.list, mMusicList);
      setListAdapter(musicList);
     }
    }
   }

   class MusicFilter implements FilenameFilter{//过滤文件类型
    public boolean accept(File dir, String name){
     return (name.endsWith(".amr"));//文件保存在SD卡中为amr文件格式 查看:DDMS---File Explorer---sdcartd中
    }
   }
第六部分 相机设置
   在Android中专门提供了Camera类来处理相机事件,是一个专门用来连接和断开相机服务的类。
   Camera 有如下事件
    Camera.AutoFocusCallback  自动调焦功能
    Camera.ErrorCallback  错误信息扑捉
    Camera.Parameters   相机的属性参数
    Camera.PictureCallback  拍照、产生图片时触发
    Camera.PreviewCallback  相机预览设置
    Camera.ShutterCallback  快门设置
    Camera.Size     图片的尺寸
   
   Camera类的方法:
    autoFocus    设置自动对焦
    getParameters   得到相机的参数
    open     启动相机服务
    release     释放相机服务
    setParameters   设置预览参数
    setPreviewDisplay  设置预览
    startPreview   开始预览
    stopPreview    停止预览
    takePicture    拍照
   Camera没有构造方法,要使用它可直接通过open方法来打开相机设备,然后通过Camera.Parameters对相机的一些属性进行设置,如图片的格式,大小等。
   takePicture拍照方法的使用要实现3个回调函数,即Camera.ShutterCallback(快门)和两个Camera.PictureCallback(图像数据)。
   拍照后要取得图像数据要实现Camera.PictureCallback的onPictureTaken方法(此方法第一个参数就是图像数据,第二个参数是相机)
   下面为一个相机拍照例子。相机需要一个界面来预览当前拍摄的效果,这里可以使用SurfaceView类。最后将照片保存到SD开中(注意:确定SD卡已经插入)
   
   public class Activity01 extends Activity{
    private Preview mPreview;

    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
  
     requestWindowFeature(Window.FEATURE_NO_TITLE);
     mPreview = new Preview(this);//创建预览视图
     setContentView(mPreview);//设置显示
    }
    public boolean onKeyUp(int keyCode, KeyEvent event){
     switch (keyCode){
      case KeyEvent.KEYCODE_DPAD_CENTER:
       mPreview.takePicture();
       break;
     }
     return true;
    }
   }

   class Preview extends SurfaceView implements SurfaceHolder.Callback{ //显示预览
    SurfaceHolder mHolder;
    Camera mCamera;
    Bitmap CameraBitmap;
   
    Preview(Context context){
     super(context);
     mHolder = getHolder();
     mHolder.addCallback(this);
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }
    public void surfaceCreated(SurfaceHolder holder) {
     mCamera = Camera.open();//启动Camera
     try {
      mCamera.setPreviewDisplay(holder);
     }catch (IOException exception) {
      mCamera.release();//释放mCamera
      mCamera = null;
     }
    }
    public void surfaceDestroyed(SurfaceHolder holder) {
     mCamera.stopPreview();//停止预览
     mCamera = null;
    }   
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
     Camera.Parameters parameters = mCamera.getParameters();//构建Camera.Parameters对相机的参数进行设置
     parameters.setPictureFormat(PixelFormat.JPEG);//设置拍照的图片格式
     parameters.setPreviewSize(320, 480);//设置Preview的尺寸
      //parameters.setPictureSize(320, 480);//设置图像分辨率
     mCamera.setParameters(parameters);//设置相机的预览参数
     mCamera.startPreview();// 开始预览
    }
    public void takePicture(){//拍照片
     if (mCamera != null){
      mCamera.takePicture(null, null, jpegCallback);
     }
    }
    private PictureCallback jpegCallback = new PictureCallback(){//拍照后输出图片
     public void onPictureTaken(byte[] _data, Camera _camera){//第一个参数就是图像数据,第二个参数是相机
      // 处理的JPEG数据资源
      CameraBitmap = BitmapFactory.decodeByteArray(_data, 0, _data.length);
      File myCaptureFile = new File("/sdcard/camera1.jpg");
      try{
       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));
       CameraBitmap.compress(Bitmap.CompressFormat.JPEG, 80, bos);
       bos.flush();//冲洗照片
       bos.close();
       /* 将拍到的图片绘制出来 */
       Canvas canvas= mHolder.lockCanvas();
       canvas.drawBitmap(CameraBitmap, 0, 0, null);
       mHolder.unlockCanvasAndPost(canvas);        
      }catch (Exception e){
       e.getMessage();
      }
     }
    };
   }
第七部分 闹钟的设置
   在Android中可以通过AlarmManager来实现闹钟,AlarmManager类是专门用来设定在某个指定的时间去完成指定的事件。
   AlarmManager提供了访问系统警报的服务,只要在程序中设置了警报服务,AlarmManger就会通过onReceive()方法去执行这些事件,就算系统处于待机状态,同样不会影响运行。可
   通过Context.getSystemService方法来获得改服务。
   AlarmManager的方法:
    cancel    取消AlarmManager服务
    set     设置AlarmManager服务
    setInexactRepeating 设置不精确周期
    setRepeating  设置精确周期
    setTimeZone   设置时区
   要实现闹钟,首先需要创建一个继承BroadcastReceiver的类,实现onReceive方法来接收这个Alarm服务,然后通过建立Intent和PendingIntent连接来调用Alarm组件。
   下例中我们点击"设置闹钟"按钮时,通过TimePickerDialog来设置时间。
   main.xml文件
   <?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"
     >
     <TextView 
      android:id="@+id/TextView01"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="@string/hello"
     />
     <Button
      android:id="@+id/Button01"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="设置闹钟"
     />
     <Button
      android:id="@+id/Button02"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:text="取消闹钟"
     />
    </LinearLayout>

   public class AlarmReceiver extends BroadcastReceiver{//创建接收Alarm服务的AlarmReceiver类。因使用了BroadcastReceiver服务,需要在AndroidManifest.xml中进行声明
                  代码如:<receiver android:name = ".AlarmReceiver" android:process =":remote"/>
    public void onReceive(Context context, Intent intent){
     Toast.makeText(context, "你设置的闹钟时间到了", Toast.LENGTH_LONG).show();
    }
   }
   public class Activity01 extends Activity{
    Button mButton1;
    Button mButton2;
    TextView mTextView;
    Calendar calendar;

    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main);
     
     calendar=Calendar.getInstance();
  
     mTextView=(TextView)findViewById(R.id.TextView01);
     mButton1=(Button)findViewById(R.id.Button01);
     mButton2=(Button)findViewById(R.id.Button02);
  
     mButton1.setOnClickListener(new View.OnClickListener(){
      public void onClick(View v){
       calendar.setTimeInMillis(System.currentTimeMillis());
       int mHour=calendar.get(Calendar.HOUR_OF_DAY);
       int mMinute=calendar.get(Calendar.MINUTE);
       new TimePickerDialog(Activity01.this,
        new TimePickerDialog.OnTimeSetListener(){               
         public void onTimeSet(TimePicker view,int hourOfDay,int minute){
          calendar.setTimeInMillis(System.currentTimeMillis());
          calendar.set(Calendar.HOUR_OF_DAY,hourOfDay);
          calendar.set(Calendar.MINUTE,minute);
          calendar.set(Calendar.SECOND,0);
          calendar.set(Calendar.MILLISECOND,0);
          /* 建立Intent和PendingIntent,来调用目标组件 */
          Intent intent = new Intent(Activity01.this, AlarmReceiver.class);
          PendingIntent pendingIntent=PendingIntent.getBroadcast(Activity01.this,0, intent, 0);
          AlarmManager am;
          am = (AlarmManager)getSystemService(ALARM_SERVICE);//获取闹钟管理的实例
          am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);//设置闹钟
          am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (10*1000), (24*60*60*1000), pendingIntent); //设置周期闹
          String tmpS="设置闹钟时间为"+format(hourOfDay)+":"+format(minute);
          mTextView.setText(tmpS);
         }         
        },mHour,mMinute,true).show();
      }
     });  
     mButton2.setOnClickListener(new View.OnClickListener(){
      public void onClick(View v){
       Intent intent = new Intent(Activity01.this, AlarmReceiver.class);
       PendingIntent pendingIntent=PendingIntent.getBroadcast(Activity01.this,0, intent, 0);
       AlarmManager am;
       am =(AlarmManager)getSystemService(ALARM_SERVICE);//获取闹钟管理的实例
       am.cancel(pendingIntent);//取消闹钟设置
       mTextView.setText("闹钟已取消!");
      }
     });
    }  
    private String format(int x){//格式化字符串(7:3->07:03)
     String s = "" + x;
     if (s.length() == 1){
      s = "0" + s;
     }
     return s;
    }
   }
第八部分 铃声设置
   在Android中可通过RingtoneManager类专门来操作各种铃声,比如来的铃声,闹钟铃声以及警告和通知铃声。
   Android自带的系统铃声都放置在"/system/medio/audio"文件中,自己下载的铃声都在SD卡中,那么就要在SD卡中建立如下文件目录
    /sdcard/music/ringtones: 一般铃声 (来电铃声)
    /sdcard/music/alarms: 闹钟铃声
    /sdcard/music/notificaitons: 警告或通知铃声
    可在DDMS ---File Explorer---sdcard中查看
   RingtoneManager类的常用方法
    getActualDefaultRingtoneUri  取得指定类型当前默认的铃声
    getCursor      返回所有可用铃声的游标
    getDefaultType     得到指定URI默认的铃声类型
    getRingtone      获得当前游标所指定的铃声,返回指定铃声的URI
    getDefaultUri     返回指定类型默认铃声的URI
    getRingtonePosition    得到指定铃声的位置
    getRingtongUri     获得得到指定位置的铃声URI
    getValidRingtoneUri    得到一个可用铃声的URI
    idDefault      得到指定的URI是否是默认的铃声
    setActualDefaultRingtoneUri  设置默认的铃声
   例:
   public class Activity01 extends Activity{
    private Button mButtonRingtone;//3个按钮
    private Button mButtonAlarm;
    private Button mButtonNotification;

    public static final int ButtonRingtone   = 0;//来电铃声
    public static final int ButtonAlarm    = 1;//警报铃声
    public static final int ButtonNotification  = 2;//通知铃声
 
    private String strRingtoneFolder = "/sdcard/music/ringtones";//来电铃声文件夹
    private String strAlarmFolder = "/sdcard/music/alarms";//警报铃声文件夹
    private String strNotificationFolder = "/sdcard/music/notifications";//通知铃声文件夹

    public void onCreate(Bundle savedInstanceState){
     super.onCreate(savedInstanceState);
     setContentView(R.layout.main);
 
     mButtonRingtone = (Button) findViewById(R.id.ButtonRingtone);
     mButtonAlarm = (Button) findViewById(R.id.ButtonAlarm);
     mButtonNotification = (Button) findViewById(R.id.ButtonNotification);
 
     mButtonRingtone.setOnClickListener(new Button.OnClickListener(){//设置来电铃声
      @Override
      public void onClick(View arg0){
       if (bFolder(strRingtoneFolder)){    
        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);//打开系统铃声设置    
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_RINGTONE);//类型为来电RINGTONE     
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "设置来电铃声");//设置显示的title     
        startActivityForResult(intent, ButtonRingtone);//当设置完成之后开启并返回到当前的Activity
       }
      }
     });
     mButtonAlarm.setOnClickListener(new Button.OnClickListener(){//设置闹钟铃声
      @Override
      public void onClick(View arg0){
       if (bFolder(strAlarmFolder)){     
        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);//打开系统铃声设置     
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_ALARM);//设置铃声类型和title
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "设置闹铃铃声");     
        startActivityForResult(intent, ButtonAlarm);//当设置完成之后返回到当前的Activity
       }
      }
     });
     mButtonNotification.setOnClickListener(new Button.OnClickListener(){//设置通知铃声
      @Override
      public void onClick(View arg0){
       if (bFolder(strNotificationFolder)){    
        Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); //打开系统铃声设置     
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);//设置铃声类型和title
        intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TITLE, "设置通知铃声");     
        startActivityForResult(intent, ButtonNotification);//当设置完成之后返回到当前的Activity
       }
      }
     });
    }
    protected void onActivityResult(int requestCode, int resultCode, Intent data){//设置铃声之后的回调函数。当选择了需要设置为铃声的音乐后,系统会调用onActivityResult
                       方法来处理我们所进行的设置,所有需要重写onActivityResult,并根据设置的不同类型的铃声来
                       告诉系统我们的设置。
     if (resultCode != RESULT_OK){
      return;
     }switch (requestCode){
      case ButtonRingtone:
       try{    
        Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);//得到我们选择的铃声     
        if (pickedUri != null){
         RingtoneManager.setActualDefaultRingtoneUri(Activity01.this, RingtoneManager.TYPE_RINGTONE, pickedUri);//将我们选择的铃声设置成为默认
        }
       }catch (Exception e){
       }
       break;
      case ButtonAlarm:
       try{     
        Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);//得到我们选择的铃声     
        if (pickedUri != null){
         RingtoneManager.setActualDefaultRingtoneUri(Activity01.this, RingtoneManager.TYPE_ALARM, pickedUri);//将我们选择的铃声设置成为默认
       }
       }catch (Exception e){
       }
       break;
      case ButtonNotification:
       try{     
        Uri pickedUri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);//得到我们选择的铃声    
        if (pickedUri != null){
         RingtoneManager.setActualDefaultRingtoneUri(Activity01.this, RingtoneManager.TYPE_NOTIFICATION, pickedUri);//将我们选择的铃声设置成为默认
        }
       }catch (Exception e){
       }
       break;
     }
     super.onActivityResult(requestCode, resultCode, data);
    }
    private boolean bFolder(String strFolder){//检测是否存在指定的文件夹,如果不存在则创建
     boolean btmp = false;
     File f = new File(strFolder);
     if (!f.exists()){
      if (f.mkdirs()){
       btmp = true;
      }else{
       btmp = false;
      }
     }else{
      btmp = true;
     }
     return btmp;
    }
   }

你可能感兴趣的:(音乐播放器、视频播放器、录音、照相、闹钟、铃声设计中的各种方法以及例子总结)