文章目錄
- 零、學習目標
- 一、服務(Service)概述
- (一)行程優先級
- (二)服務的作用
- (三)服務的生命周期
- 二、案例演示 - 啟動與停止服務
- (一)運行效果
- (二)涉及知識點
- (三)實作步驟
- 1、創建安卓應用【StartStopService】
- 2、將背景圖片拷貝到drawable目錄
- 3、主布局資源檔案activity_main.xml
- 4、字串資源檔案strings.xml
- 5、創建自定義服務類 - CustomService
- 6、在專案清單檔案里注冊自定義服務類
- 7、主界面類 - Mainactivity
- 8、啟動應用,查看效果
- (1)顯式啟動服務 + 停止服務
- (2)隱式啟動服務 + 停止服務
- 三、案例演示 - 系結與解綁服務
- (一)運行效果
- (二)涉及知識點
- (三)實作步驟
- 1、創建安卓應用【BindUnbindService】
- 2、將背景圖片拷貝到drawable目錄
- 3、主布局資源檔案activity_main.xml
- 4、字串資源檔案strings.xml
- 5、創建自定義服務類 - CustomService
- 6、在專案清單檔案里注冊自定義服務類
- 7、主界面類 - MainActivity
- 8、啟動應用,查看效果
- 四、小結
- 五、課后作業
- 任務1、啟動服務傳遞資料
- 任務2、系結服務傳遞資料
零、學習目標
- 了解安卓組件“服務”的作用
- 掌握如何創建服務、注冊服務
- 掌握如何啟動服務和停止服務
- 掌握如何系結服務和解綁服務
一、服務(Service)概述
(一)行程優先級
- 應用程式的生命周期是在Android系統中行程從啟動到終止的所有階段,也就是Android從啟動到停止的全程序,Android應用程式的生命周期的終結這個動作并非由應用程式行程本身執行,而是取決于Android系統,那么,系統是根據一個怎樣的重要性標準來終止Android應用程式呢?Android根據應用程式的組件以及組件當前運行狀態將所有的行程按重要性程度從高到低劃分為五個,如下圖所示:

- 前臺行程(完全可見的執行Activity)
- 可見行程(區域可見的執行Activity)
- 服務行程
- 后臺行程(完全不可見的執行Activity)
- 空行程(是為了快取行程,便于下次更快啟動)
- 當執行一個安卓應用程式,如果運行記憶體不足,安卓系統會按上述優先級殺死行程,
(二)服務的作用
- Service生命力頑強,它有兩方面的作用:后臺運行、跨行程訪問,學習Service基礎,利用它可以在后臺完成一些耗時的作業,比如網路連接、下載資料、播放音頻、播放視頻等等,
(三)服務的生命周期

- Service從啟動到銷毀只有三個階段:創建服務、開始服務(啟動、系結)、銷毀服務,
- 這三個階段對應三個回呼方法:
onCreate()、onStartCommand() / onBind()、onDestroy(), - 服務啟動時,執行一次
onCreate()方法與onStartCommand()方法,再次啟動服務,不會再執行onCreate()方法,但是會再執行onStartCommand()方法,停止和解綁服務時,都會執行onDestroy()方法,
二、案例演示 - 啟動與停止服務
(一)運行效果


(二)涉及知識點
- 線性布局(LinearLayout)
- 按鈕(Button)
- 服務(Service)
- 執行緒(Thread)
- Runnable介面
- 日志類(Log)
(三)實作步驟
1、創建安卓應用【StartStopService】


2、將背景圖片拷貝到drawable目錄

3、主布局資源檔案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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<Button
android:id="@+id/btnExplicitlyStartService"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="@string/explicitly_start_service"
android:onClick="doExplicitlyStartService"
android:textSize="20sp"/>
<Button
android:id="@+id/btnImplicitlyStartService"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="@string/implicitly_start_service"
android:onClick="doImplicitlyStartService"
android:textSize="20sp"/>
<Button
android:id="@+id/btnStopService"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:text="@string/stop_service"
android:onClick="doStopService"
android:textSize="20sp"/>
</LinearLayout>
4、字串資源檔案strings.xml

<resources>
<string name="app_name">啟動與停止服務</string>
<string name="explicitly_start_service">顯式啟動服務</string>
<string name="implicitly_start_service">隱式啟動服務</string>
<string name="stop_service">停止服務</string>
</resources>
5、創建自定義服務類 - CustomService
-
繼承Service類,創建CustomService類

-
宣告變數與常量

-
在onCreate()方法里輸出除錯資訊

-
在onStartCommand()方法里啟動服務

-
在onDestroy()方法里停止服務

