Service 是一种可在后台执行长时间运行操作而不提供界面的应用组件。
Android Service是组件,既不能说它是单独的进程也不能说它是单独的线程。
如果非要从通俗的语言层面来理解的话,姑且将其理解为对象。这个Service对象本身作为应用程序的一部分与它的调用者运行在相同的进程,当然如果指定了process则会运行到另外的进程。指定到其他进程的方法参加Service属性的"android:process"。
Android Service可以在后台运行,不需要给用户提供任何的界面。但是Service是默认运行在主线程的,不要以为可以直接把它放在后台作耗时操作,如果要做耗时操作还是需要在Service里另起线程的,否则你懂得,会阻塞主线程造成ANR。
Service是组件:默认运行在当前进程的主线程中的,如果需要执行耗时操作,记得在Service里创建新线程;
Service用来提高优先级:在后台场景下,Service的优先级是高于后台挂起的Activity的,也高于Activity所创建的线程。这样的话,在内存不足时,Service不会被优先杀死
import android.content.Intent;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import xx.MyApplication;
import xx.MySQLiteOpenHelper;
import xx.entity.UploadTaskEntity;
import xx.sharedpreference.SharedPreferenceConstant;
import java.lang.ref.WeakReference;
public class UploadTaskService extends android.app.Service {
private MyHandler myHandler;
private java.util.concurrent.ScheduledExecutorService scheduledExecutorService;
private int timesForSuccess;
private int timesForFailure;
private int timesForNothing;
@Nullable
@Override
public IBinder onBind(Intent intent) {
android.util.Log.d("debug", "服务在绑定的时候");
return new MyServiceBinder();
}
@Override
public void onCreate() {
super.onCreate();
android.util.Log.d("debug", "服务在创建的时候");
WeakReference<UploadTaskService> myServiceWeakReference = new WeakReference<UploadTaskService>(this);
myHandler = new MyHandler(myServiceWeakReference);
scheduledExecutorService = new java.util.concurrent.ScheduledThreadPoolExecutor(3, java.util.concurrent.Executors.defaultThreadFactory());
java.util.concurrent.ScheduledFuture<?> scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(new NetworkRunnable(), 10, 30, java.util.concurrent.TimeUnit.SECONDS);
boolean isDone = scheduledFuture.isDone();
android.util.Log.d("debug", "调度未来是否完成->" + isDone);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
android.content.ComponentName componentName = new android.content.ComponentName(this, UploadTaskService.class);
android.content.Intent intent = new android.content.Intent();
intent.setComponent(componentName);
android.content.ComponentName componentNameResult = startForegroundService(intent);
if (componentNameResult != null) {
android.util.Log.d("debug", "开启前台服务返回的结果->" + componentNameResult.getShortClassName());
}
android.app.NotificationChannel notificationChannel = new android.app.NotificationChannel("persistent", "persistent", android.app.NotificationManager.IMPORTANCE_LOW);
java.lang.Object objectNotificationManger = getSystemService(NOTIFICATION_SERVICE);
if (objectNotificationManger instanceof android.app.NotificationManager) {
android.app.NotificationManager notificationManager = (android.app.NotificationManager) objectNotificationManger;
notificationManager.createNotificationChannel(notificationChannel);
android.app.Notification notification = new android.support.v4.app.NotificationCompat.Builder(this, "persistent")
.setAutoCancel(true)
.setCategory(android.app.Notification.CATEGORY_SERVICE)
.setOngoing(true)
.setPriority(android.app.NotificationManager.IMPORTANCE_LOW)
.build();
startForeground(10, notification);
}
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
android.util.Log.d("debug", "服务在开始命令的时候(intent)->" + intent.getAction());
}
android.util.Log.d("debug", "服务在开始命令的时候(flags)->" + flags);
android.util.Log.d("debug", "服务在开始命令的时候(startId)->" + startId);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
android.util.Log.d("debug", "服务在销毁的时候");
scheduledExecutorService.shutdown();
}
@Override
public boolean onUnbind(Intent intent) {
android.util.Log.d("debug", "服务在解绑的时候");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
super.onRebind(intent);
android.util.Log.d("debug", "服务在重新绑定的时候");
}
@Override
public void onTaskRemoved(Intent rootIntent) {
super.onTaskRemoved(rootIntent);
android.util.Log.d("debug", "服务在任务移除的时候");
}
public void startNetwork() {
android.util.Log.d("debug", "手动触发上传");
Thread thread = new Thread(new NetworkRunnable());
thread.setName("manualThread");
thread.start();
}
public boolean getScheduledExecutorServiceIsShutDown() {
return scheduledExecutorService.isShutdown();
}
public java.util.Properties getProperties() {
java.util.Properties properties = new java.util.Properties();
properties.put("timesForSuccess", timesForSuccess);
properties.put("timesForFailure", timesForFailure);
properties.put("timesForNothing", timesForNothing);
return properties;
}
private void responseSuccessForNetwork(String result) {
android.util.Log.d("debug", "异步任务响应成功->" + result);
timesForSuccess ++;
}
private void responseFailureForNetwork(String result) {
android.util.Log.d("debug", "异步任务响应失败->" + result);
timesForFailure ++;
}
private void nothingResponse() {
timesForNothing ++;
}
public class MyServiceBinder extends android.os.Binder {
public UploadTaskService getMyService() {
return UploadTaskService.this;
}
}
protected static class MyHandler extends android.os.Handler {
private final WeakReference<UploadTaskService> myServiceWeakReference;
public MyHandler(WeakReference<UploadTaskService> myServiceWeakReference) {
this.myServiceWeakReference = myServiceWeakReference;
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
UploadTaskService uploadTaskService = myServiceWeakReference.get();
if (uploadTaskService != null) {
String result = (String) msg.obj;
if (msg.what == -1) {
uploadTaskService.nothingResponse();
} else if (msg.what == 0) {
uploadTaskService.responseSuccessForNetwork(result);
} else if (msg.what == 1) {
uploadTaskService.responseFailureForNetwork(result);
}
}
}
}
protected class NetworkRunnable implements Runnable {
@Override
public void run() {
android.app.Application application = getApplication();
if (application == null) {
return;
}
android.content.SharedPreferences sharedPreferencesMulti = getSharedPreferences(SharedPreferenceConstant.NAME, android.content.Context.MODE_MULTI_PROCESS);
String authorization = sharedPreferencesMulti.getString(SharedPreferenceConstant.TOKEN, null);