引言:初学Android的时候,对Service是草草了之,现在反过来复习,才发现自己有很多知识没有掌握,在这里总结一下。Service是Android的四大组件之一,是Android中实现程序后台运行最合适的解决方案之一,非常适合被用于去执行那些不需要和用户界面交互而且要求长期运行的任务。
public class MyService extends Service {
@Override
public IBinder onBind(Intent intent) {
return null;
}
//每次服务启动时都会调用
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
//在服务第一次创建的时候调用,放只需要执行一次的代码
@Override
public void onCreate() {
super.onCreate();
}
//服务销毁的时候调用
@Override
public void onDestroy() {
super.onDestroy();
}
}
<service android:name=".MyService" android:enabled="true" android:exported="true"></service>
//启动服务
@Override
public void onClick(View v) {
startService(new Intent(MainActivity.this, MyService.class));
}
//停止服务
@Override
public void onClick(View v) {
stopService(new Intent(MainActivity.this,MyService.class));
}
@Override
public void onClick(View v) {
bindService(new Intent(MainActivity.this,MyService.class), MainActivity.this, Context.BIND_AUTO_CREATE);
}
@Override
public void onClick(View v) {
unbindService(MainActivity.this);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("miomin", "服务连接成功");
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("miomin", "服务连接关闭");
}
想要更详细的了解Service生命周期,可以参考这篇博文,Activity和Service的生命周期(图)
Android5.0以后,禁止使用隐式Intent启动Service,必须使用显式意图,对于跨引用启动,我们必须指明被作为启动对象的Service的完整包名。
//使用包名构造显示意图
private Intent intent = new Intent();
intent.setComponent(new ComponentName("scu.miomin.com.learnaidl", "scu.miomin.com.learnaidl.AppService"));
switch (id) {
case R.id.btnStartService:
startService(intent);
break;
case R.id.btnStopService:
stopService(intent);
break;
case R.id.btnBindService:
bindService(intent, MainActivity.this,Context.BIND_AUTO_CREATE);
break;
case R.id.btnUnbindService:
unbindService(MainActivity.this);
break;
}
创建一个专门的Binder对象来构造Service与Activity的通信通道,在onServiceConnected()回调中接受由目标Service的unbind()方法返回的Binder对象,可以直接对Binder对象的方法进行操作,可以传入参数,返回数据等等;如果需要实现Service实时返回下载进度的功能,可以在Service中构建回调,具体的可以参考如下例子,相信大家都看得懂。
public class MyService extends Service {
// 控制任务是否执行
private boolean serviceRunning = false;
private String data = "this is default message";
public void setCallback(Callback callback) {
mCallback = callback;
}
@Override
public IBinder onBind(Intent intent) {
return new MyBinder();
}
public class MyBinder extends Binder {
public void setData(String newData) {
MyService.this.data = newData;
}
public MyService getMyService() {
return MyService.this;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onCreate() {
super.onCreate();
serviceRunning = true;
new Thread() {
@Override
public void run() {
int i = 0;
while (serviceRunning) {
i++;
String str = i + ":" + data;
if (mCallback != null)
mCallback.onDataChange(str);
Log.i("miomin", str);
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onDestroy() {
super.onDestroy();
serviceRunning = false;
}
private Callback mCallback;
public interface Callback {
void onDataChange(String date);
}
}
public class MainActivity extends AppCompatActivity implements ServiceConnection {
EditText etData;
private MyService.MyBinder myBinder;
private TextView tvOut;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.startService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(new Intent(MainActivity.this, MyService.class));
}
});
findViewById(R.id.stopService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopService(new Intent(MainActivity.this, MyService.class));
}
});
findViewById(R.id.bindService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bindService(new Intent(MainActivity.this, MyService.class), MainActivity.this, Context.BIND_AUTO_CREATE);
}
});
findViewById(R.id.unbindService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
unbindService(MainActivity.this);
}
});
etData = (EditText) findViewById(R.id.etData);
findViewById(R.id.btnSyncData).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (myBinder != null) {
myBinder.setData(etData.getText().toString());
}
}
});
tvOut = (TextView) findViewById(R.id.tvOut);
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("miomin", "服务连接成功");
myBinder = (MyService.MyBinder) service;
myBinder.getMyService().setCallback(new MyService.Callback() {
@Override
public void onDataChange(String date) {
Message message = Message.obtain();
Bundle bundle = new Bundle();
bundle.putString("data", date);
message.setData(bundle);
handler.sendMessage(message);
}
});
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tvOut.setText(msg.getData().getString("data"));
}
};
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("miomin", "服务连接关闭");
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(MainActivity.this);
}
}
AIDL接口文件,和普通的接口内容没有什么特别,只是它的扩展名为.aidl。如果想要使用AIDL进行跨进程通信,需要在两个工程的src文件夹下建立一模一样的AIDL文件,并且保证包名相同。
interface IAppServiceAidlInterface {
/** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */
void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
double aDouble, String aString);
void setData(String data);
List<Car> getAllCar();
}
@Override
public IBinder onBind(Intent intent) {
return new IAppServiceAidlInterface.Stub() {
@Override
public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
}
@Override
public void setData(String data) throws RemoteException {
AppService.this.data = data;
}
@Override
public List<Car> getAllCar() throws RemoteException {
return null;
}
};
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
IAppServiceAidlInterface AIDLBinder = IAppServiceAidlInterface.Stub.asInterface(service);
}