Service基础
Service并没有实际界面。而是一直运行在Android系统的后台运行。一般使用Service为应用程序提供一些服务。 或者不需要界面的功能。
- Service的生命周期
Service从启动到销毁的过程
- 1.创建服务
- 2.开始服务
3.销毁服务
Service需要在AndroidManifest.xml 文件的 中添加注册的代码
<receiver android:name=".receiver.BootBroadcastReceiver">
android:name 属性是唯一必需的属性,用于指定服务的类名,
还可将其他属性包括在 < service > 元素中以定义一些特性
- onStartCommand()
当组件通过调用 startService() 请求启动服务时,系统将调用此方法(如果是绑定服务则不会调用此方法)。
一旦执行此方法,服务即会启动并可在后台无限期运行。 在指定任务完成后,通过调用
stopSelf() 或 stopService() 来停止服务 - onBind()
当一个组件想通过调用 bindService() 与服务绑定时,系统将调用此方法(如果是启动服务则不会调用此方法)。
在此方法的实现中,必须通过返回 IBinder 提供一个接口,供客户端用来与服务进行通信 - onCreate()
首次创建服务时,系统将调用此方法来执行初始化操作(在调用 onStartCommand() 或 onBind() 之前)。
如果在启动或绑定之前Service已在运行,则不会调用此方法 - onDestroy()
当服务不再使用且将被销毁时,系统将调用此方法,这是服务接收的最后一个调用,
在此方法中应清理占用的资源
为了确保应用的安全性,最好始终使用显式 Intent 启动或绑定 Service,且不要为服务声明 Intent 过滤器。
启动哪个服务存在一定的不确定性,而如果对这种不确定性的考量非常有必要,
则可为服务提供 Intent 过滤器并从 Intent 中排除相应的组件名称,
但随后必须使用 setPackage() 方法设置 Intent 的软件包,这样可以充分消除目标服务的不确定性
此外,还可以通过添加 android:exported 属性并将其设置为 “false”,确保服务仅适用于本应用。
这可以有效阻止其他应用启动本应用内的服务,即便在使用显式 Intent 时也是如此
IntentService
IntentService 执行以下操作:
创建默认的工作线程,用于在应用的主线程外执行传递给 onStartCommand() 的所有 Intent
创建工作队列,用于将 Intent 逐一传递给 onHandleIntent() 实现,这样就不必担心多线程问题
在处理完所有启动请求后停止服务,因此不必自己调用 stopSelf()方法
提供 onBind() 的默认实现(返回 null)
提供 onStartCommand() 的默认实现,可将 Intent 依次发送到工作队列和 onHandleIntent()
因此,只需实现构造函数与 onHandleIntent() 方法即可
实现 ServiceConnection接口
重写两个回调方法:
onServiceConnected()
系统会调用该方法以传递服务的onBind() 方法返回的 IBinder
onServiceDisconnected()
Android 系统会在与服务的连接意外中断时,例如当服务崩溃或被终止时调用该方法。当客户端取消绑定时,系统不会调用该方法
调用 bindService(),传递 ServiceConnection 对象
当系统调用了 onServiceConnected() 的回调方法时,就可以通过IBinder对象操作服务了
要断开与服务的连接需调用 unbindService()方法。如果应用在客户端仍处于绑定状态时销毁客户端
会导致客户端取消绑定,更好的做法是在客户端与服务交互完成后立即取消绑定客户端,
这样可以关闭空闲服务
利用系统广播BroadcastReceiver 直接启动Service
public class BootBroadcastReceiver extends BroadcastReceiver {
public final static String ACTION_BOOT_COMPLETED = "android.intent.action.BOOT_COMPLETED";
public BootBroadcastReceiver() {
super();
}
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equals(ACTION_BOOT_COMPLETED)){
// 后边的XXX.class就是要启动的服务
Intent actIntent = new Intent(context.getApplicationContext(), MainActivity.class);
actIntent.setAction("android.intent.action.MAIN");
actIntent.addCategory("android.intent.category.LAUNCHER");
actIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(actIntent);
Log.v("TAG", "开机自动服务自动启动.....");
// 启动应用,参数为需要自动启动的应用的包名
Intent serIntent= new Intent(context, TestService.class);
serIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(serIntent);
Log.v("TAG", "开机程序自动启动.....");
}
}
}
<service android:name=".service.TestService"></service>
<receiver android:name=".receiver.BootBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
添加权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
对Service状态进行判断
package com.example.administrator.androidtestdemo.service;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.util.Log;
import java.util.List;
public class ServiceManager {
public static final String TAG="ServiceManager";
/**
* 判断Service是否注册
* @param context
* @param serviceAction
* @return
*/
public static boolean isRegistererService(Context context,String serviceAction){
PackageManager packageManager=context.getPackageManager();
//指定要查询的Service Action
Intent intent=new Intent(serviceAction);
//查询服务
@SuppressLint("WrongConstant")
List<ResolveInfo>resolveInfos=packageManager.queryIntentServices(intent,PackageManager.GET_INTENT_FILTERS);
if(resolveInfos.size()>0){
ResolveInfo resolveInfo=resolveInfos.get(0);
Log.i(TAG,"服务信息:"+resolveInfo.toString());
return true;
}
return false;
}
/**
* 判断service是否正在运行
* @param context
* @param serviceNmae
* @return
*/
public static boolean isStartService(Context context,String serviceNmae){
ActivityManager activityManager= (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
//返回正在运行的Service
List<ActivityManager.RunningServiceInfo> runningServiceInfos=activityManager.getRunningServices(100);
for(int i=0;i<runningServiceInfos.size();i++){
ActivityManager.RunningServiceInfo runningServiceInfo=runningServiceInfos.get(i);
if(serviceNmae.equals(runningServiceInfo.service.getClassName())){
Log.i(TAG,"服务正在运行:"+runningServiceInfo.service.getClassName());
return true;
}
}
return false;
}
}