Service则是Android提供一个允许长时间留驻后台的一个组件,最常见的 用法就是做轮询操作!或者想在后台做一些事情,比如后台下载更新!一个Service 是一段长生命周期的,没有用户界面的程序。
服务一旦被开启,就会长时间在后台运行;直到用户手工停止。
- onUnbind(intent):当该Service上绑定的所有客户端都断开时会回调该方法!
IntentService
IntentService是继承与Service并处理异步请求的一个类,在IntentService中有 一个工作线程来处理耗时操作,请求的Intent记录会加入队列。
客户端通过startService(Intent)来启动IntentService; 我们并不需要手动地区控制IntentService,当任务执行完后,IntentService会自动停止; 可以启动IntentService多次,每个耗时操作会以工作队列的方式在IntentService的 onHandleIntent回调方法中执行,并且每次只会执行一个工作线程,执行完一,再到二。
当一个后台的任务,需要分成几个子任务,然后按先后顺序执行,子任务 (简单的说就是异步操作),此时如果我们还是定义一个普通Service然后 在onStart方法中开辟线程,然后又要去控制线程,这样显得非常的繁琐; 此时应该自定义一个IntentService然后再onHandleIntent()方法中完成相关任务!
Activity与Service通信
Service 与Activity进行通信,他们之间交流的媒介就是Service中的onBind()方法! 返回一个我们自定义的Binder对象!
基本流程如下:
- 1.自定义Service中,自定义一个Binder类,然后将需要暴露的方法都写到该类中!
- 2.Service类中,实例化这个自定义Binder类,然后重写onBind()方法,将这个Binder对象返回!
- 3.Activity类中实例化一个ServiceConnection对象,重写onServiceConnected()方法,然后 获取Binder对象,然后调用相关方法即可!
简单前台服务的实现
Service一般都是运行在后来的,但是Service的系统优先级 还是比较低的,当系统内存不足的时候,就有可能回收正在后台运行的Service, 对于这种情况我们可以使用前台服务,从而让Service稍微没那么容易被系统杀死, 当然还是有可能被杀死的,所谓的前台服务就是状态栏显示的Notification!
实现过程:
在自定义的Service类中,重写onCreate(),
然后根据自己的需求定制Notification;
定制完毕后,最后调用startForeground(1,notification对象)。
定时后台线程的实现
实际开发中Service有一种常见的用法,就是执行定时任务, 比如轮询,就是每间隔一段时间就请求一次服务器,确认客户端状态或者进行信息更新 等!而Android中给我们提供的定时方式有两种使用Timer类与Alarm机制!
前者不适合于需要长期在后台运行的定时任务,CPU一旦休眠,Timer中的定时任务 就无法运行;Alarm则不存在这种情况,他具有唤醒CPU的功能,另外,也要区分CPU 唤醒与屏幕唤醒!
2.调用bindService获取中间人对象;
3.调用unbindService;解绑bindService开启的服务
public class MainActivity extends AppCompatActivity {
private Iservice iserviser;
private SeekBar seekbar;
public static Handler handler=new Handler(){
public SeekBar seekbar;
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle data=msg.getData();
int dur= data.getInt("dur");
int cur=data.getInt("curentPosition");
seekbar.setMax(dur);//
seekbar.setProgress(cur);//设置进度
}
};
private Myconn conn;
@SuppressLint("WrongConstant")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//混合开启服务
//先调用startService目的是可以保证服务在后台长期运行
Intent intent =new Intent(this,MusicService.class);
startService(intent);
//调用bindservice目的是为获取我们定义的中间人对象,就可以间接的调用服务里面的方法
conn = new Myconn();
bindService(intent, conn, BIND_AUTO_CREATE);
//找到seekbar
seekbar = findViewById(R.id.seekbar);
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
// 停止拖动的时候调用
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
//拖动的时候调用
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//进度改变的时候调用
iserviser.seekt(seekBar.getProgress());
}
});
}
//
public class Myconn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
iserviser = (Iservice)iBinder;//获取中间人对象
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);
}
}
-----------MusicService----------
public class MusicService extends Service {
private MediaPlayer mediaPlayer;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
//初始化mediaplayer
mediaPlayer = new MediaPlayer();
}
@Override
public void onDestroy() {
super.onDestroy();
}
//播放音乐的方法
public void playMusic(){
mediaPlayer.reset();//重置
//设置要播放的资源位置,可以是本地的,也可以是网络资源
try {
mediaPlayer.setDataSource("/Users/wofu/Downloads/Eleven/app/src/main/res/raw");
} catch (IOException e) {
e.printStackTrace();
}
try {
mediaPlayer.prepare();//准备播放
} catch (IOException e) {
e.printStackTrace();
}
mediaPlayer.start();//开始播放
updateSeekbar();//
}
//暂停音乐的方法
public void pauseMusic(){
mediaPlayer.pause();
}
//继续播放
public void rePlayMusic(){
mediaPlayer.start();
}
//更新进度条的方法
public void updateSeekbar(){
final int dur=mediaPlayer.getDuration();//获取当前播放的总长度
//使用定时器,定时获取当前进度
final Timer timer=new Timer();
final TimerTask task=new TimerTask() {
@Override
public void run() {
//一秒钟获取一次当前进度
int currentPosition=mediaPlayer.getCurrentPosition();
Message msg= Message.obtain();
Bundle bundle=new Bundle();
bundle.putInt("curentPosition",currentPosition);
bundle.putInt("dur",dur);
msg.setData(bundle);
MainActivity.handler .sendMessage(msg);//发送一条消息,mainactivty中的handlemessage就会执行
}
};
timer.schedule(task,100,1000);//100毫秒后每一秒中执行一次
//设置歌曲播放完成的监听,吧timer和timertask取消掉
mediaPlayer.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
@Override
public void onSeekComplete(MediaPlayer mediaPlayer) {
//歌曲播放完成
timer.cancel();
task.cancel();
}
});
}
//实现指定播放的位置
public void seekTo(int positon){
}
//在服务内部定义中间人对象
private class MyBind extends Binder implements Iservice{
public void play(){
playMusic();
}
public void pause(){
pauseMusic();
}
public void replay(){
rePlayMusic();
}
public void seekt(int position){
seekTo(position);
}
}
}
-----------服务对外放的接口--------
public interface Iservice {
public void play();
public void pause();
public void replay();
public void seekt(int position);
}
-----------activity_main-------------
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.wofu.eleven.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
android:visibility="gone"/>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/play"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="playAudio"
android:text="播放音频"/>
<Button
android:id="@+id/pause"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="pause"
android:text="暂停"/>
<Button
android:id="@+id/rePlay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="continueplay"
android:text="继续播放"/>
<SeekBar android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
==============采用bind方式绑定services============
public class MainActivity extends AppCompatActivity {
private Myservicee conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//******************************************bindservce开启服务************
Intent intentServ=new Intent(this,BindService.class);
conn = new Myservicee();
bindService(intentServ, conn,BIND_AUTO_CREATE);
}
//采用bindService方式
private class Myservicee implements ServiceConnection {
//服务链接成功时会调用,但是服务页面的Ibind返回值不能为null
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Serv ss=(Serv) service;
ss.geiqian(100);//调用服务中的方法
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(conn);//解绑服务,bind方式开启的必须要关闭
}
}
-------Bindservice---------
public class BindService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return new MyIband();
}
public void jieqian(int money) {
}
public void zhaoqian(int money) {
}
private class MyIBand extends IBinder implements Serv {
public void geiqian(int monye) {
jieqian(monye);
}
public void zhao(int monye) {
zhaoqian(monye);
}
}
}
------实现接口-----
public interface Serv {
public void geiqian(int monye);
public void zhao(int monye);
}
--------Mainactivity-----------
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
//开启sercice服务,可以吧注册特殊广播接受者放到服务当中
public void setService(){
// Intent intentServ=new Intent(this,DemoService.class);
// startService(intentServ);//开启服务
// stopService(intentServ);//关停服务
service开启方式二************
Intent intentServ=new Intent(this,DemoService.class);
bindService(intentServ,new Myservicee(),BIND_AUTO_CREATE);
}
//采用bindService方式
private class Myservicee implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
//帧动画
public void animate(){
//动画分帧动画(drawable Animation )、view动画(view Animation)、属性动画(proprty额Animaion)
final ImageView imageAnimate=(ImageView) findViewById(id.image_animate);
imageAnimate.setBackgroundResource(R.drawable.dr_animation);//设置背景资源
AnimationDrawable rocketAnimate= (AnimationDrawable) imageAnimate.getBackground();
rocketAnimate.start();
}
}
------------DemoService-------------
public class DemoService extends Service {
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
//服务第一次创建的时候调用
@Override
public void onCreate() {
super.onCreate();
TelephonyManager tlmanage= (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
tlmanage.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
}
//定义一个类来监听电话的状态
private class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
MediaRecorder re = null;
//具体判断哪一种状态
switch (state){
case TelephonyManager.CALL_STATE_IDLE://空闲状态
if(re!=null){
re.stop();
re.reset();
re.release();
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK://接听状态
re.start();//开始录制
break;
case TelephonyManager.CALL_STATE_RINGING ://响铃状态
//准备一个录音机
re=new MediaRecorder();
re.setAudioSource(MediaRecorder.AudioSource.VOICE_CALL);//设置音频来源
re.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);//设置音频的格式3gp,MP4。。。。
re.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);// 音频编码方式NB、AAC。。。。。
re.setOutputFile("mnt/sdcard/jinaitng.3gp");//保存的路径
try {
re.prepare();//准备录制
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
}
------------BootReceiver广播接受者---------------
----开机就启动就接受广播----
public class BootReciver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {//
//开启服务
Intent intentServ=new Intent(context,DemoService.class);
context.startService(intentServ);//开启服务
}
}
-----------AndroidManifest.xml--------
//注册广播接受者,开启启动
<receiver android:name=".BootReciver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
//注册服务
<service android:name=".DemoService"/>
==============BOOT开机时在接收者中开启服务,在服务中再注册广播接收者===============
/**
* Created by lambo on 2018/4/21.
* 电话的服务
*/
public class NumberAddressService extends Service {
private TelephonyManager tm;
private MylistenPhone listenPhone;
private PhonecallRecevier phonecallRecevier;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
//监听电话的类
private class MylistenPhone extends PhoneStateListener{
@Override
public void onCallStateChanged(int state, String incomingNumber) {
super.onCallStateChanged(state, incomingNumber);
switch (state){
case TelephonyManager.CALL_STATE_RINGING://正在打电话
break;
}
}
}
@Override
public void onCreate() {
super.onCreate();
//监听来电
tm= (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
listenPhone =new MylistenPhone();
tm.listen(listenPhone,PhoneStateListener.LISTEN_CALL_STATE);
//用代码注册广播接收者
phonecallRecevier = new PhonecallRecevier();
IntentFilter filt=new IntentFilter();
filt.addAction("android.intent.action.NEW_OUTGOING_CALL");
registerReceiver(phonecallRecevier,filt);
}
@Override
public void onDestroy() {
super.onDestroy();
//取消监听来电
listenPhone =new MylistenPhone();
tm.listen(listenPhone,PhoneStateListener.LISTEN_NONE);
listenPhone=null;
//取消广播接收者
unregisterReceiver(phonecallRecevier);
phonecallRecevier=null;
}
}
/**
* Created by wofu on 2018/4/20.
* 打出电话时的广播接受者
*/
public class PhonecallRecevier extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//获取拨出去的电话号码
String phone=getResultData();
//查询数据库,获取归属地----没做
}
}