目录
onStartCommand(Intent, int, int)
Service概述
在 Android 中,服务(Service)是一种可以在后台执行长时间运行操作的组件。与 Activity 不同,服务不提供用户界面,但可以保持应用程序的后台进程活跃,即使用户切换到其他应用或屏幕关闭时也能继续运行。以下是服务的一些关键概述:
1.服务的主要特点
- 无用户界面:服务没有可见的用户界面,它在后台运行。
- 长时间运行:服务适合执行需要长时间运行的任务,如音乐播放、文件下载等。
- 生命周期管理:服务有其自己的生命周期,可以通过
onCreate()
,onStartCommand()
,onBind()
,onUnbind()
, 和onDestroy()
等方法来管理。
2.服务的类型
1)Started Service (启动服务)
- 通过
startService()
方法启动。 - 一旦启动,服务将持续运行直到调用
stopSelf()
或stopService()
。 - 适用于不需要与启动它的组件保持交互的任务。
2)Bound Service (绑定服务)
-
通过
bindService()
方法绑定到客户端。 - 一旦绑定,客户端可以通过 IBinder 接口与服务进行交互。
- 适用于需要频繁交互的情况,例如获取服务中的数据或控制服务的行为。
3)Foreground Service (前台服务)
- 是一种特殊的服务,必须显示一个持续的通知给用户。
- 前台服务不容易被系统杀死,适合执行重要且用户可见的任务。
- 从 Android 8.0 (API 级别 26) 开始,如果一个服务在后台运行超过一定时间,它会被系统停止,除非它是前台服务。
3.服务的生命周期
-
onCreate()
- 当服务第一次创建时调用。初始化设置在这里完成。
-
onStartCommand(Intent, int, int)
- 每次通过
startService()
启动服务时调用。返回值决定服务如何处理重启情况。
- 每次通过
-
onBind(Intent)
- 当其他组件尝试通过
bindService()
绑定到服务时调用。返回一个 IBinder 对象以允许客户端与服务通信。
- 当其他组件尝试通过
-
onUnbind(Intent)
- 当最后一个客户端解除绑定时调用。
-
onRebind(Intent)
- 当新的客户端试图绑定到服务时调用,前提是之前所有的客户端都已解除绑定。
-
onDestroy()
- 在服务被销毁前调用,用于清理资源。
4.创建和使用服务
1--定义服务
public class MyService extends Service {
@Override
public void onCreate() {
super.onCreate();
// 初始化代码
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// 执行任务
return START_STICKY; // 返回 START_STICKY 表示如果服务被意外终止,系统会尝试重启它
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
// 返回一个 IBinder 实例,用于与服务交互
return null; // 如果不支持绑定,则返回 null
}
@Override
public void onDestroy() {
super.onDestroy();
// 清理资源
}
}
2--在 Manifest 文件中声明服务
<service android:name=".MyService" />
3--启动服务
Intent serviceIntent = new Intent(this, MyService.class);
startService(serviceIntent);
4--绑定服务
Intent serviceIntent = new Intent(this, MyService.class);
bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
// ServiceConnection 实现
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// 与服务建立连接后的操作
}
@Override
public void onServiceDisconnected(ComponentName name) {
// 服务断开连接后的操作
}
};
5--注意事项
- 性能和电池寿命:长时间运行的服务可能会消耗大量资源并影响电池寿命。因此,应该尽量减少后台服务的使用,并考虑使用 WorkManager 来替代一些后台任务。
- 权限:某些服务可能需要特定的权限才能执行,比如访问网络。
- 前台服务通知:从 Android 8.0 (API 级别 26) 开始,如果一个服务在后台运行超过一定时间,它会被系统停止,除非它是前台服务。前台服务必须显示一个持续的通知给用户。
服务是 Android 应用程序架构中的一个重要部分,合理地使用它们可以帮助你构建出更加高效和响应迅速的应用程序。
案例:Service的简单使用
1)创建一个服务
鼠标右键包名===>new ===>Service===>Service
package com.xiji.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() { } //绑定服务的时候调用 @Override public IBinder onBind(Intent intent) { System.out.println("MyService onBind"); Log.i("MyService", "onBind"); return null; } //解绑服务 @Override public boolean onUnbind(Intent intent) { System.out.println("MyService onUnbind"); Log.i("MyService", "onUnbind"); return super.onUnbind(intent); } @Override public void onCreate() { super.onCreate(); System.out.println("MyService onCreate"); Log.i("MyService", "onCreate"); } @Override public void onDestroy() { super.onDestroy(); System.out.println("MyService onDestroy"); Log.i("MyService", "onDestroy"); } //Service代理类 class MyServiceProxy extends Binder { public void userMyServiceMethods() { System.out.println("MyServiceProxy start"); Log.i("MyService", "start"); useServiceMethods(); } } //服务里面的方法 public void useServiceMethods() { System.out.println("MyService userMyServiceMethods"); Log.i("MyService", "userMyServiceMethods"); } }
2)服务相关的操作
1---通过意图启动服务
//启动服务 public void startService() { //通过意图启动服务 Intent intent = new Intent(this, MyService.class); startService(intent); }
2---通过意图关闭服务
//关闭服务 public void stopService() { //通过意图关闭服务 Intent intent = new Intent(this, MyService.class); stopService(intent); }
3--创建服务连接类
创建服务连接类并且继承ServiceConnection
//服务连接类 private class MyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //连接服务时为其中的方法赋值 myBinder = (MyService.MyServiceProxy) service; Log.i("MyService", "onServiceConnected连接服务" + service.toString()); } @Override public void onServiceDisconnected(ComponentName name) { } }
4--绑定服务
使用bindService绑定服务
//绑定服务 public void bindMyService() { Intent intent = new Intent(this, MyService.class); //没有绑定服务时才绑定服务连接 if (myServiceConnection == null) { //创建服务并且绑定 myServiceConnection = new MyServiceConnection(); //绑定服务 bindService(intent, myServiceConnection, BIND_AUTO_CREATE); Toast.makeText(this, "绑定服务", Toast.LENGTH_SHORT).show(); Log.i("MyService", "绑定服务"); return ; } Toast.makeText(this, "服务已经连接", Toast.LENGTH_SHORT).show(); }
5--解绑服务
使用unbindService解绑服务
//解绑服务 public void unBindMyService() { //有服务连接时才解绑 if (myServiceConnection != null) { unbindService(myServiceConnection); Toast.makeText(this, "解绑服务", Toast.LENGTH_SHORT).show(); Log.i("MyService", "解绑服务"); myServiceConnection = null; //服务代理重置为空,不然还能使用 if (myBinder != null) { myBinder = null; Toast.makeText(this, "服务代理重置为空", Toast.LENGTH_SHORT).show(); } return ; } Toast.makeText(this, "服务未连接", Toast.LENGTH_SHORT).show(); }
6--调用服务方法
使用服务中的代理类调用服务中的方法
//调用服务中的方法 public void useServiceMethods() { //有才调用 if (myBinder != null) { myBinder.userMyServiceMethods(); Toast.makeText(this, "调用服务中的方法", Toast.LENGTH_SHORT).show(); Log.i("MyService", "调用服务中的方法"); return; } Toast.makeText(this, "服务未连接", Toast.LENGTH_SHORT).show(); }
3)activity_main布局文件的编写
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="服务的简单操作" android:textSize="20sp" android:textColor="#000000" android:gravity="center" android:layout_gravity="center" android:padding="20dp" android:background="#09EDA5" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:gravity="center" android:background="#0D86FF" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="启动服务" android:id="@+id/startService" android:theme="@style/Theme.Design.NoActionBar" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="停止服务" android:id="@+id/stopService" android:theme="@style/Theme.Design.NoActionBar" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="绑定服务" android:id="@+id/bindService" android:theme="@style/Theme.Design.NoActionBar" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="解绑服务" android:id="@+id/unBindService" android:theme="@style/Theme.Design.NoActionBar" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="使用服务方法" android:id="@+id/useServiceMethods" android:theme="@style/Theme.Design.NoActionBar" /> </LinearLayout> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:text="服务的简单操作" android:textSize="20sp" android:textColor="#000000" android:gravity="center" android:layout_gravity="center" android:padding="20dp" android:background="#E3EFEB" android:id="@+id/tv_show" /> </LinearLayout>
4)colors.xml文件
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="black">#FF000000</color> <color name="white">#FFFFFFFF</color> <color name="red">#FF0000</color> <color name="green">#00FF00</color> <color name="blue">#0000FF</color> <color name="yellow">#FFFF00</color> <color name="orange">#FFA500</color> <color name="purple">#800080</color> <color name="pink">#FFC0CB</color> <color name="brown">#A52A2A</color> <color name="gray">#808080</color> </resources>
5)MainActivity代码
package com.xiji.myservice; import android.annotation.SuppressLint; 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 android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; public class MainActivity extends AppCompatActivity { private MyService myService; private MyService.MyServiceProxy myBinder; //服务连接 private MyServiceConnection myServiceConnection ; //五个控件按钮 private Button startServiceBtn; private Button stopServiceBtn; private Button bindServiceBtn; private Button unBindServiceBtn; private Button useServiceMethodsBtn; //视图 private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); EdgeToEdge.enable(this); setContentView(R.layout.activity_main); ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); initView(); } //控件初始化 private void initView() { //控件初始化 startServiceBtn = findViewById(R.id.startService); stopServiceBtn = findViewById(R.id.stopService); bindServiceBtn = findViewById(R.id.bindService); unBindServiceBtn = findViewById(R.id.unBindService); useServiceMethodsBtn = findViewById(R.id.useServiceMethods); textView = findViewById(R.id.tv_show); //控件初始化 initListener(); } //控件事件绑定 private void initListener() { //启动按钮事件 startServiceBtn.setOnClickListener(new View.OnClickListener() { @SuppressLint("ResourceAsColor") @Override public void onClick(View v) { //调用启动服务 方法 startService(); //修改文本 textView.setText("服务已启动"); //修改为绿色 textView.setTextColor(R.color.green); } }); //停止按钮 stopServiceBtn.setOnClickListener(new View.OnClickListener() { @SuppressLint("ResourceAsColor") @Override public void onClick(View v) { stopService(); textView.setText("服务已停止"); textView.setTextColor(R.color.red); } }); //绑定按钮 bindServiceBtn.setOnClickListener(new View.OnClickListener() { @SuppressLint("ResourceAsColor") @Override public void onClick(View v) { bindMyService(); textView.setText("服务已绑定"); textView.setTextColor(R.color.orange); } }); //解绑服务 unBindServiceBtn.setOnClickListener(new View.OnClickListener() { @SuppressLint("ResourceAsColor") @Override public void onClick(View v) { unBindMyService(); textView.setTextColor(R.color.pink); textView.setText("服务已经解绑"); } }); //调用服务中的方法 useServiceMethodsBtn.setOnClickListener(new View.OnClickListener() { @SuppressLint("ResourceAsColor") @Override public void onClick(View v) { if (myBinder != null) { useServiceMethods(); Toast.makeText(MainActivity.this, "调用服务中的方法", Toast.LENGTH_SHORT).show(); textView.setTextColor(R.color.yellow); textView.setText("调用服务中的方法"); return; } Toast.makeText(MainActivity.this, "请先绑定服务", Toast.LENGTH_SHORT).show(); } }); } //启动服务 public void startService() { //通过意图启动服务 Intent intent = new Intent(this, MyService.class); startService(intent); Toast.makeText(this, "启动服务", Toast.LENGTH_SHORT).show(); Log.i("MyService", "启动服务"); } //关闭服务 public void stopService() { Intent intent = new Intent(this, MyService.class); stopService(intent); Toast.makeText(this, "停止服务", Toast.LENGTH_SHORT).show(); Log.i("MyService", "停止服务"); } //绑定服务 public void bindMyService() { Intent intent = new Intent(this, MyService.class); //没有绑定服务时才绑定服务连接 if (myServiceConnection == null) { //创建服务并且绑定 myServiceConnection = new MyServiceConnection(); //绑定服务 bindService(intent, myServiceConnection, BIND_AUTO_CREATE); Toast.makeText(this, "绑定服务", Toast.LENGTH_SHORT).show(); Log.i("MyService", "绑定服务"); return ; } Toast.makeText(this, "服务已经连接", Toast.LENGTH_SHORT).show(); } //解绑服务 public void unBindMyService() { //有服务连接时才解绑 if (myServiceConnection != null) { unbindService(myServiceConnection); Toast.makeText(this, "解绑服务", Toast.LENGTH_SHORT).show(); Log.i("MyService", "解绑服务"); myServiceConnection = null; //服务代理重置为空,不然还能使用 if (myBinder != null) { myBinder = null; Toast.makeText(this, "服务代理重置为空", Toast.LENGTH_SHORT).show(); } return ; } Toast.makeText(this, "服务未连接", Toast.LENGTH_SHORT).show(); } //调用服务中的方法 public void useServiceMethods() { //有才调用 if (myBinder != null) { myBinder.userMyServiceMethods(); Toast.makeText(this, "调用服务中的方法", Toast.LENGTH_SHORT).show(); Log.i("MyService", "调用服务中的方法"); return; } Toast.makeText(this, "服务未连接", Toast.LENGTH_SHORT).show(); } //服务连接类 private class MyServiceConnection implements ServiceConnection { @Override public void onServiceConnected(ComponentName name, IBinder service) { //连接服务时为其中的方法赋值 myBinder = (MyService.MyServiceProxy) service; Log.i("MyService", "onServiceConnected连接服务" + service.toString()); } @Override public void onServiceDisconnected(ComponentName name) { } } }