Android学习笔记--服务(Service)
1、服务概述
1、服务是Android四大组件之一,在使用上可以分为本地服务和远程服务,本地服务是指在不影响用户操作的情况下在后台默默的执行一个耗时操作,例如下载,音频播放等。远程服务是指可以供其他应用程序调用的服务。
2、每个服务类都需要在AndroidMainfest.xml中使用<service>标签声明。
3、服务的启动方式分为两种Context.startService()和Context.bindService(), 服务的关闭可以通过外部调用Context.stopService()或者服务自身调用stopself()方法。
4、服务即不是一个单独的进程也不是一个单独的线程,它和应用程序运行在同进程的同线程中。为了能够不影响用户操作该应用程序,通常需要在服务中新建线程处理耗时操作。
2、服务的声明周期
服务有自己的声明周期,常用的回调方法有四个,分别是onCreate()、onStartCommand()、onBind()和onDestroy();
当外界首次调用startService()启动服务的时候,会首先调用onCreate(),然后调用onStartCommand(),如果此时再次调用startService(),则只执行onStartCommand()方法。当调用stopService()或者服务本身调stopself()方法是,服务会调用onDestroy(),停止下来。
我们也可以通过bindService()方法启动服务,调用此方法会首先调用onCreate(),然后调用onBind(),然后会调用实现的Binder中的所有方法。如果此时再次调用bindService()方法,服务不做任何操作。服务停止方法同上
startService()和bindService()方法可同时使用,但onCreate()方法仅会执行一次,当停止服务时,需要调用stopService()和unbindService()。而onDestroy()也是仅调用一次。
3、本地服务的使用
服务使用很简单,新建服务类继承Service(),并在相应的方法中实现相关操作即可,流程如下
1、新建服务类,继承自Service类
public Myservice extends Service {
@override
public Ibinder onBind(Intent intent) {
return null;
}
}
可以看到,Service唯一需要实现的方法就是onBind(),该方法在活动与服务进行通信的时候使用,我们暂时返回null即可
2、实现主要的方法onCreate(), onStartCommand(), onDestroy()
public Myservice extends Service {
@override public Ibinder onBind(Intent intent) {
return null;
}
@override public onCreate() {
super.onCreate();
}
@override public onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override public void run() {
/*do something*/
}
}).start();
return super.onStartCommand(intent, flags, startId);
}
@override public onDestroy() {
super .onDestroy();
}
}
onCreate()会在服务创建的时候调用,onStartCommand()会在服务启动的时候调用,onDestroy()会在服务销毁的时候调用,我们通常将耗时操作防盗onStartCommand()方法中,但是由于服务是和主线程处再同一个线程中,如果我们直接进行耗时操作,则会阻塞用户的前台操作,常用的方法如上,在onStartCommand()中新建一个线程,在线程中执行耗时操作。
另外,Android还提供了另外一种Service机制,对上述新建线程的操作做了封装,它就是IntentService,代码如下
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
/*do something*/
}
@Override
public void onDestroy() {
super .onDestroy();
}
}
我们只需要将耗时操作放在onHandleIntent中即可,Android会自动建立新线程执行操作,需要注意的是需要实现无参的构造函数,在其中调用父类的构造方法。
3、在AndroidMainfest.xml中声明服务
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android: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=".MyService" />
<service android:name=".MyIntentService" />
</application>
4、到此为止,服务类已经建立完成,在活动中启动服务即可
// Intent intent = new Intent(this, MyIntentService.class);
Intent intent = new Intent(this,MyService.class );
startService(intent); stopService(intent);
4、服务与活动的通信
在活动不需要与服务进行通信的情况下,调用startService()方法启动Service,让Service在后台运行即可。但是大多数情况下,活动需要实时了解服务的状态,或者控制服务,就需要使用bindService()方法启动服务,使用Binder进行通信,其流程如下:
1、在服务中新建类继承自Binder,在新建的类中实现公共方法来设置或者获取服务的状态,代码如下
public class Myservice extends Service {
...
class ServiceBinder extends Binder {
public void setServiceStatus() {
...
}
public int getServiceStatus() {
...
}
...
}
}
2、在服务中使用创建新建类的实例,在onBinder中返回
public class Myservice extends Service {
private ServiceBinder serviceBinder = new ServiceBinder();
@override
public IBinder onBind(Intent intent) {
return serviceBinder;
}
…
}
3、在活动中绑定服务,获取服务类中的Binder实例,与服务通信
public class MainActivity extends Activity {
private MyService.ServiceBinder serviceBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override public void onServiceDisconnected(ComponentName name) {
...
}
@Override public void onServiceConnected(ComponentName name, IBinder service) {
serviceBinder = (MyService.serviceBinder)service;
...
}
};
...
}
当活动调用bindService()方法,与服务绑定成功后,会自动回调OnServiceConnected方法。当与服务解绑定后,会自动回调onServiceDisconnected;
可以看到在onServiceConnected方法中,我们获取了MyService中的Binder类实例ServiceBinder,这样的话我们就可以通过serviceBinder对服务进行设置或状态获取操作。
5、服务示例源码
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
> <Button
android:id="@+id/start_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Service" /> <Button
android:id="@+id/stop_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Stop Service" /> <Button
android:id="@+id/bind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Bind Service" /> <Button
android:id="@+id/unbind_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Unbind Service" /> <Button
android:id="@+id/start_intent_service"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start IntentService" /> </LinearLayout>
MainActivity.java
package com.example.servicetest; import android.app.Activity;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button; public class MainActivity extends Activity implements OnClickListener { private Button startService;
private Button stopService;
private Button bindService;
private Button unbindService;
private Button intentService; private MyService.DownloadBinder downloadBiner; private ServiceConnection connection = new ServiceConnection() { public void onServiceDisconnected(android.content.ComponentName name) {
…
}; public void onServiceConnected(android.content.ComponentName name, android.os.IBinder service) {
downloadBiner = (MyService.DownloadBinder)service;
downloadBiner.startDownload();
downloadBiner.getProgress();
};
}; @Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); startService = (Button)findViewById(R.id.start_service);
stopService = (Button)findViewById(R.id.stop_service);
bindService = (Button)findViewById(R.id.bind_service);
unbindService = (Button)findViewById(R.id.unbind_service);
intentService = (Button)findViewById(R.id.start_intent_service); startService.setOnClickListener(this);
stopService.setOnClickListener(this);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
intentService.setOnClickListener(this);
} @Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.start_service:
Intent startIntent = new Intent(this, MyService.class);
startService(startIntent);
break;
case R.id.stop_service:
Intent stopIntent = new Intent(this, MyService.class);
stopService(stopIntent);
break;
case R.id.bind_service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
case R.id.start_intent_service:
Intent intentService = new Intent(this, MyIntentService.class);
startService(intentService);
break;
default:
break;
}
}
}
MyIntentService.java
package com.example.servicetest; import android.app.IntentService;
import android.content.Intent;
import android.util.Log; public class MyIntentService extends IntentService { public MyIntentService() {
// TODO Auto-generated constructor stub
super("MyIntentService");
} @Override
protected void onHandleIntent(Intent intent) {
// TODO Auto-generated method stub
Log.d("MyIntentService", "Thread id is " + Thread.currentThread().getId());
} @Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
MyService.java
package com.example.servicetest; import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log; public class MyService extends Service { private DownloadBinder mBinder = new DownloadBinder(); class DownloadBinder extends Binder { public void startDownload() {
// TODO Auto-generated method stub
Log.d("Myservice", "startDownlaod executed");
} public int getProgress() {
Log.d("Myservice", "getProgress executed");
return 0;
} } @Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
Log.d("Myservice", "onBind");
return mBinder;
} @Override
public void onCreate() {
// TODO Auto-generated method stub
Log.d("Myservice", "onCreate");
super.onCreate();
} @Override
public int onStartCommand(Intent intent, int flags, int startId) {
// TODO Auto-generated method stub
Log.d("Myservice", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
} @Override
public void onDestroy() {
// TODO Auto-generated method stub
Log.d("Myservice", "onDestroy");
super.onDestroy();
}
}
效果图如下

可点击各个按钮,查看logcat,了解服务的声明周期,startService()和onBind()的混合调用,IntentService和Binder的使用方法。
远程服务尚未学习,待续…
本文参考《Android第一行代码》中的第九章
Android学习笔记--服务(Service)的更多相关文章
- android学习笔记56——Service
Service四大组件之一,需要在AndroidMainfest.xml中添加相关配置,运行于后台,不与用户进行交换,没有UI... 配置时可通过<intent-filter.../>元素 ...
- Android学习笔记之Service
与服务通信 用bindservice 而startservice并无通信条件. service 为android为系统服务,所以程序员无法new出来,只能建立服务,共其他组件使用. package c ...
- 【转】 Pro Android学习笔记(七七):服务(2):Local Service
目录(?)[-] Local service代码 调用Local ServiceLocal Service client代码 AndroidManifestxml定义Serviceacitivty的l ...
- 【转】 Pro Android学习笔记(七八):服务(3):远程服务:AIDL文件
目录(?)[-] 在AIDL中定义服务接口 根据AIDL文件自动生成接口代码 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.n ...
- 【转】 Pro Android学习笔记(七六):服务(1):local和remote
文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件.转载须注明出处:http://blog.csdn.net/flowingflying/ Android提供服务,服务是运行在后台的 ...
- 【转】 Pro Android学习笔记(七十):HTTP服务(4):SOAP/JSON/XML、异常
目录(?)[-] SOAP JSON和XMLPullParser Exception处理 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog. ...
- 【转】 Pro Android学习笔记(六八):HTTP服务(2):HTTP POST
目录(?)[-] 找一个测试网站 HTTP POST小例子 上次学习了HTTP GET请求,这次学习一下HTTP POST. 找一个测试网站 小例子好写,但要找个测试网站就有些麻烦,一下子无从入手,都 ...
- 【转】 Pro Android学习笔记(七四):HTTP服务(8):使用后台线程AsyncTask
目录(?)[-] 5秒超时异常 AsyncTask 实现AsyncTask抽象类 对AsyncTask的调用 在哪里运行 其他重要method 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注 ...
- 【转】 Pro Android学习笔记(七五):HTTP服务(9):DownloadManager
目录(?)[-] 小例子 保存在哪里下载文件信息设置和读取 查看下载状态和取消下载 文章转载只能用于非商业性质,且不能带有虚拟货币.积分.注册等附加条件,转载须注明出处:http://blog.csd ...
随机推荐
- 从反编译的角度去观察C#6.0
1. 自动属性初始化 (Initializers for auto-properties) 1.1 C#6.0 之前的写法 public class FirstExperience { private ...
- Enable-Migrations 在应用程序配置文件中找不到xx连接字符串
在解决方案中有多个项目时,使用Enable-Migrations 命令进行数据迁移时,出现以下错误: 尝试在Enable-Migrations 命令中指定-projectName也不行,最后将要操作的 ...
- FineUI表单验证
自动编码文本 默认情况下,Label的EncodeText属性为true,会对文本中的HTML进行编码.当然我们也可以设置EncodeText=false,从而将HTML片段赋值给Text属性,请看这 ...
- Sql 函数大全 (更新中...由难到简
1.字符处理类: 1.1 指定指定字符输出的次数 ) 结果:1a1a1a1a1a (5个1a)
- python进行base64编解码
[转] 直接上代码 import base64 fin = open(r"D:\2.zip", "rb") fout = open(r"D:\2.x. ...
- Java 中字符串的子串搜索
基友前两天参加了阿里的实习生面试,问了个问题,就是关于字符串的子串搜索的问题.想想实现方式无非就是两层循环,但是 java 中是有现成实现的,于是我就去查查源码,看看 java 语言怎么实现这个的,发 ...
- Hdu1095
#include <stdio.h> int main() { int a,b; while(scanf("%d %d",&a,&b)!=EOF){ p ...
- 【好程序员笔记分享】——iOS开发之纯代码键盘退出
-iOS培训,iOS学习-------型技术博客.期待与您交流!------------ iOS开发之纯代码键盘退出(非常简单) iOS开发之纯代码键盘退出 前面说到了好几次关于键盘退出的,但 ...
- JS window对象的top、parent、opener含义
.top 该变更永远指分割窗口最高层次的浏览器窗口.如果计划从分割窗口的最高层次开始执行命令,就可以用top变量. .opener opener用于在window.open的页面引用执行该window ...
- HDU 2222 Keywords Search (AC自动机)
题意:就是求目标串中出现了几个模式串. 思路:用int型的end数组记录出现,AC自动机即可. #include<iostream> #include<cstdio> #inc ...