Service
概念:
文档地址 :http://developer.android.com/reference/android/app/Service.html
Service 是用来执行长时间后台功能的组件
Service 是在主线程中,若Service中使用长时间占用CPU的功能则需要使用多线程.
1 创建一个Service
首先建立一个继承android.app.Service的类
再去AndroidManifest.xml中的Application结点下建立一个Service
<service android:name="cn.zyh.usingservice.EchoService"></service>
这个有两种方法.
1 )是直接将这行写入Xml文件的<Application> 结点下
2) 是 使用android提供的图形化界面
在Application Nodes这栏点Add,添加一个Service结点.
再在右边的Name属性中写上名称.
2 启动Service
首先创建一个代表该动作的Intent
serviceIntent = new Intent(this, EchoService.class);
启动和运行分别使用 Context.startService()
and Context.bindService()
.
启动服务 startService(serviceIntent);
停止服务 stopService(serviceIntent);
当启动后 可以在手机的设置-应用程序-正在运行的服务中看到Service
使用StartService启动的服务 ,即使应用退出,Service仍然会继续执行.
启动和停止Service分别会调用Service类中的onCreate和onDestory方法
3 绑定服务
使用bindService启动, 可以让服务随着应用启动和关闭.
也可以先startService 再 bindService.
绑定服务的好处是可以让使用服务的对象调用服务中的方法.
使用 Context.bindService() 和 Context.unBindService() 来绑定和解绑服务.
这两个方法分别会调用Service对象的onCreate onBind方法和 onUnbind onDestory方法
bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
unbindService(this);
注意bindService 的第二个参数是一个 ServiceConnection接口对象,我们一般让你的Activity实现ServiceConnection.
需要实现2个方法
@Override
public void onServiceConnected(ComponentName name, IBinder binder)
{
// Service 成功连接后
System.out.println("onServiceConnected");
}
@Override
public void onServiceDisconnected(ComponentName name)
{
// Service 崩溃时触发,不是通过unBind方法.
}
若是你的Service对象中的onBind()方法返回null,是不会触发onServiceConnected函数的.
onBind是Service对象中的一个需要实现的方法 ,返回值是IBinder对象,但是IBinder接口已经有一个实现类了Binder.
所以返回一个继承Binder的对象就行了.
@Override
public IBinder onBind(Intent intent)
{
System.out.println("onBind");
return echoServiceBinder;
}
关于解绑后服务还继不继续运行,根据网友的讨论我再验证了下是这样的:
有三种情况:如果直接使用服务,则没有必要进行绑定,但是如果要使用服务里面的方法,则要进行绑定。具体的启动情况有下:
1.当启动时,单独调用bindService方法,在unbindService后,会执行service的onUnbind,在执行onDestroy方法。
2.当启动时,先调用startService,在调用bindService方法后,在unbindService后,会执行service的onUnbind,不会执行onDestroy方法。除非你在执行stopService.
3. 先调用startService,在调用stopService,会执行service的onDestroy方法。
另外就是无论你是通过startService还是bindService启动的服务,都只会存在一个对象,多次启动或者多次绑定是没有副作用的.
4 调用Service的函数
我们绑定服务就是为了调用服务中的方法,
@Override
public IBinder onBind(Intent intent)
{
System.out.println("onBind");
return echoServiceBinder;
}
关键就是通过service中的onBind()方法返回的对象来调用
建立一个内部类 ,使其有一个公开的方法 返回外部类对象
public class EchoServiceBinder extends Binder
{
public EchoService getService()
{
return EchoService.this;
}
}
在绑定service的Activity (实现ServiceConnection类 ) 中重写onServiceConnected方法
@Override
public void onServiceConnected(ComponentName name, IBinder binder)
{
System.out.println("onServiceConnected");
this.service = ((EchoServiceBinder) binder).getService();
}
这样 就获得了Service对象
调用其中方法那就不用说了.
=======================================
Activity
package cn.zyh.usingservice; import cn.zyh.usingservice.EchoService.EchoServiceBinder; 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.support.v4.widget.SimpleCursorAdapter.ViewBinder; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener, ServiceConnection { private Button btnStartService, btnStopService, btnBindService, btnUnbindService, btnGetCountNum; private Intent serviceIntent; private EchoService service; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnStartService = (Button) findViewById(R.id.btnStartSer); btnStopService = (Button) findViewById(R.id.btnStopSer); btnStartService.setOnClickListener(this); btnStopService.setOnClickListener(this); serviceIntent = new Intent(this, EchoService.class); btnBindService = (Button) findViewById(R.id.bind); btnUnbindService = (Button) findViewById(R.id.unbind); btnBindService.setOnClickListener(this); btnUnbindService.setOnClickListener(this); btnGetCountNum = (Button) findViewById(R.id.getCount); btnGetCountNum.setOnClickListener(this); } @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; } @Override public void onClick(View v) { switch(v.getId()) { case R.id.btnStartSer: startService(serviceIntent); break; case R.id.btnStopSer: stopService(serviceIntent); service = null; break; case R.id.bind: bindService(serviceIntent, this, Context.BIND_AUTO_CREATE); break; case R.id.unbind: unbindService(this); service = null; break; case R.id.getCount: if (service != null) { System.out.println("count:" + service.getNum()); } default: break; } } @Override public void onServiceConnected(ComponentName name, IBinder binder) { // Service成功连接后 System.out.println("onServiceConnected"); this.service = ((EchoServiceBinder) binder).getService(); } @Override public void onServiceDisconnected(ComponentName name) { System.out.println("onServiceDisConnected"); // Service 被关闭或崩溃时触发 } }Service
package cn.zyh.usingservice; import java.util.Timer; import java.util.TimerTask; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; public class EchoService extends Service { @Override public void onCreate() { System.out.println("ONCREATE"); super.onCreate(); startTimer(); } @Override public void onDestroy() { System.out.println("ONDESTORY"); super.onDestroy(); stopTimer(); } @Override public boolean onUnbind(Intent intent) { System.out.println("unBind"); return super.onUnbind(intent); } private final EchoServiceBinder echoServiceBinder = new EchoServiceBinder(); public class EchoServiceBinder extends Binder { public EchoService getService() { return EchoService.this; } } @Override public IBinder onBind(Intent intent) { return echoServiceBinder; } private Timer timer = null; private TimerTask task; private int i = 0; public void startTimer() { if (timer == null) { timer = new Timer(); task = new TimerTask() { @Override public void run() { i++; } }; } timer.schedule(task, 1000, 1000); // 延迟1秒 每隔1秒执行一次 } public void stopTimer() { task.cancel(); if (timer != null) { timer.cancel(); } task = null; timer = null; } public int getNum() { return i; } }
AndroidManifest.XML
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.zyh.usingservice" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="8" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme"> <activity android:name="cn.zyh.usingservice.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="cn.zyh.usingservice.EchoService"></service> </application> </manifest>