Android中的service

Service 是能够在后台执行长时间运行操作并且不提供用户界面的应用程序组件,其他组件能够启动Service并且在切换到其他应用程序的时候Service还在后台运行,此外,组件能够和service绑定,并与其交互,甚至执行进程间通信。例如,Service能够在后台处理网络事务、播放音乐、执行IO操作或者与ContentProvider 通信。

Service的生命周期:

这里写图片描述

Service的两种启动方式:

startService:当其他组件通过startService() 方法启动服务时,服务处于started状态。一旦启动,服务能在后台无限期运行,即使启动它的组件已经被销毁。通常启动服务执行单个操作并且不会向调用者返回结果。服务在后台完成某种操作后,服务须要停止自身。

bindService():当其他组件通过bindService()方法启动服务时,service就和启动它的组件绑定在一起,当组件被销毁时,服务也就被销毁了。多个组件可以一次绑定到一个服务上,当它们都被销毁时候,服务也被销毁。

服务可以同时属于这两种启动方式,既可以启动(无限运行)也能绑定。重点在于是否实现一些回调方法: onStartCommand()方法允许组件启动服务,onBind()方法允许组件绑定服务。

服务运行于管理它的进程的主线程,服务不会创建自己的线程,也不会运行于独立的进程(除非我们自己 定义)。这意味着,如果服务要完成CPU密集工作或者阻塞操作(如音乐回放或者联网),我们须要在服务中创建新的线程来完成这些工作。通过使用独立的线程,能够减少ANR (Application Not Response)错误风险,并且应用程序主线程仍然能用于用户与Activity的交互。

Service中的 几个方法:

我们要创建一个服务,须要继承Servcie类或者其子类。
onStartCommand() : 当其他组件调用startService()方法请求服务启动时,系统调用此方法。一旦此方法执行,服务就启动了,并且在后台无期限运行。如果我们实现此方法,则需要在任务完成时调用stopSelf()或者stopService()方法停止服务(如果只是想提供绑定,则不必实现此方法)。

onBind():当其他组件调用 bindService()方法想与服务绑定时,系统调用此方法。在此方法的实现中,我们必须通过返回IBinder提供客户端用来与服务通信的接口。此方法必须要实现,如果不想绑定,我们可以选择返回 null

onCreate(): 当服务第一次创建时,系统调用该方法执行一次性建立过程(此方法在onStartCommand()或者onBind()方法之前被调用。),如果服务已经运行,则此方法不会被调用。

onDestory():当服务不再被使用并且即将销毁时,系统调用此方法。服务应该实现此方法来清理例如线程、注册的监听、接收者等资源。这是服务收到的最后的回调。

当我们用startService方法启动服务(onStartCommand()方法被调用),服务须要使用 stopSelf()方法停止自己,或者其他组件使用stopService()方法停止该服务。

当通过bindServcie()启动服务,当启动它的页面销毁了,它也就销毁了。

Android中内存管理机制,当内存不足并且必须回收系统资源来显示用户关注的Activity时,才会强制停止服务,当服务和用户关注 的Activity绑定时,则会减小停止的概率。如果服务被声明是前台运行,那么则基本不会被停止。否则, 当服务是started状态并且长时间运行,则系统会随时间推移降低其在后台任务列表中的位置,并且有很大几率将其停止。如果服务是started状态,我们必须设计系统重启服务,系统停止服务后,资源可用时会将其重启(这也依赖于onStartCommand()方法的返回值)。

Servcie的声明和子标签:

声明Servcie 须要在Application标签中增加< servcie > 子标签。

<service  android:enabled="true/false"
        android:export="true/false"
        android:icon = "@drawable/xxx"
        android:label = "字符串内容"
        android:name="字符串"
        android:permission ="权限,字符串内容"
        android:process = "字符串内容"  >
</service>

android:enabled 服务是否可以被实例化,true表示可以。 application标签里面也有enabled属性,用于包括服务的全部应用程序组件。 这两个里面的enabled属性必须同时设置成true 才能让服务可用(默认都是true)。如果任何一个为false 则服务被禁用,并且不能实例化。

android:exported 其他应用程序能否调用服务或者与其交互。true代表可以。当为false时,只有本程序的组件能启动或者绑定此服务。

android:icon 服务的图标。必须设置成包含图片定义的可绘制资源引用。如果没有设置,则使用应用程序图标取代。

android:label 显示给用户的服务名称,如果没有设置,使用应用程序标签取代。

android:name 实现服务的子类的名称。应该是一个完整的类名。

android:premission 实体必须包含的权限名称。以便启动服务或者绑定到服务。如果startService()、bindService()或者stopServcie()方法调用者没有被授权,方法调用无效并且Intent对象也不会发送给服务。
如果没有设置此属性,使用application中的permission设置给服务。如果application中也没用设置,则服务不受权限保护。

android:process 服务允许的进程名称。通常应用程序的全部组件运行于为应用程序创建的默认进程。它与应用程序包名相同。application中的process能为所有组件设置一个默认值,但是组件能用自己的process属性重写默认值。从而允许应用程序跨越多个进程。
如果分配给该属性的名称以冒号(:)开头,仅属于应用程序的新进程会在须要时创建,服务能在该进程中运行。如果进程名称以小写字母开头,服务会允许在以此为名的全局进程,但是须要提供相应的权限。这允许不同应用程序组件共享进程,减少资源的开销。

