android之Service(服務)

Service我覺的跟Activity差不多,就是沒有界面。它是在後臺運行的。服務有自己的生命週期。接下來就學習以下內容:

想仔細瞭解的可以去官網學習
https://developer.android.com/guide/components/services.html

  1. 開啓服務生命週期和綁定服務生命週期
  2. 調用本地服務方法和遠程服務方法

開啓服務生命週期

佈局文件activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.edu.androidforservicesimple.MainActivity">


    <Button
        android:onClick="start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="開啓服務"
        />
    <Button
        android:onClick="stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="關閉服務"
        />
</LinearLayout>

就兩個按鈕,很簡單

MyService.java代碼如下:

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {
    private static final String TAG="TAG";
    public MyService() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }

    @Override
    public void onCreate() {
        Log.i(TAG, "onCreate: ........");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i(TAG, "onStartCommand: ...........");
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 已過時的方法
     * @param intent
     * @param startId
     */
    @Override
    public void onStart(Intent intent, int startId) {
        Log.i(TAG, "onStart: .........");
        super.onStart(intent, startId);
    }


    @Override
    public void onDestroy() {
        Log.i(TAG, "onDestroy: ..............");
        super.onDestroy();
    }
}

MainActivity.java代碼如下:

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private Intent intent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(MainActivity.this, MyService.class);
    }

    public void start(View view) {

        startService(intent);
    }

    public void stop(View view) {
        stopService(intent);
    }
}

運行結果分析:

點擊開啓按鈕:執行的方法是:

這裏寫圖片描述

點擊關閉按鈕:執行的方法是:

這裏寫圖片描述

如果是點擊返回鍵時 ,不會關閉,它會一直運行在後臺

這裏寫圖片描述

直到有調用 stopService(Intent i )方法,服務纔會關閉。還要補充的是:當又一次開啓服務時。onCreate()不會執行,它只會執行一次。只會執行onStartCommand()方法,

綁定服務生命週期

首先在MyService服務中添加兩個生命週期方法:
onUnbind()和onRebind()

然後改寫MainActivity.java 代碼如下:

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "TAG";
    private Intent intent;


    ServiceConnection myConn = new ServiceConnection() {
        //當服務被綁定時調用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.i(TAG, "onServiceConnected:.... ");
        }

        //當服務被解綁是調用
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.i(TAG, "onServiceDisconnected: ...........");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(MainActivity.this, MyService.class);
    }

    public void start(View view) {
        bindService(intent, myConn, BIND_AUTO_CREATE);
    }

    public void stop(View view) {
        unbindService(myConn);

    }
}

運行結果分析:

點擊開啓服務按鈕: 執行的方法是

這裏寫圖片描述

再點擊開啓按鈕時: 不執行任何方法
當點擊關閉服務按鈕時 : 執行的方法是

這裏寫圖片描述

如果點擊關閉服務按鈕後,再點擊開啓按鈕時又會執行onCreate和onBind這兩種方法。當按下返回鍵時,也會執行onUnbind和onDestroy方法。這個可以說明綁定服務時,它的生命週期跟啓動它服務的Activity活動的生命週期一樣。

我們先看下官網介紹這兩種方式的區別:

這裏寫圖片描述

這張圖已經說明的很明顯了。講完這兩種方式的生命週期,我們該學習怎麼樣調用服務裏的方法。一種時是調用本地的,還一種是遠程調用的

調用本地服務的方法

activity_main.xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.edu.androidforinvokeservicemethod.MainActivity">

    <Button
        android:text="綁定服務"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="bind"
        />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="unbind"
        android:text="解除綁定"
        />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="invoke"
        android:text="調用服務中的方法"
        />
</LinearLayout>

MyService代碼如下 :

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

public class MyService extends Service {
    public MyService() {
    }

    public class MyBinder extends Binder {
        public void getName() {
            getMethodInService();
        }
    }

    public void getMethodInService() {
        Log.i("TAG", "我是來自服務中的方法");
    }

    @Override
    public IBinder onBind(Intent intent) {

        return new MyBinder();
    }
}

