(本地、可通信的、前臺、遠程)Service使用全面介紹


前言

  • Service作為Android四大組件之一,應用非常廣泛
  • 本文將介紹Service最基礎的知識:Service的生命週期

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

  • </ul>


    目錄


    目錄

    1. Service分類

    1.1 Service的類型


    分類

    1.2 特點


    Service類型的詳細介紹

    2.具體使用解析

    2.1 本地Service

    這是最普通、最常用的後臺服務Service。

    2.1.1 使用步驟

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

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

    • 步驟2:構建用於啟動Service的Intent對象
    • 步驟3:調用startService()啟動Service、調用stopService()停止服務
    • 步驟4:在AndroidManifest.xml裡註冊Service

    2.1.2 實例Demo

    接下來我將用一個實例Demo進行本地Service說明

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

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

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

    MyService.java

    public class MyService extends Service {
    
    
    //啟動Service之後,就可以在onCreate()或onStartCommand()方法裡去執行一些具體的邏輯
    //由於這裡作Demo用,所以只打印一些語句
        @Override
        public void onCreate() {
            super.onCreate();
            System.out.println("執行了onCreat()");
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            System.out.println("執行了onStartCommand()");
            return super.onStartCommand(intent, flags, startId);
    
    
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            System.out.println("執行了onDestory()");
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    • 步驟2:在主佈局文件設置兩個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="啟動服務" />
    
        <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="停止服務" />
    </RelativeLayout>
    • 步驟3:構建Intent對象,並調用startService()啟動Service、stopService停止服務

    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()) {
    
                //點擊啟動Service Button
                case R.id.startService:
                    //構建啟動服務的Intent對象
                    Intent startIntent = new Intent(this, MyService.class);
                    //調用startService()方法-傳入Intent對象,以此啟動服務
                    startService(startIntent);
    
                //點擊停止Service Button
                case R.id.stopService:
                    //構建停止服務的Intent對象
                    Intent stopIntent = new Intent(this, MyService.class);
                    //調用stopService()方法-傳入Intent對象,以此停止服務
                    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服務
            <service android:name=".MyService">
            </service>
    
        </application>
    
    </manifest>

    Androidmanifest裡Service的常見屬性說明

    屬性 說明 備註
    android:name Service的類名
    android:label Service的名字 若不設置,默認為Service類名
    android:icon Service的圖標
    android:permission 申明此Service的權限 有提供了該權限的應用才能控制或連接此服務
    android:process 表示該服務是否在另一個進程中運行(遠程服務) 不設置默認為本地服務;remote則設置成遠程服務
    android:enabled 系統默認啟動 true:Service 將會默認被系統啟動;不設置則默認為false
    android:exported 該服務是否能夠被其他應用程序所控制或連接 不設置默認此項為 false

    2.1.3 測試結果


    測試結果.png

    2.1.4 Demo地址

    Carson.ho的Github地址:Demo_for_Service

    2.2 可通信的服務Service

    • 上面介紹的Service是最基礎的,但只能單機使用,即無法與Activity通信
    • 接下來將在上面的基礎用法上,增設“與Activity通信”的功能,即使用綁定Service服務(Binder類、bindService()、onBind()、unbindService()、onUnbind())

    2.2.1 實例Demo

    接下來我將用一個實例Demo進行可通信的服務Service說明

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

    • 步驟1:在新建子類繼承Service類,並新建一個子類繼承自Binder類、寫入與Activity關聯需要的方法、創建實例
    public class MyService extends Service {
    
        private MyBinder mBinder = new MyBinder();
    
        @Override
        public void onCreate() {
            super.onCreate();
            System.out.println("執行了onCreat()");
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            System.out.println("執行了onStartCommand()");
            return super.onStartCommand(intent, flags, startId);
    
    
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            System.out.println("執行了onDestory()");
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            System.out.println("執行了onBind()");
            //返回實例
            return mBinder;
        }
    
    
        @Override
        public boolean onUnbind(Intent intent) {
            System.out.println("執行了onUnbind()");
            return super.onUnbind(intent);
        }
    
        //新建一個子類繼承自Binder類
        class MyBinder extends Binder {
    
            public void service_connect_Activity() {
                System.out.println("Service關聯了Activity,並在Activity執行了Service的方法");
    
            }
        }
    }
    • 步驟2:在主佈局文件再設置兩個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="啟動服務" />
    
        <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="停止服務" />
    
        <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="綁定服務" />
    
        <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="解綁服務"
            />
    </RelativeLayout>
    • 步驟3:在Activity通過調用MyBinder類中的public方法來實現Activity與Service的聯繫

      即實現了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;
    
    
        //創建ServiceConnection的匿名類
        private ServiceConnection connection = new ServiceConnection() {
    
            //重寫onServiceConnected()方法和onServiceDisconnected()方法
            //在Activity與Service建立關聯和解除關聯的時候調用
            @Override
            public void onServiceDisconnected(ComponentName name) {
            }
    
            //在Activity與Service解除關聯的時候調用
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                //實例化Service的內部類myBinder
                //通過向下轉型得到了MyBinder的實例
                myBinder = (MyService.MyBinder) service;
                //在Activity調用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()) {
    
                //點擊啟動Service
                case R.id.startService:
                    //構建啟動服務的Intent對象
                    Intent startIntent = new Intent(this, MyService.class);
                    //調用startService()方法-傳入Intent對象,以此啟動服務
                    startService(startIntent);
                    break;
    
                //點擊停止Service
                case R.id.stopService:
                    //構建停止服務的Intent對象
                    Intent stopIntent = new Intent(this, MyService.class);
                    //調用stopService()方法-傳入Intent對象,以此停止服務
                    stopService(stopIntent);
                    break;
    
                //點擊綁定Service
                case R.id.bindService:
                    //構建綁定服務的Intent對象
                    Intent bindIntent = new Intent(this, MyService.class);
                    //調用bindService()方法,以此停止服務
    
                    bindService(bindIntent,connection,BIND_AUTO_CREATE);
                    //參數說明
                    //第一個參數:Intent對象
                    //第二個參數:上面創建的Serviceconnection實例
                    //第三個參數:標誌位
                    //這裡傳入BIND_AUTO_CREATE表示在Activity和Service建立關聯後自動創建Service
                    //這會使得MyService中的onCreate()方法得到執行,但onStartCommand()方法不會執行
                    break;
    
                //點擊解綁Service
                case R.id.unbindService:
                    //調用unbindService()解綁服務
                    //參數是上面創建的Serviceconnection實例
                    unbindService(connection);
                    break;
    
                    default:
                        break;
    
            }
        }
    }

    2.2.2 測試結果


    測試結果11.png

    2.2.3 Demo

    carson.ho的Github地址:Demo_for_Service

    2.3 前臺Service

    前臺Service和後臺Service(普通)最大的區別就在於:

    • 前臺Service在下拉通知欄有顯示通知(如下圖),但後臺Service沒有;

    TT9$TN8IK1SAPDT%~0IRLS2.png
    • 前臺Service優先級較高,不會由於系統內存不足而被回收;後臺Service優先級較低,當系統出現內存不足情況時,很有可能會被回收

    2.3.1 具體使用

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

    @Override
        public void onCreate() {
            super.onCreate();
            System.out.println("執行了onCreat()");
    
            //添加下列代碼將後臺Service變成前臺Service
            //構建"點擊通知後打開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("前臺服務通知的標題");//設置通知的標題
            builer.setContentText("前臺服務通知的內容");//設置通知的內容
            builer.setSmallIcon(R.mipmap.ic_launcher);//設置通知的圖標
            builer.setContentIntent(pendingIntent);//設置點擊通知後的操作
    
            Notification notification = builer.getNotification();//將Builder對象轉變成普通的notification
            startForeground(1, notification);//讓Service變成前臺Service,並在系統的狀態欄顯示出來
    
        }

    2.3.2 測試結果

    運行後,當點擊Start Service或Bind Service按鈕,Service就會以前臺Service的模式啟動(通知欄上有通知),如下圖


    點擊啟動服務

    2.4 遠程Service

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

    3. 使用場景

    • 通過上述描述,你應該對Service類型及其使用非常瞭解;
    • 那麼,我們該什麼時候用哪種類型的Service呢?
    • 各種Service的使用場景請看下圖:

      使用場景

    4. 總結


    請點贊!因為你們的贊同/鼓勵是我寫作的最大動力!

    相關文章閱讀
    Android開發:最全面、最易懂的Android屏幕適配解決方案
    Android開發:Handler異步通信機制全面解析(包含Looper、Message Queue)
    Android開發:最全面、最易懂的Webview詳解
    Android開發:JSON簡介及最全面解析方法!
    Android開發:頂部Tab導航欄實現(TabLayout+ViewPager+Fragment)
    Android開發:底部Tab菜單欄實現(FragmentTabHost+ViewPager)


    歡迎關注Carson_Ho的簡書!

    不定期分享關於安卓開發的乾貨,追求短、平、快,但卻不缺深度


        </div>