Android纯服务应用开发,Android开发Service

Service

生命周期

1、通过startService()方式,onCreate()-->onStartCommand()-->onDestroy()

注:

若一个Service被startService()多次启动,那么onCreate()也只会调用一次,即Service实例只有1个

整个生命周期的方法中,只有onStartCommand()可多次调用,其他只能调用一次

onStartCommand调用次数=startService调用次数

特点:调用者退出后Service仍然存在

应用场景:服务不需与Activity和Service通信

示例代码:

tv_content.setOnClickListener {

val intent = Intent(this@BActivity,StartServiceDemo::class.java)

intent.putExtra("content","nihao")

startService(Intent(intent))

}

tv_content_stop.setOnClickListener {

val intent = Intent(this@BActivity,StartServiceDemo::class.java)

stopService(Intent(intent))

}

定时循环任务示例代码:

public class VersionCheckServices extends Service {

private static String TAG = VersionCheckServices.class.getName();

/**

* 定时器对象

*/

private AlarmManager manager;

private PendingIntent pendingIntent;

private final int LOOP_TIME = 60;

@Nullable

@Override

public IBinder onBind(Intent intent) {

return null;

}

@Override

public void onCreate() {

super.onCreate();

manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);

}

@Override

public void onDestroy() {

if (pendingIntent != null) {

manager.cancel(pendingIntent);

}

super.onDestroy();

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

if ((ModifySetUtils.isCodeCheckVersion() || ModifySetUtils.isCheckVersion() || ModifySetUtils.isFourCheckVersion()) && !SPUtils.isCheckUser()) {

if (!AppUtils.isAppForeground()) {

new CheckVersionPassPresenter().dealCheckVersion(this,checkVersionCallBack);

} else {

next(LOOP_TIME);

}

} else {

//非审核版本就不需要继续调用服务了

stopSelf();

}

return super.onStartCommand(intent, flags, startId);

}

/**

* 检查审核版本的回调

*/

private HttpOnNextListener checkVersionCallBack = new HttpOnNextListener() {

@Override

public void onError(ApiException e) {

next(LOOP_TIME);

}

@Override

public void onNext(CheckPassVersionResult checkPassVersionResult) {

if(checkPassVersionResult.getData() != null && checkPassVersionResult.getData().isPass()){

SPNoCleanUtil.saveCheckVersion(true);

IntentUtils.startGuideActivity(VersionCheckServices.this);

} else {

next(LOOP_TIME);

SPNoCleanUtil.saveCheckVersion(false);

}

}

@Override

public void onDealCodeNext(CheckPassVersionResult baseResult) {

next(LOOP_TIME);

SPNoCleanUtil.saveCheckVersion(false);

}

};

/**

* 设置定时器,准备下次调用

*

* @param time 调用时间,秒

*/

private void next(int time) {

Intent intent = new Intent(this, VersionCheckServices.class);

pendingIntent = PendingIntent.getService(this, 0, intent, 0);

manager.set(AlarmManager.RTC, System.currentTimeMillis() + time * 1000, pendingIntent);

}}

2、通过bindService()方式,onCreate()-->onBind()-->onUnbind()-->onDestroy()

注:

客户端通过一个IBinder接口与服务进行通信

若一个Service被BindService()多次启动,那么onCreate()也只会调用一次,即Service实例只有1个

多个客户端可绑定到同一个服务上,当所有客户端都解绑后,系统会销毁服务

特点:调用者退出后,随着调用者销毁

应用场景:服务需与Activity和Service通信、需控制服务开始时刻

bindService()方式的示例代码:

先定义Service子类:

public class BindServiceDemo extends Service {

private String TAG = BindServiceDemo.class.getSimpleName();

private MyBinder mBinder = new MyBinder();

@Override

public void onCreate() {

super.onCreate();

Log.i(TAG,"onCreate");

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Log.i(TAG,"onStartCommand");

return super.onStartCommand(intent, flags, startId);

}

@Nullable

@Override

public IBinder onBind(Intent intent) {

Log.i(TAG,"onBind");

return mBinder;

}

@Override

public boolean onUnbind(Intent intent) {

Log.i(TAG,"onUnbind");

return super.onUnbind(intent);

}

@Override

public void onDestroy() {

super.onDestroy();

Log.i(TAG,"onDestroy");

}

public class MyBinder extends Binder{

public void service_connect_Activity() {

Log.i(TAG,"Service关联了Activity,并在Activity执行了Service的方法");

}

}}

在AndroidManifest.xml中注册

使用:

private var myBinder:BindServiceDemo.MyBinder?= null

//创建ServiceConnection的匿名类

private val connection = object : ServiceConnection {

//重写onServiceConnected()方法和onServiceDisconnected()方法

//在Activity与Service解除关联的时候调用

override fun onServiceDisconnected(name: ComponentName) {}

//在Activity与Service关联的时候调用

override fun onServiceConnected(name: ComponentName, service: IBinder) {

//实例化Service的内部类myBinder

//通过向下转型得到了MyBinder的实例

myBinder = service as BindServiceDemo.MyBinder

//在Activity调用Service类的方法

myBinder?.service_connect_Activity()

}

}

tv_bind_service.setOnClickListener {

val intent = Intent(this@BActivity,BindServiceDemo::class.java)

bindService(intent,connection, Context.BIND_AUTO_CREATE)

}

