Android四大组件——Service

Service服务

服务是一个没用界面的,在后台运行的程序,它的优先级比Activity高(即内存不足的时候会优先关掉Activity而不会关掉Service)

服务运行在后台,服务分两种,一种是系统的服务,一种是自定义的服务。

我们在运行程序的时候可以调用服务的具体方法来实现程序的一些功能,例如获得wifi的系统服务来控制wifi的开关。

 

我们先来看看Service的生命周期:

 

可以看出服务有两种生命周期,左边的start只能控制服务的开关,而不能返回服务对象,右边的bind则可以返回服务对象。

说白了,程序就是要获得一个服务对象,然后调用它的方法。所以一般我们使用服务对象都是通过绑定服务来调用服务的方法。

 

一.我们先来讲解一下如何自定义一个服务。(记得得在Androidmanifest.xml注册,只需要名字就可以了)

/**
 * 自定义服务
 * 一般我们都是用程序调用系统的服务
 * 这里是演示程序之间调用服务
 * 
 * 服务有两种生命周期路径
 * 1:(startService->onCreate->onStartCommand->()->stopService->onDestroy)
 * 2:(bindService->onCreate-onBind->()->onUnbind->unbindService->onDestroy) 
 * Start服务与启动源没有关系,不能得到服务器对象,bind可以。
 */
public class MyService extends Service{
    
    @Override//开启服务
    public ComponentName startService(Intent service) {
        return super.startService(service);
    }
    @Override//结束服务
    public boolean stopService(Intent name) {
        // TODO Auto-generated method stub
        return super.stopService(name);
    }
    @Override//绑定服务
    public boolean bindService(Intent service, ServiceConnection conn, int flags) {
        // TODO Auto-generated method stub
        return super.bindService(service, conn, flags);
    }
    @Override//解除绑定
    public void unbindService(ServiceConnection conn) {
        // TODO Auto-generated method stub
        super.unbindService(conn);
    }
    
    @Override//开启服务的时候调用
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Log.i("tag", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }
    //一个Binder类用来返回当前服务对象
    public class MyBinder extends Binder{
        public MyService getService(){
            return MyService.this;
        }
    }
    @Override//绑定或者启动服务的时候调用
    public void onCreate() {
        // TODO Auto-generated method stub
        Log.i("tag", "onCreate");
        super.onCreate();
    }
    @Override
    /**
     * 绑定的时候调用,返回一个服务对象,可是这个方法不能直接放回Service对象
     * 需要创建一个自定义类MyBinder继承Binder类,实现获得当前服务对象的方法。
     * 从而使MyBinder类包含了服务对象的数据给调用服务的程序使用。
     * Binder类通过ServiceConnection()方法获得Service对象
     */
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.i("tag", "onBind");
        return new MyBinder();
    }
    @Override//解除绑定的时候调用
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.i("tag", "onUnbind");
        return super.onUnbind(intent);
    }
    
    @Override//服务结束或者取消绑定的时候调用
    public void onDestroy() {
        // TODO Auto-generated method stub
        Log.i("tag", "onDestroy");
        super.onDestroy();
    }
    //服务类的方法,用于被其他程序调用该服务的时候可以调用这些方法
    public void Play(){
        Log.i("tag", "播放");
    }
    
    public void Next(){
        Log.i("tag", "下一首");
    }
    
    public void Pre(){
        Log.i("tag", "上一首");
    }
    
    public void Pause(){
        Log.i("tag", "暂停");
    }
}

具体的实现方法可以自己定义。

接下来我们的Activity就要调用该服务了。怎么调用的呢?

我们得获关键得该Service对象,所以我们得绑定该服务

(这里其实就是在进行者如何获得Service对象,Service没用构造方法)

这是我们的界面:

 

每个按钮对应了Activity的相应相应方法:

public class MainActivity extends Activity {

