服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另一个应用程序,服务仍然能够保持正常运行

尽管如此,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行

实际上服务也并不会自动开启线程,所有的代码都是默认运行在主线程当中的,也就是说我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则可能出现主线程被阻塞的情况

定义一个服务

新建一个空Service

服务中处理事情的逻辑需要重写Service的另一些方法

public class MyService extends Service {
    public MyService(){

    }
    @Override
    public IBinder onBind(Intent intent){
        throw new UnsupportedOperation("Not yet implemented");
    }
    @Override
    public void onCreate(){
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent,int flags,int startId){
        return super.onStartCommand(intent,flags,startId);
    }
    @Override
    public void onDestory(){
        super.onDestory();
    }
}

Service一些重载方法的作用

注意Service作为四大组件之一所以也需要在AndroidManifest.xml中注册

启动和停止服务

启动

Intent startIntent = new Intent(this,MyService.class);
startService(startIntent);

停止

Intent stopIntent = new Intent(this,MyService.class);
stopService(stopIntent);

在Service中停止自己

stopSelf();

活动和服务进行通信

利用onBind()方法,在活动中指挥服务干什么,服务就去干什么

比如说,目前我们希望在MyService里提供一个下载功能,然后在活动中可以决定何时开始下载,以及随时查看下载进度。实现这个功能的思路是创建一个专门的Binder对象来对下载功能进行管理,修改MyService中的代码,如下所示

public class MyService extends Service{
    private DownloadBinder mBinder = new DownloadBinder();

    class DownloadBinder extends Binder{
        public void startDownload(){
            Log.d("MyService","startDownload executed");
        }
        public int getProgress(){
            Log.d("MyService","getProgress executed");
            return 0;
        }
    }

    @Override
    public IBinder onBind(Intent intent){
        return mBinder;
    }
}

可以看到,这里我们新建了一个DownloadBinder类,并让它继承自Binder,然后在它的内部提供了开始下载以及查看下载进度的方法。当然这只是两个模拟方法,并没有实现真正的功能,我们在这两个方法中分别打印了一行日志。

接着,在MyService中创建了DownloadBinder的实例,然后在onBind()方法里返回了这个实例,这样MyService中的工作就全部完成了。

在需要绑定服务的Activity里

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private MyService.DownloadBinder downloadBinder;

    private ServiceConnection connection = new ServiceConnection(){
        @Override
        public void onServiceDisconnected(ComponentName name){

        }
        @Override
        public void onServiceConnected(ComponentName name,IBinder service){
            downloadBinder = (MyService.Downloader) service;
            downloadBinder.startDownload();
            downloadBinder.getProgress();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button bindService = (Button) findViewById(R.id.bind_service);
        Button unbindService = (Button) findViewById(R.id.unbind_service);
        bindService.setOnClickListener(this);
        unbindService.setOnClickListener(this);
    }
    @Override
    protected void onClick(View v){
        switch(v.getId()){
            ...
            case R.id.bind_service:
                 Intent bindIntent = new Intent(this,MyService.class);
                 bindService(bindIntent,connection,BIND_AUTO_CREATE);
                 break;
            case R.id.unbind_service:
                 unbindService(connection);
                 break;
            default:
                 break;
        }
    }
}

Acticity以上代码的解释

Activity的bindService()和unbindService()

服务可以和多个Activity绑定

另外需要注意,任何一个服务在整个应用程序范围内都是通用的,即MyService不仅可以和MainActivity绑定,还可以和任何其他的活动进行绑定,而且绑定后他们都可以获取到相同的DownloadBinder实例

服务的生命周期


使用前台服务
…这部分先省略

耗时服务的编写方法

在服务的每个具体的方法里开启一个子线程,然后在这里去处理耗时逻辑

public class MyService extends Service{
    ...
    @Override
    public int onStartCommand(Intent intent,int flags,int startId){
        new Thread(new Runnable(){
            @Override
            public void run(){
                //处理具体的逻辑
                stopSelf();
                //服务执行完毕后停止服务
            }
        }).start();
        return super.onStartCommand(intent,flags,startId)
    }
}

以上这种写法并不复杂,但是总会有一些程序员忘记开启线程,或者忘记调用stopSelf()方法。为了可以简单地创建一个异步的,会自动停止的服务,Android专门提供了一个IntentService类。这个类很好地解决了前面所提到的两种尴尬。下面我们就看一下他的用法
使用IntentService

public class MyIntentService extends IntentService{
    public MyIntentService(){
        super("MyIntentService");
        //调用父类的有参构造函数
    }
    @Override
    protected void onHandlerIntent(Intent intent){
        //打印当前线程的id
        Log.d("MyIntentService","Thread is "+ Thread.currentThread().getId());
    }
    @Override
    public void onDestory(){
        super.onDestory();
        Log.d("MyIntentService","onDestory executed");
    }
}

MyIntentService里的代码解释

混合使用

混合使用startService()stopService()和bindService()unbindService()
两组方法

一个具体解释

安卓的系统服务

所有系统服务

所有系统服务,都可以通过getSystemService函数获得

以电话服务为例

TelephonyManager t = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)
t.getDeviceId();//获得设备id
t.getNetworkOperatorName();//获得移动服务商猫宁子
t.getSimState();//获得sim卡状态
...

一个监听通话状态的例子

使用系统服务需要在AndroidManifest.xml中添加对相应服务的访问权限

<use-permisson android:name="android.permisson.READ_PHONE_STATE"/>