安卓Service服务

    Service简介

Service是运行在后台的,没有界面的,用来处理耗时比较长的。Service不是一个单独的进程,也不是一个单独的线程。

Service有两种类型

本地服务(Local Service):用于应用程序内部

远程服务(Remote Sercie):用于android系统内部的应用程序之间

前者用于实现应用程序自己的一些耗时任务,比如查询升级信息,并不占用应用程序比如Activity所属线程,而是单开线程后台执行,这样用户体验比较好。

后者可被其他应用程序复用,比如天气预报服务,其他应用程序不需要再写这样的服务,调用已有的即可。

  Service的生命周期以及启动方式

Service有startService()和bindService()两种启动Service方法,每种方法Service的生命周期是不一样的。

1 通过startService()启动服务

Service会经历 onCreate() --> onStartCommand()

stopService()的时候直接onDestroy()

如果是调用者直接退出而没有调用stopService的话,Service会一直在后台运行, 下次调用者再起来仍然可以stopService()。

2 通过bindService() 启动服务

Service会运行onCreate()-->onBind() ,此时调用者和Service绑定在一起

unbindService()的时候 运行 onUnbind()-->onDestroyed()

调用者退出了,Srevice就会调用onUnbind()-->onDestroyed()

所谓绑定在一起就共存亡了。

注意:Service的onCreate()的方法只会被调用一次,也就是说无论你多少次的调用startService()或bindService(),Service只被创建一次。

Android中的服务和Windows中的服务是类似的,服务一般没有用户操作界面,它运行于系统中不容易被用户发觉,可以使用它开发如监控之类的程序。

服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关联,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。

如果采用Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建,多次调用startService()方法并不会导致多次创建服务,但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

如果采用Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定,也就是说onCreate()和onBind()方法并不会被多次调用。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的 onUnbind()-->onDestroy()方法。

三 具体运用

1、开始服务,开始服务一般都是界面和服务简单数据交互。示例为从主界面传递一个值给服务,服务接收。

流程:

示例:

项目工程目录结构:

主界面,活动页面前台运行

package com.example.service;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity
{
 Button button1;
 @Override
 protected void onCreate ( Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  button1 = (Button) this.findViewById(R.id.button1);
  button1.setOnClickListener(new OnClickListener()
  {
   @Override
   public void onClick ( View v)
   {
    startMyService();
   }
  });
 }
 // 服务开启方法
 protected void startMyService ()
 {
  Intent intent = new Intent("com.example.service.MyService");
  // 利用Intent向服务传递数据,数据通过界面输入
  intent.putExtra("myMessage", "MainActivity--lhyService123456【这是活动前台传递过来的数据】!");
  this.startService(intent);//开始服务
 }
 @Override
 public 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;
 }
}

服务类,后台运行:

package com.example.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service
{
 @Override
 public IBinder onBind ( Intent arg0)
 {
  // TODO Auto-generated method stub
  return null;
 }
 @Override
 public void onCreate ()
 {
  Log.i("lhy", "服务创建onCreate ()-----------");
  super.onCreate();
 }
 // 启动服务,目前该方法不用
 // @Override
 // public void onStart ( Intent intent, int startId)
 // {
 // // TODO Auto-generated method stub
 // super.onStart(intent, startId);
 // }
 @Override
 public int onStartCommand ( Intent intent, int flags, int startId)
 {
  Log.i("lhy", "服务开启,在后台运行,正在做事情当中。。。。。。。。。。。。。");
  // 接收activity传递过来的数据
  String message = intent.getStringExtra("myMessage");
  Log.i("lhy", "MyService--服务后台接收前台活动输入的数据:" + message);
  return super.onStartCommand(intent, flags, startId);
 }
 @Override
 public void onDestroy ()
 {
  // TODO Auto-generated method stub
  super.onDestroy();
 }
}

活动前台页面样式布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:text="开始服务示例演示" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="38dp"
android:text="开始服务" />
<EditText
android:id="@+id/editText1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="38dp"
android:ems="10" >
<requestFocus />
</EditText>
</RelativeLayout>

AndroidMainfest.xml文件中注册服务

<service android:name="com.example.service.MyService" >
<intent-filter>
<action android:name="com.example.service.MyService" />
</intent-filter>
</service>

