Carson帶你學(xué)Android:Service使用教程(本地驮履、可通信的鱼辙、前臺、遠(yuǎn)程)


前言

  • Service作為Android四大組件之一玫镐,應(yīng)用非常廣泛
  • 本文將介紹Service最基礎(chǔ)的知識:Service的生命周期

如果你對Service還未了解倒戏,建議先閱讀我寫的文章:
Android四大組件:Service史上最全面解析


目錄

目錄

1. Service分類

1.1 Service的類型

分類

1.2 特點(diǎn)

Service類型的詳細(xì)介紹

2.具體使用解析

2.1 本地Service

這是最普通、最常用的后臺服務(wù)Service摘悴。

2.1.1 使用步驟

  • 步驟1:新建子類繼承Service類

需重寫父類的onCreate()峭梳、onStartCommand()舰绘、onDestroy()和onBind()方法

  • 步驟2:構(gòu)建用于啟動Service的Intent對象
  • 步驟3:調(diào)用startService()啟動Service蹂喻、調(diào)用stopService()停止服務(wù)
  • 步驟4:在AndroidManifest.xml里注冊Service

2.1.2 實(shí)例Demo

接下來我將用一個(gè)實(shí)例Demo進(jìn)行本地Service說明

建議先下載Demo再進(jìn)行閱讀:(carson.ho的Github地址)Demo_for_Service

  • 步驟1:新建子類繼承Service類

需重寫父類的onCreate()、onStartCommand()捂寿、onDestroy()和onBind()

MyService.java

public class MyService extends Service {


//啟動Service之后口四,就可以在onCreate()或onStartCommand()方法里去執(zhí)行一些具體的邏輯
//由于這里作Demo用,所以只打印一些語句
    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("執(zhí)行了onCreat()");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("執(zhí)行了onStartCommand()");
        return super.onStartCommand(intent, flags, startId);


    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("執(zhí)行了onDestory()");
    }

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

  • 步驟2:在主布局文件設(shè)置兩個(gè)Button分別用于啟動和停止Service
    activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="scut.carson_ho.demo_service.MainActivity">

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/startService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="啟動服務(wù)" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@+id/startService"
        android:id="@+id/stopService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止服務(wù)" />
</RelativeLayout>

  • 步驟3:構(gòu)建Intent對象秦陋,并調(diào)用startService()啟動Service蔓彩、stopService停止服務(wù)

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button startService;
    private Button stopService;

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

        startService = (Button) findViewById(R.id.startService);
        stopService = (Button) findViewById(R.id.stopService);

        startService.setOnClickListener(this);
        startService.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            //點(diǎn)擊啟動Service Button
            case R.id.startService:
                //構(gòu)建啟動服務(wù)的Intent對象
                Intent startIntent = new Intent(this, MyService.class);
                //調(diào)用startService()方法-傳入Intent對象,以此啟動服務(wù)
                startService(startIntent);
                
            //點(diǎn)擊停止Service Button
            case R.id.stopService:
                //構(gòu)建停止服務(wù)的Intent對象
                Intent stopIntent = new Intent(this, MyService.class);
                //調(diào)用stopService()方法-傳入Intent對象,以此停止服務(wù)
                stopService(stopIntent);
                
        }
    }
}
  • 步驟4:在AndroidManifest.xml里注冊Service
    AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="scut.carson_ho.demo_service">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

        </activity>

        //注冊Service服務(wù)
        <service android:name=".MyService">
        </service>

    </application>

</manifest>

Androidmanifest里Service的常見屬性說明

屬性 說明 備注
android:name Service的類名
android:label Service的名字 若不設(shè)置,默認(rèn)為Service類名
android:icon Service的圖標(biāo)
android:permission 申明此Service的權(quán)限 有提供了該權(quán)限的應(yīng)用才能控制或連接此服務(wù)
android:process 表示該服務(wù)是否在另一個(gè)進(jìn)程中運(yùn)行(遠(yuǎn)程服務(wù)) 不設(shè)置默認(rèn)為本地服務(wù)驳概;remote則設(shè)置成遠(yuǎn)程服務(wù)
android:enabled 系統(tǒng)默認(rèn)啟動 true:Service 將會默認(rèn)被系統(tǒng)啟動赤嚼;不設(shè)置則默認(rèn)為false
android:exported 該服務(wù)是否能夠被其他應(yīng)用程序所控制或連接 不設(shè)置默認(rèn)此項(xiàng)為 false

