Android_四大组件之Service
一、概述
Service是四大组件之一。它主要用于在后台执行耗时的逻辑,即使用户切换到其他应用甚至退出应用,它也能继续在后台运行。
下面主要介绍了service的两种形式启动和绑定 ,并通过简单例子说明了主要过程和用法。还包含服务与线程,服务的强制停止与前台服务等。
二、Service的主要过程
1.Service启动有两种形式:
(1).通过 startService() 启动 服务。一旦启动,服务即处于“启动”状态,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响。 已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。
(2).通过 bindService() 绑定 到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。 仅当与另一个应用组件绑定时,绑定服务才会运行。 多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。
接下来,通过简单代码 说明下这两种形式的大致过程。下图是Service的生命周期,比较清晰。
图1
2. Service基本用法:
(1) Service最重要的是自定义的服务类,继承android.app.Service。实现上述图片 Service生命周期包含的主要过程的方法,onCreate() onStartCommand() onBind() onUnbind() onDestroy()。
onStartCommand()
当另一个组件(如 Activity)通过调用 startService() 请求启动服务时,系统将调用此方法。一旦执行此方法,服务即会启动并可在后台无限期运行。 如果您实现此方法,则在服务工作完成后,需要由您通过调用 stopSelf() 或 stopService() 来停止服务。(如果您只想提供绑定,则无需实现此方法。)
onBind()
当另一个组件想通过调用 bindService() 与服务绑定时,系统将调用此方法。在此方法的实现中,您必须通过返回 IBinder 提供一个接口,供客户端用来与服务进行通信。请务必实现此方法,但如果您并不希望允许绑定,则应返回 null。
onCreate()
首次创建服务时,系统将调用此方法来执行一次性设置程序(在调用 onStartCommand() 或 onBind() 之前)。如果服务已在运行,则不会调用此方法。
onDestroy()
当服务不再使用且将被销毁时,系统将调用此方法。服务应该实现此方法来清理所有资源,如线程、注册的侦听器、接收器等。 这是服务接收的最后一个调用。
下面通过简单的例子,大致说明下启动服务(startService)和绑定服务(bindService)
(2).启动服务--startService(Intent intent)
创建TestService服务类,仅在主要方法里添加一些log.
package com.flx.testservice; import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log; public class TestService extends Service {
final private static String TAG = "flx_TestServer"; @Override
public void onCreate() {
Log.d(TAG, "TestServer thread id =" + Thread.currentThread().getId());
Log.d(TAG, "onCreate");
super.onCreate();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand flags=" + flags + ";startId=" + startId);
stopSelf();
/*返回变量 用于描述系统应该如何在服务终止的情况下继续运行服务
START_NOT_STICKY
除非有挂起 Intent 要传递,否则系统不会重建服务。这是最安全的选项,可以避免在不必要时以及应用能够轻松重启所有未完成的作业时运行服务。
START_STICKY
会重建服务并调用onStartCommand(),但不会重新传递最后一个 Intent。这适用于不执行命令、但无限期运行并等待作业的媒体播放器(或类似服务)。
START_REDELIVER_INTENT
会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand()。这适用于主动执行应该立即恢复的作业(例如下载文件)的服务。
*/
return super.onStartCommand(intent, flags, startId);
} @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 onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
}
}
在AndroidManifest.xml中声明service
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.flx.testservice"> <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="com.flx.testservice.MainActivity"
android:label="@string/title_activity_main"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity> /*
android:exported="false"表示阻止被其他应用隐式调用,只能自己应用调用
*/
<service android:name=".TestService"
android:exported="true" /> </application> </manifest>
添加MainActivity类和布局
package com.flx.testservice; import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button; public class MainActivity extends Activity implements View.OnClickListener {
final private static String TAG = "flx_TestServer";
private Button mStartServerBtn;
private Button mStopServerBtn; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); Log.d(TAG, "MainActivity thread id =" + Thread.currentThread().getId()); setContentView(R.layout.activity_main); mStartServerBtn = findViewById(R.id.start_service_btn);
mStopServerBtn = findViewById(R.id.stop_service_btn); mStartServerBtn.setOnClickListener(this);
mStopServerBtn.setOnClickListener(this);
} @Override
public void onClick(View v) {
Intent serverIntent = new Intent(this, TestService.class);
switch (v.getId()) {
case R.id.start_service_btn:
startService(serverIntent);
break;
case R.id.stop_service_btn:
stopService(serverIntent);
break;
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <Button
android:id="@+id/start_service_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="StartService" /> <Button
android:id="@+id/stop_service_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="StopService" />
</LinearLayout>
Activity界面效果:
图2
启动服务:
点击StartService按钮,在点击StopService按钮。打印出来的log如下:
2019-07-28 04:08:53.307 19866-19866/com.flx.testservice D/flx_TestServer: onCreate
2019-07-28 04:08:53.312 19866-19866/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=1
2019-07-28 04:10:10.025 19866-19866/com.flx.testservice D/flx_TestServer: onDestroy
从代码和log看,通过点击StartService按钮,Acitivity组件调用startService(Intent intent)启动服务, 然后onCreate() onStartCommand()依次执行,Service的具体执行逻辑就可以放在这两个里面。点击StopService按钮,组件调用stopService(Intent intent) 停止服务,onDestroy()被回调。符合图1 左边部分(启动服务生命周期)过程。
点击StartService按钮3次,在点击StopService按钮。打印出来的log如下:
2019-07-28 04:13:02.272 19866-19866/com.flx.testservice D/flx_TestServer: onCreate
2019-07-28 04:13:02.277 19866-19866/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=1
2019-07-28 04:13:04.025 19866-19866/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=2
2019-07-28 04:13:04.714 19866-19866/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=3
2019-07-28 04:13:15.569 19866-19866/com.flx.testservice D/flx_TestServer: onDestroy
Service中的onCreate()只在首次创建服务时调用, 如果服务已经在运行了则不会再调用。它在onStartCommand()(和onBind() 后面可以看到)之前。
停止服务:
启动服务 可在后台无限运行,即使启动服务的组件已经销毁(除非系统资源紧张,系统收回了内存资源而被销毁)。因此,服务必须自己停止,两种方式,1是服务自身调用stopSelf()自行停止运行,另一种是组件通过调用stopService(Intent intent)来停止。
*但是,如果服务同时处理多个 onStartCommand() 请求,则不应在处理完一个启动请求之后停止服务,因为可能已经收到了新的启动请求(在第一个请求结束时停止服务会终止第二个请求)。为了避免这一问题,可以使用 stopSelf(int) 确保服务停止请求始终是最近的启动请求。也就说,在调用 stopSelf(int) 时,传递与停止请求的 ID 对应的启动请求的 ID(传递给 onStartCommand() 的 startId)。如果调用的 stopSelf(int) 与之前服务收到了新的启动请求,ID 不匹配,服务也就不会停止。
做个简单的验证:
如点击3次StartService,在点击StopService,在点击StartService,log如下
2019-07-27 10:05:49.677 28103-28103/com.flx.testservice D/flx_TestServer: onCreate
2019-07-27 10:05:49.683 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=1
2019-07-27 10:05:51.205 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=2
2019-07-27 10:05:51.866 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=3
2019-07-27 10:05:54.610 28103-28103/com.flx.testservice D/flx_TestServer: onDestroy
2019-07-27 10:05:55.603 28103-28103/com.flx.testservice D/flx_TestServer: TestServer thread id =2
2019-07-27 10:05:55.603 28103-28103/com.flx.testservice D/flx_TestServer: onCreate
2019-07-27 10:05:55.607 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=1
可以看出startId是onStartCommand执行的次数有关。点击StopService是组件调用的stopService,不管执行了几次启动服务,都会直接停止服务。
下面不点击StopService的按钮,在onStartCommand中有加stopSelf(5); 当startId=5时,ID匹配了会自己停止服务,其他情况不会停止。log如下,是符合的。
2019-07-27 10:11:51.214 28103-28103/com.flx.testservice D/flx_TestServer: onCreate
2019-07-27 10:11:51.218 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=1
2019-07-27 10:11:55.993 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=2
2019-07-27 10:11:56.662 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=3
2019-07-27 10:11:57.405 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=4
2019-07-27 10:11:58.159 28103-28103/com.flx.testservice D/flx_TestServer: onStartCommand flags=0;startId=5
2019-07-27 10:11:58.181 28103-28103/com.flx.testservice D/flx_TestServer: onDestroy
(3) 绑定服务---bindService
最开始已经介绍了启动服务和绑定服务。
要创建绑定服务,首先必须定义指定客户端如何与服务通信的接口。 服务与客户端之间的这个接口必须是 IBinder 的实现,并且服务必须从 onBind() 回调方法返回它。一旦客户端收到 IBinder,即可开始通过该接口与服务进行交互。
多个客户端可以同时绑定到服务。客户端完成与服务的交互后,会调用 unbindService() 取消绑定。一旦没有客户端绑定到该服务,系统就会销毁它(不必按通过 onStartCommand() 启动的服务那样来停止绑定服务)。
上述代码添加绑定服务相关代码和log,由于模拟多个客户端,所以创建了2个组件和ServiceConnection.
TestService.java
package com.flx.testservice; import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log; public class TestService extends Service {
final private static String TAG = "flx_TestServer"; @Override
public void onCreate() {
Log.d(TAG, "TestServer thread id =" + Thread.currentThread().getId());
Log.d(TAG, "onCreate");
super.onCreate();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand flags=" + flags + ";startId=" + startId);
stopSelf();
/*返回变量 用于描述系统应该如何在服务终止的情况下继续运行服务
START_NOT_STICKY
除非有挂起 Intent 要传递,否则系统不会重建服务。这是最安全的选项,可以避免在不必要时以及应用能够轻松重启所有未完成的作业时运行服务。
START_STICKY
会重建服务并调用onStartCommand(),但不会重新传递最后一个 Intent。这适用于不执行命令、但无限期运行并等待作业的媒体播放器(或类似服务)。
START_REDELIVER_INTENT
会重建服务,并通过传递给服务的最后一个 Intent 调用 onStartCommand()。这适用于主动执行应该立即恢复的作业(例如下载文件)的服务。
*/
return super.onStartCommand(intent, flags, startId);
} @Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind");
return binder;
} @Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind");
return super.onUnbind(intent);
} @Override
public void onDestroy() {
Log.d(TAG, "onDestroy");
super.onDestroy();
} private MyBinder binder = new MyBinder();
int testNum = ;
class MyBinder extends Binder{
public void test(int num) {
Log.d(TAG, "MyBinder test()="+(testNum+=num));
}
}
}
MainActivity.java
package com.flx.testservice; import android.app.Activity;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.view.View;
import android.widget.Button; public class MainActivity extends Activity implements View.OnClickListener {
final private static String TAG = "flx_TestServer"; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); Log.d(TAG, "MainActivity thread id =" + Thread.currentThread().getId()); setContentView(R.layout.activity_main); Button mStartServerBtn = findViewById(R.id.start_service_btn);
Button mStopServerBtn = findViewById(R.id.stop_service_btn);
Button mBindServerBtn = findViewById(R.id.bind_service_btn);
Button mBindServerBtn2 = findViewById(R.id.bind_service_btn2);
Button mUnbindServerBtn = findViewById(R.id.unbind_service_btn);
Button mUnbindServerBtn2 = findViewById(R.id.unbind_service_btn2); mStartServerBtn.setOnClickListener(this);
mStopServerBtn.setOnClickListener(this);
mBindServerBtn.setOnClickListener(this);
mBindServerBtn2.setOnClickListener(this);
mUnbindServerBtn.setOnClickListener(this);
mUnbindServerBtn2.setOnClickListener(this);
} @Override
public void onClick(View v) {
Intent serverIntent = new Intent(this, TestService.class);
switch (v.getId()) {
case R.id.start_service_btn:
startService(serverIntent);
break;
case R.id.stop_service_btn:
stopService(serverIntent);
break;
case R.id.bind_service_btn:
bindService(serverIntent, mServerConnect, Service.BIND_AUTO_CREATE);
break;
case R.id.bind_service_btn2:
bindService(serverIntent, mServerConnect2, Service.BIND_AUTO_CREATE);
break;
case R.id.unbind_service_btn:
unbindService(mServerConnect);
break;
case R.id.unbind_service_btn2:
unbindService(mServerConnect2);
break;
}
} private ServiceConnection mServerConnect2 = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "ServiceConnection2 onServiceConnected");
TestService.MyBinder myBinder = (TestService.MyBinder) service;
myBinder.test();
} @Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "ServiceConnection2 onServiceDisconnected");
}
}; private ServiceConnection mServerConnect = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(TAG, "ServiceConnection onServiceConnected");
TestService.MyBinder myBinder = (TestService.MyBinder) service;
myBinder.test();
} @Override
public void onServiceDisconnected(ComponentName name) {
Log.d(TAG, "ServiceConnection onServiceDisconnected");
}
};
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <Button
android:id="@+id/start_service_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="StartService" /> <Button
android:id="@+id/stop_service_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="StopService" /> <Button
android:id="@+id/bind_service_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="BindService" /> <Button
android:id="@+id/bind_service_btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="BindService2"/> <Button
android:id="@+id/unbind_service_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="UnbindService"/> <Button
android:id="@+id/unbind_service_btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAllCaps="false"
android:text="UnbindService2"/>
</LinearLayout>
效果界面
图3
点击BindService按钮,组件调用的bindService()绑定服务。再点击UnbindService按钮,组件调用unbindService解除绑定。
2019-07-28 04:45:52.546 22060-22060/com.flx.testservice D/flx_TestServer: onCreate
2019-07-28 04:45:52.549 22060-22060/com.flx.testservice D/flx_TestServer: onBind
2019-07-28 04:45:52.577 22060-22060/com.flx.testservice D/flx_TestServer: ServiceConnection onServiceConnected
2019-07-28 04:45:52.577 22060-22060/com.flx.testservice D/flx_TestServer: MyBinder test()=10
2019-07-28 04:45:55.043 22060-22060/com.flx.testservice D/flx_TestServer: onUnbind
2019-07-28 04:45:55.045 22060-22060/com.flx.testservice D/flx_TestServer: onDestroy
绑定及解除绑定依次执行了onCreate(),onBind(),onUnbind(),onDestory()。符合图1右边部分的 绑定服务的生命周期。绑定过的组件,再次点击也是无效的,不能多此绑定。
点击BindService按钮,再点击BindService2按钮,点击UnbindService按钮或者点击UnbindService2按钮,效果如下:
2019-07-28 04:59:18.137 22837-22837/com.flx.testservice D/flx_TestServer: onCreate
2019-07-28 04:59:18.139 22837-22837/com.flx.testservice D/flx_TestServer: onBind
2019-07-28 04:59:18.152 22837-22837/com.flx.testservice D/flx_TestServer: ServiceConnection onServiceConnected
2019-07-28 04:59:18.152 22837-22837/com.flx.testservice D/flx_TestServer: MyBinder test()=10
2019-07-28 04:59:19.029 22837-22837/com.flx.testservice D/flx_TestServer: ServiceConnection2 onServiceConnected
2019-07-28 04:59:19.029 22837-22837/com.flx.testservice D/flx_TestServer: MyBinder test()=20
所以如果不是所有绑定的都解除绑定,服务是不会销毁停止。当两个绑定都解除绑定后,服务会被销毁(BindService->BindService2->UnbindService->UnbindService2)
2019-07-28 05:01:50.802 23164-23164/com.flx.testservice D/flx_TestServer: onCreate
2019-07-28 05:01:50.803 23164-23164/com.flx.testservice D/flx_TestServer: onBind
2019-07-28 05:01:50.815 23164-23164/com.flx.testservice D/flx_TestServer: ServiceConnection onServiceConnected
2019-07-28 05:01:50.815 23164-23164/com.flx.testservice D/flx_TestServer: MyBinder test()=10
2019-07-28 05:01:51.453 23164-23164/com.flx.testservice D/flx_TestServer: ServiceConnection2 onServiceConnected
2019-07-28 05:01:51.453 23164-23164/com.flx.testservice D/flx_TestServer: MyBinder test()=20
2019-07-28 05:01:52.738 23164-23164/com.flx.testservice D/flx_TestServer: onUnbind
2019-07-28 05:01:52.745 23164-23164/com.flx.testservice D/flx_TestServer: onDestroy
注:如果服务已解除绑定,再执行解除绑定会报错。
java.lang.IllegalArgumentException: Service not registered: com.flx.testservice.MainActivity$2@72e6895
bindService是有返回值的,所以在解除绑定前做一个判断就可以避免了。
返回值的说明---true if the system is in the process of bringing up a service that your client has permission to bind to; false if the system couldn't find the service or if your client doesn't have permission to bind to it. If this value is true, you should later call unbindService(ServiceConnection) to release the connection.
ManiActivity中修改如下即可:
private boolean mIsConn = false;
private boolean mIsConn2 = false;
@Override
public void onClick(View v) {
Intent serverIntent = new Intent(this, TestService.class);
switch (v.getId()) {
case R.id.start_service_btn:
startService(serverIntent);
break;
case R.id.stop_service_btn:
stopService(serverIntent);
break;
case R.id.bind_service_btn:
mIsConn=bindService(serverIntent, mServerConnect, Service.BIND_AUTO_CREATE);
break;
case R.id.bind_service_btn2:
mIsConn2=bindService(serverIntent, mServerConnect2, Service.BIND_AUTO_CREATE);
break;
case R.id.unbind_service_btn:
if (mIsConn){
mIsConn = false;
unbindService(mServerConnect);
}
break;
case R.id.unbind_service_btn2:
if (mIsConn2) {
mIsConn2 = false;
unbindService(mServerConnect2);
}
break;
}
Log.d(TAG, "MainActivity after click mIsConn="+mIsConn+";mIsConn2="+mIsConn2);
}
三、其他注意
1.Service和线程
2019-07-28 07:26:21.978 27802-27802/com.flx.testservice D/flx_TestServer: MainActivity thread id =2
2019-07-28 07:26:24.663 27802-27802/com.flx.testservice D/flx_TestServer: MainActivity after click mIsConn=true;mIsConn2=false
2019-07-28 07:26:24.703 27802-27802/com.flx.testservice D/flx_TestServer: TestServer thread id =2
上述例子中有打印Activity和Service的线程id, 是一样的。
默认情况下,服务是在应用的主线程中运行的。服务在其托管进程的主线程中运行,它既不创建自己的线程,也不在单独的进程中运行(除非另行指定)。因此,如果服务执行的是密集型或阻塞性操作,则仍应在服务内创建新线程。服务和线程没有直接关系。
服务如果不停止会一直运行在后台(特殊情况下面说),即使Activity被销毁,只要进程还在 服务就能一直运行,这是线程做不到的。
2.强制停止服务
如果系统内存不足,达到一定条件,一直运行的服务可能被强制停止。如果不主动停止,服务在后台一直运行下去,随着服务在后台运行时间越来越长,系统会不断降低服务在后台列表的位置,当系统资源不足情况下,会越容易被强制停止 释放资源被系统回收。
那么如何尽量保证服务不会被强制停止呢?(比较正常合理的情况)
(1)如果服务绑定到具有用户焦点的Activity上,则不太可能被强制停止。
(2)onStartCommand的返回值 可以决定当系统资源 再次足够可用了,是否重启服务或已什么方式重启服务。具体的值在上述TestService中onStartCommand()方法中 注释里详细说明了。
(3)设置为前台服务。
前台服务被认为是用户主动意识到的一种服务,因此在内存不足时,系统也不会考虑将其终止。 前台服务必须为状态栏提供通知,除非服务停止或从前台移除,否则不能清除通知。例如,状态栏中的通知可能表示正在播放的歌曲,并允许用户启动 Activity 来与音乐播放器进行交互。
设置前台服务:
startForeground(int id, Notification notification), 注意,id不能为0
大致如下,在Service类onCreate()中添加的。
@Override
public void onCreate() {
Log.d(TAG, "TestServer thread id =" + Thread.currentThread().getId());
Log.d(TAG, "onCreate");
String CHANNEL_ID = "test_service_channelId";
String CHANNEL_NAME = "test_service";
NotificationChannel notificationChannel = new NotificationChannel(CHANNEL_ID,CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(notificationChannel);
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_background)
.setContentTitle("TestService Notification ABC")
.setContentText("AAAAA")
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(, notification);
super.onCreate();
}
因为用的Andoid P调试的,通知的创建如上代码。 注意别忘了添加权限。<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
效果如图
图4
即使最近任务中关闭应用,任务也是运行的,通知栏一直存在。停止任务后才会消失。
停止前台服务:
停止前台服务使用stopForeground(boolean removeNotification),方法中的boolean值表示是否移除通知栏的通知,该方法不会停止服务。但如果服务被停止了,则前台服务的通知也会被移除。
Android_四大组件之Service的更多相关文章
- Android四大组件之Service
Android四大组件之Service Android支持服务的概念,服务是在后台运行的组件,没有用户界面,Android服务可用有与活动独立的生命周期.Android支持两种类型的服务: 本地服务: ...
- Java乔晓松-android的四大组件之一Service(服务的绑定)
android的四大组件之一Service(服务的绑定) 怎么绑定服务,又怎么解除服务,代码如下: MainActivity.java源码: package com.example.lesson14_ ...
- 【Android开发日记】之入门篇(五)——Android四大组件之Service
这几天忙着驾校考试,连电脑都碰不到了,今天总算告一段落了~~Service作为Android的服务组件,默默地在后台为整个程序服务,辅助应用与系统中的其他组件或系统服务进行沟通.它跟Activity的 ...
- Android 四大组件之Service
---恢复内容开始--- 1,Service的生命周期
- Android成长日记-Android四大组件之Service组件的学习
1.什么是Service? Service是Android四大组件中与Activity最相似的组件,它们都代表可执行的程序,Service与Activity的区别在于:Service一直在后台运行,它 ...
- 谈Android四大组件之Service篇
Service简介 Service是Android系统中的四大组件之一,它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序.Service必须在AndroidManifest.xml中声明 ...
- Android 四大组件之service与Broadcast
Android 四大组件之一:service: Service有五个生命周期:onCreat,onStartCommand, onBind,onUnbind, onDestroy 主要有绑定和非绑定两 ...
- Android四大组件之一Service介绍-android学习之旅(十二)
基本概念: service是android四大组件之一,运行在后台执行耗时操作,并不提供用户界面.其他组件如acticity可以通过startService启动该组件,也可以通过bindService ...
- 四大组件之Service小结
总结提高,与君共勉! 1.Service是什么 Service 是看不到界面的,,就是一个没有界面的Activity, 并且长期在后台运行的一个组件.. 由于ANR对Activity和Broadcas ...
随机推荐
- Codeforce-CodeCraft-20 (Div. 2)-B. String Modification (找规律+模拟)
Vasya has a string s of length n. He decides to make the following modification to the string: Pick ...
- codeforce 227E 矩阵快速幂求斐波那契+N个连续数求最大公约数+斐波那契数列的性质
E. Anniversary time limit per test2 seconds memory limit per test256 megabytes inputstandard input o ...
- POJ - 2251 Dungeon Master(搜索)
You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is composed of un ...
- 在TX2上多线程读取视频帧进行caffe推理
参考文章:Multi-threaded Camera Caffe Inferencing TX2之多线程读取视频及深度学习推理 背景 一般在TX2上部署深度学习模型时,都是读取摄像头视频或者传入视频文 ...
- CF #632 (Div. 2) 对应题号CF1333
1333A Little Artem 在一个\(n\)行\(m\)列的格子上染色,每个格子能染黑白两种 构造一种方案,使得四个方向有至少一个白色格子的黑色格子的数量,比四个方向有至少一个黑色格子的白色 ...
- CF906D Power Tower
扩展欧拉定理 CF906D Power Tower 洛谷交的第二个黑题 题意 给出一个序列\(w-1,w_2,\cdots,w_n\),以及\(q\)个询问 每个询问给出\(l,r\),求: \[w_ ...
- Pika源码学习--pika的通信和线程模型
pika的线程模型有官方的wiki介绍https://github.com/Qihoo360/pika/wiki/pika-%E7%BA%BF%E7%A8%8B%E6%A8%A1%E5%9E%8B,这 ...
- Redux在项目中的文件结构
React + Redux 今天我们来唠唠在React一般项目中,使用Redux进行状态管理的时候,相对的如何存放reducer.action.api之类文件的结构与使用时机吧.本章默认看官们已经 ...
- python恺撒密码 与 字符串反码 【chr()与ord()函数的两种不同应用】
恺撒密码 描述 恺撒密码是古罗马凯撒大帝用来对军事情报进行加解密的算法,它采用了替换方法对信息中的每一个英文字符循环替换为字母表序列中该字符后面的第三个字符,即,字母表的对应关系如下: ...
- saltstack升级
1.背景 saltstack出现安全漏洞,5.1前后爆出很多设备已经变成矿机. 2.处理方法 升级到最新版本salt 3.官方升级方法 yum install https://repo.saltsta ...