控制台输出信息:MainActivity--lhyService123456 是活动界面传递过来,在服务端接收的数据

2、绑定服务,一般都是界面与服务深层次数据交互,进程之间数据传递,绑定服务需要连接对象,连接对象中可以获得服务类的内部类对象,这样活动前台可以利用服务类内部类对象操作服务里面的任何方法和属性。

具体流程:

示例:

项目工程目录结构:

活动前台界面

package com.example.servicebind;
import com.example.servicebind.MyServices.MyBind;
import android.os.Bundle;
import android.os.IBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity
{
 Button button1;
 Button button2;
 MyBind myBind;
 @Override
 protected void onCreate ( Bundle savedInstanceState)
 {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  button1 = (Button) this.findViewById(R.id.button1);
  button1.setOnClickListener(onClickListener);
  button2 = (Button) this.findViewById(R.id.button2);
  button2.setOnClickListener(onClickListener);
 }
 // 按钮事件监听
 OnClickListener onClickListener = new OnClickListener()
 {
  @Override
  public void onClick ( View v)
  {
   switch (v.getId())
   {
   case R.id.button1:
    startMyServiceBind();
    break;
   case R.id.button2:
    stopMyServiceBind();
    break;
   default:
    break;
   }
  }
 };
 // 按钮点击事件监听方法,也就是绑定服务
 protected void startMyServiceBind ()
 {
  // 如果部内部类对象不为空,那么就直接调用内部类方法,否则重新绑定服务,建立连接
  if (myBind != null)
  {
   // 利用服务内部对象,调用服务内部类方法,相当于调用了服务类的的数据
   myBind.myBindFun();
   Log.i("lhy", myBind.getStr());
  }
  else
  {
   // 绑定服务方法*******************************
   Intent intent = new Intent("com.example.servicebind.MyServices");
   // intent意图,serviceConnection连接, Context.BIND_AUTO_CREATE绑定自动创建
   this.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
  }
 }
 protected void stopMyServiceBind ()
 {
  if (serviceConnection == null)
  {
   return;
  }
  else
  {
   this.unbindService(serviceConnection);
   Log.i("lhy", "服务解除!!");
   serviceConnection = null;
  }
 }
 // 绑定服务开始,类似于事件监听,一个服务连接
 ServiceConnection serviceConnection = new ServiceConnection()
 {
  // 绑定失败之后
  @Override
  public void onServiceDisconnected ( ComponentName name)
  {
   // TODO Auto-generated method stub
  }
  // 绑定成功之后,也就是服务建立了连接
  @Override
  public void onServiceConnected ( ComponentName name, IBinder service)
  {
   // 获取服务类内部对象,IBinder service,该参数就是服务类回调方法OnBind()返回的数据,也就是服务内部对象
   myBind = (MyBind) service;
  }
 };
}

服务类,后台运行

package com.example.servicebind;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyServices extends Service
{
 // 服务类成员变量
 String str = "MyServiceMessage";
 // 服务类成员方法
 public void fun1 ()
 {
  Log.i("lhy", "服务内部方法fun1()");
 }
 // 服务类内部类
 public class MyBind extends Binder
 {
  // 内部类调用外部类方法
  public void myBindFun ()
  {
   fun1();
  }
  // 内部类调用外部类成员变量
  public void setStr ( String str)
  {
   MyServices.this.str = str;
  }
  public String getStr ()
  {
   return MyServices.this.str;
  }
 }
 @Override
 public void onCreate ()
 {
  Log.i("lhy", "服务创建onCreate()");
  super.onCreate();
 }
 @Override
 public IBinder onBind ( Intent intent)
 {
  Log.i("lhy", "服务绑定onBind()");
  // 实例化内部类对象,该对象可以无条件调用其外部类(本服务类)的一切方法和成员变量
  return new MyBind();
 }
 @Override
 public boolean onUnbind ( Intent intent)
 {
  Log.i("lhy", "服务解除onUnbind()");
  return super.onUnbind(intent);
 }
}

活动界面布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="绑定服务演示" />
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/textView1"
android:layout_below="@+id/textView1"
android:layout_marginTop="23dp"
android:text="绑定服务" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/button1"
android:layout_below="@+id/button1"
android:layout_marginTop="14dp"
android:text="解除服务" />
</RelativeLayout>

