IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 安卓服务Service -> 正文阅读

[移动开发]安卓服务Service

1、Service概念及用途

2、Service生命周期

3、Service与Activity通信

4、IntentService

5、跨进程访问AIDL

6、关于服务的应用

?

一、Service概念及用途

1、Service(服务)是一个没有用户界面的在后台运行执行耗时操作的应用组件。

2、其他应用组件能够启动Service,并且当用户切换到另外的应用场景,Service将持续在后台运行。

3、一个组件能够绑定到一个service来交互,例如,一个service可能会处理网络操作,播放音乐,操作文件I/O或者与内容提供者(content provider)交互,所有这些活动都是在后台进行。

4、Service有两种状态,“启动的”和“绑定”

Service的种类(了解)

按运行地点分类:

其实remote服务还是很少见的,并且一般都是系统服务。

按运行类型分类:

后台服务我们可以自己创建 ONGOING 的 Notification 这样就成为前台服务吗?答案是否定的,前台服务是在做了上述工作之后需要调用 startForeground (?android 2.0 及其以后版本?)或 setForeground (android 2.0 以前的版本)使服务成为 前台服务。这样做的好处在于,当服务被外部强制终止掉的时候,ONGOING 的 Notification 任然会移除掉。

按使用方式分类:

以上面三种方式启动的服务其生命周期也有区别,将在随后给出。

类别

区别

?优点

缺点?

?应用

本地服务(Local)

该服务依附在主进程上

?服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外Local服务因为是在同一进程因此不需要IPC,也不需要AIDL。相应bindService会方便很多。

?主进程被Kill后,服务便会终止。

?非常常见的应用如:HTC的音乐播放服务,天天动听音乐播放服务。

远程服务(Remote)

该服务是独立的进程,

?服务为独立的进程,对应进程名格式为所在包名加上你指定的android:process字符串。由于是独立的进程,因此在Activity所在进程被Kill的时候,该服务依然在运行,不受其他进程影响,有利于为多个进程提供服务具有较高的灵活性。

?该服务是独立的进程,会占用一定资源,并且使用AIDL进行IPC稍微麻烦一点。

?一些提供系统服务的Service,这种Service是常驻的。

类别

区别

应用

前台服务

会在通知一栏显示 ONGOING 的 Notification,

当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。常见的如音乐播放服务。

后台服务

默认的服务即为后台服务,即不会在通知一栏显示?ONGOING 的?Notification。

当服务被终止的时候,用户是看不到效果的。某些不需要运行或终止提示的服务,如天气更新,日期同步,邮件同步等。

类别

区别

startService 启动的服务

主要用于启动一个服务执行后台任务,不进行通信。停止服务使用stopService

bindService 启动的服务

该方法启动的服务要进行通信。停止服务使用unbindService

startService?同时也 bindService 启动的服务

停止服务应同时使用stepService与unbindService

Service 与 Thread 的区别

1). Thread:Thread 是程序执行的最小单元,它是分配CPU的基本单位。可以用 Thread 来执行一些异步的操作。

2). Service:Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote?Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!

二、生命周期

onCreate  onStart  onDestroy  onBind?

startService:

? 多次启动服务,startid会上升,强行杀死带服务的进程,则Service的startid会加+;

1、一旦启动,service就在后台运行,即使启动它的应用组件已经被销毁了。

2、通常started状态的service执行单任务并且不返回任何结果给启动者。比如当下载或上传一个文件,当这项操作完成时,service应该停止它本身。

bindService:

? 只能绑定一次,绑定之后不能再重新绑定,也不能取消绑定两次。

? 绑定会和当前应用程序共存亡,当前绑定的Activity销毁,自己也会销毁

1、一个绑定的service提供一个允许组件与service交互的接口,可以发送请求、获取返回结果,还可以通过夸进程通信来交互(IPC)。

2、绑定的service只有当应用组件绑定后才能运行,多个组件可以绑定一个service,当调用unbind()方法时,这个service就会被销毁了。

startService和bindService一起使用

特别注意:

***:service与activity一样都存在与当前进程的主线程中,所以,一些阻塞UI的操作,比如耗时操作不能放在service里进行,比如另外开启一个线程来处理诸如网络请求的耗时操作。

1、你应当知道在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自动解除,并且Service会自动停止);

2、你应当注意 使用 startService 启动服务之后,一定要使用 stopService停止服务