-
查看自定義服務類完整源代碼
package net.hw.start_stop_service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
/**
* 功能:自定義服務類
* 作者:華衛
* 日期:2020年12月29日
*/
public class CustomService extends Service {
private final String TAG = "start_stop_service"; // 標記
private Thread thread; // 執行緒
private boolean isRunning; // 執行緒回圈控制變數
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "CustomService.onCreate() invoked.");
}
@Override
public int onStartCommand(Intent intent, int flags, final int startId) {
Log.d(TAG, "CustomService.onStartCommand() invoked.");
// 設定執行緒回圈控制變數為真
isRunning = true;
// 判斷意圖是否為空
if (intent != null) {
// 創建執行緒
thread = new Thread(new Runnable() {
@Override
public void run() {
while (isRunning) {
Log.d(TAG, "服務正在進行中……startId: " + startId + ", hashCode: " + CustomService.this.hashCode());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
// 啟動執行緒
thread.start();
}
// 設定服務的非粘性
return Service.START_NOT_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "CustomService.onDestroy() invoked.");
isRunning = false;
thread = null; // 銷毀執行緒
stopSelf(); // 停止服務
}
}
6、在專案清單檔案里注冊自定義服務類

7、主界面類 - Mainactivity

-
撰寫代碼顯式啟動服務

-
撰寫代碼隱式啟動服務

-
撰寫代碼停止服務

-
查看主界面類完整源代碼
package net.hw.start_stop_service;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 利用布局資源檔案設定用戶界面
setContentView(R.layout.activity_main);
}
/**
* 顯式啟動服務
*
* @param view
*/
public void doExplicitlyStartService(View view) {
// 創建啟動指定服務的意圖
Intent intent = new Intent(this, CustomService.class);
// 按照意圖啟動指定服務
startService(intent);
}
/**
* 隱式啟動服務
*
* @param view
*/
public void doImplicitlyStartService(View view) {
// 創建意圖
Intent intent = new Intent();
// 設定意圖動作(暗號或頻道)
intent.setAction("custom_service");
// 設定意圖包名
intent.setPackage(getPackageName());
// 按照意圖啟動服務
startService(intent);
}
/**
* 停止服務
*
* @param view
*/
public void doStopService(View view) {
// 創建啟動指定服務的意圖
Intent intent = new Intent(this, CustomService.class);
// 按意圖停止服務
stopService(intent);
}
}
8、啟動應用,查看效果
(1)顯式啟動服務 + 停止服務


服務的生命周期方法:
- onCreate()——只執行一次,一般進行初始化作業
- onStartCommand——執行多次(每次啟動服務都會呼叫它)
- onDestroy()——只執行一次,一般進行掃尾作業
(2)隱式啟動服務 + 停止服務


三、案例演示 - 系結與解綁服務
(一)運行效果

(二)涉及知識點
- 線性布局(LinearLayout)
- 按鈕(Button)
- 服務(Service)
- 日志類(Log)
(三)實作步驟
1、創建安卓應用【BindUnbindService】


2、將背景圖片拷貝到drawable目錄

3、主布局資源檔案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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/background"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/btnBindService"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:onClick="doBindService"
android:text="@string/bind_service"
android:textSize="20sp" />
<Button
android:id="@+id/btnUnbindService"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:onClick="doUnbindService"
android:text="@string/unbind_service"
android:textSize="20sp" />
</LinearLayout>
4、字串資源檔案strings.xml

<resources>
<string name="app_name">系結與解綁服務</string>
<string name="bind_service">系結服務</string>
<string name="unbind_service">解綁服務</string>
</resources>
5、創建自定義服務類 - CustomService

-
宣告常量

-
撰寫創建回呼方法

-
撰寫系結回呼方法

-
撰寫銷毀回呼方法

-
查看自定義服務類完整源代碼
package net.hw.bind_unbind_service;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
/**
* 功能:自定義服務類
* 作者:華衛
* 日期:2020年12月29日
*/
public class CustomService extends Service {
private final String TAG = "bind_unbind_service"; // 標記
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "CustomService.onCreate() invoked.");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "CustomService.onBind() invoked.");
// 獲取從視窗傳遞過來的資料
String message = intent.getStringExtra("message");
// 顯示資料
Log.d(TAG, "恭喜,成功系結服務!主視窗傳遞的資料:" + message);
// 回傳系結器物件
return new Binder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "CustomService.onDestroy() invoked.");
}
}
6、在專案清單檔案里注冊自定義服務類

7、主界面類 - MainActivity

-
宣告常量與變數

-
撰寫代碼系結服務

-
撰寫代碼解綁服務

-
重寫銷毀回呼方法

-
查看主界面類完整源代碼
package net.hw.bind_unbind_service;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
private final String TAG = "bind_unbind_service"; // 標記
private ServiceConnection conn; // 服務連接物件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 系結服務
*
* @param view
*/
public void doBindService(View view) {
// 創建意圖,顯式指明要系結的服務
Intent intent = new Intent(MainActivity.this, CustomService.class);
// 讓意圖攜帶資料
intent.putExtra("message", "安卓開發真是有趣~");
// 創建服務連接物件
conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "服務斷開連接~");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "服務已經連接~");
}
};
// 按意圖系結服務
bindService(intent, conn, Service.BIND_AUTO_CREATE);
}
/**
* 解綁服務
*
* @param view
*/
public void doUnbindService(View view) {
// 判斷服務連接是否為空
if (conn != null) {
// 解綁服務
unbindService(conn);
}
}
/**
* 銷毀視窗時解綁服務
*/
@Override
protected void onDestroy() {
super.onDestroy();
// 判斷服務連接是否為空
if (conn != null) {
// 解綁服務
unbindService(conn);
}
}
}
8、啟動應用,查看效果


四、小結
- 本次課,我們學習了如何創建服務、注冊服務,以及如何啟動或系結服務,我們知道了,在主視窗可以啟動或系結服務,并且可以利用意圖將資料傳遞給后臺默默作業的服務,但是現在有一個問題,后臺服務完成作業的進度如何傳遞給前臺的視窗并以某種方式顯示給用戶看呢?那就要用到我們下一講涉及的內容——廣播接收者(BroadcastReceiver),
- 對于活動視窗(Activity)、服務(Service)與廣播接收者(BroadcastReceiver)三個安卓核心組件,需要掌握Activity與Service之間如何利用BroadcastReceiver實作相互通信,這個知識點在我們后面的實訓專案《基于媒體庫音樂播放器》中會用到,
五、課后作業
任務1、啟動服務傳遞資料
- 界面如下圖所示

- 輸入資料,單擊【啟動服務】按鈕兩次,查看LogCat

任務2、系結服務傳遞資料
- 界面如下圖所示

- 輸入資料,單擊四次【系結服務】,查看LogCat

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/242808.html
標籤:其他
