建设网站的目的和意义,重庆网站网络推广,wordpress 批量爆破,做网站怎么建站点Service 为后台运行#xff0c;不可见#xff0c;没有界面。优先级高于Activity#xff08;内存不足时先杀掉Activity#xff09;#xff0c;运行在主线程且不能做耗时操作。
一、Service 启动方式
1、startService() 通过 startService 启动后#xff0c;service会一直… Service 为后台运行不可见没有界面。优先级高于Activity内存不足时先杀掉Activity运行在主线程且不能做耗时操作。
一、Service 启动方式
1、startService() 通过 startService 启动后service会一直无限期运行下去当外部调用了 stopService() 或stopSelf() 方法时该Service才会停止运行并销毁。当系统资源不足时 会回收一些不重要的serviceservice 被系统回收也会停止运行并被销毁。
生命周期
onCreate() 1、如果 service 没被创建过调用 startService() 后会执行 onCreate() 回调 2、如果 service 已处于运行中调用 startService() 不会执行 onCreate() 方法。 此方法适合完成一些初始化工作。
onStartCommand() 如果多次执行了 startService() 方法那么 Service 的 onStartCommand() 方法也会相应的多次调用。 onBind() Service中的onBind()方法是抽象方法Service类本身就是抽象类所以onBind()方法是必须重写的即使我们用不到。 使用 startService 方法启动 ServiceonBind() 方法基本用不到重写时返回一个 null 即可。
onDestory() 在销毁的时候会执行Service该方法。 代码实例
MainActivity.java
public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 启动serviceIntent intent new Intent(MainActivity.this, TestService.class);startService(intent);}
}
TestService.java
public class TestService extends Service {private static final String TAG TestService;Overridepublic IBinder onBind(Intent intent) {return null;}Overridepublic void onCreate() {Log.d(TAG, onCreate);super.onCreate();}Overridepublic int onStartCommand(Intent intent, int flags, int startId) {Log.d(TAG, onStartCommand);return super.onStartCommand(intent, flags, startId);}Overridepublic void onDestroy() {Log.d(TAG, onDestroy);super.onDestroy();}
}
AndroidManifest.xml
?xml version1.0 encodingutf-8?
manifest xmlns:androidhttp://schemas.android.com/apk/res/androidpackagecom.xiaoxu.testdemoapplicationandroid:allowBackuptrueandroid:iconmipmap/ic_launcherandroid:labelstring/app_nameandroid:roundIconmipmap/ic_launcher_roundandroid:supportsRtltrueandroid:themestyle/Theme.MainActivity serviceandroid:name.TestServiceandroid:enabledtrueandroid:exportedtrue /activityandroid:name.MainActivityandroid:exportedtrue intent-filteraction android:nameandroid.intent.action.MAIN /category android:nameandroid.intent.category.LAUNCHER //intent-filter/activity/application
/manifest
2、bindService bindService 启动的服务和调用者之间是典型的 client-server 模式。调用者是 clientservice则是 server 端。service只有一个但绑定到 service 上面的 client 可以有一个或多个。这里所提到的 client 指的是组件比如某个Activity。 client 可以通过 IBinder 接口获取 Service 实例从而实现在 client 端直接调用 Service 中的方法以实现灵活交互这在通过 startService 方法启动中是无法实现的。 bindService 启动服务的生命周期与其绑定的 client 息息相关。当 client 销毁时client 会自动与 Service 解除绑定。当然client 也可以明确调用 Context 的 unbindService() 方法与 Service 解除绑定。当没有任何 client 与 Service 绑定时Service 会自行销毁。
生命周期
onCreate() 当服务通过 onStartCommand() 和 onBind() 被第一次创建的时候系统调用该方法。该调用要求执行一次性安装。 onBind() 当其他组件想要通过 bindService() 来绑定服务时系统调用该方法。如果你实现该方法你需要返回 IBinder 对象来提供一个接口以便客户来与服务通信。你必须实现该方法如果你不允许绑定则直接返回 null。 onUnbind() 当客户中断所有服务发布的特殊接口时系统调用该方法。 onRebind() 当新的客户端与服务连接且此前它已经通过onUnbind(Intent)通知断开连接时系统调用该方法。 onDestroy() 当服务不再有用或者被销毁时系统调用该方法。你的服务需要实现该方法来清理任何资源如线程已注册的监听器接收器等。 代码实例
MainAcivity.java
public class MainAcivity extends Activity{private TextService mService null;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent new Intent(this, TestService.class);bindService(intent, conn, Context.BIND_AUTO_CREATE);}private ServiceConnection conn new ServiceConnection() {Overridepublic void onServiceConnected(ComponentName name, IBinder binder) {MyBinder mBinder (MyBinder)binder;mService mBinder.getService();String name mService.getUserName();}Overridepublic void onServiceDisconnected(ComponentName name) {}};Overrideprotected void onDestroy() {super.onDestroy();unbindService(conn);}
}
MyService.java
public class TestService extends Service{//通过 binder 实现调用者 client 与 Service 之间的通信private MyBinder binder new MyBinder();// client 可以通过 Binder 获取 Service 实例public class MyBinder extends Binder {public MyService getService() {return TestService.this;}}Overridepublic void onCreate() {super.onCreate();}Overridepublic int onStartCommand(Intent intent, int flags, int startId) {return START_NOT_STICKY;}Overridepublic IBinder onBind(Intent intent) {return binder;}Overridepublic boolean onUnbind(Intent intent) {return false;}Overridepublic void onDestroy() {super.onDestroy();}// getUserName 是 Service 暴露出去供 Client 调用的公共方法public int getUserName() {return XiaoXu;}
}
3、startForegroundService Android 8.0 系统不允许后台应用创建后台服务只能使用 startForegroundService() 启动服务创建服务后应用必须在 5 秒内调用该服务的 startForeground() 显示一条可见通知声明有服务在挂着不然系统会停止服务 ANR 提示。 系统的要求 Notification 要加 Channel并且要在 onStartCommand 中执行 startForeground()因为这个主要是针对后台保活的服务如果在服务运行期间再次使用 startForegroundService() 启动服务那么这次就不会调用服务的 onCreate 方法只会调用onStartCommand 方法。如果不在 onStartCommand 方法里再挂个通知的话系统会认为你使用了 startForegroundService 却不在 5 秒内给通知很傻地就停止服务 ANR 提示。
代码实例
MainActivity.java
public class MainActivity extends Activity {Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 启动serviceIntent intent new Intent(this, TestService.class) ;startForegroundService(intent);}
}
TestService.java
public class TestService extends Service {private static final String TAG TestService;private Notification notification;public static final String CHANNEL_ID_STRING service_01;Overridepublic IBinder onBind(Intent intent) {return null;}Overridepublic void onCreate() {super.onCreate();}Overridepublic int onStartCommand(Intent intent, int flags, int startId) {NotificationManager manager (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);NotificationChannel mChannel new NotificationChannel(CHANNEL_ID_STRING,getString(R.string.app_name),NotificationManager.IMPORTANCE_LOW);manager.createNotificationChannel(mChannel);notification new Notification.Builder(getApplicationContext(), CHANNEL_ID_STRING).build();// 下面第一个参数不能为 0startForeground(1, notification);return super.onStartCommand(intent, flags, startId);}Overridepublic void onDestroy() {super.onDestroy();}
} 可以看到使用 startForegroundService 启动方式与 startService 基本相同只是在 Service 的 onStartCommand 增加弹出通知的操作。startForeground 方法中的第一个参数不能为 0是因为这个通知不能与正常通知 id 相同否则通知会被“隐藏”这不是官方想看到的就会出现 Context.startForegroundService() did not then call Service.startForeground() 异常。
二、其他
1、使用场景
startService 前台应用调用 startService 启动 ServiceService 独立运行不需要与 Activity 进行交互。
bindService 前台应用调用 bindService 启动 ServiceAndroid 与 Service 进行绑定并且 Activity 可以得到 Service 的实例实现与 Service 的交互。
startForegroundService 后台应用调用 startForegroundService 启动 ServiceAndroid 8.0 之后强制要求以提示用户。例如在收到开机广播时启动服务使用 startService 会无法启动只能使用 startForegroundService 进行启动并弹出通知提示用户。
2、隐藏通知 有时在使用 startForegroundService 启动服务时想隐藏常驻通知。
1显示通知后马上调用 stopForeground(true) 取消通知。在 Android 11 中测试服务被杀掉。
2提前注册一个没有声音没有震动的通知channel注册一个无声无振动的通知渠道。startForeground 时与该通知使用同一个 id就可以隐藏我们的通知了。未尝试
参考Android8 避免startForeground方法弹出通知
3、AIDL Service死亡监听 服务的死亡监听我们使用第二种启动方式。
启动 Service
private void bindService(Context context) {Intent serviceIntent new Intent();serviceIntent.setAction(com.cx.test);serviceIntent.setPackage(com.cx.test.MyService);boolean bindSuccess context.bindService(serviceIntent, mServiceConnection, Service.BIND_AUTO_CREATE);
}
绑定结果回调
private IPushInterface mIPushInterface;private ServiceConnection mServiceConnection new ServiceConnection() {Overridepublic void onServiceConnected(ComponentName componentName, IBinder iBinder) {if (iBinder ! null) {//通过AIDL拿到服务mIPushInterface IPushInterface.Stub.asInterface(iBinder);try {//服务死亡监听if (mIPushInterface ! null) {mIPushInterface.asBinder().linkToDeath(mDeathRecipient, 0);}} catch (RemoteException e) {e.printStackTrace();}}}Overridepublic void onServiceDisconnected(ComponentName componentName) {//连接失败}
};
死亡监听回调
private IBinder.DeathRecipient mDeathRecipient new IBinder.DeathRecipient() {Overridepublic void binderDied() {if (mContext ! null) {//重新绑定服务bindService(mContext);}}
};