    private Intent intent1;    //定义开启哪一个服务
    private Intent intent2;    //定义绑定哪一个服务
    MyService service;         //服务对象,程序关键就是获得想要服务对象得到服务的方法。/**
     * 怎么得到服务对象?service对象没用构造方法。
     * Binder类通过ServiceConnection对象的方法获得Service对象
     * 可以看作程序和服务之间绑定的的连接器。用来返回服务器对象。
     */
    ServiceConnection conn = new ServiceConnection() {
        @Override
        //当程序与服务连接丢失时调用,当服务崩溃或者被杀死时候服务会丢失,取消绑定不会
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub
        }
        @Override
        /**
         * 当程序与服务连接成功时调用
         * ComponentName name:组件名
         * IBinder service:绑定服务的时候返回的包含了服务对象的对象
         * 通过IBinder的方法获得服务对象。
         */
        public void onServiceConnected(ComponentName name, IBinder binder) {
            // TODO Auto-generated method stub
            service = ((MyBinder)binder).getService();//获得服务对象
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
    public void Click(View v){
        switch(v.getId()){
        case R.id.start:
            intent1 = new Intent(MainActivity.this,MyService.class);
            startService(intent1);
            break;
        case R.id.stop:
            stopService(intent1);
            break;
        case R.id.binder:
            intent2 = new Intent(MainActivity.this,MyService.class);
            /**
             * bindService(Intent service, ServiceConnection conn, int flags);boolean
             * service: Intent对象,里面包含了需要绑定的服务
             * conn:    可以看作程序和服务之间绑定的的连接器。用来返回服务器对象。
             * flags:   绑定服务的标签。下面的是绑定服务的时候自动创建服务
             */
            bindService(intent2, conn, Service.BIND_AUTO_CREATE);
            break;
        case R.id.play:
            service.Play();
            break;
        case R.id.next:
            service.Next();
            break;
        case R.id.pre:
            service.Pre();
            break;
        case R.id.puase:
            service.Pause();
            break;
        case R.id.unbinder:
            unbindService(conn);//不能多次取消绑定,只能结绑一次,不然会报错,不解除绑定直接退出也会报错
            break;
        }
    }
    /**
     * 总结:service对象是通过程序与服务绑定后,调用服务的onBinder方法返回一个带有service对象的iBunder对象给ServiceConnection。
     * onBinder不能直接返回service对象,得通过载体对象iBunder对象间接返回。iBunder类已经定义了取service对象的方法了。
     * 为什么不能直接返回呢?因为service没用构造方法,得通过载体对象返回。
     * 然后通过重写ServiceConnection中的连接成功时候的方法。将service对象从iBunder对象中取出来。
     * 有了service对象就可以实现service对象中的方法。
     */
    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        service.onDestroy();
        super.onDestroy();
    }
}

输出结果(按钮从上按到下):

我们可以实现自定义的服务了

但是我们比较常用的是实现系统的服务

如何实现系统服务呢?

我们通过用Content.getSystemService(String Name)方法获得系统服务,Name是不同服务对应的名称

 

一般调用这些服务都需要获得权限

Content.getSystemService(String Name)方法返回值一般都是一个相应类型的“管理器”例如(WifiManger Wifi管理器,ConnectiviyManger 网络连接管理器)

 

这里用Wifi做一个例子

在原来的界面再加一个按钮控制wifi开关:

case R.id.Wifi:
            WifiManager manger = (WifiManager) MainActivity.this.getSystemService(WIFI_SERVICE);
            if(manger.isWifiEnabled()){
                manger.setWifiEnabled(false);
                Toast toast = Toast.makeText(MainActivity.this, "WIFI已关闭", Toast.LENGTH_SHORT);
                toast.show();
            } else {
                manger.setWifiEnabled(true);
                Toast toast = Toast.makeText(MainActivity.this, "WIFI已打开", Toast.LENGTH_SHORT);
                toast.show();
            }
            break;

打开和关闭系统有点延迟,但是测试是可以的。

 

如果有什么错误,或者我理解错误或不当的,恳请大家纠正,谢谢!嘻嘻嘻~

 

posted on 2017-03-17 12:40  艹艹哒丶  阅读(233)  评论(0编辑  收藏  举报

导航