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 ...
随机推荐
- MySql 事务+异常处理+异常抛出
-- 测试用表 -- innodb 支持事务 CREATE TABLE `tb_test` ( `id` ) NOT NULL AUTO_INCREMENT, `name` ) NOT NULL, P ...
- .NET程序猿 - 提升幸福感的组件一览
1.Newtonsoft.Json.net 操作JSON最简便的方式. .Net 3.5开始,Framework集成Json序列化器:JavaScriptSerializer,然而Json.net给 ...
- CocoaPod安装
http://www.360doc.com/content/14/0309/10/11029609_358970353.shtml http://www.bubuko.com/infodetail-4 ...
- (四)CodeMirror - API
内容相关 cm.getValue() cm.setValue() cm.getRange() editor.getRange({line:1},{line:2}) // 获取内容块字符 cm.repl ...
- 6 log4j -- 一个笨的使用方法
log4j的说明: Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件,甚至是套接口服务器.NT的事件记录器.UNIX Syslog ...
- vector -1
vector的特色有支持随机存取,在集合尾端增删元素很快,但是在集合中间增删元素比较费时. vector以模板(泛型)方式实现,可以保存任意类型的变数,包括使用者自定义的资料型态,例如:它可以是放置整 ...
- WordPress插件制作教程(二): 编写一个简单的插件
上一篇说到了如何创建一个插件,我想大家看了之后一定会有所收获,这一篇简单给大家写一个插件样例,让大家有一个基本的印象.这个插件的样例就是当你激活这个插件后会在你的每篇文章中插入一段自己定义好的内容,比 ...
- Service Lane
Link https://www.hackerrank.com/challenges/service-lane def main(): n, t = map(int, raw_input().spli ...
- hadoop集群之HDFS和YARN启动和停止命令
假如我们只有3台linux虚拟机,主机名分别为hadoop01.hadoop02和hadoop03,在这3台机器上,hadoop集群的部署情况如下: hadoop01:1个namenode,1个dat ...
- c# post方式发送请求
public static bool CheckNew(string serverIP) { bool passed = false; try { string url = string.Format ...