一、Service
-
Service 是 Android 提供的后台组件,用于执行长时间运行的操作,不依赖用户界面(UI)
-
Service 默认运行在主线程,耗时任务需手动管理线程
-
Service 适用于无需用户交互的任务,例如,音乐播放、数据同步、位置跟踪等
二、Service 类型
1、启动式服务
-
通过 startService 方法启动
-
即使启动它的组件(例如,Activity、Fragment)被销毁,Service 仍可继续运行
-
任务完成后需手动调用 stopSelf 方法或 stopService 方法停止
2、绑定式服务
-
通过 bindService 方法绑定
-
多个组件(例如,Activity、Fragment)可绑定到同一个 Service
-
当所有绑定组件解绑时(调用 unbindService 方法),Service 自动销毁
三、Service 初识
1、Service
- FirstService.java
package com.my.service.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class FirstService extends Service {
public static final String TAG = FirstService.class.getSimpleName();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
}
2、AndroidManifest.xml
<service android:name=".myservice.FirstService" />
3、Activity Layout
- activity_first_service_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstServiceTestActivity">
<Button
android:id="@+id/btn_start_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开启服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
- FirstServiceTestActivity.java
package com.my.service;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import com.my.service.myservice.FirstService;
public class FirstServiceTestActivity extends AppCompatActivity {
public static final String TAG = FirstServiceTestActivity.class.getSimpleName();
private Button btnStartService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_first_service_test);
btnStartService = findViewById(R.id.btn_start_service);
btnStartService.setOnClickListener(v -> {
startService(new Intent(this, FirstService.class));
});
}
}
- 输出结果
onStartCommand
四、Service 简单任务
1、Service
- WorkService.java
package com.my.service.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class WorkService extends Service {
public static final String TAG = WorkService.class.getSimpleName();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG, i + "");
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
}
2、AndroidManifest.xml
<service android:name=".myservice.WorkService" />
3、Activity Layout
- activity_work_service_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".WorkServiceTestActivity">
<Button
android:id="@+id/btn_start_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开启服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
- WorkServiceTestActivity.java
package com.my.service;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import com.my.service.myservice.WorkService;
public class WorkServiceTestActivity extends AppCompatActivity {
public static final String TAG = WorkServiceTestActivity.class.getSimpleName();
private Button btnStartService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_work_service_test);
btnStartService = findViewById(R.id.btn_start_service);
Intent intent = new Intent(this, WorkService.class);
btnStartService.setOnClickListener(v -> {
startService(intent);
});
}
}
- 输出结果
0
1
2
3
4
五、启动式服务
1、Service
- StartAndStopService.java
package com.my.service.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class StartAndStopService extends Service {
public static final String TAG = StartAndStopService.class.getSimpleName();
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "onStartCommand");
Log.i(TAG, "任务开始执行");
new Thread(() -> {
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务执行完毕");
}).start();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i(TAG, "onDestroy");
}
}
2、AndroidManifest.xml
<service android:name=".myservice.StartAndStopService" />
3、Activity Layout
- activity_start_and_stop_service_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".StartAndStopServiceTestActivity">
<Button
android:id="@+id/btn_start_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开启服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_stop_service"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="停止服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_start_service" />
</androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
- StartAndStopServiceTestActivity.java
package com.my.service;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import com.my.service.myservice.StartAndStopService;
public class StartAndStopServiceTestActivity extends AppCompatActivity {
public static final String TAG = StartAndStopServiceTestActivity.class.getSimpleName();
private Button btnStartService;
private Button btnStopService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_and_stop_service_test);
btnStartService = findViewById(R.id.btn_start_service);
btnStopService = findViewById(R.id.btn_stop_service);
Intent intent = new Intent(this, StartAndStopService.class);
btnStartService.setOnClickListener(v -> {
startService(intent);
});
btnStopService.setOnClickListener(v -> {
stopService(intent);
});
}
}
5、Test
- 点击【开启服务】按钮,输出结果
onStartCommand
任务开始执行
任务执行完毕
- 点击【停止服务】按钮,输出结果
onDestroy
六、绑定式服务
1、Service
- BindAndUnbindService.java
package com.my.service.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class BindAndUnbindService extends Service {
public static final String TAG = BindAndUnbindService.class.getSimpleName();
private IBinder LocalBinder = new LocalBinder();
public class LocalBinder extends Binder {
public BindAndUnbindService getService() {
return BindAndUnbindService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return LocalBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.i(TAG, "onUnbind");
return super.onUnbind(intent);
}
public void work() {
Log.i(TAG, "任务开始执行");
new Thread(() -> {
try {
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("任务执行完毕");
}).start();
}
}
2、AndroidManifest.xml
<service android:name=".myservice.BindAndUnbindService" />
3、Activity Layout
- activity_bind_and_unbind_service_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BindAndUnbindServiceTestActivity">
<Button
android:id="@+id/btn_bind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_work"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="执行任务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_bind" />
<Button
android:id="@+id/btn_unbind"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="解绑服务"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_work" />
</androidx.constraintlayout.widget.ConstraintLayout>
4、Activity Code
- BindAndUnbindServiceTestActivity.java
package com.my.service;
import androidx.appcompat.app.AppCompatActivity;
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.util.Log;
import android.widget.Button;
import com.my.service.myservice.BindAndUnbindService;
public class BindAndUnbindServiceTestActivity extends AppCompatActivity {
public static final String TAG = BindAndUnbindServiceTestActivity.class.getSimpleName();
private Button btnBind;
private Button btnWork;
private Button btnUnbind;
private BindAndUnbindService bindAndUnbindService;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i(TAG, "onServiceConnected");
BindAndUnbindService.LocalBinder localBinder = (BindAndUnbindService.LocalBinder) service;
bindAndUnbindService = localBinder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i(TAG, "onServiceDisconnected");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bind_and_unbind_service_test);
btnBind = findViewById(R.id.btn_bind);
btnWork = findViewById(R.id.btn_work);
btnUnbind = findViewById(R.id.btn_unbind);
btnBind.setOnClickListener(v -> {
bindService(new Intent(this, BindAndUnbindService.class), serviceConnection, Context.BIND_AUTO_CREATE);
});
btnWork.setOnClickListener(v -> {
bindAndUnbindService.work();
});
btnUnbind.setOnClickListener(v -> {
unbindService(serviceConnection);
});
}
}
5、Test
- 点击【开启服务】按钮,输出结果
onBind
onServiceConnected
- 点击【执行任务】按钮,输出结果
任务开始执行
任务执行完毕
- 点击【解绑服务】按钮,输出结果
onUnbind