Android 四大组件之一Service
2014-04-04 11:42
405 查看
Android的四大组件包括Activity,Service,contentProvider,broadcast receiver。
Service和Activity是比较像的,都需要继承Service,都需要在AndroidMainfest.xml中注册,在其中的inter-filter中配置可以响应的Intent事件,都是从context中派生出来的。区别在于Service一直运行在后台,没有自己的界面。
启动Service:
1. 用Context的startService方法,访问者与Service没有关联,即使访问者退出了Service仍然继续运行。
2. 用Context的bindService方法,访问者与Service绑定在一起,访问者一旦退出,Service也退出了。并且可以进行数据交换。
用第一种方法启动如下:
使用第二种方法时:
Service类实现步骤:
1. 新建IBinder子类MyBinder,在其中可以添加方法来控制Service类中的数据,以后Activity会调用这些方法。
2. 重写public IBinder onBind(Intent intent),来返回Service中新建的MyBinder实例。
Activity中实现步骤:
1. 实现一个ServiceConnection对象,在其中的连接时触发的事件函数中获取返回的MyBinder的实例。
2. bindService(Intent service,ServiceConnect,flag)
3. 通过调用MyBinder中的方法即可以获取Service中的数据。
注意:
当访问者主动调用unBindService()方法来断开连接时不会触发ServiceConnect中的onServiceDisconnect方法。
当BindService一个已经启动的Service,系统只是把Service的IBinder对象返回来,unbindService时只是把切断了联系,并没有停止该组件。
疑惑:
调用unbindService后,仍可以去用Mybinder的实例去掉用里面的方法。关键是Service已经onDestory了,方法怎么还能访问里面的变量呢。
可能是这样的,onDestory只是通知了系统但Service并没有被销毁。如果没有进行ServiceConnection去掉用就会出错。
示例
Service:
Activity
==============================================================================================
Once this method executes, the service is started and can run in the background indefinitely. If you implement this, it is your responsibility to stop the service when its work is done, by calling
or
returns, recreate the service and call
the last intent. Instead, the system calls
there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
在用StartService启动Service时,onStartCommand的返回值如果是START_STICKY的话,比如在onStartCommand中是耗时任务导致ANR,被系统kill掉,这是这个Service还会再起来。 先运行onCreate,在运行onStartCommand
每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,这个方法return 一个int值,return 的值有四种:
START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
Service和Activity是比较像的,都需要继承Service,都需要在AndroidMainfest.xml中注册,在其中的inter-filter中配置可以响应的Intent事件,都是从context中派生出来的。区别在于Service一直运行在后台,没有自己的界面。
启动Service:
1. 用Context的startService方法,访问者与Service没有关联,即使访问者退出了Service仍然继续运行。
2. 用Context的bindService方法,访问者与Service绑定在一起,访问者一旦退出,Service也退出了。并且可以进行数据交换。
用第一种方法启动如下:
final Intent intent = new Intent(); intent.setAction("FIRST_SERVICE"); // <action android:name="FIRST_SERVICE" > startService(intent); // 启动 stopService(intent); // 停止
使用第二种方法时:
Service类实现步骤:
1. 新建IBinder子类MyBinder,在其中可以添加方法来控制Service类中的数据,以后Activity会调用这些方法。
2. 重写public IBinder onBind(Intent intent),来返回Service中新建的MyBinder实例。
Activity中实现步骤:
1. 实现一个ServiceConnection对象,在其中的连接时触发的事件函数中获取返回的MyBinder的实例。
2. bindService(Intent service,ServiceConnect,flag)
3. 通过调用MyBinder中的方法即可以获取Service中的数据。
注意:
当访问者主动调用unBindService()方法来断开连接时不会触发ServiceConnect中的onServiceDisconnect方法。
当BindService一个已经启动的Service,系统只是把Service的IBinder对象返回来,unbindService时只是把切断了联系,并没有停止该组件。
疑惑:
调用unbindService后,仍可以去用Mybinder的实例去掉用里面的方法。关键是Service已经onDestory了,方法怎么还能访问里面的变量呢。
可能是这样的,onDestory只是通知了系统但Service并没有被销毁。如果没有进行ServiceConnection去掉用就会出错。
示例
Service:
package com.bindservice; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; /***************************************** * 使用BindService启动Service时,需要实现onBind方法 * * IBinder相当于Service中的内部钩子,绑定时将返回给其他组件 *****************************************/ public class BindService extends Service { private int count; private boolean quit; // 定义onBind方法返回的对象 private MyBinder binder = new MyBinder(); private String TAG = "BindServiceDemo"; // 必须实现的方法 @Override public IBinder onBind(Intent intent) { // TODO Auto-generated method stub Log.i(TAG, "=== onBind ==="); return binder; } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "=== onCreate ==="); // 启动一个线程动态修改count的值 new Thread() { @Override public void run() { while (!quit) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } count++; } } }.start(); } // 解除绑定时调用的方法 public boolean onUnbind(Intent intent) { Log.i(TAG, "=== onUnbind ==="); System.out.println("=== onUnbind ==="); return true; } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "=== onDestroy ==="); this.quit = true; } public class MyBinder extends Binder { public int getCount() { // 获取Service的运行状态 return count; } } }
Activity
package com.bindservice; import android.os.Bundle; import android.os.IBinder; import android.app.Activity; import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; /************************************************ * 主要是借助IBind实现的Activity与Service之间通信。 * * 在Activity中实现ServiceConnect用于建立连接时回调。从而能够获取新建的Service的IBinder对象 * 通过IBinder中的方法(在Service中已经实现)来控制Service中的数据 * ***********************************************/ public class MainActivity extends Activity { // 定义启动Service的IBind对象 BindService.MyBinder binder; // 定义一个ServiceConnect 对象 private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceDisconnected(ComponentName name) { // TODO Auto-generated method stub } // 当Activity与Service连接时回调该方法 @Override public void onServiceConnected(ComponentName name, IBinder service) { // TODO Auto-generated method stub // 获取Service的onBind方法返回的MyBind对象 binder = (BindService.MyBinder) service; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button bindbutton = (Button) findViewById(R.id.bindButton); Button unbindButton = (Button) findViewById(R.id.unbindButton); Button statusButton = (Button) findViewById(R.id.statusButton); final Intent intent = new Intent(); intent.setAction("BIND_SERVICE"); bindbutton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // 绑定指定的Service bindService(intent, conn, Service.BIND_AUTO_CREATE); } }); unbindButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // 解除绑定 unbindService(conn); } }); statusButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub // 获取Service的count的值 Toast.makeText(MainActivity.this, "BindService count: " + binder.getCount(), Toast.LENGTH_SHORT).show(); } }); } @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; } }
==============================================================================================
onStartCommand()The system calls this method when another component, such as an activity, requests that the service be started, by calling
startService().
Once this method executes, the service is started and can run in the background indefinitely. If you implement this, it is your responsibility to stop the service when its work is done, by calling
stopSelf()
or
stopService(). (If you only want to provide binding, you don't need to implement this method.)
START_STICKYIf the system kills the service after
onStartCommand()
returns, recreate the service and call
onStartCommand(), butdo not redeliver
the last intent. Instead, the system calls
onStartCommand()with a null intent, unless
there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting for a job.
在用StartService启动Service时,onStartCommand的返回值如果是START_STICKY的话,比如在onStartCommand中是耗时任务导致ANR,被系统kill掉,这是这个Service还会再起来。 先运行onCreate,在运行onStartCommand
每次调用startService(Intent)的时候,都会调用该Service对象的onStartCommand(Intent,int,int)方法,这个方法return 一个int值,return 的值有四种:
START_STICKY:如果service进程被kill掉,保留service的状态为开始状态,但不保留递送的intent对象。随后系统会尝试重新创建service,由于服务状态为开始状态,所以创建服务后一定会调用onStartCommand(Intent,int,int)方法。如果在此期间没有任何启动命令被传递到service,那么参数Intent将为null。
START_NOT_STICKY:“非粘性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启该服务。
START_REDELIVER_INTENT:重传Intent。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统会自动重启该服务,并将Intent的值传入。
START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,但不保证服务被kill后一定能重启。
相关文章推荐
- Android里面的命名规范
- Android中Activity的四种启动模式详解(转)
- android选择图片或拍照图片上传到服务器(包括上传参数) (转)
- android 通知
- 亲测ubuntu下android源码的下载
- Android ViewPager实例代码介绍。
- Fragments (Android官方文档中文版) (转)
- Android中保存图片的两种方式
- 使用apkplug实现Android客户端插件化
- android 文件转base64,Base64转文件
- Load image/css/js locally from Webview in Android Mobile app
- android数据读写
- Android 数据库升级中数据保持和导入已有数据库(转)
- <摘>android手机自带浏览器无法识别apk文件
- Android将Activity打成jar包供第三方调用(解决资源文件不能打包的问题)
- 【Cursor】Android 中关于 【Cursor】 类的介绍
- android:如果手机安装了app则打开一个activity,如果没有安装则去到android market如何在HTML页面实现
- Android中用文件初始化sqlite 数据库的文(一) (转)
- Android开发环境搭建
- Android中的颜色设置