启动service
service启动有四种形式。
1.显示启动(如直接按service的全路径启动)
2.隐示启动(如通过intent-filter的action标签启动)
3.通过bindservice显示启动。
4.通过bindservice隐示启动。
Demo
创建一个service的子类,如
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
public class ForceGroundServer extends Service {
private static final String TAG = "ForceGroundServer";
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
return null;
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
sendNotification();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy: ");
}
private final String CHANNEL_ID = "TestID";
@RequiresApi(api = Build.VERSION_CODES.O)
private void sendNotification() {
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "TEstName", NotificationManager.IMPORTANCE_HIGH);
channel.enableLights(true);//设置提示灯
channel.setLightColor(Color.BLUE);//设置提示灯颜色
channel.setShowBadge(true);//显示logo
channel.setDescription("test");//设置描述
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);//锁屏可见
manager.createNotificationChannel(channel);
Notification testNotification = new Notification.Builder(this)
.setChannelId(CHANNEL_ID)
.setContentText("服务已经至于前台了")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
.build();
//id 不能是0
startForeground(1, testNotification);
}
}
显示启动
private final static String TARGET_APP_PACKAGE = "com.example.mycolorpicker";
private final static String TARGET_SERVICE_NAME = TARGET_APP_PACKAGE + ".ForceGroundServer";
private final static String TARGET_SERVICE_ACTION = TARGET_SERVICE_NAME + ".action";
private void startServerVisible() {
Intent intent = new Intent();
intent.setComponent(new ComponentName(
TARGET_APP_PACKAGE,
TARGET_SERVICE_NAME));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
Log.d(TAG, "startForegroundService");
} else {
startService(intent);
Log.d(TAG, "startService");
}
}
隐示启动
private void startServerHide() {
Intent intent = new Intent();
intent.setPackage(TARGET_APP_PACKAGE);
intent.setAction(TARGET_SERVICE_ACTION);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(intent);
} else {
startService(intent);
}
}
设置前台服务
首先需要在Manifest中声明权限需求。
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
若无此权限声明,系统会抛SecurityException异常
java.lang.RuntimeException: Unable to create service com.example.mycolorpicker.ForceGroundServer: java.lang.SecurityException: Permission Denial: startForeground from pid=12931, uid=10247 requires android.permission.FOREGROUND_SERVICE
上面通过startForegroundService启动了servervice,会执行Service的Oncreate和OnStartCommand,service需要在5秒内调用startForeground,否则系统就会报TimeExceptio异常,app闪退。
ndroid.app.ForegroundServiceDidNotStartInTimeException: Context.startForegroundService() did not then call Service.startForeground(): ServiceRecord{263b8f7 u0 com.example.mycolorpicker/.ForceGroundServer}
at android.app.ActivityThread.throwRemoteServiceException(ActivityThread.java:2046)
at android.app.ActivityThread.access$2900(ActivityThread.java:275)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2271)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:211)
at android.os.Looper.loop(Looper.java:300)
at android.app.ActivityThread.main(ActivityThread.java:8291)
at java.lang.reflect.Method.invoke(Native Method)