• android 使用 service 实现音乐


    今天的球员趁service。播放音乐service结束,进度条activity结束,因此,基础工作activity和service互动,本文将使用IBinder互动。主要activity能够调用service的函数。能够參考我的这篇博客

    本文关键点:利用利用IBinder实现activity 控制service 

    实现功能:

    1 控制播放进度:

    activity调用service的函数,对MediaPlayer进行控制。

    包含启动时的播放和滑动seekbar时。对MediaPlayer进行设置,达到控制播放进度的控制。

    2 播放进度更新:

      在activity开启多线程。后台每隔100ms就发送一次message,在UI线程中利用handler对message进行判定,之后activity调用service的函数。得到播放的进度(百分比),及时更新seekbar的进度条。

    效果图例如以下:


    布局非常easy,例如以下所看到的:

    <?xml version="1.0" encoding="utf-8"?

    > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="play"/> <Button android:id="@+id/playButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="play" /> <Button android:id="@+id/pauseButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="pause" /> <SeekBar android:id="@+id/seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:max="100" android:progress="10" /> </LinearLayout>

    activity的代码例如以下:

    <pre name="code" class="java">public class MainActivity extends Activity {
    
    	Boolean mBound = false;
    	
    	MusicService mService;
    	
    	SeekBar seekBar;
    	
    	//多线程,后台更新UI
    	Thread myThread;
    	
    	//控制后台线程退出
    	boolean playStatus = true;
    	
    	
    	//处理进度条更新
    	Handler mHandler = new Handler(){
    		@Override  
            public void handleMessage(Message msg){  
    			switch (msg.what){
    				case 0:
    					//从bundle中获取进度。是double类型,播放的百分比
    					double progress = msg.getData().getDouble("progress");
    					
    					//依据播放百分比,计算seekbar的实际位置 
    		            int max = seekBar.getMax();  
    		            int position = (int) (max*progress);
    		            
    		            //设置seekbar的实际位置
    		            seekBar.setProgress(position);  
    		            break;
    		        default:
    		        	break;
    			}
                
            }  
    	};
    	
    	
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		//定义一个新线程。用来发送消息。通知更新UI
    		myThread = new Thread(new MyThread());
    		
    		
    		//绑定service;
    		Intent serviceIntent = new Intent(this , MusicService.class);
    		
    		//假设未绑定,则进行绑定
    		if(!mBound){
    			bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
    		}
    			
    		//初始化播放button
    		Button playButton = (Button)findViewById(R.id.playButton);
    		playButton.setOnClickListener(new OnClickListener(){
    
    			@Override
    			public void onClick(View arg0) {
    				// TODO Auto-generated method stub	
    				if(mBound){
    					mService.play();
    				}			
    			}
    			
    		});
    		
    		//初始化暂停button
    		Button pauseButton = (Button)findViewById(R.id.pauseButton);	
    		pauseButton.setOnClickListener(new OnClickListener(){
    			@Override
    			public void onClick(View arg0) {
    				// TODO Auto-generated method stub
    				//首先须要判定绑定情况
    				if(mBound){
    					mService.pause();
    				}
    			}
    		});
    		
    	    seekBar = (SeekBar)findViewById(R.id.seekbar);
    		seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
    			
    			@Override
    			public void onStopTrackingTouch(SeekBar seekBar) {
    			//手动调节进度
    				// TODO Auto-generated method stub
    				//seekbar的拖动位置
    				int dest = seekBar.getProgress();
    				//seekbar的最大值
    				int max = seekBar.getMax();
    				//调用service调节播放进度
    				mService.setProgress(max, dest);
    			}
    
    			@Override
    			public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
    				// TODO Auto-generated method stub
    				
    			}
    
    			@Override
    			public void onStartTrackingTouch(SeekBar arg0) {
    				// TODO Auto-generated method stub
    				
    			}
    			
    		});		
    				
    	}
    	
    	//实现runnable接口。多线程实时更新进度条
    	public class MyThread implements Runnable{
    		
    	
    		//通知UI更新的消息
    		
    		
    		//用来向UI线程传递进度的值
    		Bundle data = new Bundle();
    		
    		//更新UI间隔时间
    		int milliseconds = 100;
    		double progress;
    		@Override
    		public void run() {
    			// TODO Auto-generated method stub
    			
    			//用来标识是否还在播放状态,用来控制线程退出
    			while(playStatus){  
    				
                    try {  
                    	//绑定成功才干開始更新UI
                        if(mBound){
                        	
                        	//发送消息,要求更新UI
                        	
                        	Message msg = new Message();
                        	data.clear();
                 	
                        	progress = mService.getProgress();
                			msg.what = 0;
                			
                			data.putDouble("progress", progress);
                			msg.setData(data);
                			mHandler.sendMessage(msg);
                        }
                        Thread.sleep(milliseconds);  
            			//Thread.currentThread().sleep(milliseconds);  
    					//每隔100ms更新一次UI
            			
                    } catch (InterruptedException e) {  
                        // TODO Auto-generated catch block  
                        e.printStackTrace();  
                    }  
    			
    			}
    		}
    		
    	}
    	
    	 /** Defines callbacks for service binding, passed to bindService() */  
        private ServiceConnection mConnection = new ServiceConnection() {  
      
            @Override  
            public void onServiceConnected(ComponentName className,  
                    IBinder binder) {  
                // We've bound to LocalService, cast the IBinder and get LocalService instance  
            	MyBinder myBinder = (MyBinder) binder;
                
            	//获取service
            	mService = (MusicService) myBinder.getService();  
                
                //绑定成功
                mBound = true;  
                
                //开启线程,更新UI
                myThread.start();
            }  
      
            @Override  
            public void onServiceDisconnected(ComponentName arg0) {  
                mBound = false;  
            }  
        };  
    	   
    	@Override
    	public boolean onCreateOptionsMenu(Menu menu) {
    		// Inflate the menu; this adds items to the action bar if it is present.
    		getMenuInflater().inflate(R.menu.main, menu);
    		return true;
    	}
    	
    	@Override
    	public void onDestroy(){
    		//销毁activity时。要记得销毁线程
    		playStatus = false;
    		super.onDestroy();
    	}
    
    }
    


    
    service的代码例如以下:
    

    public class MusicService extends Service {
    
    	
    	IBinder musicBinder  = new MyBinder();
    	
    	//获取到activity的Handler。用来通知更新进度条
    	Handler mHandler; 
    	
    	//播放音乐的媒体类
    	MediaPlayer mediaPlayer;
    	
    	//本地歌曲的路径
        String path = "/storage/sdcard1/Music/浪漫满屋.mp3";
        
        private String TAG = "MyService";
    	
    	@Override  	
        public void onCreate() {  
            super.onCreate();  
            Log.d(TAG, "onCreate() executed");  
            
            init();
            
        }  
      
    	@Override
    	public IBinder onBind(Intent arg0) {
    		// TODO Auto-generated method stub
    	    //当绑定后。返回一个musicBinder
    		return musicBinder;
    	}
    	
    	class MyBinder extends Binder{
    		
    		public Service getService(){
    			return MusicService.this;
    		}
    	}
    	
    	//初始化音乐播放
    	void init(){
    		//进入Idle
    		mediaPlayer = new MediaPlayer();
    		try {
    			//初始化
    			mediaPlayer.setDataSource(path);
    		    
    			mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);  
    			
    			// prepare 通过异步的方式装载媒体资源
    			mediaPlayer.prepareAsync();
    		
    		} catch (Exception e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    	
    	//返回当前的播放进度,是double类型,即播放的百分比
    	public double getProgress(){
    		int position = mediaPlayer.getCurrentPosition();  
            
            int time = mediaPlayer.getDuration();  
            
            double progress = (double)position / (double)time;
            
            return progress;  
    	}
    	
    	//通过activity调节播放进度
    	public void setProgress(int max , int dest){	
    		int time = mediaPlayer.getDuration();
    		mediaPlayer.seekTo(time*dest/max);
    	}
    	
    	//測试播放音乐
    	public void play(){		
    		if(mediaPlayer != null){
    			mediaPlayer.start();
    		}
    			
    	}
    	//暂停音乐   
        public void pause() {  
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {  
                mediaPlayer.pause();  
            }  
        }  
        
      //service 销毁时。停止播放音乐,释放资源
      	@Override
      	public void onDestroy() {
    	     // 在activity结束的时候回收资源
    	     if (mediaPlayer != null && mediaPlayer.isPlaying()) {
    	         mediaPlayer.stop();
    	         mediaPlayer.release();
    	         mediaPlayer = null;
    	     }
    	     super.onDestroy();
         }
    }

    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    ILMerge将源DLL合并到目标EXE
    Nginx+redis的Asp.net
    JwtBearer认证
    Token认证登录以及权限控制
    ES索引
    Linux文本编辑器vim
    集群 安装 配置FastDFS
    When to use next() and return next() in Node.js
    spring-boot-starter-druid
    nodejs express
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4611245.html
Copyright © 2020-2023  润新知