2.1.3 測試結(jié)果

測試結(jié)果.png

2.1.4 Demo地址

Carson.ho的Github地址:Demo_for_Service

2.2 可通信的服務(wù)Service

  • 上面介紹的Service是最基礎(chǔ)的,但只能單機(jī)使用顺又,即無法與Activity通信
  • 接下來將在上面的基礎(chǔ)用法上更卒,增設(shè)“與Activity通信”的功能,即使用綁定Service服務(wù)(Binder類稚照、bindService()蹂空、onBind()俯萌、unbindService()、onUnbind())

2.2.1 實(shí)例Demo

接下來我將用一個(gè)實(shí)例Demo進(jìn)行可通信的服務(wù)Service說明

建議先下載Demo再進(jìn)行閱讀:(carson.ho的Github地址)Demo_for_Service

  • 步驟1:在新建子類繼承Service類上枕,并新建一個(gè)子類繼承自Binder類咐熙、寫入與Activity關(guān)聯(lián)需要的方法、創(chuàng)建實(shí)例
public class MyService extends Service {

    private MyBinder mBinder = new MyBinder();

    @Override
    public void onCreate() {
        super.onCreate();
        System.out.println("執(zhí)行了onCreat()");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        System.out.println("執(zhí)行了onStartCommand()");
        return super.onStartCommand(intent, flags, startId);


    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        System.out.println("執(zhí)行了onDestory()");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        System.out.println("執(zhí)行了onBind()");
        //返回實(shí)例
        return mBinder;
    }


    @Override
    public boolean onUnbind(Intent intent) {
        System.out.println("執(zhí)行了onUnbind()");
        return super.onUnbind(intent);
    }

    //新建一個(gè)子類繼承自Binder類
    class MyBinder extends Binder {

        public void service_connect_Activity() {
            System.out.println("Service關(guān)聯(lián)了Activity,并在Activity執(zhí)行了Service的方法");

        }
    }
}
  • 步驟2:在主布局文件再設(shè)置兩個(gè)Button分別用于綁定和解綁Service
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="scut.carson_ho.demo_service.MainActivity">

    <Button
        android:layout_centerInParent="true"
        android:id="@+id/startService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="啟動服務(wù)" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@+id/startService"
        android:id="@+id/stopService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="停止服務(wù)" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@id/stopService"
        android:id="@+id/bindService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="綁定服務(wù)" />

    <Button
        android:layout_centerInParent="true"
        android:layout_below="@id/bindService"
        android:id="@+id/unbindService"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="解綁服務(wù)"
        />
</RelativeLayout>

  • 步驟3:在Activity通過調(diào)用MyBinder類中的public方法來實(shí)現(xiàn)Activity與Service的聯(lián)系