tv_unbind_service.setOnClickListener {

//仅此示例,正常要判是否已经绑定成功

unbindService(connection)

}

IntentService

多线程IntentService

本质:Handler + HandlerThread

为什么要使用IntentService呢,

因为1、普通的Service不是一个单独的进程,它和它的应用程序在同一个进程中

2、Service不是一个线程,就意味着应该避免在Service中进行耗时操作

工作流程:客户端通过startService(Intent)来启动IntentService; 我们并不需要手动地区控制IntentService,当任务执行完后,IntentService会自动停止; 可以启动IntentService多次,每个耗时操作会以工作队列的方式在IntentService的 onHandleIntent回调方法中执行,并且每次只会执行一个工作线程,执行完一,再到二这样!

生命周期: onCreate() --> onStartCommand() --> onHandleIntent() --> onDestroy()

多次调用 startService(Intent)会多次调用onStartCommand()和onHandleIntent()

注意:

一. 工作任务队列 = 顺序执行

由于onCreate()只会调用一次 = 只会创建1个工作线程

二、不建议通过 bindService() 启动 IntentService

因为bindService()的生命周期是onCreate() --> onBind() --> onunBind() --> onDestory(),并不会调onStartCommand(),因此不会将消息发送到消息队列,那么onHandleIntent()将不会回调,即无法实现多线程操作

远程服务Service

远程服务与本地服务最大的区别:远程Service与调用者不在同一个进程里,而本地服务则是与调用者在同一个进程里

使用场景:

多个应用程序共享同一个后台服务(远程服务)

具体使用:

为了让远程Service与多个应用程序的组件(四大组件)进行跨进程通信(IPC),需要使用AIDL。

AIDL:Android接口定义语言

操作步骤:

一:先定义后台服务(服务器端)

步骤1:新建AIDL文件,创建提供给客户端的接口,定义好接口方法

步骤2:在Service子类中实现AIDL中定义的接口方法,即回调给客户端接口和客户端通信

关键通过AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub()。生成binder,然后binder在客户端绑定成功后onServiceConnected传入改binder,然后在客户端通过AIDL_Service1.Stub.asInterface(binder)反转成AIDL_Service1实例,就可以拿到服务器端传过来的信息

示例代码:

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

aidl_service1 = AIDL_Service1.Stub.asInterface(service);

try {

aidl_service1.toDoService();

} catch (RemoteException e) {

e.printStackTrace();

}

}

步骤3:在AndroidManifest.xml中注册为android:exported="true"的,还有加上,可以隐式intent绑定远程Service

二:客户端

步骤1:拷贝服务器端的aidl文件到main目录下,是整个aidl目录拷贝过来,不要做任何改动

步骤2:使用Stub.asInterface接口获取服务器的Binder,根据需要调用服务提供的接口方法

步骤3:通过bindService()方法启动,intent指定服务器端的服务名称和包名,绑定远程Service

示例代码:

服务器

定义aidl接口(鼠标右键new里面有AIDL,创建完Rebuild Project):

df38f26086df

service_aidl.png

定义Service子类:

public class AIDLServiceDemo extends Service {

private String TAG = AIDLServiceDemo.class.getSimpleName();

AIDL_Service1.Stub mBinder = new AIDL_Service1.Stub() {

@Override

public void toDoService() throws RemoteException {

Log.i(TAG,"客户端通过AIDL与远程后台成功通信");

}

};

@Override

public void onCreate() {

super.onCreate();

Log.i(TAG,"onCreate");

}

@Override

public int onStartCommand(Intent intent, int flags, int startId) {

Log.i(TAG,"onStartCommand");

return super.onStartCommand(intent, flags, startId);

}

@Nullable

@Override

public IBinder onBind(Intent intent) {

Log.i(TAG,"onBind");

return mBinder;

}

@Override

public boolean onUnbind(Intent intent) {

Log.i(TAG,"onUnbind");

return super.onUnbind(intent);

}

@Override

public void onDestroy() {

super.onDestroy();

Log.i(TAG,"onDestroy");

}}

在AndroidManifest.xml中注册:

android:exported="true">

客户端:

完全拷贝aidl文件过来:

df38f26086df

service_client.png

绑定和使用:

public class MainActivity extends AppCompatActivity {

private TextView tvBindService;

private AIDL_Service1 aidl_service1;

private ServiceConnection connection = new ServiceConnection() {

@Override

public void onServiceConnected(ComponentName name, IBinder service) {

aidl_service1 = AIDL_Service1.Stub.asInterface(service);

try {

aidl_service1.toDoService();

} catch (RemoteException e) {

e.printStackTrace();

}

}

@Override

public void onServiceDisconnected(ComponentName name) {

}

};

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tvBindService = findViewById(R.id.tv_bind_remote_service);

tvBindService.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Intent intent = new Intent("com.cong.myapplication.service.AIDL_Service1");

intent.setPackage("com.cong.myapplication.service");

bindService(intent,connection,BIND_AUTO_CREATE);

}

});

}}

Androidmanifest里Service的常见属性说明

android:name:Service的类名

android:permission:申明此Service的权限。注:有提供了该权限的应用才能控制或连接此服务

android:process:表示该服务是否在另一个进程中运行(远程服务)。注:不设置默认为本地服务;remote则设置成远程服务

android:exported:该服务是否能够被其他应用程序所控制或连接

注:不设置默认为false

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值