一. 本地Service
1. 简介
这是最普通、最常用的后台服务Service。
2. 使用步骤
步骤1:新建子类继承Service类,在AndroidManifest.xml里注册Service。(需重写父类的onCreate()、onStartCommand()、onDestroy()和onBind()方法)
步骤2:构建用于启动Service的Intent对象。
步骤3:调用startService()启动Service、调用stopService()停止服务。
3. 实例
① 新建子类继承Service类,在AndroidManifest.xml里注册Service
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class MyService extends Service { private static final String TAG = MyService.class.getSimpleName();
private MediaPlayer mediaPlayer;
@Override public void onCreate() { super.onCreate(); Log.d(TAG,"onCreate");
mediaPlayer = MediaPlayer.create(this,R.raw.bg_music); mediaPlayer.setVolume(0.8f,0.8f); }
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG,"onStart");
mediaPlayer.start();
return super.onStartCommand(intent, flags, startId); }
@Override public void onDestroy() { super.onDestroy();
mediaPlayer.stop();
Log.d(TAG,"onDestroy"); }
@Override public IBinder onBind(Intent intent) { return null; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="swu.xl.service_local">
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" 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 android:name=".MyService"/>
</application>
</manifest>
|
② 构建用于启动Service的Intent对象
1
| Intent intent = new Intent(this, MyService.class);
|
③ 调用startService()启动Service、调用stopService()停止服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Override public void onClick(View v) {
Intent intent = new Intent(this, MyService.class);
switch (v.getId()){ case R.id.start: startService(intent); break; case R.id.stop: stopService(intent); break; } }
|
④ 运行结果
1 2 3 4 5 6
| 2020-05-25 10:51:33.071 21236-21236/swu.xl.service_local D/MyService: onCreate 2020-05-25 10:51:33.096 21236-21236/swu.xl.service_local D/MyService: onStart
2020-05-25 10:51:39.673 21236-21236/swu.xl.service_local D/MyService: onDestroy
|
4. 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 |
二. 可通信的Service
1. 简介
上面介绍的Service是最基础的,但只能单机使用,即无法与Activity通信。
接下来将在上面的基础用法上,增设“与Activity通信”的功能,即使用绑定Service服务。
2. 使用步骤
步骤1:新建子类继承Service类,在AndroidManifest.xml里注册Service。并新建一个子类继承自Binder类、获取Service实例,进而实现Activity与Service的通信。
步骤2:构建用于启动Service的Intent对象。以及监听绑定的ServiceConnection对象。
步骤3:调用bindService()启动Service、调用unbindService()停止服务。
3. 实例
① 新建子类继承Service类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| @SuppressLint("Registered") public class MyService extends Service {
private static final String TAG = MyService.class.getSimpleName();
private MediaPlayer mediaPlayer; private float volume = 0.8f;
private IBinder iBinder = new LocalBinder();
@Override public void onCreate() { super.onCreate(); Log.d(TAG,"onCreate");
mediaPlayer = MediaPlayer.create(this,R.raw.bg_music); mediaPlayer.setVolume(volume,volume); mediaPlayer.start(); }
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG,"onStart");
return super.onStartCommand(intent, flags, startId); }
@Override public void onDestroy() { super.onDestroy();
mediaPlayer.stop();
Log.d(TAG,"onDestroy"); }
@Override public IBinder onBind(Intent intent) { Log.d(TAG,"onBind"); return iBinder; }
@Override public boolean onUnbind(Intent intent) { Log.d(TAG,"unbind"); return super.onUnbind(intent); }
public class LocalBinder extends Binder { MyService getService(){ return MyService.this; } }
public float getVolume(){ return volume; } }
|
② 构建Intent对象和ServiceConnection对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) {
MyService.LocalBinder localBinder = (MyService.LocalBinder) service;
MyService myService = localBinder.getService();
Toast.makeText(myService, "当前的音量:"+myService.getVolume(), Toast.LENGTH_SHORT).show(); }
@Override public void onServiceDisconnected(ComponentName name) { } };
|
③ 调用bindService()启动Service、调用unbindService()停止服务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) {
MyService.LocalBinder localBinder = (MyService.LocalBinder) service;
MyService myService = localBinder.getService();
Toast.makeText(myService, "当前的音量:"+myService.getVolume(), Toast.LENGTH_SHORT).show(); }
@Override public void onServiceDisconnected(ComponentName name) { } };
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Button start = findViewById(R.id.start); Button stop = findViewById(R.id.stop);
start.setOnClickListener(this); stop.setOnClickListener(this); }
@Override public void onClick(View v) {
Intent intent = new Intent(this, MyService.class);
switch (v.getId()){ case R.id.start: bindService(intent,serviceConnection,BIND_AUTO_CREATE); break; case R.id.stop: unbindService(serviceConnection); break; } } }
|
④ 运行结果
1 2 3 4 5 6
| 2020-05-25 13:05:48.925 10778-10778/swu.xl.service_connection D/MyService: onCreate 2020-05-25 13:05:48.940 10778-10778/swu.xl.service_connection D/MyService: onBind
2020-05-25 13:05:49.963 10778-10778/swu.xl.service_connection D/MyService: unbind 2020-05-25 13:05:49.966 10778-10778/swu.xl.service_connection D/MyService: onDestroy
|
4. bindService的第三个参数标志位
BIND_AUTO_CREATE表示在Activity和Service建立关联后自动创建Service。
这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行。
三. 前台Service
1. 简介
前台Service在下拉通知栏有显示通知,但后台Service没有。
前台Service优先级较高,不会由于系统内存不足而被回收;后台Service优先级较低,当系统出现内存不足情况时,很有可能会被回收。
2. 使用步骤
用法很简单,只需要在原有的Service类对onCreate()方法进行稍微修改。
3. 实例
① 新建子类继承Service类,在AndroidManifest.xml里注册Service并添加前台权限,并在onCreate中添加通知。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| public class MyService extends Service { private static final String TAG = MyService.class.getSimpleName();
private MediaPlayer mediaPlayer;
@Override public void onCreate() { super.onCreate(); Log.d(TAG,"onCreate");
mediaPlayer = MediaPlayer.create(this,R.raw.bg_music); mediaPlayer.setVolume(0.8f,0.8f);
String CHANNEL_ONE_ID = "CHANNEL_ONE_ID"; String CHANNEL_ONE_NAME= "CHANNEL_ONE_ID"; NotificationChannel notificationChannel= null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { notificationChannel= new NotificationChannel(CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_HIGH); notificationChannel.enableLights(true); notificationChannel.setLightColor(Color.RED); notificationChannel.setShowBadge(true); notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); NotificationManager manager= (NotificationManager) getSystemService(NOTIFICATION_SERVICE); assert manager != null; manager.createNotificationChannel(notificationChannel); }
Intent notificationIntent = new Intent(this,MainActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(this,0,notificationIntent,0);
Notification.Builder builder = new Notification.Builder(this); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { builder.setChannelId(CHANNEL_ONE_ID); } builder.setContentTitle("前台服务通知的标题"); builder.setContentText("前台服务通知的内容"); builder.setSmallIcon(R.mipmap.ic_launcher); builder.setContentIntent(pendingIntent);
Notification notification = builder.build(); notification.flags|= Notification.FLAG_NO_CLEAR; startForeground(1, notification); }
@Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(TAG,"onStart");
mediaPlayer.start();
return super.onStartCommand(intent, flags, startId); }
@Override public void onDestroy() { super.onDestroy();
mediaPlayer.stop();
Log.d(TAG,"onDestroy"); }
@Override public IBinder onBind(Intent intent) { return null; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="swu.xl.service_local"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" 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 android:name=".MyService"/>
</application>
</manifest>
|
② 构建用于启动Service的Intent对象
1
| Intent intent = new Intent(this, MyService.class);
|
③ 调用startService()启动Service、调用stopService()停止服务
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Override public void onClick(View v) {
Intent intent = new Intent(this, MyService.class);
switch (v.getId()){ case R.id.start: startService(intent); break; case R.id.stop: stopService(intent); break; } }
|
④ 运行结果

4. Android 8.0中使用Notification
参考:在Android 8.0中使用Notification中发生 Bad notification for startForeground错误
四. 远程Service
参考:Android多进程
参考文章:Android:远程服务Service(含AIDL & IPC讲解)
源码
Service
参考文章
Android:(本地、可通信的、前台、远程)Service使用全面介绍