这片文章对service总结的不错,
什么是服务
服务是一个没有可视化界面的组件,它可以在后台长期运行并进行各种操作。
服务的创建
我们只需要继承Service类并实现相应的方法即可创建服务
要想启动服务,还得在AndroidManifest中注册服务
服务类的示例代码
package com.whathecode.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.widget.Toast;
public class ExtendsionService extendsService
{
/**
* 当服务第一次被创建的时候调用此方法
*/
@Override
publicvoid onCreate()
{
super.onCreate();
Toast.makeText(getBaseContext(),"服务被创建了", Toast.LENGTH_SHORT).show();
}
/**
* 当通过startService方法启动服务时此方法被调用
*/
@Override
publicint onStartCommand(Intent intent,int flags, int startId)
{
Toast.makeText(getBaseContext(),"服务被启动了", Toast.LENGTH_SHORT).show();
returnsuper.onStartCommand(intent, flags, startId);
}
@Override
publicIBinder onBind(Intent intent)
{
returnnull;
}
@Override
publicvoid onDestroy()
{
super.onDestroy();
}
}
使用startService启动服务
主界面的逻辑代码:
package com.whathecode.servicedemo;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extendsActivity
{
Intent service =null;
@Override
protectedvoid onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建服务
service =new Intent(this, ExtendsionService.class);
}
publicvoid start(View view)
{
//启动服务
startService(service);
}
publicvoid stop(View view)
{
//停止服务
stopService(service);
}
}
注册服务:
1
|
<
service
android:name="com.whathecode.servicedemo.BackgroundService"></
service
>
|
运行效果:
注意:
当我们第一次点击启动服务按钮的时候,onCreate方法和onStartCommand方法依次执行,
但在第二次点击启动服务按钮的时候,这个服务已经处于运行状态,onCreate方法不再执行第二次,
而onStartCommand方法总是在调用startService启动服务的时候执行。
onDestroy方法在stopService方法被调用后执行。
除了使用startService方法启动服务外,我们还可以使用Bind的方式启动服务。
前者和后者的不同在于:
服务的生命周期不依赖于启动者。服务被启动后一直在后台运行直到调用stopService被停止。
使用Bind方式启动服务,服务的生命周期依赖于启动者。即服务在启动者退出后自动销毁。
使用Bind方式启动服务
主要使用bindService方法启动服务,unbindService方法销毁服务。
使用此方式启动服务的好处是,bind定成功的时候服务返回一个IBinder对象,
我们可以通过在服务类里面实现这个对象,从而访问服务里面的具体方法。
从而达到和服务沟通的目的。
注意:
我们不能以直接实例化服务的方式调用里面的方法。
另外:
如果在退出服务的时候没有解绑,那么程序就会抛出异常IllegalArgumentException异常。
因此,每次调用bindService启动服务,完成后需要退出服务都需要使用unbindService 解绑。
示例代码:
package com.whathecode.servicedemo;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.view.View;
public class MainActivity extendsActivity
{
Intent service =null;
IReceptionist rpst;
/**
* bindService和unbindService方法使用的参数
*/
privateServiceConnection conn = newServiceConnection()
{
//此方法在服务连接被意外终止的时候被调用,
@Override
publicvoid onServiceDisconnected(ComponentName name)
{
}
//当服务被连接上的时候自动调用这个方法,第二个参数是服务类onBind方法中返回的对象
@Override
publicvoid onServiceConnected(ComponentName name, IBinder service)
{
rpst = (IReceptionist) service;
rpst.callExtendsionNumber();
}
};
@Override
protectedvoid onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//创建服务
service =new Intent(this, ExtendsionService.class);
}
publicvoid start(View view)
{
//启动服务
startService(service);
}
publicvoid stop(View view)
{
//停止服务
stopService(service);
}
publicvoid bind(View view)
{
//绑定服务
bindService(service, conn , BIND_AUTO_CREATE);
}
publicvoid unBind(View view)
{
//解绑服务
unbindService(conn);
}
}
继承ServiceBinder对象,并实现自定义接口:
通过这个方式,我们可以暴露只需要的方法,实现代码的保护。
IReceptionist接口代码:
package com.whathecode.servicedemo;
public interface IReceptionist
{
publicvoid callExtendsionNumber();
}
ExtendsionService服务类代码:
package com.whathecode.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class ExtendsionService extendsService
{
privatestatic final String TAG = "ExtendsionService";
/**
* 当服务第一次被创建的时候调用此方法
*/
@Override
publicvoid onCreate()
{
super.onCreate();
Toast.makeText(getBaseContext(),"服务被创建了", Toast.LENGTH_SHORT).show();
}
/**
* 当通过startService方法启动服务时此方法被调用
*/
@Override
publicint onStartCommand(Intent intent,int flags, int startId)
{
Toast.makeText(getBaseContext(),"服务被启动了", Toast.LENGTH_SHORT).show();
returnsuper.onStartCommand(intent, flags, startId);
}
@Override
publicIBinder onBind(Intent intent)
{
returnnew ServiceBinder();
}
@Override
publicvoid onDestroy()
{
Toast.makeText(getBaseContext(),"服务被销毁了", Toast.LENGTH_SHORT).show();
Log.d(TAG,"服务被销毁了");
super.onDestroy();
}
publicvoid putExtendsion()
{
Toast.makeText(getBaseContext(),"正在帮你转接分机", Toast.LENGTH_SHORT).show();
}
/**
*
* 继承Binder并实现IReceptionist接口
* 继承Binder类的目的是onBind方法中需要返回这个类型的对象
*
* 实现IReceptionist接口是暴露方法的需要
*/
privateclass ServiceBinder extends Binder implements IReceptionist
{
publicvoid callExtendsionNumber()
{
putExtendsion();
}
privatevoid otherMethod()
{
}
}
}
运行效果:
注意看上图,我们在按下返回键的时候,Activity被销毁,由它启动的服务也跟着被销毁。
这样的服务貌似作用不大,有没有办法在退出Activity的时候不退出服务呢?
答案是有的:Android允许我们先启动一个服务,然后再调用bindService绑定到服务,
这样,我们既可以达到和服务沟通的目的,也可以使服务长期在后台运行。
看下图:
通过下面的图,就可以更清楚地理解上面代码的工作原理: