6 四大组件之Service

6-1 Servie概述

组件篇——Service

定义:
  1.后台运行,不可见,没有界面
  2.优先级高于Activity

  Service是Android系统的后台服务组件,适用于开发无界面、长时间运行的应用功能。

Service特点如下:

  没有用户界面

  不会轻易被Android系统终止

  在系统资源恢复后Service也将自动恢复

  运行状态

  可用于进程间通信

用途:
  播放音乐,记录地理信息位置的改变,监听某种动作

注意:
  -运行在主线程,不能用它来做耗时的请求或者动作
  -可以在服务中开一个线程,在线程中做耗时操作

类型:

  本地服务(Local Service):

    应用程序内部

    start方式:startService stopService stopSelf stopSelfResult

      启动方式使用Service

      通过调用Context.startService()启动Service,通过调用Context.stopService()或Service.stopSefl()停止Service

    Bind方式:bindService unbindService

      绑定方式使用Service

      使用Service的组件通过Context.bindService()建立服务链接,通过Context.unbindService()停止服务链接

      如果在绑定过程中Service没有启动,Context.bindService()会自动启动Service

  远程服务(Remote Service):

    Android系统内部的应用程序间之间

    定义IBinder接口

生命周期:

  通过startService()方法启动的服务于调用者没有关系,即使调用者关闭了,服务仍然运行想停止服务要调用Context.stopService(),此时系统会调用onDestory(),使用此方法启动时,服务首次启动系统先调用服务的onCreate()-->onStart(),如果服务已经启动再次调用只会触发onStart()方法

  onCreate():Service的生命周期开始,完成Service的初始化工作;

  onStart():活动生命周期开始;

  onDestroy():Service的生命周期结束,释放Service所有占用的资源;


  使用bindService()启动的服务与调用者绑定,只要调用者关闭服务就终止,使用此方法启动时,服务首次启动系统先调用服务的onCreate()-->onBind(),如果服务已经启动再次调用不会再触发这2个方法,调用者退出时系统会调用服务的onUnbind()-->onDestory(),想主动解除绑定可使用Contex.unbindService(),系统依次调用onUnbind()-->onDestory();

  bindService()绑定Servcie, onCreate()和onBindle()将先后被调用。

  unbindService()取消绑定Servcie,onUnbind()将被调用,如果onUnbind()返回true,则表示在调用者绑定新服务时,onRebind()函数将被调用

非绑定式的service的生命周期
  startService()--->onCreate()--->onStartCommand()--->ServingRunning--->onStop()--->onDestory()服务停止

绑定式的service的生命周期
  bindService()--->onCreate()--->onBind()--->用户与服务绑定 在解绑服务 onUnbind()--->onDestory()服务停止

start方式特点:

  -服务跟启动源没有任何联系 

  -无法得到服务对象

Bind方式特点:

  -通过Ibinder接口实例,返回一个ServerConnnection对象给启动源
  -通过ServiceConnection对象的相关方法可以得到Service对象

 

6-2 Start启动

start方式的启动时:

  第一次创建Service需要调用onCreate(),而后调用onStartCommand(),不管调用了多少次的onStartCOmmand(),停止的时候只调用一次onDestroy();

StartService
1. 使用方法:
  (1)写一个MyStartService继承自Service,重写它的各种方法onCreate()、onStartCommand()、onDestory()
  (2)在AndroidManifest.xml中注册这个Service
  (3)在主线程Activity中通过startSerice(intent)方式启动
  (4)通过stopService(intent)方式停止

2. 关于StartService
  (1)启动方式是通过启动intent方式实现
  (2)启动之后该Service和启动源没有关系,即使主线程退出了,service还会继续运行

由于Service和Activity类似,属于Android四大组件之一,所以我们需要在AndroidManifest.xml中进行注册。我们的组件都需要在AndroidManifest.xml中进行注册。

3.启动Service

显式启动

  Intent中指明Service所在的类,并调用startService(Intent)函数启动Service

final Intent serviceIntent = new Intent(this,RandomService.class);startService(serviceIntent);

隐式启动

  需要隐式开启Service,则可以在注册Service时,声明Intent-filter的action属性

<service android:name=".RandomService" ><intent-filter><action android:name="StartRandomService" /></intent-filter>
</service>
final Intent serviceIntent = new Intent();
serviceIntent.setAction("edu.hrbeu.RandomService");

 

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" ><TextViewandroid:id="@+id/textView1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Start:" /><Buttonandroid:id="@+id/start"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="StartService" /><Buttonandroid:id="@+id/stop"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="StopService" /><TextViewandroid:id="@+id/textView2"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Bind:" /><Buttonandroid:id="@+id/bind"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="BindService" /><Buttonandroid:id="@+id/play"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="播放" /><Buttonandroid:id="@+id/pause"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="暂停" /><Buttonandroid:id="@+id/next"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="下一首" /><Buttonandroid:id="@+id/pervious"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="上一首" /><Buttonandroid:id="@+id/unbind"android:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="doClick"android:text="UnBindService" /></LinearLayout>

MainActivity.java

package com.example.test;import android.app.Activity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.view.View;public class MainActivity extends Activity {Intent intent1;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void doClick(View v) {switch (v.getId()) {case R.id.start:intent1 = new Intent(MainActivity.this, MyStartService.class);startService(intent1);break;case R.id.stop:stopService(intent1);break;}}
}

MyStartService.java

package com.example.test;import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;public class MyStartService extends Service {@Overridepublic void onCreate() {// TODO Auto-generated method stubLog.i("info", "Service--onCreate()");super.onCreate();}@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {// TODO Auto-generated method stubLog.i("info", "Service--onStartCommand()");return super.onStartCommand(intent, flags, startId);}@Overridepublic void onDestroy() {// TODO Auto-generated method stubLog.i("info", "Service--onDestroy()");super.onDestroy();}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubLog.i("info", "Service--onBind()");return null;}}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.test"android:versionCode="1"android:versionName="1.0" ><uses-sdkandroid:minSdkVersion="15"android:targetSdkVersion="15" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><activityandroid:name=".MainActivity"android:label="@string/app_name" ><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity>    <service android:name="com.example.servicedemo.MyStartService"></service></application></manifest>

 

6-3 Bind启动

1.通过绑定服务获取回传数据:
  通过Ibinder接口实例(继承的类里面返回一个Ibinder对象的抽象方法),返回一个serviceConnection对象给启动源,因为Ibinder里面含有我们要的数据,这里可以定义个内部类继承Binder里面做想返回的参数

 

2.使用onBind()方法的IBinder返回值给启动源返回信息 但是IBinder不能直接使用 需要通过Ibinder接口实例 返回一个ServiceConnection对象给启动源,通过ServiceConnection对象的相关方法可以得到Service,MyBinder是继承自Binder类的,而Binder类实际上实现了IBinder接口。

public class MyBinder extends Binder{public MyBindServic getService(){return MyBindService.this;//返回这个Service的实例}
} public IBunder onBind(Intent intent){return new MyBinder();
}

 

3.在启动源定义ServiceConnection 该对象在绑定服务时传输到服务端(bindService(intent,conn,Service.BIND_AUTO_CREATE)) 绑定后 通过onServiceConnected() 方法获取service对象

 

4.unbindservice执行后,不能重复调用,会报错,并且在destroy的时候必须解绑, stopserveice则不会,

 

5.服务的两种启动方式:

  1).通过startService(Intent intent)启动,stopService(Intent intent)停止,比较简单。服务启动后与启动源无关,也无返回服务本身。需注意要在配置文件中注册服务。

  2).通过bindService(Intent intent,ServiceConnection conn,int flags)绑定服务启动,unbindService(ServiceConnection conn)去绑定停止,该方式可以返回服务本身,与启动源相关。

 

6.通过bindService绑定服务启动的具体步骤:

  1)Intent intent = new Intent(上下文, 目标服务名.class);
    bindService(intent, conn, Service.BIND_AUTO_CREATE);//绑定

  2)在自定义的服务类中通过自定义一个内部类:
    public class MyBinder extends Binder {
      public MyBindService getService() {
        return MyBindService.this;// 获取服务
      }
    }来返回服务本身
    同时在自定义服务类重新父类Service的方法:
    public IBinder onBind(Intent intent) {
      // TODO Auto-generated method stub
      return new MyBinder();
    }
    该方法可返回服务本身.

    3)在启动源的Activity中创建一个ServiceConnection实例,初始化ServiceConnection接口,在接口方法中重写方法

      ServiceConnection conn = new ServiceConnection() {
        //当启动源跟service的连接意外丢失的时候会调用
        //比如service崩溃了,或被强行杀死了
        public void onServiceDisconnected(ComponentName name) {
        }
        //当启动源跟service成功连接之后会调用这个方法

        public void onServiceConnected(ComponentName name, IBinder service) {
          myBindService = ((MyBinder)service).getService();//大类转化为自身的小类,获取内部类中的方法,从而获得服务本身
      }};

    4)bindService()中指定ServiceConnection conn参数

     bindService(intent2, conn, Service.BIND_AUTO_CREATE);

    5)在自定义的继承于Servic类的类中,添加需要的方法,在启动Service的Activity中可以直接调用服务中的方法。

  通过bindService()启动的服务是和启动源(Activity)绑定在一起的,如果Activity退出的时候没有调用unbindService()进行解绑定(停止),那么程序会报错。所以我们需要在Activity的onDestroy()方法中调用unbindService()进行解绑定。而且对于已经解绑定的服务再次进行解绑定,那么也会报错,这点和通过startService启动的服务不同,stopService()方法可以调用多次。

 

