Service 绑定
2016-12-03 23:03
246 查看
一、Activity之间协调:
1.当在同一个进程中从一个Activity开启另一个Activity时,它们的生命周期方法是这样的:
A Activity 开启了 B Activity:
A调用onPause(),B调用onCreate(),onStart(),onResume(),此时B Activity与用户进行交互,
然后A Activity的onStop()方法调用,所以如果两个界面共享一些数据,如存储在数据库
中的数据,则应该在A Activity的onPause()方法中保存数据,而不是onStop()方法。
2.横竖屏切换
当用户旋转屏幕,切换屏幕状态时,会创建新的Activity实例。
二、Service的onStartCommand()方法返回值
1.一个服务的onStartCommand()方法必须返回一个整数值,这个整数值描述了在系统因为内存等问题杀死
该服务后,该服务在系统获得了可用内存等资源如何继续该服务,返回值必须为以下其中之一:
a.START_NOT_STICKY:不要重新创建该服务,除非有意图重新开启该服务;
b.START_STICKY:用一个空的意图重新创建该服务,如果有新的意图,则用新的意图开启,适用于媒体播放器等逻辑;
c.START_REDELIVER_INTENT:用上一次开启该服务的意图重启该服务,也就是继续进行上次未完成的任务,
适用于文件下载,上传等逻辑。
2.运行一个前台服务:
前台服务是用户主动意识到的一种服务,因此在内存不足时,系统也不会考虑将其终止。 前台服务必须为状态栏
提供通知,放在“正在进行”标题下方,这意味着除非服务停止或从前台移除,否则不能清除通知。
要让服务运行与前台,需调用startForeground()方法,接收两个参数,一个是通知的唯一标志性ID,一个是
notification对象,如:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
4000
注:ID值不能为0;
要从前台移除服务,请调用 stopForeground()。此方法接收一个布尔值,指示是否也移除状态栏通知。 此方法不会停止
服务。 但是,如果在服务正在前台运行时将其停止,则通知也会被移除。
3.定义可绑定的服务:
a.定义和客户(client)交互的接口有三种方式,分别是:
(1)继承Binder类,适用于此服务为应用进程所私有,且client跟该服务处于同一应用进程中;
实现步骤:服务中定义一个类继承Binder类,在服务的onBind()方法中返回一个自定义Binder实例对象,client在
onServiceConnected()方法中获取该对象;
(2)使用Messager类提供跨进程绑定服务:
实现步骤:
服务实现一个 Handler,由其接收来自client的每个调用的回调,
Handler 用于创建 Messenger 对象(对 Handler 的引用),
Messenger 创建一个 IBinder,服务通过 onBind() 使其返回client,
client使用 IBinder 将 Messenger(引用服务的 Handler)实例化,然后使用后者将 Message 对象发送给服务,
服务在其 Handler 中(具体地讲,是在 handleMessage() 方法中)接收每个 Message。
这样,client并没有调用服务的“方法”。而client传递的“消息”(Message 对象)是服务在其 Handler 中接收的。
如:
service:
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
Activity:
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}(3)AIDL,有待后续拓展
4.客户端(client)绑定服务:
client调用bindService()方法,然后服务会调用onBind()方法返回IBinder对象,但是因为
这个绑定过程是异步的,bindService()调用后立即结束并不会返回IBinder()对象,因此需要一个ServiceConnection实例,
这个借口提供onServiceConnected()和onServiceDisconnected()回调方法,当服务已经绑定时会调用onServiceConnected()方法,
并获得IBinder实例对象;当服务崩溃或者被系统杀死时onServiceDisconnected()方法调用,而不是用户调用unbindService()时调用。
如:
LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Because we have bound to an explicit
// service that is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "onServiceDisconnected");
mBound = false;
}
};绑定服务:
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
5.bind service 生命周期:
6.Service完整生命周期:
1.当在同一个进程中从一个Activity开启另一个Activity时,它们的生命周期方法是这样的:
A Activity 开启了 B Activity:
A调用onPause(),B调用onCreate(),onStart(),onResume(),此时B Activity与用户进行交互,
然后A Activity的onStop()方法调用,所以如果两个界面共享一些数据,如存储在数据库
中的数据,则应该在A Activity的onPause()方法中保存数据,而不是onStop()方法。
2.横竖屏切换
当用户旋转屏幕,切换屏幕状态时,会创建新的Activity实例。
二、Service的onStartCommand()方法返回值
1.一个服务的onStartCommand()方法必须返回一个整数值,这个整数值描述了在系统因为内存等问题杀死
该服务后,该服务在系统获得了可用内存等资源如何继续该服务,返回值必须为以下其中之一:
a.START_NOT_STICKY:不要重新创建该服务,除非有意图重新开启该服务;
b.START_STICKY:用一个空的意图重新创建该服务,如果有新的意图,则用新的意图开启,适用于媒体播放器等逻辑;
c.START_REDELIVER_INTENT:用上一次开启该服务的意图重启该服务,也就是继续进行上次未完成的任务,
适用于文件下载,上传等逻辑。
2.运行一个前台服务:
前台服务是用户主动意识到的一种服务,因此在内存不足时,系统也不会考虑将其终止。 前台服务必须为状态栏
提供通知,放在“正在进行”标题下方,这意味着除非服务停止或从前台移除,否则不能清除通知。
要让服务运行与前台,需调用startForeground()方法,接收两个参数,一个是通知的唯一标志性ID,一个是
notification对象,如:
Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
System.currentTimeMillis());
Intent notificationIntent = new Intent(this, ExampleActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
notification.setLatestEventInfo(this, getText(R.string.notification_title),
getText(R.string.notification_message), pendingIntent);
startForeground(ONGOING_NOTIFICATION_ID, notification);
4000
注:ID值不能为0;
要从前台移除服务,请调用 stopForeground()。此方法接收一个布尔值,指示是否也移除状态栏通知。 此方法不会停止
服务。 但是,如果在服务正在前台运行时将其停止,则通知也会被移除。
3.定义可绑定的服务:
a.定义和客户(client)交互的接口有三种方式,分别是:
(1)继承Binder类,适用于此服务为应用进程所私有,且client跟该服务处于同一应用进程中;
实现步骤:服务中定义一个类继承Binder类,在服务的onBind()方法中返回一个自定义Binder实例对象,client在
onServiceConnected()方法中获取该对象;
(2)使用Messager类提供跨进程绑定服务:
实现步骤:
服务实现一个 Handler,由其接收来自client的每个调用的回调,
Handler 用于创建 Messenger 对象(对 Handler 的引用),
Messenger 创建一个 IBinder,服务通过 onBind() 使其返回client,
client使用 IBinder 将 Messenger(引用服务的 Handler)实例化,然后使用后者将 Message 对象发送给服务,
服务在其 Handler 中(具体地讲,是在 handleMessage() 方法中)接收每个 Message。
这样,client并没有调用服务的“方法”。而client传递的“消息”(Message 对象)是服务在其 Handler 中接收的。
如:
service:
public class MessengerService extends Service {
/** Command to the service to display a message */
static final int MSG_SAY_HELLO = 1;
/**
* Handler of incoming messages from clients.
*/
class IncomingHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
final Messenger mMessenger = new Messenger(new IncomingHandler());
/**
* When binding to the service, we return an interface to our messenger
* for sending messages to the service.
*/
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
return mMessenger.getBinder();
}
}
Activity:
public class ActivityMessenger extends Activity {
/** Messenger for communicating with the service. */
Messenger mService = null;
/** Flag indicating whether we have called bind on the service. */
boolean mBound;
/**
* Class for interacting with the main interface of the service.
*/
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
// established, giving us the object we can use to
// interact with the service. We are communicating with the
// service using a Messenger, so here we get a client-side
// representation of that from the raw IBinder object.
mService = new Messenger(service);
mBound = true;
}
public void onServiceDisconnected(ComponentName className) {
// This is called when the connection with the service has been
// unexpectedly disconnected -- that is, its process crashed.
mService = null;
mBound = false;
}
};
public void sayHello(View v) {
if (!mBound) return;
// Create and send a message to the service, using a supported 'what' value
Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
try {
mService.send(msg);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to the service
bindService(new Intent(this, MessengerService.class), mConnection,
Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
}(3)AIDL,有待后续拓展
4.客户端(client)绑定服务:
client调用bindService()方法,然后服务会调用onBind()方法返回IBinder对象,但是因为
这个绑定过程是异步的,bindService()调用后立即结束并不会返回IBinder()对象,因此需要一个ServiceConnection实例,
这个借口提供onServiceConnected()和onServiceDisconnected()回调方法,当服务已经绑定时会调用onServiceConnected()方法,
并获得IBinder实例对象;当服务崩溃或者被系统杀死时onServiceDisconnected()方法调用,而不是用户调用unbindService()时调用。
如:
LocalService mService;
private ServiceConnection mConnection = new ServiceConnection() {
// Called when the connection with the service is established
public void onServiceConnected(ComponentName className, IBinder service) {
// Because we have bound to an explicit
// service that is running in our own process, we can
// cast its IBinder to a concrete class and directly access it.
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
// Called when the connection with the service disconnects unexpectedly
public void onServiceDisconnected(ComponentName className) {
Log.e(TAG, "onServiceDisconnected");
mBound = false;
}
};绑定服务:
Intent intent = new Intent(this, LocalService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
5.bind service 生命周期:
6.Service完整生命周期:
相关文章推荐
- Android系统源码阅读(5):Service在进程内绑定
- Android 绑定Service的实现方法二:使用Messenger
- 绑定Service的三种实现方式之使用AIDL
- android89--Activity怎么和service绑定,怎么在activity中启动自己对应的service
- Android应用程序绑定服务(bindService)的过程源代码分析
- Fragmet+Tabhost+重复绑定service
- 安卓绑定本地服务Service并与之通信
- android学习之绑定Service并与之通信
- Android Service解绑后再次绑定以及绑定服务出现空指针问题
- 绑定Service的三种实现方式之使用Messenger
- 以绑定的方式来启动service
- Android中Activity和Service的绑定(二)
- 安卓非绑定方式的service生命周期测试
- Service绑定(上)
- android service绑定Activity注意
- Android -- service的开启方式, start开启和绑定开启服务,调用服务的的方法, aidl调用远程服务
- 经过多次试验后第一个成功地实现 HTTPService 与 MXML 之间传递数据,ArrayCollection 与DataGrid 之间成功绑定
- 深入剖析Android四大组件(二)——Service服务之启动与绑定
- android Bound Service使用:继续Binder类绑定服务
- Android菜鸟的成长笔记(18)——绑定本地Service并与之通信