1、服务是可以在后台执行长时间运行操作的应用程序组件,它不提供用户界面。
2、service声明周期:开始-->运行-->结束
3、service和线程(何时用线程/service)
服务只是一个可以在后台运行的组件,用户没有与您的应用程序交互,您应该仅在需要时创建服务。
如果必须在主线程之外执行工作,但仅当用户与应用程序交互时,则应创建新线程。例如,如果您想播放一些音乐,但仅当您的活动正在运行时,您可以在onCreate()中创建一个线程,在onStart()中开始运行它,并在onStop()中停止它。还可以考虑使用AsyncTask或HandlerThread来代替传统的线程类。
4. service和IntentService
Service:这是所有服务的基类。当您扩展这个类时,重要的是创建一个新线程,在这个线程中服务可以完成它的所有工作;默认情况下,服务使用应用程序的主线程,这会降低应用程序正在运行的任何活动的性能。
IntentService:这是服务的一个子类,它使用一个工作线程来处理所有的启动请求,一次一个。如果您不要求您的服务同时处理多个请求,这是最好的选择。实现onHandleIntent(),它接收每个启动请求的意图,以便您可以完成后台工作。
5. Service的声明和使用
1. 继承service基类
2. manifest文件中添加service的声明
3. service的权限控制(LocalService)
一般情况下为了安全起见,一般建议用LocalService的方式,如果要用正常service,要加权限控制,声明权限,在bindService的app中使用该权限即可,另外android:exported = “true”(默认为false)
<manifest ... >
...
<application ... >
<service android:name=".ExampleService"
android:exported="true"
android:permission="com.gxf.test">
<intent-filter android:priority="1000"
android:autoVerify="true"/>
</service>
</application>
</manifest>
6. Service和JobScheduler(待补充)
7. Service运行在主进程中,因此在service里面不能运行耗时操作
8. Bound Service的步骤以及三种方式
1: Implement ServiceConnection
2: Call bindService()
, passing the ServiceConnection
implementation.
3:When the system calls your onServiceConnected()
callback method, you can begin making calls to the service, using the methods defined by the interface.
4:To disconnect from the service, call unbindService()
.
8.1 Extending the Binder class
public class LocalService extends Service {
// Binder given to clients
private final IBinder binder = new LocalBinder();
// Random number generator
private final Random mGenerator = new Random();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
LocalService getService() {
// Return this instance of LocalService so clients can call public methods
return LocalService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
/** method for clients */
public int getRandomNumber() {
return mGenerator.nextInt(100);
}
}
public class BindingActivity extends Activity {
LocalService mService;
boolean mBound = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
@Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, LocalService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
unbindService(connection);
mBound = false;
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute) */
public void onButtonClick(View v) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
int num = mService.getRandomNumber();
Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to LocalService, cast the IBinder and get LocalService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
}
8.2 Using a Messenger
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.
*/
static class IncomingHandler extends Handler {
private Context applicationContext;
IncomingHandler(Context context) {
applicationContext = context.getApplicationContext();
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_SAY_HELLO:
Toast.makeText(applicationContext, "hello!", Toast.LENGTH_SHORT).show();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Target we publish for clients to send messages to IncomingHandler.
*/
Messenger mMessenger;
/**
* 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();
mMessenger = new Messenger(new IncomingHandler(this));
return mMessenger.getBinder();
}
}
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 bound;
/**
* 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);
bound = 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;
bound = false;
}
};
public void sayHello(View v) {
if (!bound) 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 (bound) {
unbindService(mConnection);
bound = false;
}
}
}
8.3 AIDL方式实现
8.3.1 Create .aidl file
// IRemoteService.aidl package com.example.android; // Declare any non-default types here with import statements /** Example service interface */ interface IRemoteService { /** Request the process ID of this service, to do evil things with it. */ int getPid(); /** 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); }
8.3.2 Implement the interface
public class RemoteService extends Service { @Override public void onCreate() { super.onCreate(); } @Override public IBinder onBind(Intent intent) { // Return the interface return binder; } private final IRemoteService.Stub binder = new IRemoteService.Stub() { public int getPid(){ return Process.myPid(); } public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) { // Does nothing } }; }
IRemoteService iRemoteService; private ServiceConnection mConnection = new ServiceConnection() { // Called when the connection with the service is established public void onServiceConnected(ComponentName className, IBinder service) { // Following the example above for an AIDL interface, // this gets an instance of the IRemoteInterface, which we can use to call on the service iRemoteService = IRemoteService.Stub.asInterface(service); } // Called when the connection with the service disconnects unexpectedly public void onServiceDisconnected(ComponentName className) { Log.e(TAG, "Service has unexpectedly disconnected"); iRemoteService = null; } };
reference: https://developer.android.google.cn/guide/components/services?hl=en