Service是Android系统的服务组件,适用于开发没有用户界面且长时间在后台运行的功能
因为手机硬件性能和屏幕尺寸的限制,通常Android系统仅允许一个应用程序处于激活状态并显示在手机屏幕上,而暂停其他处于未激活状态的程序。
因此,Android系统需要一种后台服务机制,允许在没有用户界面的情况下,使程序能够长时间在后台运行,实现应用程序的后台服务功能。
在实际应用中,有很多应用需要使用Service,比如MP3播放器要求在关闭播放器界面后,仍然能够后台保持音乐持续播放。
下面我将Service基础知识简单归纳为以下6点:
- 1.Service适用于什么功能?
Service使用于无须用户干预,且有规则地运行或长期运行的后台共功能。
- 2.Service的特点
Service没有用户界面,相比于其他应用程序更加有利于降低系统资源的消耗。
Service比Activity具有更高优先级,在资源紧张时,Service不会被Android系统优先终止。
即使Service被系统终止,在系统资源恢复后Service也将自动回复运行状态,因此可以认为Service是在系统中可以稳定长期运行的组件。
- 3.Service的用处
1.实现后台服务功能
2.可用于进程间通信
- 4.Service的生命周期
完整的生命周期从onCreate()开始到onDestroy()结束,在onCreate()中完成Service的初始化工作,在onDestroy()中释放所有占用的资源。
可以粗略的认为活动生命周期以onDestroy()标志结束。
- 5.通过启动方式使用Service
实现
通过Context.startService()启动Service,通过Context.stopService()停止Seivice。
Context指其他组件,因此Service一定是由其它组件启动的,但停止过程可以通过其他组件或自身完成。
特点
启动Service的组件无法获取Service的对象实例,因此也无法调用Service中的任何函数,
也不能获取Service中的任何状态和数据信息。所以以启动方式的Service需要具备自管理的能力。
- 6.通过绑定方式使用Service
实现
在其他组件中调用Context.bindService()建立服务连接,调用Context.unbindService()停止服务连接。
如果在绑定过程中Service未启动,Context.bindService()会自动启动Service。
特点
其他组件可以获取Service的实例对象并调用Service中的函数,可以获取Service中的状态和数据信息。
同一个Service可以和被多个组件绑定服务连接,即同一个Service可以同时为多个组件服务。
概念: 本地服务的调用者和服务都在同一个程序中,是不需要跨进程就可以实现服务的调用。
以下为一个设计到本地服务的简单Demo,包括启动方式和绑定方式的使用。主界面如图:
RandomService.java(启动方式)完整代码:
package com.example.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.widget.Toast;
/** * Created by yinghao on 2016/5/6. */
public class RandomService extends Service {
/* onStartCommand 取代 onStart 但在 super.onStartCommand(intent, flags, startId); 方法中调用了 onStart()方法(为了兼容) */
private Thread workThread;
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "调用onCreate()", Toast.LENGTH_SHORT).show();
workThread = new Thread(null, backgroundWork, "workThread");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(RandomService.this, "onStart()", Toast.LENGTH_SHORT).show();
if (!workThread.isAlive()) {
workThread.start();
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(RandomService.this, "onStartCommand()", Toast.LENGTH_SHORT).show();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Toast.makeText(this, "调用onDestroy()", Toast.LENGTH_SHORT).show();
workThread.interrupt();
super.onDestroy();
}
private Runnable backgroundWork = new Runnable() {
@Override
public void run() {
try {
while (!Thread.interrupted()) {
double randomDouble = Math.random();
MainActivity.UpdateGUI(randomDouble);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
/** * Service 被绑定后调用的函数,能够返回Service对象实例 */
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
MathService.java(绑定方式)完整代码:
package com.example.servicedemo;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.widget.Toast;
/** * Created by yinghao on 2016/5/6. */
public class MathService extends Service {
/** * 以绑定形式使用此Service 获取Service实例 */
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder{
MathService getService() {
return MathService.this;
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(MathService.this, "本地绑定", Toast.LENGTH_SHORT).show();
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Toast.makeText(MathService.this, "取消本地绑定:MathService", Toast.LENGTH_SHORT).show();
return super.onUnbind(intent);
}
public long add(long a, long b) {
return a + b;
}
}
MainActivity.java完整代码:
package com.example.servicedemo;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.simplerandomservicedemo.R;
public class MainActivity extends AppCompatActivity {
private Button mStartButton;
private Button mStopButton;
private static TextView mLabelTextVie;
private static Handler handler = new Handler();
private static double random;
/** * Handler 将Runnable对象 传递给 界面线程的队列中 * 使其能更新UI */
public static void UpdateGUI(double refreshDouble) {
random = refreshDouble;
handler.post(RefreshLable);
}
public static Runnable RefreshLable = new Runnable() {
@Override
public void run() {
mLabelTextVie.setText(String.valueOf(random));
}
};
private MathService mathService;
private boolean isBound = false;
private TextView sum;
private Button bindButton;
private Button unbindButton;
private Button addButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/** * Handler */
final Intent intent = new Intent(this,RandomService.class);
mStartButton = (Button) findViewById(R.id.start);
mStopButton = (Button) findViewById(R.id.stop);
mLabelTextVie = (TextView) findViewById(R.id.tv_label);
mStartButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(intent);
}
});
mStopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopService(intent);
}
});
/** * bind Service */
sum = (TextView) findViewById(R.id.tv_result);
bindButton = (Button) findViewById(R.id.bind);
unbindButton = (Button) findViewById(R.id.unbind);
addButton = (Button) findViewById(R.id.add);
final Intent serviceIntent = new Intent(MainActivity.this, MathService.class);
bindButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!isBound) {
bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
isBound = true;
}
}
});
unbindButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isBound) {
unbindService(mConnection);
//若把上面取消绑定改为下面的关闭Service 则无法再次绑定成功
// stopService(serviceIntent);
mathService = null;
isBound = false;
}
}
});
addButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mathService == null) {
sum.setText("未绑定服务");
return;
}
long a = Math.round(Math.random() * 100);
long b = Math.round(Math.random() * 100);
long result = mathService.add(a, b);
String msg = String.valueOf(a)+"+"+String.valueOf(b)+"="+result;
sum.setText(msg);
}
});
}
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mathService = ((MathService.LocalBinder) service).getService();
}
@Override
public void onServiceDisconnected(ComponentName name) {
mathService = null;
}
};
}