即實(shí)現(xiàn)了Activity指揮Service干什么Service就去干什么的功能

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button startService;
    private Button stopService;
    private Button bindService;
    private Button unbindService;

    private MyService.MyBinder myBinder;


    //創(chuàng)建ServiceConnection的匿名類
    private ServiceConnection connection = new ServiceConnection() {

        //重寫onServiceConnected()方法和onServiceDisconnected()方法
        //在Activity與Service建立關(guān)聯(lián)和解除關(guān)聯(lián)的時(shí)候調(diào)用
        @Override
        public void onServiceDisconnected(ComponentName name) {
        }

        //在Activity與Service解除關(guān)聯(lián)的時(shí)候調(diào)用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            //實(shí)例化Service的內(nèi)部類myBinder
            //通過向下轉(zhuǎn)型得到了MyBinder的實(shí)例
            myBinder = (MyService.MyBinder) service;
            //在Activity調(diào)用Service類的方法
            myBinder.service_connect_Activity();
        }
    };

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


        startService = (Button) findViewById(R.id.startService);
        stopService = (Button) findViewById(R.id.stopService);

        startService.setOnClickListener(this);
        stopService.setOnClickListener(this);

        bindService = (Button) findViewById(R.id.bindService);
        unbindService = (Button) findViewById(R.id.unbindService);

        bindService.setOnClickListener(this);
        unbindService.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            //點(diǎn)擊啟動Service
            case R.id.startService:
                //構(gòu)建啟動服務(wù)的Intent對象
                Intent startIntent = new Intent(this, MyService.class);
                //調(diào)用startService()方法-傳入Intent對象,以此啟動服務(wù)
                startService(startIntent);
                break;

            //點(diǎn)擊停止Service
            case R.id.stopService:
                //構(gòu)建停止服務(wù)的Intent對象
                Intent stopIntent = new Intent(this, MyService.class);
                //調(diào)用stopService()方法-傳入Intent對象,以此停止服務(wù)
                stopService(stopIntent);
                break;

            //點(diǎn)擊綁定Service
            case R.id.bindService:
                //構(gòu)建綁定服務(wù)的Intent對象
                Intent bindIntent = new Intent(this, MyService.class);
                //調(diào)用bindService()方法,以此停止服務(wù)

                bindService(bindIntent,connection,BIND_AUTO_CREATE);
                //參數(shù)說明
                //第一個(gè)參數(shù):Intent對象
                //第二個(gè)參數(shù):上面創(chuàng)建的Serviceconnection實(shí)例
                //第三個(gè)參數(shù):標(biāo)志位
                //這里傳入BIND_AUTO_CREATE表示在Activity和Service建立關(guān)聯(lián)后自動創(chuàng)建Service
                //這會使得MyService中的onCreate()方法得到執(zhí)行辨萍,但onStartCommand()方法不會執(zhí)行
                break;

            //點(diǎn)擊解綁Service
            case R.id.unbindService:
                //調(diào)用unbindService()解綁服務(wù)
                //參數(shù)是上面創(chuàng)建的Serviceconnection實(shí)例
                unbindService(connection);
                break;

                default:
                    break;

        }
    }
}

2.2.2 測試結(jié)果

測試結(jié)果11.png

2.2.3 Demo

carson.ho的Github地址:Demo_for_Service

2.3 前臺Service

前臺Service和后臺Service(普通)最大的區(qū)別就在于:

  • 前臺Service在下拉通知欄有顯示通知(如下圖)棋恼,但后臺Service沒有;
TT9$TN8IK1SAPDT%~0IRLS2.png
  • 前臺Service優(yōu)先級較高锈玉,不會由于系統(tǒng)內(nèi)存不足而被回收蘸泻;后臺Service優(yōu)先級較低,當(dāng)系統(tǒng)出現(xiàn)內(nèi)存不足情況時(shí)嘲玫,很有可能會被回收

2.3.1 具體使用

用法很簡單悦施,只需要在原有的Service類對onCreate()方法進(jìn)行稍微修改即可,如下圖:

@Override
    public void onCreate() {
        super.onCreate();
        System.out.println("執(zhí)行了onCreat()");

        //添加下列代碼將后臺Service變成前臺Service
        //構(gòu)建"點(diǎn)擊通知后打開MainActivity"的Intent對象
        Intent notificationIntent = new Intent(this,MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);

        //新建Builer對象
        Notification.Builder builer = new Notification.Builder(this);
        builer.setContentTitle("前臺服務(wù)通知的標(biāo)題");//設(shè)置通知的標(biāo)題
        builer.setContentText("前臺服務(wù)通知的內(nèi)容");//設(shè)置通知的內(nèi)容
        builer.setSmallIcon(R.mipmap.ic_launcher);//設(shè)置通知的圖標(biāo)
        builer.setContentIntent(pendingIntent);//設(shè)置點(diǎn)擊通知后的操作

        Notification notification = builer.getNotification();//將Builder對象轉(zhuǎn)變成普通的notification
        startForeground(1, notification);//讓Service變成前臺Service,并在系統(tǒng)的狀態(tài)欄顯示出來

    }