Started Service的两种创建方式

1 继承Service 类,当继承此类时,创建新线程来执行服务的全部工作是非常重要的。因为服务默认使用应用程序主线程,这可能降低应用程序Activity的运行性能。

2 继承IntentService类,IntentService是Service的子类,它每次使用一个工作线程来处理全部请求。再不需要同时处理多个请求时,这是最佳选择。我们仅需要实现onHandleIntent()方法,此方法接收每次启动请求的Intent 以便完成后台任务。

继承IntentService的栗子:

public class MyService extends IntentService {
    public MyService() {
        super("MyService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        long endTime = System.currentTimeMillis() + 3 * 1000;
        while (System.currentTimeMillis() < endTime) {
            synchronized (this) {
                try {
                    Log.i("----", String.valueOf(endTime - System.currentTimeMillis()));
                    wait(endTime - System.currentTimeMillis());
                    Log.i(">>>>", String.valueOf(endTime - System.currentTimeMillis()));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

继承Service类实现:

public class Myservice extends Service {

    private Looper mServiceLooper;
    private MyserviceHandler mServiceHandler;


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

    private final class MyserviceHandler extends Handler{
        public MyserviceHandler(Looper looper){
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            long endTime = System.currentTimeMillis()+5*1000;
            while (System.currentTimeMillis()<endTime){
                synchronized (this){
                    try {
                        wait(endTime - System.currentTimeMillis());
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
            stopSelf(msg.arg1);
        }
    }

    @Override
    public void onCreate() {
        HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
        thread.start();
        mServiceLooper = thread.getLooper();
        mServiceHandler = new MyserviceHandler(mServiceLooper);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        mServiceHandler.sendMessage(msg);
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        Toast.makeText(Myservice.this, "over", Toast.LENGTH_SHORT).show();
    }
}

Bound Service 的两种实现方式

  1. 继承Binder 类实现。
    如果服务仅仅用于本地应用程序并且不必跨进程工作,我们可以实现自己的Binder类来为客户端提供访问服务的共公方法。

实现步骤为:
创建Binder类实例来完成下列操作之一:
- 包含客户端能调用的共公方法
- 返回当前Service实例,其中包含客户端能调用的共公方法
- 返回服务管理的其他实例,其中包含客户端能调用的共公方法

从onBind()回调方法中返回Binder类实例
从onServiceConnected()回调方法接收Binder类实例,并且使用提供的方法调用绑定服务。

public class MainActivity extends PermissionActivity {

    Myservice myservice;
    boolean bound = false;
    Button btn ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (bound){
                    int num = myservice.getRandomNumber();
                    btn.setText(String.valueOf(num));
                }
            }
        });
    }


    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this,Myservice.class);
        bindService(intent,connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (bound){
            unbindService(connection);
            bound = false;
        }
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Myservice.LocalBinder binder = (Myservice.LocalBinder) iBinder;
            myservice = binder.getService();
            bound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            bound = false;
        }
    };

}

service类为

public class Myservice extends Service {

    private final IBinder binder = new LocalBinder();
    private final Random generator = new Random();


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

    public class LocalBinder extends Binder {
        Myservice getService() {
            return Myservice.this;
        }
    }

    public int getRandomNumber() {
        return generator.nextInt(100);
    }

}
  1. 使用Messenger类。
    如果我们需要服务与远程进程通信,则可以使用Messenger来为服务提供接口。此方法允许不使用AIDL 执行进程间的通信。

如何使用Messager:
1. 实现Handler的服务因为每次从客户端调用而收到回调
2. Handler用于创建Messenger对象。
3. Messenger创建IBinder,服务从onBind()方法将其返回到客户端。
4. 客户端使用IBinder来实例化Messenger,然后使用它来发送Message对象到服务
5. 服务在其Handler的handleMessage()方法接收Message

我们的MessengerService

public class MessengerService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Toast.makeText(getApplicationContext(), "Binding", Toast.LENGTH_SHORT).show();
        return messenger.getBinder();
    }

    static final int TAG = 1;

    class IncomingHander extends Handler {
        @Override
        public void handleMessage(Message msg) {

            switch (msg.what) {
                case 1:
                    Toast.makeText(getApplicationContext(), "11111", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    super.handleMessage(msg);
                    break;
            }
        }
    }

    final Messenger messenger = new Messenger(new IncomingHander());


}

我们的Activity:

public class MainActivity extends PermissionActivity {

    Messenger messenger = null;
    boolean bound = false;
    Button btn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!bound) {
                    Message msg = Message.obtain(null, MessengerService.TAG, 0, 0);
                    try {
                        messenger.send(msg);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }


    @Override
    protected void onStart() {
        super.onStart();
        Intent intent = new Intent(this, MessengerService.class);
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (bound) {
            unbindService(connection);
            bound = false;
        }
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            messenger = new Messenger(iBinder);
            bound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            messenger = null;
            bound = false;
        }
    };

}

放一个demo :http://download.csdn.net/detail/qq_27561483/9628907

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值