Service是用于后台服务的,当应用程序被挂到后台的时候,问了保证应用某些组件仍然可以工作而引入了Service这个概念。
那么这里面要强调的是Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR,为了解决这样的问题,引入了IntentService
创建MyService服务,并且在清单文件里配置
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
Log.i("MyService-->","onBind");
return null;
}
@Override
public void onCreate() {
super.onCreate();
Log.i("MyService-->","onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("MyService-->","onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("MyService-->","onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.i("MyService-->","onDestroy");
清单文件
button3?.setOnClickListener {
var intent = Intent(this@Main2Activity, MyService::class.java)
startService(intent)
}
看看StartService()的方式的生命周期
//打开Activity
D/MainActivity-->: onCreate
D/MainActivity-->: onStart
D/MainActivity-->: onResume
//点击开启服务
D/MyService-->: onCreate
D/MyService-->: onStartCommand
//点击back,关闭Activity
D/MainActivity-->: onPause
D/MainActivity-->: onStop
D/MainActivity-->: onDestroy
点击back,退出Activity,发现Service 并没有调用onDestroy,看后台正在运行的服务列表,确实有MyService,这说明通过StartService开启的服务,不受Activity启动的生命周期管理,自行运行在后台,如果关闭服务可以通过StopService,或者服务自身调用stopSelf()
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService-->","onStartCommand");
//调用自身的方法
stopSelf();
return super.onStartCommand(intent, flags, startId);
}
D/MyService-->: onCreate
D/MyService-->: onStartCommand
//直接调用了关闭方法
D/MyService-->: onDestroy
var intent = Intent(this@Main2Activity, MyService::class.java)
button3?.setOnClickListener {
//开启服务
startService(intent)
}
button4?.setOnClickListener {
//关闭服务
stopService(intent)
}
//开启
D/MyService-->: onCreate
D/MyService-->: onStartCommand
//关闭
D/MyService-->: onDestroy
如果我多次开启服务:
D/MyService-->: onCreate
D/MyService-->: onStartCommand
D/MyService-->: onStartCommand
D/MyService-->: onStartCommand
D/MyService-->: onStartCommand
D/MyService-->: onStartCommand
D/MyService-->: onStartCommand
D/MyService-->: onStartCommand
onCreate:只会调用一次,
多次开启服务,会调用多次 onStartCommand()
onDestroy() 也是只调用一次
var conn: ServiceConnection = MyServiceConnection()
var intent = Intent(this@Main2Activity, MyService::class.java)
button5?.setOnClickListener {
//绑定服务
bindService(intent, conn, Context.BIND_AUTO_CREATE)
}
button6?.setOnClickListener {
//解绑服务
unbindService(conn)
}
class MyServiceConnection : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
}
}
生命周期:
//点击绑定服务
D/MyService-->: onCreate
D/MyService-->: onBind
//点击解绑服务
D/MyService-->: onUnbind
D/MyService-->: onDestroy
java.lang.IllegalArgumentException: Service not registered:
Activity的代码:
class Main2Activity : AppCompatActivity() {
//内部类引用
var conn: ServiceConnection = MyServiceConnection()
//接口返回的binder的接口引用
var iService: IService? = null
override
fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d("MainActivity-->", "onCreate")
var intent = Intent(this@Main2Activity, MyService::class.java)
button3?.setOnClickListener {
//开启服务
startService(intent)
}
button4?.setOnClickListener {
//关闭服务
stopService(intent)
}
button5?.setOnClickListener {
//绑定服务
bindService(intent, conn, Context.BIND_AUTO_CREATE)
}
button6?.setOnClickListener {
//解绑服务
unbindService(conn)
}
button7?.setOnClickListener {
//调用服务里的方法
iService?.callServiceMethod()
}
}
inner class MyServiceConnection : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
iService = service as IService
}
}
}
MyService代码:
public class MyService extends Service {
public MyService() {
}
class MyBinder extends Binder implements IService {
@Override
public void callServiceMethod() {
call();
}
}
@Override
public IBinder onBind(Intent intent) {
Log.d("MyService-->", "onBind");
return new MyBinder();
}
@Override
public void onCreate() {
super.onCreate();
Log.d("MyService-->", "onCreate");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService-->", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d("MyService-->", "onUnbind");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyService-->", "onDestroy");
}
public void call() {
Log.d("MyService-->", "我是服务里面 方法,我被调用了");
}
}
IService接口
public interface IService {
void callServiceMethod();
}
//点击调用service的方法,打印:“我是服务里面 方法,我被调用了”
Thread:Thread 是程序执行的最小单元,可以用 Thread 来执行一些异步的操作。
Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。
是有区别的。这里涉及到进程的级别:
1、前台进程
用户当前正在做的事情需要这个进程。如果满足下面的条件之一,一个进程就被认为是前台进程:
这个进程拥有一个正在与用户交互的Activity(这个Activity的onResume()方法被调用)。
这个进程拥有一个绑定到正在与用户交互的activity上的Service。
这个进程拥有一个前台运行的Service(service调用了方法startForeground()).
这个进程拥有一个正在执行其任何一个生命周期回调方法(onCreate(),onStart(),或onDestroy())的Service。
这个进程拥有正在执行其onReceive()方法的BroadcastReceiver。
通常,在任何时间点,只有很少的前台进程存在。它们只有在达到无法调合的矛盾时才会被杀--如内存太小而不能继续运行时。通常,到了这时,设备就达到了一个内存分页调度状态,所以需要杀一些前台进程来保证用户界面的反应
2、可见进程
一个进程不拥有运行于前台的组件,但是依然能影响用户所见。满足下列条件时,进程即为可见:
这个进程拥有一个不在前台但仍可见的Activity(它的onPause()方法被调用)。当一个前台activity启动一个对话框时,就出了这种情况。
3、服务进程
一个可见进程被认为是极其重要的。并且,除非只有杀掉它才可以保证所有前台进程的运行,否则是不能动它的。
这个进程拥有一个绑定到可见activity的Service。
一个进程不在上述两种之内,但它运行着一个被startService()所启动的service。
尽管一个服务进程不直接影响用户所见,但是它们通常做一些用户关心的事情(比如播放音乐或下载数据),所以系统不到前台进程和可见进程活不下去时不会杀它。
4、后台进程
一个进程拥有一个当前不可见的activity(activity的onStop()方法被调用)。
这样的进程们不会直接影响到用户体验,所以系统可以在任意时刻杀了它们从而为前台、可见、以及服务进程们提供存储空间。通常有很多后台进程在运行。它们被保存在一个LRU(最近最少使用)列表中来确保拥有最近刚被看到的activity的进程最后被杀。如果一个activity正确的实现了它的生命周期方法,并保存了它的当前状态,那么杀死它的进程将不会对用户的可视化体验造成影响。因为当用户返回到这个activity时,这个activity会恢复它所有的可见状态。
5、空进程
一个进程不拥有入何active组件。
保留这类进程的唯一理由是高速缓存,这样可以提高下一次一个组件要运行它时的启动速度。系统经常为了平衡在进程高速缓存和底层的内核高速缓存之间的整体系统资源而杀死它们。
如上边说的,在服务里和单独开一个子线程,如果当前应用程序内存不足是,和首先销毁单独开启的子线程的进程,而开启服务的进程优先级比较高,更好执行我没的异步任务,这就是为什么选择Service的原因
是的,同在一个Activity的mainThrea,也就是UI线程,所以在服务里,也不能执行耗时操作,如果执行会出现ANR
为了可以简单地创建一个异步的、会自动停止的服务,Android专门提供了一个IntentService类,这个类就很好的解决在服务里不能执行耗时操作。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent()回调方法中执行,并且每次只会执行一个工作线程,执行完第一个后,再执行第二个,以此类推。
public class MyIntentService2 extends IntentService {
//调用父类有参构造函数。这里我们手动给服务起个名字为:MyIntentService2
public MyIntentService2() {
super("MyIntentService2");
}
//该方法在会在一个单独的线程中执行,来完成工作任务。任务结束后,该Service自动停止
@Override
protected void onHandleIntent(Intent intent) {
//直接执行耗时的操作
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("MyIntentService2", "onDestroy");
}
}
//清单文件
//开启IntentService
var intent = Intent(this@Main2Activity, MyIntentService2::class.java)
startService(intent)
//继承于Service的特性
public abstract class IntentService extends Service {
//looper对象
private volatile Looper mServiceLooper;
//创建一个handle 用来接受和处理Startcomment传过来的intent
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
//因为handler队列的关系,他会一个一个的执行
onHandleIntent((Intent)msg.obj);
//如果没有了,就调用自己的关闭方法
stopSelf(msg.arg1);
}
}
public IntentService(String name) {
super();
mName = name;
}
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
super.onCreate();
//初始化的时候 创建一个Handler继承Threa,里面有Handle
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
//执行HandlerThread中run()方法,里面的looper.loop()开启无线循环
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(@Nullable Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
//发送到Handler中
mServiceHandler.sendMessage(msg);
}
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
//接受传过来的intent
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onDestroy() {
mServiceLooper.quit();
}
@Override
@Nullable
public IBinder onBind(Intent intent) {
return null;
}
@WorkerThread
protected abstract void onHandleIntent(@Nullable Intent intent);
}
(1) 它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents。
(2) 创建了一个工作队列,来逐个发送intent给onHandleIntent()。
(3) 不需要主动调用stopSelft()来结束服务。因为,在所有的intent被处理完后,系统会自动关闭服务。
(4) 默认实现的onBind()返回null
(5) 默认实现的onStartCommand()的目的是将intent插入到工作队列中
1.可以通过bindService 返回MyBinder的引用,就行通讯
2.可以通过Messenger实现通讯
https://blog.csdn.net/iispring/article/details/48329925
可以的。弹吐司有个条件就是得有一个 Context 上下文,而 Service 本身就是 Context 的子类,因此在 Service 里面弹吐司是完全可以的。比如我们在 Service 中完成下载任务后可以弹一个吐司通知用户
他们都是 Android 开发中使用频率最高的类。
其中 Activity 和 Service 都是 Android 四大组件
之一。他俩都是 Context 类的子类 ContextWrapper 的子类,因此他俩可以算是兄弟关系吧。
不过
兄弟俩各有各自的本领,Activity 负责用户界面的显示和交互,Service 负责后台任务的处理。Activity
和 Service 之间可以通过 Intent 传递数据,
因此可以把 Intent 看作是通信使者。
IPC,全称Inter-Process Communication,字面意思就是进程间通信或者跨进程通信。
那什么是进程呢?它和线程有什么关系?
进程是系统进行资源分配和调度的基本单位,是操作系统结构的基础;早期表现为一个程序,现在可以看作线程的容器。
线程是CPU调度的最小单位。一个进程可以包含一个或者多个线程,进程向系统申请资源,线程使用进程拥有的资源。
IPC不是Android所独有的,是现代操作系统都存在的机制,对于Android来说。它是一种基于Linux内核的移动OS,他的进程通信方式不仅仅包含信号量、套接字、管道等等,还包括了Android独有的、特色的Binder机制。
序列化:内存中的对象->磁盘
反序列化:磁盘中对象->内存
但是:虽然Parcelable的性能要强于Serializable,但是仍然有特殊的情况需要使用Serializable,而不去使用Parcelable,因为Parcelable无法将数据进行持久化,因此在将数据保存在磁盘的时候,仍然需要使用后者,因为前者无法很好的将数据进行持久化.(原因是在不同的Android版本当中,Parcelable可能会不同,因此数据的持久化方面仍然是使用Serializable)
AIDL(Android Interface Definition Language)是Android系统自定义的接口描述语言。可以用来实现进程间的通讯方式之一,底层主要用到Binder。
AIDL 编写:
模拟demo 底层binder实现客户端与服务端通信,binder里面又用到内存映射 mmap()方法
1.创建一个项目textService
创建一个MySrvice 集成Service 清单文件配置下,
并且指定意图过滤器--》最好是当前应用的包名
android:enabled="true"
android:exported="true"
这俩个必须有个为true,才可以被其他应用远程调用
public class MyService extends Service {
public MyService() {
}
private class MyBinder extends IService.Stub {
@Override
public void callMethod() throws RemoteException {
show();
}
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
@Override
public void onCreate() {
Log.i("远程", "我是远程服务我创建了");
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
//服务里面的方法,可以被远程调用
void show() {
Log.i("远程", "我是远程,我方法别调用了");
}
}
IService.Stub
首先创建一个aidl文件夹,光标☞到app-src-main上,点击右键,选择aidl,输入aidl的文件名
里面不可以有public 等修饰符
build下项目,或着同步一下,会在app-build-generated-source-debug-包名下生产aidl文件
远程服务到此就ok了
客户段
public class MainActivity extends AppCompatActivity {
IService mIService;
ServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
//点击绑定服务
public void bind(View view) {
Intent intent = new Intent();
//指定同样意图过滤器
intent.setAction("mall.kotlin.com.textservice");
//指定远程服务的包名(必须指定,不然就会报错)
intent.setPackage(getPackageName());
conn = new conn();
bindService(intent, conn, BIND_AUTO_CREATE);
}
//调用远程服务里面的方法
public void call(View view) {
try {
mIService.callMethod();
} catch (RemoteException e) {
e.printStackTrace();
}
}
private class conn implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIService = IService.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
mIService = IService.Stub.asInterface(service);
这个是怎么生成的?
首先吧远程服务的aidl文件夹,复制到当前项目main下面,并且里面的包名和远程服务的aidl里面的包名一致,build下项目,同样在当前source里面生产一个IService.stub类
mIService = IService.Stub.asInterface(service);这个mIservice就是当前本地的远程服务的接口,嗲用他就可以调用远程服务的里面的方法
这里不在细致分析,提供几个链接供大家分享
https://www.jianshu.com/p/4ee3fd07da14
https://www.jianshu.com/p/719fc4758813
开发艺术-->