最后在AndroidMainfest.xml文件中注册服务:

<service android:name="com.example.servicebind.MyServices" >
<intent-filter>
<action android:name="com.example.servicebind.MyServices" />
</intent-filter>
</service>
控制台输出信息:点击【绑定服务】和【解除服务】
 

Android服务Service的更多相关文章

  1. Android服务Service具体解释(作用,生命周期,AIDL)系列文章-为什么须要服务呢?

    Android服务Service具体解释(作用,生命周期,AIDL) 近期沉迷于上班,没有时间写博客了.解衣入睡,未眠.随起床写一篇博客压压惊! ##我们android系统为什么须要服务Service ...

  2. Android服务(Service)研究

    Service是android四大组件之一,没有用户界面,一直在后台运行. 为什么使用Service启动新线程执行耗时任务,而不直接在Activity中启动一个子线程处理? 1.Activity会被用 ...

  3. Android服务Service总结

    转自 http://blog.csdn.net/liuhe688/article/details/6874378 富貴必從勤苦得,男兒須讀五車書.唐.杜甫<柏學士茅屋> 作为程序员的我们, ...

  4. android服务Service(上)- IntentService

    Android学习笔记(五一):服务Service(上)- IntentService 对于需要长期运行,例如播放音乐.长期和服务器的连接,即使已不是屏幕当前的activity仍需要运行的情况,采用服 ...

  5. Android服务——Service

    服务 Service 是一个可以在后台执行长时间运行操作而不使用用户界面的应用组件.服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行. 此外,组件可以绑定到服务,以与之进行 ...

  6. android 服务service开启和关闭

    startService()方法开启一个服务. 服务只会开启一次,如果服务已经创建,并且没有销毁,多次调用startService方法只会执行onStartCommand方法和onStart方法. 服 ...

  7. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  8. Android服务之Service(其一)

    android中服务是运行在后台的东西,级别与activity差不多.既然说service是运行在后台的服务,那么它就是不可见的,没有界面的东西.你可以启动一个服务Service来播放音乐,或者记录你 ...

  9. Android 服务类Service 的详细学习

    http://blog.csdn.net/vipzjyno1/article/details/26004831 Android服务类Service学习四大组建   目录(?)[+] 什么是服务 服务有 ...

随机推荐

  1. LN : leetcode 215 Kth Largest Element in an Array

    lc 215 Kth Largest Element in an Array 215 Kth Largest Element in an Array Find the kth largest elem ...

  2. Qt获取本机IP地址

    Qt获取本机IP地址: Qt版本:4.8.6 #include <QtNetwork/QNetworkInterface.h> QString ipAddr; QList<QHost ...

  3. How exception works ?

    这是2013年写的一篇旧文,放在gegahost.net上面 http://raison.gegahost.net/?p=28 February 18, 2013 How exception work ...

  4. Python学前基础知识

    Python基础计算机常识:硬件性能:CPU.内存输入设备:鼠标.键盘外部存储设备:硬盘输出设备;显示器.打印机(不算自带)通讯设备:无线网卡----------------------------- ...

  5. strict说明

  6. CAD交互绘制带颜色宽度的直线(网页版)

    用户可以在CAD控件视区任意位置绘制直线. 主要用到函数说明: _DMxDrawX::DrawLine 绘制一个直线.详细说明如下: 参数 说明 DOUBLE dX1 直线的开始点x坐标 DOUBLE ...

  7. 两个div之间的蜜汁间隙

    两个div左右相邻,想让他们紧挨在一起 加了margin:0:padding:0: 不知道为什么还是会有间隙. 然后在两个div的父元素加了:font-size:0: 就终于挨在一起惹.

  8. RNN静态与动态

    静态.多层RNN:import numpy as np import tensorflow as tf # 导入 MINST 数据集 from tensorflow.examples.tutorial ...

  9. JavaScript/JQuery radioButton(单选按钮)练习20190409

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  10. C-基础:函数返回局部变量

    一般的来说,函数是可以返回局部变量的. 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了.因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错.但是如果返回的是局部变量的地 ...