Android之本地Service(LocalService)

简介:介绍Android系统中的本地Service,即Local Service。


什么是 Service

Service即服务,与Activity不同的是,Service是没有界面、不能自己启动的,运行在后台的程序。当我们退出应用时,Service进程并没有结束,而是仍然运行在后台。

什么时候使用Service?举个常见的例子:播放音乐,在播放音乐的同时想要边干些其他事情,就需要隐藏或退出播放音乐的应用,如果没有使用Service,会因为音乐应用将被暂停而听不到音乐,所以这时候就得用到Service了。

在Android系统中,Service分为两种:Local ServiceRemote Service

  • 本地服务, Local Service 用于应用程序内部。在Service可以调用Context.startService()启动,调用Context.stopService()结束。在内部可以调用Service.stopSelf() 或 Service.stopSelfResult()来自己停止。无论调用了多少次startService(),都只需调用一次stopService()来停止。

  • 远程服务, Remote Service 用于android系统内部的应用程序之间。可以定义接口并把接口暴露出来,以便其他应用进行操作。客户端建立到服务对象的连接,并通过那个连接来调用服务。调用Context.bindService()方法建立连接,并启动,以调用 Context.unbindService()关闭连接。多个客户端可以绑定至同一个服务。如果服务此时还没有加载,bindService()会先加载它。
    提供给可被其他应用复用,比如定义一个天气预报服务,提供与其他应用调用即可。

Service和其他组件一样,都是运行在主线程中,因此不能用它来做耗时的请求或者动作。如果需要,可以在服务中开一个新线程,在该线程中做耗时动作。


Service的生命周期

Service的生命周期并不像Activity那么复杂,它只继承了onCreate(), onStart(), onDestroy()三个方法,当我们第一次启动Service时,先后调用了onCreate(),onStart()这两个方法,当停止Service时,则执行onDestroy()方法,这里需要注意的是,如果Service已经启动了,当我们再次启动Service时,不会在执行onCreate()方法,而是直接执行onStart()方法。

context.startService() ->onCreate()- >onStart()->Service running – 调用context.stopService() ->onDestroy()

context.bindService()->onCreate()->onBind()->Service running – 调用>onUnbind() -> onDestroy()


实例

创建Android项目,创建MainService.java,代码如下:

package com.test.service;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;

public class MainService extends Service {

    public class MyBinder extends Binder {

        public MainService getService() {
            return MainService.this;
        }
    }

    private MyBinder binder;

    @Override
    public IBinder onBind(Intent vIntent) {
        System.out.println("onBind");
        return binder;
    }

    @Override
    public boolean onUnbind(Intent vIntent) {
        System.out.println("onUnbind");
        return super.onUnbind(vIntent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("onCreate");
        binder = new MyBinder();
    }

    @Override
    public void onStart(Intent vIntent, int vStartId) {
        super.onStart(vIntent, vStartId);
        System.out.println("onStart");
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("onDestroy");
    }

    public void next() {
        System.out.println("播放下一首");
    }

    public void end() {
        System.out.println("停止");
    }

    public void play() {
        System.out.println("播放");
    }

    public void pre() {
        System.out.println("播放上一首");
    }
}

在AndroidManifest.xml中application节点下添加声明:

<service
    android:name="com.test.service.MainService"
    android:enabled="true" >
</service>

接下来编写主界面布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onStarClick"
            android:text="Start" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onStopClick"
            android:text="Stop" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onBindClick"
            android:text="Bind" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onUnbindClick"
            android:text="Unbind" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onPreClick"
            android:text="Pre" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNextClick"
            android:text="Next" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onPlayClick"
            android:text="Play" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onEndClick"
            android:text="End" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNewClick"
            android:text="new" />

    </LinearLayout>

</LinearLayout>

界面布局中,按钮添加了onClick属性,因此,在代码中必须要实现对应的方法,主界面代码如下:

package com.test.service;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;

import com.test.service.MainService.MyBinder;

public class MainActivity extends Activity {

    private MainService mService = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void onStarClick(View v) {
        Intent service = new Intent(this, MainService.class);
        startService(service);
    }

    public void onStopClick(View v) {
        Intent service = new Intent(this, MainService.class);
        stopService(service);
    }

    public void onBindClick(View v) {
        bindService(new Intent(this, MainService.class), sc,
                Context.BIND_AUTO_CREATE);
    }

    public void onUnbindClick(View v) {
        if (sc != null) {
            unbindService(sc);
            sc = null;
        }
    }

    public ServiceConnection sc = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName vName) {
            mService = null;
            System.out.println("服务断开!");
        }

        @Override
        public void onServiceConnected(ComponentName vName, IBinder vService) {
            System.out.println("onServiceConnected");
            MyBinder binder = (MainService.MyBinder) vService;
            mService = binder.getService();
        }
    };

    public void onPreClick(View v) {
        if (mService != null) {
            mService.pre();
        }
    }

    public void onNextClick(View v) {
        if (mService != null) {
            mService.next();
        }
    }

    public void onPlayClick(View v) {
        if (mService != null) {
            mService.play();
        }
    }

    public void onEndClick(View v) {
        if (mService != null) {
            mService.end();
        }
    }

    public void onNewClick(View v) {
        startActivity(new Intent(this, NewActivity.class));
    }
}

在绑定服务的时候,需要一个服务连接对象,ServiceConnection,服务一旦连接,就会调用onServiceConnected方法,我们可以在这个方法里面返回我们的本地服务对象,具体看代码;而在服务断开时候会调用onServiceDisconnected方法,我们可以清理一些服务资源。

界面上第一排有四个按钮:Start(启动服务)、Stop(停止服务)、Bind(绑定服务)和Unbing(解除绑定)。
第二排有四个按钮,分别对应播放器的几个功能,具体实现在MainService中。
最后有个new按钮,该按钮启动一个新的页面-New界面,用来测试新界面与Service的链接情况。

New界面的布局如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onPreClick"
            android:text="Pre" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onNextClick"
            android:text="Next" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onPlayClick"
            android:text="Play" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onEndClick"
            android:text="End" />
    </LinearLayout>

</LinearLayout>

New界面的代码如下:

package com.test.service;

import com.test.service.MainService.MyBinder;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;

public class NewActivity extends Activity {

    private MainService mService = null;

    @Override
    protected void onCreate(Bundle vSavedInstanceState) {
        super.onCreate(vSavedInstanceState);
        setContentView(R.layout.activity_new);
        Intent service = new Intent(this, MainService.class);
        startService(service);
        bindService(service, sc, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(sc);
    }

    public ServiceConnection sc = new ServiceConnection() {

        @Override
        public void onServiceDisconnected(ComponentName vName) {
            mService = null;
            System.out.println("服务断开!");
        }

        @Override
        public void onServiceConnected(ComponentName vName, IBinder vService) {
            System.out.println("onServiceConnected");
            MyBinder binder = (MainService.MyBinder) vService;
            mService = binder.getService();
        }
    };

    public void onPreClick(View v) {
        if (mService != null) {
            mService.pre();
        }
    }

    public void onNextClick(View v) {
        if (mService != null) {
            mService.next();
        }
    }

    public void onPlayClick(View v) {
        if (mService != null) {
            mService.play();
        }
    }

    public void onEndClick(View v) {
        if (mService != null) {
            mService.end();
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值