MainActivity.java代碼如下:

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    private Intent intent;
    private MyService.MyBinder myBinder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent(MainActivity.this, MyService.class);
    }

    ServiceConnection myConn = new ServiceConnection() {
        //綁定服務時調用
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myBinder = (MyService.MyBinder) service;
        }

        //解除綁定時調用
        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    /**
     * 綁定服務
     *
     * @param view
     */
    public void bind(View view) {
        bindService(intent, myConn, BIND_AUTO_CREATE);
    }

    /**
     * 解綁服務
     *
     * @param view
     */
    public void unbind(View view) {
        unbindService(myConn);
    }

    /**
     * 調用服務中的方法
     *
     * @param view
     */
    public void invoke(View view) {

        myBinder.getName();
    }
}

先點擊綁定按鈕,再點擊調用按鈕

運行結果:
這裏寫圖片描述

最後提一下,估計有人想new 一個服務實例來調用服務中的方法,其實這根本不行。因爲這是系統爲我們創建的。

這裏寫圖片描述

接下來就重點學習怎麼調用遠程服務中的方法

首先創建個遠程服務端

創建個adil文件 在main目錄下:
這裏寫圖片描述

代碼如下:

interface Person {
    void getName();
}

就是聲明瞭一個方法,補充下,該方法不能有修飾符

在rebuild下該項目,會出現person接口

這裏寫圖片描述

接下來就編寫MyService.java 代碼如下:

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class MyService extends Service {
    public MyService() {
    }

    public class MyBinder extends Person.Stub {

        @Override
        public void getName() throws RemoteException {
            getMethodInService();
        }
    }

    public void getMethodInService(){

        Log.i("TAG", " 我是來自遠程服務中的方法。。。。 ");

    }
    @Override
    public IBinder onBind(Intent intent) {

        return new MyBinder();
    }
}

接下來我們再創建個Moudle,創建之前我們先把遠程服務的清單文件改下,設置下動作。因爲我們要通過這個來開啓遠程服務

 <service
            android:name=".MyService"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="edu.jju.remote"></action>
            </intent-filter>
        </service>

創建好了新的Moudle 就把遠程服務下定義的adil文件直接複製過來,帶包一起復制。然後複製到新創建的Moudle Main目錄下

這裏寫圖片描述

複製完然後就rebuild下

activity_main.xml代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.edu.androidforinvokeremoteservice.MainActivity">


    <Button
        android:onClick="bind"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="綁定遠程服務"
        />
    <Button
        android:onClick="invoke"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="調用遠程服務中的方法"
        />
</LinearLayout>

就是兩個按鈕,簡單。哈哈

MainActivity.java代碼如下:

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.example.edu.androidforremoteservice.Person;

public class MainActivity extends AppCompatActivity {
    private Intent intent;
    private Person person;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intent = new Intent();
        intent.setAction("edu.jju.remote");//該動作是遠程服務當中的
    }

    ServiceConnection myConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            person = Person.Stub.asInterface(service);//這個跟調用本地服務方法有些區別
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {

        }
    };

    /**
     * 綁定遠程服務
     * @param view
     */
    public void bind(View view) {
        bindService(intent, myConn, BIND_AUTO_CREATE);
    }

    /**
     * 調用遠程服務中的方法
     * @param view
     * @throws RemoteException
     */
    public void invoke(View view) throws RemoteException {
        person.getName();
    }
}

然後就是怎麼測試了。應該先運行遠程服務後,再執行這個調用遠程服務的項目

點擊綁定遠程服務按鈕,然後點擊調用遠程服務方法按鈕。
運行結果:
這裏寫圖片描述

我居然一次就運行成功了,沒出問題。太佩服自己了。。哈哈

我已經把service服務講的差不多了,如果更詳細的瞭解服務的話可以去官網看。你也可以把我上面寫的跟着做一遍也差不多瞭解服務的基本知識了。基本上代碼全部在上面。

總結:

服務的啓動方式有兩種,一種是啓動另一種是綁定。綁定這種的生命週期跟綁定它的Activity生命週期一樣。再接下來我們就學習怎麼調用服務中的方法,也是兩種情況,1 調用本地服務中的方法,2 調用遠程服務中的方法。它們核心思想也是向外暴露接口,我感覺差不多。哈哈。。

源碼下載

https://github.com/songshuilin/AndroidForBlog

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章