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>