写点什么

HarmonyOS-Service&Android-Service(1),程序员中年危机

用户头像
Android架构
关注
发布于: 刚刚

public class AndroidService extends Service {@Overridepublic void onCreate() {super.onCreate();}...}


或者创建 IntentService(Service 子类)子类,串行执行所有启动服务请求。


public class AndroidIntentService extends IntentService {


public AndroidIntentService() {super("AndroidIntentService");}@Overrideprotected void onHandleIntent(Intent intent) {try {Thread.sleep(5000);} catch (InterruptedException e) {// Restore interrupt status.Thread.currentThread().interrupt();}}}

注册

HarmonyOS:Service 需要在应用配置文件中进行注册,注册类型 type 需要设置为 service。


{"module": {"abilities": [


{


"name": ".ServiceAbility","type": "service","visible": true...}]...}...}


Android:开发者必须在应用的清单文件中声明所有服务。如要声明服务,需要添加 元素作为 元素的子元素,name 属性是唯一必需的属性。


<manifest ... >...<application ... ><service android:name=".AndroidService" />...</application></manifest>

启动服务

HarmonyOS

HarmonyOS 中 Ability 为开发者提供了 startAbility()方法来启动另外一个 Ability。因为 Service 也是 Ability 的一种,开发者同样可以通过将 Intent 传递给该方法来启动 Service。不仅支持启动本地 Service,还支持启动远程 Service。其中启动本地服务如下:


Intent intent = new Intent();Operation operation = new Intent.OperationBuilder().withDeviceId("").withBundleName("com.huawei.hiworld.himusic").withAbilityName("com.huawei.hiworld.himusic.entry.ServiceAbility").build();intent.setOperation(operation);startAbility(intent);


参数说明:


  • DeviceId:表示设备 ID。如果是本地设备,则可以直接留空;如果是远程设备,可以通过 ohos.distributedschedule.interwork.DeviceManager 提供的 getDeviceList 获取设备列表。

  • BundleName:表示包名称。

  • AbilityName:表示待启动的 Ability 名称。 启动远程服务如下:


Operation operation = new Intent.OperationBuilder().withDeviceId("deviceId").withBundleName("com.huawei.hiworld.himusic").withAbilityName("com.huawei.hiworld.himusic.entry.ServiceAbility").withFlags(Intent.FLAG_ABILITYSLICE_MULTI_DEVICE) // 设置支持分布式调度系统多设备启动的标识.build();Intent intent = new Intent();intent.setOperation(operation);startAbility(intent);


Ability 将通过 startAbility() 方法来启动 Service。 如果 Service 尚未运行,则系统会先调用 onStart()来初始化 Service,再回调 Service 的 onCommand()方法来启动 Service。 如果 Service 正在运行,则系统会直接回调 Service 的 onCommand()方法来启动 Service。

Android

开发者可以通过将 Intent 传递给 startService() 或 startForegroundService(),从 Activity 或其他应用组件启动服务。Android 系统会调用服务的 onStartCommand() 方法,并向其传递 Intent,从而指定要启动的服务。如果应用面向 API 级别 26 或更高版本,除非应用本身在前台运行,否则系统不会对使用或创建后台服务施加限制。如果应用需要创建前台服务,则其应调用 startForegroundService()。此方法会创建后台服务,但它会向系统发出信号,表明服务会将自行提升至前台。创建服务后,该服务必须在五秒内调用自己的 startForeground() 方法。


Intent intent = new Intent(this, AndroidService.class);startService(intent);


startService() 方法会立即返回,并且 Android 系统会调用服务的 onStartCommand() 方法。如果服务尚未运行,则系统首先会调用 onCreate(),然后调用 onStartCommand()。 如果服务亦未提供绑定,则应用组件与服务间的唯一通信模式便是使用 startService() 传递的 Intent。但是,如果开发者希望服务返回结果,则启动服务的客户端可以为广播(通过 getBroadcast() 获得)创建一个 PendingIntent,并将其传递给启动服务的 Intent 中的服务。然后,服务便可使用广播传递结果。 多个服务启动请求会导致多次对服务的 onStartCommand() 进行相应的调用。但是,如要停止服务,只需一个服务停止请求(使用 stopSelf() 或 stopService())即可。

启动前台服务(可选)

HarmonyOS

开发者只需在 Service 创建的方法里,调用 keepBackgroundRunning()将 Service 与通知绑定。调用 keepBackgroundRunning()方法前需要在配置文件中声明。ohos.permission.KEEP_BACKGROUND_RUNNING 权限,该权限是 normal 级别,同时还需要在配置文件中添加对应的 backgroundModes 参数。在 onStop()方法中调用 cancelBackgroundRunning?()方法可停止前台 Service。使用前台 Service 的 onStart()代码示例如下:


// 创建通知,其中 1005 为 notificationIdNotificationRequest request = new NotificationRequest(1005);NotificationRequest.NotificationNormalContent content = new NotificationRequest.NotificationNormalContent();content.setTitle("title").setText("text");NotificationRequest.NotificationContent notificationContent = new NotificationRequest.NotificationContent(content);request.setContent(notificationContent);


// 绑定通知,1005 为创建通知时传入的 notificationIdkeepBackgroundRunning(1005, request);


在配置文件中配置如下:


{


"name": ".ServiceAbility","type": "service","visible": true,"backgroundModes": ["dataTransfer","location"]}

Android

开发者创建前台服务,需要调用 startForeground(),这个方法同样需要 notificationId 和 Notification 实例:


Intent notificationIntent = new Intent(this, AndroidActivity.class);PendingIntent pendingIntent =PendingIntent.getActivity(this, 0, notificationIntent, 0);


Notification notification =new Notification.Builder(this, CHANNEL_DEFAULT_IMPORTANCE).setContentTitle(getText(R.string.notification_title)).setContentText(getText(R.string.notification_message)).setSmallIcon(R.drawable.icon).setContentIntent(pendingInte


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


nt).setTicker(getText(R.string.ticker_text)).build();startForeground(ONGOING_NOTIFICATION_ID, notification);


注意:Notification ID 不能为 0,同时在 Android 9 (API level 28) 获取更高版本中前台服务需要申明:FOREGROUND_SERVICE 权限:


<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...><uses-permission android:name="android.permission.FOREGROUND_SERVICE"/><application ...>...</application></manifest>


如果应用目标 level 高于 Android 10 (API level 29) 在清单文件中还要申明相关前台服务类型:


<manifest>...<service ... android:foregroundServiceType="location|camera" /></manifest>


代码中也要申明:


Notification notification = ...;Service.startForeground(notification,FOREGROUND_SERVICE_TYPE_LOCATION | FOREGROUND_SERVICE_TYPE_CAMERA);

绑定服务(可选)

HarmonyOS

如果 Service 需要与 Page Ability 或其他应用的 Service Ability 进行交互,则应创建用于连接的 Connection。Service 支持其他 Ability 通过 connectAbility()方法与其进行连接。 在使用 connectAbility()处理回调时,需要传入目标 Service 的 Intent 与 IAbilityConnection 的实例。IAbilityConnection 提供了两个方法供开发者实现:onAbilityConnectDone()用来处理连接的回调,onAbilityDisconnectDone()用来处理断开连接的回调。


// 创建连接回调实例 private IAbilityConnection connection = new IAbilityConnection() {// 连接到 Service 的回调 @Overridepublic void onAbilityConnectDone(ElementName elementName, IRemoteObject iRemoteObject, int resultCode) {// 在这里开发者可以拿到服务端传过来 IRemoteObject 对象,从中解析出服务端传过来的信息}


// 断开与连接的回调 @Overridepublic void onAbilityDisconnectDone(ElementName elementName, int resultCode) {}};// 连接 ServiceconnectAbility(intent, connection);


同时,Service 侧也需要在 onConnect()时返回 IRemoteObject,从而定义与 Service 进行通信的接口。onConnect()需要返回一个 IRemoteObject 对象,HarmonyOS 提供了 IRemoteObject 的默认实现,用户可以通过继承 RemoteObject 来创建自定义的实现类。Service 侧把自身的实例返回给调用侧的代码示例如下:


// 创建自定义 IRemoteObject 实现类 private class MyRemoteObject extends RemoteObject {public MyRemoteObject() {super("MyRemoteObject");}}


// 把 IRemoteObject 返回给客户端 @Overrideprotected IRemoteObject onConnect(Intent intent) {return new MyRemoteObject();}

Android

绑定服务是客户端-服务器接口中的服务器。借助绑定服务,组件(例如 Activity)可以绑定到服务、发送请求、接收响应,以及执行进程间通信 (IPC)。绑定服务通常只在为其他应用组件提供服务时处于活动状态,不会无限期在后台运行。创建提供绑定的服务时,您必须提供 IBinder,进而提供编程接口,以便客户端使用此接口与服务进行交互。开发者可以通过三种方法定义接口:扩展 Binder 类,使用 Messenger,使用 AIDL(一般不用)。


  • 扩展 Binder 类。创建代码如下:


public class LocalService extends Service {private final IBinder binder = new LocalBinder();private final Random mGenerator = new Random();


public class LocalBinder extends Binder {LocalService getService() {return LocalService.this;}}@Overridepublic IBinder onBind(Intent intent) {return binder;}


public int getRandomNumber() {return mGenerator.nextInt(100);}}


启动如下:


public class BindingActivity extends Activity {LocalService mService;boolean mBound = false;


@Overrideprotected void onStart() {super.onStart();Intent intent = new Intent(this, LocalService.class);bindService(intent, connection, Context.BIND_AUTO_CREATE);}


@Overrideprotected void onStop() {super.onStop();unbindService(connection);mBound = false;}public void onButtonClick(View v) {if (mBound) {int num = mService.getRandomNumber();...}}


private ServiceConnection connection = new ServiceConnection() {


@Overridepublic void onServiceConnected(ComponentName className,IBinder service) {LocalBinder binder = (LocalBinder) service;mService = binder.getService();mBound = true;}


@Overridepublic void onServiceDisconnected(ComponentName arg0) {mBound = false;}};}


  • 使用 Messenger。创建代码如下:


public class MessengerService extends Service {static final int MSG_SAY_HELLO = 1;


static class IncomingHandler extends Handler {private Context applicationContext;


IncomingHandler(Context context) {applicationContext = context.getApplicationContext();}


@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_SAY_HELLO:...break;default:super.handleMessage(msg);}}}Messenger mMessenger;@Overridepublic IBinder onBind(Intent intent) {...mMessenger = new Messenger(new IncomingHandler(this));return mMessenger.getBinder();}}


服务会在 Handler 的 handleMessage() 方法中接收传入的 Message,并根据 what 成员决定下一步操作。客户端只需根据服务返回的 IBinder 创建 Messenger,然后利用 send() 发送消息。例如,以下简单 Activity 展示如何绑定到服务并向服务传递 MSG_SAY_HELLO 消息:


public class ActivityMessenger extends Activity {Messenger mService = null;boolean bound;


private ServiceConnection mConnection = new ServiceConnection() {public void onServiceConnected(ComponentName className, IBinder service) {mService = new Messenger(service);bound = true;}


public void onServiceDisconnected(ComponentName className) {mService = null;bound = false;}};

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
HarmonyOS-Service&Android-Service(1),程序员中年危机