2.3.2 測試結(jié)果

運(yùn)行后去团,當(dāng)點(diǎn)擊Start Service或Bind Service按鈕抡诞,Service就會以前臺Service的模式啟動(通知欄上有通知),如下圖


點(diǎn)擊啟動服務(wù)

2.4 遠(yuǎn)程Service

具體請看我寫的另外一篇文章:Android:遠(yuǎn)程服務(wù)Service(含AIDL & IPC講解)

3. 使用場景

  • 通過上述描述土陪,你應(yīng)該對Service類型及其使用非常了解昼汗;
  • 那么,我們該什么時(shí)候用哪種類型的Service呢鬼雀?
  • 各種Service的使用場景請看下圖:


    使用場景

4. 總結(jié)

  • 本文對Service的使用進(jìn)行了全面解析(本地顷窒、可通信、前臺和遠(yuǎn)程Service)
  • 如果你還想了解關(guān)于Service的其他知識源哩,請瀏覽以下文章:

Android四大組件:Service史上最全面解析
Android:Service生命周期最全面解析
Android:(本地鞋吉、可通信的、前臺励烦、遠(yuǎn)程)Service使用全面介紹
Android:遠(yuǎn)程服務(wù)Service(含AIDL & IPC講解)
Android多線程全面解析:IntentService用法&源碼

  • Carson帶你學(xué)四大組件文章系列:

Carson帶你學(xué)Android:頁面活動-Activity
Carson帶你學(xué)Android:廣播-BroadcastReceiver
Carson帶你學(xué)Android:服務(wù)-Service
Carson帶你學(xué)Android:內(nèi)存承載器-ContentProvider


歡迎關(guān)注Carson_Ho的簡書

不定期分享關(guān)于安卓開發(fā)的干貨谓着,追求短、平坛掠、快赊锚,但卻不缺深度


請點(diǎn)贊屉栓!因?yàn)槟愕墓膭钍俏覍懽鞯淖畲髣恿Γ?/h1>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舷蒲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子友多,更是在濱河造成了極大的恐慌牲平,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夷陋,死亡現(xiàn)場離奇詭異欠拾,居然都是意外死亡胰锌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進(jìn)店門藐窄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來资昧,“玉大人,你說我怎么就攤上這事荆忍「翊” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵刹枉,是天一觀的道長叽唱。 經(jīng)常有香客問我,道長微宝,這世上最難降的妖魔是什么棺亭? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蟋软,結(jié)果婚禮上镶摘,老公的妹妹穿的比我還像新娘。我一直安慰自己岳守,他們只是感情好凄敢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著湿痢,像睡著了一般涝缝。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上譬重,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天拒逮,我揣著相機(jī)與錄音,去河邊找鬼害幅。 笑死消恍,一個(gè)胖子當(dāng)著我的面吹牛岂昭,可吹牛的內(nèi)容都是我干的以现。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼约啊,長吁一口氣:“原來是場噩夢啊……” “哼邑遏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起恰矩,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤记盒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后外傅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纪吮,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俩檬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了碾盟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片棚辽。...
    茶點(diǎn)故事閱讀 39,795評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖冰肴,靈堂內(nèi)的尸體忽然破棺而出屈藐,到底是詐尸還是另有隱情,我是刑警寧澤熙尉,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布联逻,位于F島的核電站,受9級特大地震影響检痰,放射性物質(zhì)發(fā)生泄漏包归。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一铅歼、第九天 我趴在偏房一處隱蔽的房頂上張望箫踩。 院中可真熱鬧,春花似錦谭贪、人聲如沸境钟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慨削。三九已至,卻和暖如春套媚,著一層夾襖步出監(jiān)牢的瞬間缚态,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工堤瘤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玫芦,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓本辐,卻偏偏與公主長得像桥帆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子慎皱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容