一. 本地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
| 12
 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;
 }
 }
 
 | 
| 12
 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()停止服务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | @Overridepublic 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;
 }
 }
 
 | 
④ 运行结果
| 12
 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类
| 12
 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对象
| 12
 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()停止服务。
| 12
 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;
 }
 }
 }
 
 | 
④ 运行结果
| 12
 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中添加通知。
| 12
 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;
 }
 }
 
 | 
| 12
 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()停止服务
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | @Overridepublic 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使用全面介绍