3、同时使用 startService 与 bindService 要注意到,Service 的终止,只需要unbindService,不管 startService 与 bindService 的调用顺序,调用 unbindService 服务再调用stop就会停止。

4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的 Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。

5、在 sdk 2.0 及其以后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过之前的 onStart 任然有效。这意味着,如果你开发的应用程序用的 sdk 为 2.0 及其以后的版本,那么你应当使用 onStartCommand 而不是 onStart。

?

?1、先start再bind: ?那么bind不会再执行oncreate方法,如果按back,只会取消绑定,不会stop服务。

? ? ? unbind->ondestroy

? ? ? ?先unbind再stop: ?unbind ?ondestroy

? ? ? ?先stop再unbind:执行stop的时候 不会执行destroy的方法,直到执行unbind的时候才会unbind和destroy方法

2、先bind再start: oncreate->bind->onstart ?

? ? ? ? ??unbind->ondestroy

? ? ? ?先unbind再stop: ?unbind ?ondestroy

? ? ? ?先stop再unbind:执行stop的时候 不会执行destroy的方法,直到执行unbind的时候才会unbind和destroy方法

?

三、Service与Activity通信

Activity与Service通信 ?使用Intent

Service与Activity通信 ?使用 ServiceConnection

?

public?String?getTime(){

????????String?time?=?new?Date().toString();

????????return?time;

????}

????class?MyBinder?extends?Binder{

????????public?MyService?getMyService(){

????????????return?MyService.this;

????????}

????}

????@Override

????public?IBinder?onBind(Intent?intent)?{

????????Log.i("msg",?"onBind");

????????return?new?MyBinder();

????}

?

ServiceConnection?conn?=?new??ServiceConnection()?{

????????@Override

????????public?void?onServiceDisconnected(ComponentName?name)?{

????????????Log.i("msg",?"onServiceDisconnected");

????????}

????????@Override

????????public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{

????????????Log.i("msg",?"onServiceConnected");

????????????MyBinder??myBinder?=?(MyBinder)service;

????????????MyService?myService?=?myBinder.getMyService();

????????????Log.i("msg",?myService.getTime());

????????}

????};

?

四、IntentService

1、IntentService是继承于Service并处理异步请求的一个类

2、在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样

3、当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。

4、启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行

5、每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

6、所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。

优点:省去了在Service中手动开线程的麻烦,第二,当操作完成时,我们不用手动停止Service,第三,it's so easy to use!

?

public?class?MyIntentService?extends?IntentService?{

????public?MyIntentService()?{

????????super("name");

????}??

????@Override

????public?void?onCreate()?{

????????Log.i("msg",?"onCreate?");

????????super.onCreate();

????}

????@Override

????protected?void?onHandleIntent(Intent?intent)?{

????????Log.i("msg",?"onHandleIntent");

????????try?{

????????????Thread.sleep(15000);

????????}?catch?(InterruptedException?e)?{

????????????//?TODO?Auto-generated?catch?block

????????????e.printStackTrace();

????????}

????}

}

startService(new?Intent(this,MyIntentService.class));

????????startService(new?Intent(this,MyIntentService.class));

说明:onHandleIntent里面是可以执行耗时操作,并且是以队列的形式一个一个执行

?

五、AIDL跨进程之间的访问

?

Server

1、建立一个aidl的文件 ?建立在包里面,如果自动在gen里面生命一个IPerson的java文件,则正确 ? 这个java文件是最终继承了BInder对象

2、写一个类继承IPerson,然后实现里面的方法

3、写一个Service类 ?,把onBInder方法的返回值设置成Person对象,注册

?

package?com.bwf.a75_serviceaidl_server;

?interface?IPerson?{

????void?setAge(int?age);

????void?setName(String?name);

????String?show();

}

?

public?class?Person?extends?IPerson.Stub{

????private?String?name;

????private?int?age;

????@Override

????public?void?setAge(int?age)?throws?RemoteException?{

????????this.age?=?age;

????}

????@Override

????public?void?setName(String?name)?throws?RemoteException?{

????????//?TODO?Auto-generated?method?stub

????????this.name?=?name;

????}

????@Override

????public?String?show()?throws?RemoteException?{

????????Log.i("msg",?"name:?"+name+"??age:?"+age);

????????return?"name:?"+name+"??age:?"+age;

????}

}

?

? ? @Override