7.StartService和BindService

  1). StartService启动后启动源和Service没有关系,BindService调用bindService()启动service后启动源和Service相关,在退出activity之前必须要调用unbindService()取消绑定。

  2). startService()和bindService()可以混合使用。如果我们想要Activity退出了,但是服务还在继续,那么我们就要选用startService的方式来启动服务,如果我们想要在Activity中获取Service对象,那么我们需要用bindService方法结合ServiceConnection来启动Service,但是这种方法,由于将Service和Activity绑定在了一起,所以当Activity退出的时候,我们需要unbindService()来停掉Service,否则就会报错。

 

8.BindService

  通过bindService()得到的Service是和启动源(Activity)绑定在一起的,在Activity退出的时候需要调用unbindService()进行解绑定(停止)。

  调用bindService()时会调用到目标Service的onBind()函数,通过IBinder接口实例,返回一个ServiceConnection对象给启动源。然后启动源可以通过ServiceConnection对象得到启动的Service对象

MyBindService.java

package com.example.test;import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;public class MyBindService extends Service{@Overridepublic void onCreate() {// TODO Auto-generated method stubLog.i("info", "BindService--onCreate()");super.onCreate();}public class MyBinder extends Binder{public MyBindService getService(){return MyBindService.this;}}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubLog.i("info", "BindService--onBind()");return new MyBinder();}@Overridepublic void unbindService(ServiceConnection conn) {// TODO Auto-generated method stubLog.i("info", "BindService--unbindService()");super.unbindService(conn);}@Overridepublic void onDestroy() {// TODO Auto-generated method stubLog.i("info", "BindService--onDestroy()");super.onDestroy();}public void Play(){Log.i("info", "播放");}public void Pause(){Log.i("info", "暂停");}public void Pervious(){Log.i("info", "上一首");}public void next(){Log.i("info", "下一首");}
}

MainActivity.java

package com.example.test;import com.example.test.MyBindService.MyBinder;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.view.Menu;
import android.view.View;public class MainActivity extends Activity {Intent intent1;Intent intent2;MyBindService service;ServiceConnection conn = new ServiceConnection() {@Override//当服务跟启动源断开的时候 会自动回调public void onServiceDisconnected(ComponentName name) {// TODO Auto-generated method stub
            }@Override//当服务跟启动源连接的时候 会自动回调public void onServiceConnected(ComponentName name, IBinder binder) {// TODO Auto-generated method stubservice = ((MyBinder)binder).getService();}};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void doClick(View v){switch (v.getId()) {case R.id.start:intent1 =     new Intent(MainActivity.this, MyStartService.class);startService(intent1);break;case R.id.stop:stopService(intent1);break;case R.id.play:service.Play();break;case R.id.pause:service.Pause();break;case R.id.pervious:service.Pervious();break;case R.id.next:service.next();break;case R.id.bind:
//绑定Service:
//bindService()方法绑定服务
//Intent对象传递给bindService(),声明需要启动的Service
//Context.BIND_AUTO_CREATE表明只要绑定存在,就自动建立Service;同时也告知Android系统,这个Service的重要程度与调用者相同
            intent2 = new Intent(MainActivity.this, MyBindService.class);startService(intent2);bindService(intent2, conn, Service.BIND_AUTO_CREATE);//绑定了break;case R.id.unbind:unbindService(conn);break;}}@Overrideprotected void onDestroy() {// TODO Auto-generated method stub
        stopService(intent2);
//解绑Service:
//取消绑定使用unbindService()方法,并将ServiceConnnection对象传递给unbindService()方法。
//unbindService()方法调用成功后,系统并不会再次调用onServiceDisconnected()方法
//onServiceDisconnected()方法仅在意外断开绑定时才被调用。
        unbindService(conn);//解绑定super.onDestroy();}@Overridepublic boolean onCreateOptionsMenu(Menu menu) {// Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);return true;}}

 

转载于:https://www.cnblogs.com/crazyzx/articles/5350862.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/288321.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WCF服务寄宿IIS时.SVC文件无法浏览的解决办法

在IIS中托管服务和经典的ASMX Web服务托管相似,需要在IIS下创建虚拟目录,并提供一个.svc文件和Web.config配置文件。另外,托管时,服务的基地址必须与.svc文件的地址相同。 一、操作步骤: (1)打开IIS,新建网站,选择物理路径 (2)打开IIS,在默认网站下添加应用程序,…

C#语法糖系列 —— 第一篇:聊聊 params 参数底层玩法

首先说说为什么要写这个系列&#xff0c;大概有两点原因。这种文章阅读量确实高...对 IL 和 汇编代码 的学习巩固所以就决定写一下这个系列&#xff0c;如果大家能从中有所收获&#xff0c;那就更好啦&#xff01;一&#xff1a;params 应用层玩法 首先上一段 测试代码。class …

nginx 修改配置文件使之支持pathinfo,且隐藏index.php

声明环境&#xff1a; nginx centos6.8 使用lnmp一键包搭建环境&#xff08;2019年2月19日 &#xff09;以前使用过别的办法去修改配置文件&#xff0c;但是过于繁琐&#xff0c;最近发现新版本中&#xff0c;在nginx 的 conf目录下发现了文件“enable-php-pathinfo.conf”&am…

关于在Windows下AndroidStudio.使用React-Native开发android报错红屏“run react-native start”解决

以下是报错&#xff0c;不过他已经给了解决办法&#xff0c;报错提示的大概中文译为“无法加载脚本&#xff0c;请确保你的Metro服务以及那个包正确”&#xff0c;由于我个人并不是专业安卓&#xff0c;公司项目没办法就上了&#xff0c;所以我就不关包了&#xff0c;包肯定是正…

主成分分析法_数学建模 || 葡萄酒的评价(1)主成分分析法

首先要说一下&#xff0c;这篇文章我在其他的平台发过&#xff0c;也是本人亲自写的&#xff0c;如果大家觉得眼熟的话放弃轻松&#xff0c;没有抄袭&#xff0c;主要是因为与我这 “葡萄酒的评价” 题目成系列了&#xff0c;因此在这里再把这个贴出来。2012 年 A 题葡萄酒的评…

imagePreview接口调用微信自带图片播放器

2019独角兽企业重金招聘Python工程师标准>>> 在微信浏览器中&#xff0c;出现在网页上的图片通过点按一小段时间&#xff0c;可以调出微信隐藏的图片播放器&#xff0c;在播放器中看图可以随意放大缩小&#xff0c;体验更炫酷。不过这个功能默认只对通过微信后台编辑…

TypeError: 'MongoClient' object is not callable

在声明数据库的时候&#xff0c;将中括号[ ]换成了圆括号&#xff08;&#xff09;错误&#xff1a;修改完成后的代码&#xff1a;client pymongo.MongoClient(localhost)db client[my_database]#注意这里用中括号&#xff01;&#xff01; 之后再运行程序&#xff0c;就能存…

信息系统开发有管理

做了一套题&#xff0c;又总结了下《信息系统开发与管理》。感觉又有了新的认识。这本书应该说总体的设计都是非常具有逻辑性的。内容设计的有些水到渠成。要说结构的话&#xff0c;应该算是总—分结构吧。一開始就以一篇概述全面的介绍了此书。我总结了以下的图。 信息、系统、…

Main 和 静态构造函数 到底谁先执行?

最近被问到一个很有意思的问题&#xff0c;到底是 Main函数 先执行还是 静态构造函数 先执行&#xff1f;参考如下代码&#xff1a;class Program{static Program(){Console.WriteLine("我是 静态构造 函数&#xff01;");}static void Main(string[] args){Console.…

c 正则提取html,c – 正则表达式以获取HTML表格内容

确实没有可能的正则表达式解决方案适用于任意数量的表数据,并将每个单元格放入单独的后向引用中.这是因为通过反向引用,您需要为要创建的每个backref创建一个独特的开放式窗口,并且您不知道自己有多少个单元格.使用一种或另一种循环来提取数据没有任何问题.例如,在最后一个,在P…

(五)python3 只需3小时带你轻松入门—— 逻辑运算符

如果if判断中存在多个表达式判断&#xff0c;需要使用逻辑运算符。 例如有一个变量a&#xff0c;需要判断是否在1到5之间&#xff0c;那么则需要判断a是否大于1且a小于5。这个时候需要使用and逻辑运算符进行判断。 and python中使用and判断左右两边表达式是同时正确&#xff0c…

(四)python3 只需3小时带你轻松入门—— 流程控制

缩进 python中使用缩进代表代码块&#xff1b;每一个块代表一个层次&#xff08;分支&#xff09;&#xff0c;每个单独的分支是独立的&#xff0c;但是从整体逻辑上又是相融的&#xff1b;就像一本书一样&#xff0c;每个知识点是独立的&#xff0c;但是每个知识点组成了这本书…

ASP.NET Core 正确获取查询字符串参数

前言有网友在交流群中询问&#xff0c;如何获取查询字符串参数&#xff1a;默认情况下&#xff0c;ASP.NET Core 的模型绑定以键值对的形式从 HTTP 请求中的以下列表中指示的顺序扫描源并获取数据&#xff1a;表单域请求正文路由数据查询字符串参数上传的文件因此&#xff0c;不…

(三)python3 只需3小时带你轻松入门—— 变量的简单运算

变量运算 在编程时&#xff0c;需要对数据进行计算&#xff0c;计算的形式不限于&#xff1a;字符串拼接、相加减、相乘除及普遍的数学运算、剔除或指定剔除、添加或指定添加等。 在python中&#xff1a; *表示乘法/表示除法表示加法-表示减法 a,b10,11 cog3 j2 print(ca)#加…

使用XMLConfiguration解析xml,properties等相应信息

org.apache.commons.configuration.XMLConfiguration; Apache Common-Configuration工具可以从Properties文件&#xff0c;XML文件,JNDI,JDBC数据源&#xff0c;System Properties,Applet parameters,Servlet Parameters等读取相应信息 使用步骤 前提&#xff0c;引入commons-c…

C#语法糖系列 —— 第二篇:聊聊 ref,in 修饰符底层玩法

自从 C# 7.3 放开 ref 之后&#xff0c;这玩法就太花哨了&#xff0c;也让 C# 这门语言变得越来越多范式&#xff0c;越来越重&#xff0c;这篇我们就来聊聊 ref&#xff0c;本质上来说 ref 的放开就是把 C/C 指针的那一套又拿回来了&#xff0c;而且还封装成一套自己的玩法&am…

(二)python3 只需3小时带你轻松入门——基本变量

输入 在程序运行过程中&#xff0c;数据从外部流向程序&#xff0c;称为输入。在程序运行过程中&#xff0c;接收用户从键盘上键入值&#xff0c;可以使用input()函数。 input("请输入你要输入的值:")在输入值时&#xff0c;一般是代表接下来的运算需要使用到用户所…

Fiddler之为什么我没有抓到网络请求的js链接

1 问题 我开了Fiddler&#xff0c;没有抓到js的连接请求&#xff0c;因为我需要替换js文件&#xff0c;我以为我是没有开启抓起https的连接&#xff0c;但是的确开启了。 2 原因 浏览器里面有缓存&#xff0c;部分js文件不会再进行请求。 2 解决办法 在浏览器页面按下F12,然…

html5一年四季的变化,家乡四季的变化作文(精选5篇)

家乡四季的变化作文(精选5篇)在日常生活或是工作学习中&#xff0c;大家或多或少都会接触过作文吧&#xff0c;写作文是培养人们的观察力、联想力、想象力、思考力和记忆力的重要手段。那么你有了解过作文吗&#xff1f;下面是小编精心整理的家乡四季的变化作文(精选5篇)&#…

ThinkPHP多次重复提交问题的根源

2019独角兽企业重金招聘Python工程师标准>>> 由于用户刷新网页&#xff0c;导致页面所有变量回归初始空值 $code_session2 session(code2); $code2 I(code2);if($code2 ! $code_session2) {session(code2, $code2);M(dati)->data($data)->add();} 解决方法是…