一.代码位置

二.引用

  1. 将JitPack存储库添加到您的构建文件中
    将其添加到存储库末尾的root build.gradle中:

    1
    2
    3
    4
    5
    6
    allprojects {
    repositories {
    ...
    maven { url 'https://jitpack.io' }
    }
    }
  2. 添加依赖项

    1
    2
    3
    4
    dependencies {
    ...
    implementation 'com.github.itemuse:XLib:Tag'
    }
  3. 初始化 Application中init

    1
    2
    3
    4
    5
    6
    7
    import cn.xy.library.XApp;
    ...
    @Override
    public void onCreate() {
    super.onCreate();
    XApp.init(this);
    }

三.使用方法

  • 启动服务

提供三种传参启动方法

1
2
3
XService.startService(TestService.class);
XService.startService(new Intent(this,TestService.class));
XService.startService("com.xy.app.TestService");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Start the service.
*
* @param intent The intent.
*/
public static void startService(Intent intent) {
try {
intent.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
XApp.getApp().startForegroundService(intent);
} else {
XApp.getApp().startService(intent);
}
} catch (Exception e) {
e.printStackTrace();
}
}
  • 停止服务

1
2
3
XService.stopService(TestService.class);
XService.stopService(new Intent(this,TestService.class));
XService.unbindService(mConnection);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Stop the service.
*
* @param intent The intent.
* @return {@code true}: success<br>{@code false}: fail
*/
public static boolean stopService(@NonNull Intent intent) {
try {
return XApp.getApp().stopService(intent);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
  • 绑定服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
XService.bindService(TestService.class,mConnection, Service.BIND_AUTO_CREATE);
XService.bindService("com.softwinner.app.TestService",mConnection, Service.BIND_AUTO_CREATE);
XService.bindService(new Intent(this,TestService.class),mConnection, Service.BIND_AUTO_CREATE);

private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}


@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
};
  • *绑定服务

1
XService.unbindService(mConnection);
  • 查询存活服务

目前测试的情况,5.0 6.0 7.0可以查询到所有系统存货的服务,8.0 9.0 10.0上只可以查询到本进程的服务。

1
2
3
4
5
6
7
8
9
10
public static Set<String> getAllRunningServices() {
ActivityManager am = (ActivityManager) App.getApp().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> info = am.getRunningServices(0x7FFFFFFF);
Set<String> names = new HashSet<>();
if (info == null || info.size() == 0) return null;
for (RunningServiceInfo aInfo : info) {
names.add(aInfo.service.getClassName());
}
return names;
}
  • 查询服务是否存活

1
2
3
4
5
6
7
8
9
10
11
12
13
public static boolean isServiceRunning(@NonNull final String className) {
try {
ActivityManager am = (ActivityManager) App.getApp().getSystemService(Context.ACTIVITY_SERVICE);
List<RunningServiceInfo> info = am.getRunningServices(0x7FFFFFFF);
if (info == null || info.size() == 0) return false;
for (RunningServiceInfo aInfo : info) {
if (className.equals(aInfo.service.getClassName())) return true;
}
return false;
} catch (Exception ignore) {
return false;
}
}
  • 使用service注意

使用了startservice,也用了bindservice的情况下启用一个服务。
未stopservice之前,unbindservice服务是不会被销毁。
未unbindservice之前,stopservice服务是不会被销毁的。

  • 前台服务和后台服务区别

前台服务 后台服务
会在通知一栏显示 ONGOING 的 Notification,当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。 默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification。当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,日期同步,邮件同步等。

三.8.0之后的服务

  • Android 8.0 之前
    创建前台服务的方式通常是先创建一个后台服务,然后将该服务推到前台。

  • Android 8.0 之后
    系统不允许后台应用创建后台服务。 引入了一种全新的方法,即 Context.startForegroundService(),以在前台启动新服务。

在系统创建服务后,应用有五秒的时间来调用该服务的 startForeground() 方法以显示新服务的用户可见通知。

如果应用在此时间限制内未调用 startForeground(),则系统将停止服务并声明此应用为 ANR。

以我的音乐服务为例,在onStartCommand方法里增加一个Notification

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
public class MusicService extends MService<MusicPresenter> implements MusicView {

...
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Notification.Builder builder = new Notification.Builder(XApp.getApp());
Intent nfIntent = new Intent(this, MusicActivity.class);
builder.setContentIntent(PendingIntent.
getActivity(this, 0, nfIntent, 0))
.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),R.drawable.ic_launcher))
.setContentTitle("微音正在后台运行")
.setSmallIcon(R.drawable.ic_launcher)
.setContentText("要显示的内容")
.setWhen(System.currentTimeMillis());
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel notificationChannel = new NotificationChannel("1", "Name",NotificationManager.IMPORTANCE_MIN);
notificationChannel.enableLights(false);//如果使用中的设备支持通知灯,则说明此通知通道是否应显示灯
notificationChannel.setShowBadge(false);//是否显示角标
notificationChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.createNotificationChannel(notificationChannel);
builder.setChannelId("1");
}
Notification notification = builder.build(); // 获取构建好的Notification
notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
// 参数一:唯一的通知标识;参数二:通知消息。
startForeground(110, notification);// 开始前台服务
return super.onStartCommand(intent, flags, startId);
}
}

总结
Android O 后台应用想启动服务就老老实实的加个notification给用户看,表示你自己在后台占着资源,杀不杀由用户决定,偷偷地在后台跑没有framework帮忙想都别想,一个anr+crash套餐了解一下。

1
2
- activity: Context.startForegroundService() 
- Service:startForeground(int id, Notification notification)(id must not be 0)