????public?IBinder?onBind(Intent?intent)?{

????????return?new?Person();

????}

? ?<service?android:name="com.bwf.a75_serviceaidl_server.MyService"?android:exported="true">

????????????<intent-filter?>

????????????????<action?android:name="com.bwf.service"/>

????????????????<category?android:name="android.intent.category.DEFAULT"/>

????????????</intent-filter>

????????</service>

?

2、Client

1、建一个和Server一样的包名,然后再把IPersonjava类复制过来

2、

?

private?IPerson?per;

????private?ServiceConnection?conn?=?new?ServiceConnection()?{

????????@Override

????????public?void?onServiceDisconnected(ComponentName?name)?{

????????????//?TODO?Auto-generated?method?stub

????????}

????????@Override

????????public?void?onServiceConnected(ComponentName?name,?IBinder?service)?{

????????????Log.i("msg",?"onServiceConnected");

????????????per?=?IPerson.Stub.asInterface(service);

????????????try?{

????????????????per.setAge(30);

????????????????per.setName("Tom");

????????????????Log.i("msg",?"onServiceConnected?"+per.show());

????????????}?catch?(RemoteException?e)?{

????????????????//?TODO?Auto-generated?catch?block

????????????????e.printStackTrace();

????????????}

????????}

????};

????@Override

????protected?void?onCreate(Bundle?savedInstanceState)?{

????????super.onCreate(savedInstanceState);

????????setContentView(R.layout.activity_main);

????????Intent?intent?=?new?Intent();

????????intent.setAction("com.bwf.service");

????????bindService(intent,?conn,?Context.BIND_AUTO_CREATE);

????}

????@Override

????protected?void?onDestroy()?{

????????unbindService(conn);

????????super.onDestroy();

????}

?

六、应用:使用服务播放音乐

?

public?class?MyService?extends?Service?{

????private?MediaPlayer?media;

????@Override

????public?void?onCreate()?{

????????Log.i("msg",?"onCreate");

????????media?=?MediaPlayer.create(this,?R.raw.aw);

????????media.setLooping(false);

????????try?{

????????????media.prepare();//准备

????????}?catch?(IllegalStateException?e)?{

????????????//?TODO?Auto-generated?catch?block

????????????e.printStackTrace();

????????}?catch?(IOException?e)?{

????????????//?TODO?Auto-generated?catch?block

????????????e.printStackTrace();

????????}

????????super.onCreate();

????}

????@Override

????public?int?onStartCommand(Intent?intent,?int?flags,?int?startId)?{

????????Log.i("msg",?"onStartCommand:?"+intent.getStringExtra("info"));

????????switch?(intent.getIntExtra("oop",?0))?{

????????case?1://开始音乐

????????????if(media?!=?null?&&?!media.isPlaying()?){

????????????????media.start();//播放

????????????}

????????????break;

????????case?2://重头开始

????????????if(media?!=?null){????

????????????????media.seekTo(0);

//????????????????media.stop();

//????????????????media?=?MediaPlayer.create(this,?R.raw.aw);

//????????????????try?{

//????????????????????media.prepare();

//????????????????}?catch?(IllegalStateException?e)?{

//????????????????????//?TODO?Auto-generated?catch?block

//????????????????????e.printStackTrace();

//????????????????}?catch?(IOException?e)?{

//????????????????????//?TODO?Auto-generated?catch?block

//????????????????????e.printStackTrace();

//????????????????}

//????????????????media.start();

????????????}

????????????break;

????????case?3://暂停

????????????if(media?!=?null?&&?media.isPlaying()){

????????????????media.pause();

????????????}

????????????break;

????????default:

????????????break;

????????}

????????return?super.onStartCommand(intent,?flags,?startId);

????}

????@Override

????public?IBinder?onBind(Intent?intent)?{

????????Log.i("msg",?"onBind");

????????return?null;

????}

????@Override

????public?boolean?onUnbind(Intent?intent)?{

????????Log.i("msg",?"onUnbind");

????????return?super.onUnbind(intent);

????}

????@Override

????public?void?onDestroy()?{

????????Log.i("msg",?"onDestroy");

????????if(media?!=?null){

????????????media.stop();

????????????media.release();//释放

????????????media?=?null;

????????}

????????super.onDestroy();

????}

}

?

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-10 22:41:17  更:2022-03-10 22:42:57 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 18:30:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码