1.Service生命周期以及绑定本地服务
onCreate() : 在该Service第一次被创建的时候被调用
onBind() : 该方法是Service子类必须实现的一个方法,该方法返回一个IBinder对象,应用程序通过该对象与Service进行通信。
onDestroy() : 该Service被关闭之前被调用
onStartCommand() :每次客户端调用startService(intent)的方法启动时都会调用。
onUnbind(Intent intent) ;接绑时调用
代码如下:
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private TextView getText;
private Button get;
private Button start;
private Button stop;
private Button bind;
private Button unbind;
private MyService.MyBinder binder;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MyService.MyBinder)service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
binder = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.start :
startService(new Intent(this,MyService.class));
break;
case R.id.stop :
stopService(new Intent(this,MyService.class));
break;
case R.id.bind :
bindService(new Intent(this,MyService.class),conn, Service.BIND_AUTO_CREATE);
break;
case R.id.unbind :
unbindService(conn);
break;
case R.id.get :
getText.setText(""+binder.getCount());
break;
}
}
private void init(){
getText = (TextView)findViewById(R.id.get_text);
start = (Button)findViewById(R.id.start);
stop = (Button)findViewById(R.id.stop);
bind = (Button)findViewById(R.id.bind);
unbind = (Button)findViewById(R.id.unbind);
get = (Button)findViewById(R.id.get);
start.setOnClickListener(this);
stop.setOnClickListener(this);
bind.setOnClickListener(this);
unbind.setOnClickListener(this);
get.setOnClickListener(this);
}
}
MyService
public class MyService extends Service {
private static final String TAG = "haha";
private MyBinder mBinder = new MyBinder();
public MyService() {
}
class MyBinder extends Binder{
public int getCount(){
return 2;
}
}
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "onBind: ");
// TODO: Return the communication channel to the service.
return mBinder;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate: ");
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d(TAG, "onStart: ");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG, "onDestroy: ");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
}
startService()启动Service:
stopService停止Service:
bindService绑定本地服务:
unbindService解绑服务;
2.IntentService
Service本身存在的两个问题:
(1)不会专门启动一个单独的进程,Service与它所在的应用在同一进程中。
(2)不是一个新的线程,因此不应该在Service中直接进行耗时的操作。
IntentService的特征:
(1)IntentService会创建单独的work线程来处理所有的Intent请求。
(2)IntentService会创建单独的work线程来处理onHandleIntent()方法实现的代码,因此开发者无需处理多线程的问题。
(3)当请求处理完成后,IntentService会自动停止,因此开发者无需调用stopSelf()方法来停止该Service
(4)为Service的onBind()方法提供了默认实现,默认实现的onBind()方法返回null.。
(5)为Service的onStartCommand()提供了默认的实现,该实现会将请求的Intent添加到队列中。
综上所述:扩展IntentService实现Service无需重写onBind,onStartCommand(),只需要重写onHandleIntent()方法即可。
工作流程:
客户端通过startService(Intent)来启动IntentService; 我们并不需要手动地区控制IntentService,当任务执行完后,IntentService会自动停止; 可以启动IntentService多次,每个耗时操作会以工作队列的方式在IntentService的 onHandleIntent回调方法中执行,并且每次只会执行一个工作线程,执行完一,再到二这样!
3.Activity与Service通信
基本流程如下:
1.自定义Service中,自定义一个Binder类,然后将需要暴露的方法都写到该类中!
2.Service类中,实例化这个自定义Binder类,然后重写onBind()方法,将这个Binder对象返回!
3.Activity类中实例化一个ServiceConnection对象,重写onServiceConnected()方法,然后 获取Binder对象,然后调用相关方法即可!
MyService
public class MyService extends Service {
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return new MyBinder();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
static class MyBinder extends Binder{
public int getNumber(){
return 520;
}
}
}
MainActivity :
public class MainActivity extends AppCompatActivity {
private MyService.MyBinder myBinder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(this,MyService.class);
bindService(intent,serviceConnection,BIND_AUTO_CREATE);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
myBinder = (MyService.MyBinder)service;
Log.d("TAG", "onServiceConnected: "+myBinder.getNumber());
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
4. 简单定时后台线程的实现
Android中给我们提供的定时方式有两种使用Timer类与Alarm机制!前者不适合于需要长期在后台运行的定时任务,CPU一旦休眠,Timer中的定时任务 就无法运行;Alarm则不存在这种情况,他具有唤醒CPU的功能,另外,也要区分CPU 唤醒与屏幕唤醒!
使用流程:
Step 1:获得Service: AlarmManager manager = (AlarmManager) getSystemService(ALARM_SERVICE);
Step 2:通过set方法设置定时任务 int anHour = 2 * 1000; long triggerAtTime = SystemClock.elapsedRealtime() + anHour; manager.set(AlarmManager.RTC_WAKEUP,triggerAtTime,pendingIntent);
Step 3:定义一个Service 在onStartCommand中开辟一条事务线程,用于处理一些定时逻辑
Step 4:定义一个Broadcast(广播),用于启动Service 最后别忘了,在AndroidManifest.xml中对这Service与Boradcast进行注册!
参数详解: set(int type,long startTime,PendingIntent pi)
①type: 有五个可选值:
AlarmManager.ELAPSED_REALTIME: 闹钟在手机睡眠状态下不可用,该状态下闹钟使用相对时间(相对于系统启动开始),状态值为3;
AlarmManager.ELAPSED_REALTIME_WAKEUP 闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟也使用相对时间,状态值为2;
AlarmManager.RTC 闹钟在睡眠状态下不可用,该状态下闹钟使用绝对时间,即当前系统时间,状态值为1;
AlarmManager.RTC_WAKEUP 表示闹钟在睡眠状态下会唤醒系统并执行提示功能,该状态下闹钟使用绝对时间,状态值为0;
AlarmManager.POWER_OFF_WAKEUP 表示闹钟在手机关机状态下也能正常进行提示功能,所以是5个状态中用的最多的状态之一, 该状态下闹钟也是用绝对时间,状态值为4;不过本状态好像受SDK版本影响,某些版本并不支持;