Service
没有用户界面在后台运行执行耗时操作的应用组件,存在于当前进程 的主线程中;
但是一些阻塞UI操作(耗时操作,网络请求,联网操作、数据请求)不能放在service中,需另开启一个线程处理。
启动方式,不同的启动方式对应不同的生命周期
注:他的生命周期中只有onStartCommand 可以执行多次,其他都只执行一次;
1. startServie(intent);
onCreate > onStartCommand >onDestory
2.BindService(intent,ServiceConnection,BIND_AUTO_CREATE);
onCreate > onBind > unOnbind > onDestory
注册
包名+类名
<span style="font-size:14px;"><service android:name="com.scxh.android.service.MusicService" /></span>
实现:
继承Service
一:通过startService开启服务可以通过intent传参数。
startServie(intent);
二:通过BindService,在onBind中会返回一个IBinder 对象,我们通常在service里写个接口,里面定义方法,再写一个类来实现这个接口,并继承Binder
1.建立一个接口,定义方法
2.定义一个类实现这个接口,并继承Binder
3. 在onBind方法中返回这个接口实例对象;
4.在activity 声明接口,在 new ServiceConnection 里的onServiceConnected方法中将里面的IBinder service 对象强转成接口对象,(当他们建立连接就会得到这个对象)
通过这个接口的实例来实现后台的操作,以播放器为例:
startServie(intent);和BindService 一起在用
服务器端:
package com.scxh.android.service;
import java.io.IOException;
import java.util.ArrayList;
import Constance.MusicBean;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MusicService extends Service {
MediaPlayer mPlayer;
// 接口的实例
MusicServiceBinder musicBinder = new MusicServiceBinder();
// 数据源 和当前播放位置 是从 activity中通过startService穿过来的
ArrayList<MusicBean> mListData;
int currentPosition;
@Override
public void onCreate() {
super.onCreate();
}
/*
* MediaPlayer 的初始化
*/
private void initPlayer() {
if (mPlayer == null) {
mPlayer = new MediaPlayer();
}
try {
mPlayer.reset();
mPlayer.setDataSource(mListData.get(currentPosition).getPath());
mPlayer.prepare();
mPlayer.start();
if (musicBinder != null) {
musicBinder.changeState();
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
/*
* 一首歌曲播放完以后的方法
*/
mPlayer.setOnCompletionListener(new OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mp) {
musicBinder.nextMusic();
mp.start();
}
});
}
/*
* 接收从activity传过来的数据源及position
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mListData = intent.getParcelableArrayListExtra("musicList");
currentPosition = intent.getIntExtra("currentPosition", 0);
initPlayer();
return super.onStartCommand(intent, flags, startId);
}
/*
* 返回一个接口的实例
*/
@Override
public IBinder onBind(Intent intent) {
return musicBinder;
}
@Override
public void onDestroy() {
super.onDestroy();
if (mPlayer != null) {
mPlayer.stop();
mPlayer.release();
}
}
/*
* 定義的接口
*/
public interface MusicBinder {
// 得到player的播放状态
public boolean playMusic();
// 点击下一首
public int nextMusic();
// 点击上一首
public int lastMusic();
// 得到当前播放的时间
public int currentTime();
// 得到当前歌曲的总时间
public int TotalTime();
// 当前选中的歌曲播放
public String seekTo(int position);
// 得到正在播放歌曲的名字
public String getCurrentTitle();
// 拖动进度条,设置他的播放位置
public void setCurrentTime(int progress);
// 改变他的播放状态
public boolean changeState();
}
/*
* 接口实现类,继承的binder
*/
public class MusicServiceBinder extends Binder implements MusicBinder {
@Override
public boolean playMusic() {
if (mPlayer.isPlaying()) {
mPlayer.pause();
return false;
} else {
mPlayer.start();
return true;
}
}
@Override
public int nextMusic() {
if (++currentPosition > mListData.size() - 1) {
currentPosition = mListData.size() - 1;
}
mPlayer.reset();
initPlayer();
sendBroadcast(intent);
return currentPosition;
}
@Override
public int lastMusic() {
if (--currentPosition < 0) {
currentPosition = 0;
}
mPlayer.reset();
initPlayer();
sendBroadcast(intent);
return currentPosition;
}
@Override
public int currentTime() {
if (mPlayer != null) {
return mPlayer.getCurrentPosition();
}
return 0;
}
@Override
public int TotalTime() {
if (mPlayer != null) {
return mPlayer.getDuration();
}
return 0;
}
@Override
public void setCurrentTime(int progress) {
if (mPlayer != null) {
mPlayer.seekTo(progress);
}
}
@Override
public boolean changeState() {
if (mPlayer.isPlaying()) {
return true;
} else {
return false;
}
}
@Override
public String seekTo(int position) {
if (mPlayer != null) {
mPlayer.reset();
try {
mPlayer.setDataSource(mListData.get(position).getPath());
mPlayer.prepare();
currentPosition = position;
mPlayer.start();
return mListData.get(position).getName();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
@Override
public String getCurrentTitle() {
return mListData.get(currentPosition).getName();
}
}
}
Activity中
<span style="font-size:14px;">package com.scxh.android.music;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Random;
import Constance.MusicBean;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.scxh.android.music.adapter.MusicBaseAdapter;
import com.scxh.android.music.adapter.MusicPagerAdapter;
import com.scxh.android.service.MusicService;
import com.scxh.android.service.MusicService.MusicBinder;
public class PlayActivity extends Activity implements OnClickListener,
OnSeekBarChangeListener {
LayoutInflater inflater;
ViewPager mPager;
int oldPostion = 1;// 记录小圆点
ImageView mDot1, mDot2, mDot3, mListImg;
ImageButton mLastBtn, mPlayBtn, mNextBtn, mCollection;
SeekBar mSeekBar;
TextView mCurrentTxt, mTotalTxt, mTitle;
ArrayList<MusicBean> mListData;
int selectPosition;
File file = new File(Environment.getExternalStorageDirectory() + "/music");
boolean threadFlag = true;
Handler mHandler = new Handler();
// 接口对象
MusicBinder mBinder;
//建立连接时的两个方法
ServiceConnection sConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mBinder = null;
}
//建立连接后,能得到onBind中返回的IBinder对象
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mBinder = (MusicBinder) service;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.playactivity_layout);
initView();// 初始化view
receiveData();// listActivity传过来的歌曲数据和当前选中的位置
setPagerItem();// 为ViewPager添加item布局
setPagerListener();
registerListener();// view注册监听
Intent intent = new Intent(this, MusicService.class);<span style="font-family: Arial, Helvetica, sans-serif;"> </span></span>
<span style="font-size:14px;"><span style="white-space: pre;"> </span>intent.putParcelableArrayListExtra("musicList", mListData);</span>
<span style="font-size:14px;"> intent.putExtra("currentPosition", selectPosition);
startService(intent);//启动服务
mTitle.setText(mListData.get(selectPosition).getName());
<span style="white-space:pre"> </span>//绑定服务
bindService(intent, sConnection, BIND_AUTO_CREATE);
new Thread(new UIThread()).start();
}
/*
* 接收到listActivity传过来的歌曲数据和当前选中的位置
*/
private void receiveData() {
Intent intent = getIntent();
mListData = intent.getParcelableArrayListExtra("musicList");
selectPosition = intent.getIntExtra("selectPosition", 0);
}
private void registerListener() {
mLastBtn.setOnClickListener(this);
mPlayBtn.setOnClickListener(this);
mNextBtn.setOnClickListener(this);
mSeekBar.setOnSeekBarChangeListener(this);
mListImg.setOnClickListener(this);
}
private void initView() {
inflater = LayoutInflater.from(this);
mPager = (ViewPager) findViewById(R.id.pager_music);
mDot1 = (ImageView) findViewById(R.id.dot1_img);
mDot2 = (ImageView) findViewById(R.id.dot2_img);
mDot3 = (ImageView) findViewById(R.id.dot3_img);
mListData = new ArrayList<MusicBean>();
mLastBtn = (ImageButton) findViewById(R.id.last_song_btn);
mPlayBtn = (ImageButton) findViewById(R.id.palying_btn);
mNextBtn = (ImageButton) findViewById(R.id.next_song_btn);
mSeekBar = (SeekBar) findViewById(R.id.progressbar);
mCurrentTxt = (TextView) findViewById(R.id.current_progress_txt);
mTotalTxt = (TextView) findViewById(R.id.total_progress_txt);
mListImg = (ImageView) findViewById(R.id.list_img);
mCollection = (ImageButton) findViewById(R.id.collection_ibtn);
mTitle = (TextView) findViewById(R.id.tile_play_txt);
}
ImageView img;
/*
* PagerView添加组件
*/
private void setPagerItem() {
ArrayList<View> data = new ArrayList<View>();
View item1 = inflater.inflate(R.layout.pager_item1_list_layout, null);
MusicBaseAdapter baseAdapter = new MusicBaseAdapter(this);
baseAdapter.setData(mListData);
final ListView listView = (ListView) item1
.findViewById(R.id.list_item1_pager);
listView.setAdapter(baseAdapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
mTitle.setText(mBinder.seekTo(position));
}
});
View item2 = inflater.inflate(R.layout.pager_item2_image_layout, null);
img = (ImageView) item2.findViewById(R.id.img_music_playing);
View item3 = inflater.inflate(R.layout.pager_item3_lyric_layout, null);
data.add(item1);
data.add(item2);
data.add(item3);
MusicPagerAdapter adapter = new MusicPagerAdapter();
adapter.setData(data);
mPager.setAdapter(adapter);
}
@SuppressWarnings("deprecation")
private void setPagerListener() {
final ArrayList<View> dotData = new ArrayList<View>();
dotData.add(mDot1);
dotData.add(mDot2);
dotData.add(mDot3);
mPager.setCurrentItem(1);
dotData.get(1).setBackgroundResource(R.drawable.dot_pressed);
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int arg0) {
dotData.get(oldPostion).setBackgroundResource(
R.drawable.dot_default);
dotData.get(arg0).setBackgroundResource(R.drawable.dot_pressed);
oldPostion = arg0;
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
@Override
public void onClick(View v) {
switch (v.getId()) {
//播放/暂停的监听
case R.id.palying_btn:
boolean playFlag = mBinder.playMusic();
if (playFlag == true) {
mPlayBtn.setBackgroundResource(R.drawable.play_song_selector);
} else {
mPlayBtn.setBackgroundResource(R.drawable.pause_song_selector);
}
break;
//点击下一首
case R.id.next_song_btn:
if (mBinder != null) {
int nextPostion = mBinder.nextMusic();
mTitle.setText(mListData.get(nextPostion).getName());
}
mPlayBtn.setBackgroundResource(R.drawable.play_song_selector);
break;
//点击上一首
case R.id.last_song_btn:
if (mBinder != null) {
int lastPosition = mBinder.lastMusic();
mTitle.setText(mListData.get(lastPosition).getName());
}
mPlayBtn.setBackgroundResource(R.drawable.play_song_selector);
break;
case R.id.list_img:
startActivity(new Intent(this, ListActivity.class));
finish();
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
}
int mProgress;//记录拖动的进度条进度
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
mSeekBar.setProgress(progress);
mProgress = progress;
}
/*
* 刷新界面的(SeekBar 進度及顯示)
*/
public class UIThread implements Runnable {
@Override
public void run() {
while (threadFlag) {
if (mBinder != null) {
mHandler.post(new Runnable() {
@Override
public void run() {
int current = mBinder.currentTime();
int total = mBinder.TotalTime();
mSeekBar.setMax(total);
mSeekBar.setProgress(current);
mCurrentTxt.setText(timeFormat(current));
mTotalTxt.setText(timeFormat(total));
}
});
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
/*
* 拖動进度条的监听,避免因延迟造成播放卡顿,所以在onStopTrackingTouch方法中将进度传到服务器
*/
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mBinder.setCurrentTime(mProgress);
}
private String timeFormat(int time) {
SimpleDateFormat df = new SimpleDateFormat("mm:ss");
String timeStr = df.format(new Date(time));
return timeStr;
}
}
</span>