(一)service和activity通訊方式
阿新 • • 發佈:2018-12-21
實現效果圖:
使用service在後臺播放音樂,拖動進度條,與服務進行互動,改變音樂的播放進度
(1)首先,我們需要申請讀取本地檔案的許可權,播放本機的音樂
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
(2)把服務註冊了。因為服務是四大元件之一,需要註冊,位置和activity平行
<service
android:name="com.example.administrator.testz.MusicService"
android:enabled="true"
android:exported="true">
</service>
(3)使用MyBind接收資料,進出處理 ,重點是code,根據code的值來進行服務和介面的互動
import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.app.Service; import android.content.Intent; import android.media.MediaPlayer; import android.os.Binder; import android.os.Build; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.support.annotation.Nullable; import android.support.annotation.RequiresApi; import android.view.animation.LinearInterpolator; import java.io.IOException; /** * Created by Administrator on 2018\11\13 0013. */ public class MusicService extends Service { private int flag = 0; public static MediaPlayer mediaPlayer = new MediaPlayer(); private IBinder mBinder = new MyBinder(); public static ObjectAnimator animator; public static String which= ""; public static int returnFlag = 0; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder;//一定要返回binder } public class MyBinder extends Binder{ @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code){ case 101: //播放 處理服務的函式 playOrPauseHandler(); break; case 102: //處理服務的函式 停止 stopHandler(); break; case 103: //處理服務的函式 退出 quitHandler(); break; case 104: //處理服務的函式 介面重新整理 break; case 105: //處理服務的函式 拖動進度處理 break; default: break; } return super.onTransact(code, data, reply, flags); } } //退出 private void quitHandler() { animator.end(); mediaPlayer.stop(); mediaPlayer.release(); } //停止 private void stopHandler() { which = "stop"; animator.pause(); if(mediaPlayer != null){ mediaPlayer.pause(); mediaPlayer.stop(); try { mediaPlayer.prepare(); mediaPlayer.seekTo(0); } catch (IOException e) { e.printStackTrace(); } } } //播放 @RequiresApi(api = Build.VERSION_CODES.KITKAT) private void playOrPauseHandler() { flag++; if(flag>=1000){ flag=2; } which = "pause"; if(mediaPlayer.isPlaying()){ mediaPlayer.pause(); animator.pause(); }else { mediaPlayer.start(); if(flag==1 || returnFlag == 1){ animator.setDuration(5000); //設定持續時間 animator.setInterpolator(new LinearInterpolator()); //設定勻速轉動 animator.setRepeatCount(ValueAnimator.INFINITE); //設定無限迴圈 animator.setRepeatMode(ValueAnimator.RESTART); //設定重複模式 RESTART:重新從頭開始執行。 REVERSE:反方向執行 animator.start(); //開始 }else{ animator.start(); } } } //獲取檔案路徑 設定播放屬性 public MusicService(){ try { String Assets_path1 = "/storage/emulated/0/Android/data/暗香.mp3"; mediaPlayer.setDataSource(Assets_path1); mediaPlayer.prepare(); //prepare()或prepareAsync()方法把流媒體裝載進MediaPlayer,呼叫start()方法播放流媒體 mediaPlayer.setLooping(true); //設定是否迴圈播放。 }catch (Exception e){ e.printStackTrace(); } } //設定轉動 public void setAnimation(){ if(mediaPlayer.isPlaying()){ animator.setDuration(5000); //設定持續時間 animator.setInterpolator(new LinearInterpolator()); //設定勻速轉動 animator.setRepeatCount(ValueAnimator.INFINITE); //設定無限迴圈 animator.setRepeatMode(ValueAnimator.RESTART); //設定重複模式 RESTART:重新從頭開始執行。 REVERSE:反方向執行 animator.start(); //開始 } } @Override public void onDestroy() { super.onDestroy(); mediaPlayer.stop(); mediaPlayer.release(); //釋放資源 } }
(4)主介面呼叫
import android.Manifest; import android.animation.ObjectAnimator; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.icu.text.SimpleDateFormat; import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.support.annotation.NonNull; import android.support.annotation.RequiresApi; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.ImageView; import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; @RequiresApi(api = Build.VERSION_CODES.N) public class MainActivity extends AppCompatActivity implements View.OnClickListener { private IBinder mBinder; private ServiceConnection mConnection; /*控制元件*/ private Button playButton; private Button stopButton; private Button quitButton; private ImageView image; private TextView currentTime; private TextView endTime; private TextView txt_state; private SeekBar seekBar; private MusicService musicService; private SimpleDateFormat time = new SimpleDateFormat("mm:ss"); public Handler handler = new Handler(); public Runnable runnable = new Runnable() { @Override public void run() { if(musicService.mediaPlayer.isPlaying()){ txt_state.setText("Playing"); }else{ if(musicService.which.equals("stop")){ txt_state.setText("stop"); }else if(musicService.which.equals("pause")){ txt_state.setText("pause"); } } currentTime.setText(time.format(musicService.mediaPlayer.getCurrentPosition())); endTime.setText(time.format(musicService.mediaPlayer.getDuration())); seekBar.setProgress(musicService.mediaPlayer.getCurrentPosition()); seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { if(b){ //直接拖懂 mediaplayer的seekto方法 musicService.mediaPlayer.seekTo(seekBar.getProgress()); } } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); handler.postDelayed(runnable,100); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); musicService = new MusicService(); //繫結服務,開啟服務 mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder iBinder) { mBinder = iBinder; //資料繫結 } @Override public void onServiceDisconnected(ComponentName componentName) { mConnection = null; } }; Intent intent = new Intent(this,MusicService.class); startService(intent); bindService(intent,mConnection, Context.BIND_AUTO_CREATE); //初始化 initViews(); initEvent(); //事件 } private void initEvent() { playButton.setOnClickListener(this); stopButton.setOnClickListener(this); quitButton.setOnClickListener(this); } private void initViews() { image = (ImageView)findViewById(R.id.image); txt_state = (TextView)findViewById(R.id.txt_state); currentTime = (TextView)findViewById(R.id.start_time); endTime = (TextView)findViewById(R.id.end_time); seekBar = (SeekBar)findViewById(R.id.seekbar); playButton = (Button)findViewById(R.id.isPlayButton); stopButton = (Button)findViewById(R.id.stopButton); quitButton = (Button) findViewById(R.id.quitButton); musicService.animator = ObjectAnimator.ofFloat(image,"rotation",0,350); //動畫繫結 } @Override public void onClick(View view) { switch (view.getId()){ case R.id.isPlayButton: playButtonHandler(); break; case R.id.stopButton: stopButtonHandler(); break; case R.id.quitButton: quitButtonHanler(); break; } } //退出 private void quitButtonHanler() { try { int code = 103; Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); mBinder.transact(code,data,reply,0); }catch (RemoteException e){ e.printStackTrace(); } handler.removeCallbacks(runnable); unbindService(mConnection); try { finish(); System.exit(0); }catch (Exception e){ e.printStackTrace(); } } private void stopButtonHandler() { try { int code = 102; Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); mBinder.transact(code,data,reply,0); }catch (RemoteException e){ e.printStackTrace(); } } private void playButtonHandler() { if(musicService.mediaPlayer.isPlaying()){ txt_state.setText("Pause"); playButton.setText("play"); }else{ txt_state.setText("Playing"); playButton.setText("Pause"); } try { int code = 101; Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); mBinder.transact(code,data,reply,0); }catch (RemoteException e){ e.printStackTrace(); } } @Override protected void onResume() { super.onResume(); if(musicService != null){ musicService.setAnimation(); } checkStoragePerssion(this); if(musicService.mediaPlayer.isPlaying()){ txt_state.setText("playing"); }else{ if(musicService.which.equals("stop")){ txt_state.setText("stop"); }else if(musicService.which.equals("pause")){ txt_state.setText("pause"); } } seekBar.setProgress(musicService.mediaPlayer.getCurrentPosition()); //獲取當前進度 seekBar.setMax(musicService.mediaPlayer.getDuration()); //獲取最大值 handler.post(runnable); } private void checkStoragePerssion(MainActivity mainActivity) { String[] PERMISSIONS_STORAGE = {Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}; final int REQUEST_EXTERNAL_STORAGE = 1; try{ int permission = ActivityCompat.checkSelfPermission(mainActivity,"android.permission.READ_EXTERNAL_STORAGE"); if(permission!= PackageManager.PERMISSION_GRANTED){ ActivityCompat.requestPermissions(mainActivity,PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE); } }catch (Exception e){ e.printStackTrace(); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { if(grantResults.length>0&&grantResults[0]== PackageManager.PERMISSION_GRANTED){ Toast.makeText(MainActivity.this,"您已授予應用許可權",Toast.LENGTH_SHORT).show(); }else{ Toast.makeText(MainActivity.this,"應用許可權不足,啟動失敗",Toast.LENGTH_SHORT).show(); System.exit(0); } return; } @Override protected void onRestart() { super.onRestart(); musicService.returnFlag = 1; } @Override protected void onDestroy() { super.onDestroy(); unbindService(mConnection); mConnection = null; try { MainActivity.this.finish(); }catch (Exception e){ e.printStackTrace(); } } }
(5)介面效果
<ImageView
android:layout_width="200dp"
android:layout_height="200dp"
android:id="@+id/image"
android:layout_marginTop="20dp"
android:scaleType="centerInside"
android:layout_centerHorizontal="true"
android:src="@mipmap/likena" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/txt_state"
android:text=""
android:layout_below="@+id/image"
android:padding="15dp"/>
<TableRow
android:id="@+id/tbr_row1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/txt_state"
android:padding="15dp">
<TextView
android:id="@+id/start_time"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:text="00:00"
android:textSize="20sp" />
<SeekBar
android:layout_width="0dp"
android:layout_weight="4"
android:layout_height="wrap_content"
android:id="@+id/seekbar"
android:layout_gravity="center_vertical" />
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:id="@+id/end_time"
android:text="00:00"
android:textSize="20sp"/>
</TableRow>
<TableRow
android:id="@+id/tbr_row2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tbr_row1"
android:gravity="center_horizontal"
android:padding="15dp">
<Button
android:id="@+id/isPlayButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22dp"
android:text="PLAY" />
<Button
android:id="@+id/stopButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22dp"
android:text="STOP"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"/>
<Button
android:id="@+id/quitButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="22dp"
android:text="QUIT" />
</TableRow>