diff --git a/AccessibilityService/AccessibilityService/README.md b/AccessibilityService/AccessibilityService/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..45fcee4fce4389fb73f1f4582ad8d19ad7392264
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/README.md
@@ -0,0 +1,22 @@
+# Accessibility Service
+
+### Introduction
+
+This sample shows how to use the accessibility service. This service inherits from **AccessibleAbility** to listen for window changes, click events, and physical keys of the system to perform some operations.
+
+1. Configure the types of events to listen for in the **accessibility\_ability\_config.xml** file.
+
+2. **MyAccessibilityService** inherits from **AccessibleAbility**. It listens for screen changing events and provides prompts; listens for click events, plays voice prompts, and executes global events; listens for the volume key events to scroll the text up and down.
+
+### Usage
+
+1. Go to **Settings** \> **Accessibility features** \> **Accessibility** \> **Installed services**, enable **Accessibility**, and return to the app operation.
+
+2. Go to the app screen and touch **Click, Back to home**. The service listens to the touch of the button, broadcasts the button content, and executes the global HOME event to return to the home screen.
+
+3. Touch **KeyPressEventPage**. On the screen displayed, the text can be scrolled up and down by pressing the volume key.
+
+### Constraints
+
+This sample can only be run on large-system devices.
+
diff --git a/AccessibilityService/AccessibilityService/README_zh.md b/AccessibilityService/AccessibilityService/README_zh.md
new file mode 100644
index 0000000000000000000000000000000000000000..88881c48da90fe8a6822e6490d4f23a49773c9aa
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/README_zh.md
@@ -0,0 +1,22 @@
+# 无障碍服务
+
+### 简介
+
+本示例为用户演示无障碍服务功能的使用,继承AccessibleAbility实现无障碍服务中监听窗口变化和点击事件以及系统物理按键来做一些操作。
+
+1、accessibility\_ability\_config.xml中配制要监听事件的类型。
+
+2、MyAccessibilityService继承AccessibleAbility,实现监听窗口变化进行提示,监听按钮点击进行语音播报并执行全局事件,监听系统音量键实现文本内容的上下滚动。
+
+### 使用说明
+
+1、根据提示,前往设置-辅助功能-无障碍-已安装的服务 中打开无障碍服务的开关后返回该应用操作。
+
+2、进入此应用界面,点击“点击,返回桌面”,无障碍服务会监听按钮的点击,进行语音播报按钮内容并执行全局HOME事件,返回桌面。
+
+3、点击“系统按键事件”按钮进入新界面,该界面通过监听系统音量键实现文本内容的上下滚动。
+
+### 约束与限制
+
+本示例支持在大型设备上运行。
+
diff --git a/AccessibilityService/AccessibilityService/build.gradle b/AccessibilityService/AccessibilityService/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..b25795fc1d8bc01db48078a95070172cb77e5c2f
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/build.gradle
@@ -0,0 +1,47 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+apply plugin: 'com.huawei.ohos.app'
+
+//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
+ohos {
+ compileSdkVersion 6
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+}
+
+buildscript {
+ repositories {
+ maven {
+ url 'https://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ maven {
+ url 'http://repo.ark.tools.huawei.com/artifactory/maven-public'
+ }
+ maven {
+ url 'http://mirrors.tools.huawei.com/maven/'
+ }
+ }
+ dependencies {
+ classpath 'com.huawei.ohos:hap:2.4.5.0'
+ }
+}
+
+allprojects {
+ repositories {
+ maven {
+ url 'https://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ maven {
+ url 'http://repo.ark.tools.huawei.com/artifactory/maven-public'
+ }
+ maven {
+ url 'http://mirrors.tools.huawei.com/maven/'
+ }
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/build.gradle b/AccessibilityService/AccessibilityService/entry/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..b1b882781763d89e6ecfc352a0b382a7efb80354
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/build.gradle
@@ -0,0 +1,20 @@
+apply plugin: 'com.huawei.ohos.hap'
+//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
+ohos {
+ compileSdkVersion 6
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+ buildTypes {
+ release {
+ proguardOpt {
+ proguardEnabled false
+ rulesFiles 'proguard-rules.pro'
+ }
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/config.json b/AccessibilityService/AccessibilityService/entry/src/main/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..a79e90f4603d00b17117b597f7cac782221fff85
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/config.json
@@ -0,0 +1,68 @@
+{
+ "app": {
+ "bundleName": "ohos.samples.accessibilityservice",
+ "vendor": "samples",
+ "version": {
+ "code": 1000000,
+ "name": "1.0.0"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "ohos.samples.accessibilityservice",
+ "name": ".MyApplication",
+ "mainAbility": ".MainAbility",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "entry",
+ "moduleType": "entry",
+ "installationFree": false
+ },
+ "abilities": [
+ {
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ],
+ "orientation": "unspecified",
+ "name": ".MainAbility",
+ "icon": "$media:icon",
+ "description": "$string:mainability_description",
+ "label": "$string:entry_MainAbility",
+ "type": "page",
+ "launchType": "standard"
+ },
+ {
+ "name": ".service.MyAccessibilityService",
+ "visible": true,
+ "type": "service",
+ "permissions": [
+ "ohos.permission.CONNECT_ACCESSIBILITY_ABILITY"
+ ],
+ "skills": [
+ {
+ "actions": ["ohos.accessibilityservice.AccessibilityService"]
+ }
+ ],
+ "metaData": {
+ "customizeData": [
+ {
+ "name": "ohos.accessibleability",
+ "extra": "$profile:accessibility_ability_config"
+ }
+ ],
+ "results": []
+ }
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/MainAbility.java b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/MainAbility.java
new file mode 100644
index 0000000000000000000000000000000000000000..10b7e314c982618f10d51096b36e4fb47af3b7f2
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/MainAbility.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.accessibilityservice;
+
+import ohos.samples.accessibilityservice.slice.MainAbilitySlice;
+import ohos.aafwk.ability.Ability;
+import ohos.aafwk.content.Intent;
+
+/**
+ * MainAbility
+ *
+ * @since 2021-07-23
+ */
+public class MainAbility extends Ability {
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setMainRoute(MainAbilitySlice.class.getName());
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/MyApplication.java b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/MyApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..d49bd1424228737dfa31083b8e98a1557b260e05
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/MyApplication.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.accessibilityservice;
+
+import ohos.aafwk.ability.AbilityPackage;
+
+/**
+ * MyApplication
+ *
+ * @since 2021-07-23
+ */
+public class MyApplication extends AbilityPackage {
+ @Override
+ public void onInitialize() {
+ super.onInitialize();
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/service/MyAccessibilityService.java b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/service/MyAccessibilityService.java
new file mode 100644
index 0000000000000000000000000000000000000000..020c49f4d1dd686c1b5146a28358aa9a225314cf
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/service/MyAccessibilityService.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.accessibilityservice.service;
+
+import ohos.accessibility.AccessibilityEventInfo;
+import ohos.accessibility.ability.AccessibilityInfo;
+import ohos.accessibility.ability.AccessibleAbility;
+import ohos.agp.window.dialog.ToastDialog;
+import ohos.global.resource.Element;
+import ohos.global.resource.NotExistException;
+import ohos.global.resource.WrongTypeException;
+import ohos.multimodalinput.event.KeyEvent;
+import ohos.samples.accessibilityservice.ResourceTable;
+import ohos.samples.accessibilityservice.tts.TtsManager;
+import ohos.samples.accessibilityservice.utils.LogUtils;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Optional;
+
+/**
+ * MyAccessibilityService
+ *
+ * @since 2021-07-23
+ */
+public class MyAccessibilityService extends AccessibleAbility {
+ private static final String TAG = MyAccessibilityService.class.getSimpleName();
+
+ private static final String BUNDLE_NAME = "ohos.samples.accessibilityservice";
+
+ private static boolean isNeedCustomVolumeKey = false;
+
+ private boolean isInSpecialApp = false;
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEventInfo accessibilityEventInfo) {
+ int eventType = accessibilityEventInfo.getAccessibilityEventType();
+ int windowType = accessibilityEventInfo.getWindowChangeTypes();
+ LogUtils.info(TAG, "onAccessibilityEvent,enventType=" + eventType + "windowType" + windowType);
+ switch (eventType) {
+ case AccessibilityEventInfo.TYPE_VIEW_CLICKED_EVENT:
+ LogUtils.info(TAG, "type view clicked");
+ ArrayList contentList = accessibilityEventInfo.getContentList();
+ try {
+ Element element = getContext().getResourceManager()
+ .getElement(ResourceTable.String_string_button_perform_click);
+ String string = element.getString();
+ for (CharSequence content : contentList) {
+ LogUtils.info(TAG, "type view clicked,content:" + content.toString() + ",string:" + string);
+ if (content.toString().equals(string)) {
+ LogUtils.info(TAG, "type view clicked,content:equals");
+ TtsManager.getInstance().speakText(content.toString(), null);
+ performCommonAction(AccessibleAbility.GLOBAL_ACTION_HOME);
+ }
+ }
+ } catch (IOException | NotExistException | WrongTypeException e) {
+ LogUtils.error(TAG, "type view clicked,Exception:" + e.getMessage());
+ }
+ break;
+ default:
+ break;
+ }
+ switch (windowType) {
+ case AccessibilityEventInfo.WINDOWS_CHANGE_ADDED:
+ Optional accessibilityInfo = getRootAccessibilityInfo();
+ String bundleName = accessibilityInfo.get().getBundleName().toString();
+ LogUtils.info(TAG, "WINDOWS_CHANGE_ADDED:" + bundleName);
+ if (bundleName.equals(BUNDLE_NAME) && isInSpecialApp == false) {
+ isInSpecialApp = true;
+ LogUtils.info(TAG, "You are in the " + bundleName);
+ runUIThread(() -> new ToastDialog(getContext()).setText("You are in the " + BUNDLE_NAME).show());
+ }
+ break;
+ case AccessibilityEventInfo.WINDOWS_CHANGE_REMOVED:
+ Optional accessibilityInfo1 = getRootAccessibilityInfo();
+ LogUtils.info(TAG, "WINDOWS_CHANGE_REMOVED");
+ if (!accessibilityInfo1.get().getBundleName().equals(BUNDLE_NAME)) {
+ isInSpecialApp = false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public static void setNeedCustomVolumeKey(boolean needCustomVolumeKey) {
+ isNeedCustomVolumeKey = needCustomVolumeKey;
+ }
+
+ @Override
+ public void onInterrupt() {
+ }
+
+ private void runUIThread(Runnable runnable) {
+ getUITaskDispatcher().asyncDispatch(runnable);
+ }
+
+ @Override
+ protected void onAbilityConnected() {
+ LogUtils.info(TAG, "onAbilityConnected");
+ }
+
+ @Override
+ protected boolean onKeyPressEvent(KeyEvent keyEvent) {
+ LogUtils.info(TAG, "onKeyPressEvent,isNeedCustomVolumeKey:" + isNeedCustomVolumeKey);
+ if (isNeedCustomVolumeKey) {
+ if (keyEvent.getKeyCode() == KeyEvent.KEY_VOLUME_DOWN || keyEvent.getKeyCode() == KeyEvent.KEY_VOLUME_UP) {
+ if (keyEvent.getKeyCode() == KeyEvent.KEY_VOLUME_DOWN && keyEvent.isKeyDown()) {
+ runUIThread(() -> {
+ try {
+ Class mClass = Class.forName("ohos.samples.accessibilityservice.slice.KeyPressEventSlice");
+ mClass.getDeclaredMethod("scrollDown").invoke(mClass.newInstance(), new Object[]{});
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException
+ | ClassNotFoundException | InstantiationException e) {
+ LogUtils.error(TAG, "KEY_VOLUME_DOWN error:" + e.getMessage());
+ }
+ });
+ }
+ if (keyEvent.getKeyCode() == KeyEvent.KEY_VOLUME_UP && keyEvent.isKeyDown()) {
+ runUIThread(() -> {
+ try {
+ Class mClass = Class.forName("ohos.samples.accessibilityservice.slice.KeyPressEventSlice");
+ mClass.getDeclaredMethod("scrollUp").invoke(mClass.newInstance(), new Object[]{});
+ } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException
+ | ClassNotFoundException | InstantiationException e) {
+ LogUtils.error(TAG, "KEY_VOLUME_UP error:" + e.getMessage());
+ }
+ });
+ }
+ return true;
+ }
+ }
+ return super.onKeyPressEvent(keyEvent);
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/slice/KeyPressEventSlice.java b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/slice/KeyPressEventSlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..cab0cb1fc37592abd4d91f60b1561fdca75148e3
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/slice/KeyPressEventSlice.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.accessibilityservice.slice;
+
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.agp.components.Component;
+import ohos.agp.components.TabList;
+import ohos.samples.accessibilityservice.ResourceTable;
+import ohos.samples.accessibilityservice.service.MyAccessibilityService;
+import ohos.samples.accessibilityservice.utils.LogUtils;
+
+/**
+ * MainAbilitySlice
+ *
+ * @since 2021-07-23
+ */
+public class KeyPressEventSlice extends AbilitySlice {
+ private static final String TAG = KeyPressEventSlice.class.getSimpleName();
+
+ private static TabList tabList;
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_ability_key_press_event);
+ MyAccessibilityService.setNeedCustomVolumeKey(true);
+ initComponents();
+ }
+
+ /**
+ * scrollUp
+ */
+ public void scrollUp() {
+ LogUtils.info(TAG, "scrollUp");
+ if (tabList != null && tabList.getSelectedTabIndex() > 0) {
+ tabList.selectTabAt(tabList.getSelectedTabIndex() - 1);
+ }
+ }
+
+ /**
+ * scrollDown
+ */
+ public void scrollDown() {
+ LogUtils.info(TAG, "scrollDown");
+ if (tabList != null && tabList.getSelectedTabIndex() < tabList.getTabCount() - 1) {
+ tabList.selectTabAt(tabList.getSelectedTabIndex() + 1);
+ }
+ }
+
+ private void initComponents() {
+ Component component = findComponentById(ResourceTable.Id_tabList);
+ if (component instanceof TabList) {
+ tabList = (TabList) component;
+ }
+ for (int i = 0; i < 10; i++) {
+ TabList.Tab tab = tabList.new Tab(getContext());
+ tab.setText(ResourceTable.String_text_content);
+ tabList.addTab(tab);
+ }
+ tabList.selectTabAt(0);
+ }
+
+
+ @Override
+ public void onActive() {
+ super.onActive();
+ }
+
+ @Override
+ public void onForeground(Intent intent) {
+ super.onForeground(intent);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ tabList.removeAllComponents();
+ MyAccessibilityService.setNeedCustomVolumeKey(false);
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/slice/MainAbilitySlice.java b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/slice/MainAbilitySlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..ad3f7e51fa4e7bee59dc2ba66c4136b3236355c2
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/slice/MainAbilitySlice.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.accessibilityservice.slice;
+
+import ohos.agp.components.Component;
+import ohos.agp.window.dialog.ToastDialog;
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.samples.accessibilityservice.ResourceTable;
+import ohos.samples.accessibilityservice.tts.TtsManager;
+
+/**
+ * MainAbilitySlice
+ *
+ * @since 2021-07-23
+ */
+public class MainAbilitySlice extends AbilitySlice {
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_ability_main);
+ TtsManager.getInstance().init(this);
+ initComponents();
+ }
+
+ private void initComponents() {
+ Component performBtn = findComponentById(ResourceTable.Id_perform_button);
+ performBtn.setClickedListener(this::onClickListener);
+ Component keyEventButton = findComponentById(ResourceTable.Id_keyPressEvent_button);
+ keyEventButton.setClickedListener(this::enterKeyPressEventPage);
+ }
+
+ private void enterKeyPressEventPage(Component component) {
+ present(new KeyPressEventSlice(), new Intent());
+ }
+
+ private void onClickListener(Component component) {
+ String tips = getString(ResourceTable.String_string_button_perform_click);
+ new ToastDialog(getContext()).setText(tips).show();
+ }
+
+ @Override
+ public void onActive() {
+ super.onActive();
+ }
+
+ @Override
+ public void onForeground(Intent intent) {
+ super.onForeground(intent);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ TtsManager.getInstance().destroy();
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/tts/TtsManager.java b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/tts/TtsManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..167040b69d3163836bc52b2517e6f67f3692f924
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/tts/TtsManager.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.accessibilityservice.tts;
+
+import ohos.ai.tts.TtsClient;
+import ohos.ai.tts.TtsListener;
+import ohos.ai.tts.TtsParams;
+import ohos.ai.tts.constants.TtsEvent;
+import ohos.app.Context;
+import ohos.data.distributed.common.KvManagerConfig;
+import ohos.data.distributed.common.KvManagerFactory;
+import ohos.samples.accessibilityservice.utils.LogUtils;
+import ohos.utils.PacMap;
+
+/**
+ * TtsManager
+ *
+ * @since 2021-07-23
+ */
+public class TtsManager {
+ private static final String TAG = TtsManager.class.getSimpleName();
+
+ private static TtsManager instance;
+
+ private final TtsClient ttsClient;
+
+ private Context mContext;
+
+ private final TtsListener tsListener = new TtsListener() {
+ @Override
+ public void onStart(String s) {
+ LogUtils.info(TAG, "TtsListener,onStart:" + s);
+ }
+
+ @Override
+ public void onProgress(String s, byte[] bytes, int i) {
+ LogUtils.info(TAG, "TtsListener,onProgress:" + s);
+ }
+
+ @Override
+ public void onFinish(String s) {
+ LogUtils.info(TAG, "TtsListener,onFinish:" + s);
+ }
+
+ @Override
+ public void onError(String s, String s1) {
+ LogUtils.info(TAG, "TtsListener,onError:" + s);
+ }
+
+ @Override
+ public void onEvent(int event, PacMap pacMap) {
+ LogUtils.info(TAG, "TtsListener,onEvent:" + event);
+ if (event == TtsEvent.CREATE_TTS_CLIENT_SUCCESS) {
+ TtsParams ttsParams = new TtsParams();
+ String deviceId = KvManagerFactory.getInstance()
+ .createKvManager(new KvManagerConfig((mContext))).getLocalDeviceInfo().getId();
+ ttsParams.setDeviceId(deviceId);
+ ttsClient.init(ttsParams);
+ }
+ }
+
+ @Override
+ public void onSpeechStart(String s) {
+ LogUtils.info(TAG, "TtsListener,onSpeechStart:" + s);
+ }
+
+ @Override
+ public void onSpeechProgressChanged(String s, int i) {
+ LogUtils.info(TAG, "TtsListener,onSpeechProgressChanged:" + s);
+ }
+
+ @Override
+ public void onSpeechFinish(String s) {
+ LogUtils.info(TAG, "TtsListener,onSpeechFinish:" + s);
+ }
+ };
+
+ /**
+ * getInstance
+ *
+ * @return TtsManager
+ */
+ public static TtsManager getInstance() {
+ if (instance == null) {
+ synchronized (TtsManager.class) {
+ instance = new TtsManager();
+ }
+ }
+ return instance;
+ }
+
+ TtsManager() {
+ ttsClient = TtsClient.getInstance();
+ }
+
+ /**
+ * log error
+ *
+ * @param context Context
+ */
+ public void init(Context context) {
+ mContext = context;
+ ttsClient.create(context, tsListener);
+ }
+
+ /**
+ * log error
+ *
+ * @param text String
+ * @param utteranceId String
+ */
+ public void speakText(String text, String utteranceId) {
+ ttsClient.speakText(text, utteranceId);
+ }
+
+ /**
+ * destroy
+ */
+ public void destroy() {
+ ttsClient.destroy();
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/utils/LogUtils.java b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/utils/LogUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..59363ca8fc1afa7993eb039d0ead271450a30564
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/java/ohos/samples/accessibilityservice/utils/LogUtils.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.accessibilityservice.utils;
+
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+
+import java.util.Objects;
+
+/**
+ * LogUtils
+ *
+ * @since 2021-07-23
+ */
+public class LogUtils {
+ private static final String APP_NAME = "AccessibilityService";
+ private static final HiLogLabel LABAL_LOG = new HiLogLabel(3, 0xD000f00, APP_NAME);
+ private static final String LOG_FORMAT = "%{public}s:%{public}s";
+
+ private LogUtils() {
+ }
+
+ /**
+ * log info
+ *
+ * @param className String
+ * @param msg String
+ */
+ public static void info(String className, String msg) {
+ HiLog.info(LABAL_LOG, LOG_FORMAT, getLogPrefix(className), msg);
+ }
+
+ /**
+ * log error
+ *
+ * @param className String
+ * @param msg String
+ */
+ public static void error(String className, String msg) {
+ HiLog.error(LABAL_LOG, LOG_FORMAT, getLogPrefix(className), msg);
+ }
+
+ private static String getLogPrefix(String tag) {
+ Thread currentThread = Thread.currentThread();
+ String threadName = currentThread.getName();
+ StackTraceElement[] stackTraceElements = currentThread.getStackTrace();
+ int lineNum = 0;
+ for (int index = 0; index < stackTraceElements.length; index++) {
+ if (Objects.equals(stackTraceElements[index].getClassName(), LogUtils.class.getName())
+ && stackTraceElements.length > index + 1
+ && !Objects.equals(stackTraceElements[index + 1].getClassName(), LogUtils.class.getName())) {
+ lineNum = stackTraceElements[index + 1].getLineNumber();
+ }
+ }
+ return "[" + threadName + "]" + "(" + tag + ".java" + lineNum + ")";
+ }
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/float.json b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..c9a3fdc5cd5f813cfe5cf31d91a91de9a82f84f9
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,28 @@
+{
+ "float": [
+ {
+ "name": "layout_padding",
+ "value": "20vp"
+ },
+ {
+ "name": "button_height",
+ "value": "40vp"
+ },
+ {
+ "name": "button_text_size",
+ "value": "18fp"
+ },
+ {
+ "name": "tips_text_size",
+ "value": "17fp"
+ },
+ {
+ "name": "content_text_size",
+ "value": "18fp"
+ },
+ {
+ "name": "layout_margin",
+ "value": "20vp"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/pattern.json b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/pattern.json
new file mode 100644
index 0000000000000000000000000000000000000000..6ab70783157d6f75ce5ac6a00e53639eb04e09b8
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/pattern.json
@@ -0,0 +1,43 @@
+{
+ "pattern": [
+ {
+ "name": "button_base",
+ "value": [
+ {
+ "name": "width",
+ "value": "200vp"
+ },
+ {
+ "name": "height",
+ "value": "$float:button_height"
+ },
+ {
+ "name": "text_size",
+ "value": "$float:button_text_size"
+ },
+ {
+ "name": "margin",
+ "value": "20vp"
+ },
+ {
+ "name": "layout_alignment",
+ "value": "horizontal_center"
+ }
+ ]
+ },
+ {
+ "name": "button_blue",
+ "parent": "button_base",
+ "value": [
+ {
+ "name": "background_element",
+ "value": "$graphic:button_blue"
+ },
+ {
+ "name": "text_color",
+ "value": "#FFFFFF"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/string.json b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..ef0d88e10eb5233c715c013ed413eb21c04946d1
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,48 @@
+{
+ "string": [
+ {
+ "name": "entry_MainAbility",
+ "value": "AccessibleAbility"
+ },
+ {
+ "name": "mainability_description",
+ "value": "AccessibleAbility"
+ },
+ {
+ "name": "accessibility_service_description",
+ "value": "accessibleService"
+ },
+ {
+ "name": "mainability_HelloWorld",
+ "value": "Hello World"
+ },
+ {
+ "name": "string_button_perform_click",
+ "value": "Click,back to home"
+ },
+ {
+ "name": "string_button_accessibility_settings_click",
+ "value": "goto AccessibilitySettings"
+ },
+ {
+ "name": "Tips1",
+ "value": "Go Settings-Accessibility features-Accessbility-Installed services,enable AccessibleAbility,then back to this application."
+ },
+ {
+ "name": "Tips2",
+ "value": "After turning on the accessibility service switch:\n1. There will be a prompt when you listen to the application interface\n2. Click the button to perform the home button operation\n3. The volume key operation of the system key event interface will execute the text scroll up and down to select"
+ },
+ {
+ "name": "string_button_key_press_event",
+ "value": "KeyPressEventPage"
+ },
+ {
+ "name": "key_event_tips",
+ "value": "Press the volume up button to scroll up, press the volume down button to scroll down."
+ },
+ {
+ "name": "text_content",
+ "value": "This is a text content."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/background_ability_main.xml b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/background_ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..44fb1387798e43f7b7fdf3f4886d8213bcc2618b
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/background_ability_main.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue.xml b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c7ac8a58fa538cb49c2002099764577c5465bfe3
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue_empty.xml b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue_empty.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e90b693d2efa580d4767d55250f0e5a2c6ab5958
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue_empty.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue_pressed.xml b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue_pressed.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fe2343b5ec2010eb2435bcee605b37b0c3f29d97
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/graphic/button_blue_pressed.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/layout/ability_key_press_event.xml b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/layout/ability_key_press_event.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8d124272584dc2899ddacedcf69811e284242960
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/layout/ability_key_press_event.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/layout/ability_main.xml b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/layout/ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7fb2b26615a032991de0aae82328a26c8b392ce8
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/layout/ability_main.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/media/icon.png b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/media/icon.png differ
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/base/profile/accessibility_ability_config.xml b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/profile/accessibility_ability_config.xml
new file mode 100644
index 0000000000000000000000000000000000000000..007d5a184759e15433e7eec6194dfa6cb6c7ad96
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/base/profile/accessibility_ability_config.xml
@@ -0,0 +1,28 @@
+
+
+
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/en/element/string.json b/AccessibilityService/AccessibilityService/entry/src/main/resources/en/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..b24f1d12f352001375e6977c3181b9ced1312960
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/en/element/string.json
@@ -0,0 +1,44 @@
+{
+ "string": [
+ {
+ "name": "entry_MainAbility",
+ "value": "AccessibleAbility"
+ },
+ {
+ "name": "mainability_description",
+ "value": "Java_Empty Ability"
+ },
+ {
+ "name": "mainability_HelloWorld",
+ "value": "Hello World"
+ },
+ {
+ "name": "string_button_perform_click",
+ "value": "Click,back to home"
+ },
+ {
+ "name": "string_button_accessibility_settings_click",
+ "value": "goto AccessibilitySettings"
+ },
+ {
+ "name": "Tips1",
+ "value": "Go Settings-Accessibility features-Accessbility-Installed services,enable AccessibleAbility,then back to this application."
+ },
+ {
+ "name": "Tips2",
+ "value": "After turning on the accessibility service switch:\n1. There will be a prompt when you listen to the application interface\n2. Click the button to perform the home button operation\n3. The volume key operation of the system key event interface will execute the text scroll up and down to select"
+ },
+ {
+ "name": "string_button_key_press_event",
+ "value": "KeyPressEventPage"
+ },
+ {
+ "name": "key_event_tips",
+ "value": "Press the volume up button to scroll up, press the volume down button to scroll down."
+ },
+ {
+ "name": "text_content",
+ "value": "This is a text content."
+ }
+ ]
+}
diff --git a/AccessibilityService/AccessibilityService/entry/src/main/resources/zh/element/string.json b/AccessibilityService/AccessibilityService/entry/src/main/resources/zh/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..a13a6732380dc2e6c6b8aecdd35ade6620cec338
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/entry/src/main/resources/zh/element/string.json
@@ -0,0 +1,40 @@
+{
+ "string": [
+ {
+ "name": "entry_MainAbility",
+ "value": "无障碍服务"
+ },
+ {
+ "name": "mainability_description",
+ "value": "无障碍服务"
+ },
+ {
+ "name": "string_button_perform_click",
+ "value": "点击,返回桌面"
+ },
+ {
+ "name": "string_button_accessibility_settings_click",
+ "value": "前往无障碍服务设置"
+ },
+ {
+ "name": "Tips1",
+ "value": "前往设置-辅助功能-无障碍-已安装的服务,打开无障碍服务的开关,然后返回该应用操作。"
+ },
+ {
+ "name": "Tips2",
+ "value": "打开无障碍服务开关后:\n1、监听到进入该应用界面会有提示\n2、点击按钮执行home键操作\n3、系统按键事件界面音量键操作会执行文本上下滚动选中"
+ },
+ {
+ "name": "string_button_key_press_event",
+ "value": "系统按键事件"
+ },
+ {
+ "name": "key_event_tips",
+ "value": "按音量上键向上滚动,按音量下键向下滚动。"
+ },
+ {
+ "name": "text_content",
+ "value": "这是一个文本内容。"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AccessibilityService/AccessibilityService/screenshots/device/key_press_event.png b/AccessibilityService/AccessibilityService/screenshots/device/key_press_event.png
new file mode 100644
index 0000000000000000000000000000000000000000..984f2cb5588bdaa91388a69fa441e79f05276058
Binary files /dev/null and b/AccessibilityService/AccessibilityService/screenshots/device/key_press_event.png differ
diff --git a/AccessibilityService/AccessibilityService/screenshots/device/main.png b/AccessibilityService/AccessibilityService/screenshots/device/main.png
new file mode 100644
index 0000000000000000000000000000000000000000..78a92f6a7fc25c1ef2e10b36fcb6a8b4dae5c0d8
Binary files /dev/null and b/AccessibilityService/AccessibilityService/screenshots/device/main.png differ
diff --git a/AccessibilityService/AccessibilityService/settings.gradle b/AccessibilityService/AccessibilityService/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..4773db73233a570c2d0c01a22e75321acfbf7a07
--- /dev/null
+++ b/AccessibilityService/AccessibilityService/settings.gradle
@@ -0,0 +1 @@
+include ':entry'
diff --git a/data/Search/README.md b/data/Search/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a1d4bdd6c09dbcecb17dc5213a6ca7f8ad2bb667
--- /dev/null
+++ b/data/Search/README.md
@@ -0,0 +1,26 @@
+# Search Service
+
+### Introduction
+
+The search service provides developers with the same full-text search capabilities as a search engine. This sample demonstrates how to use common search APIs to create location index forms and insert, update, delete, and search location index data.
+
+### Usage
+
+1. Connect to the search service when starting an app.
+
+2. Touch **build location indexForm** and create a location index form. After a success message is returned, touch **read indexForm**. The location information index, including **title**, **tag**, **bucket\_id**, **latitude**, **longitude** and **device\_id**, is displayed.
+
+3. Touch **insert location indexData** and insert 10 pieces of location data. A success message is returned.
+
+4. Touch **update location indexData** to update location information.
+
+5. Touch **get search hint count**. For example, search for "location" in the **title** and **tag** fields. The search criteria are as follows: **bucket\_id** and **CommonItem.IDENTIFIER** are from **0** to **5**. An index is hit if "location" is found in **tag** or **CommonItem.TITLE**. The latitude is **\[-80.0f, 80.0f\]**, and the longitude is **\[-90.0, 90.0\]**. Sort the search results in ascending order based on **CommonItem.CATEGORY**, and in descending order based on **tag** if the values of **CommonItem.CATEGORY** are the same. The number of location index data records that meet the search criteria is returned.
+
+6. Touch **search by group** **search by page** to query the location index data. The search criteria are the same as those in step 5. The data meeting the search criteria is returned.
+
+7. Touch **delete indexData by query** or **delete indexData** to delete location index data.
+
+### Constraints
+
+This sample can only be run on large-system devices.
+
diff --git a/data/Search/README_zh.md b/data/Search/README_zh.md
new file mode 100644
index 0000000000000000000000000000000000000000..42af47739a1022337c2267150f1b4354574eb908
--- /dev/null
+++ b/data/Search/README_zh.md
@@ -0,0 +1,26 @@
+# 融合搜索
+
+### 简介
+
+融合搜索为开发者提供搜索引擎级的全文搜索能力,本示例为用户演示融合搜索的索引构造、索引数据插入、更新、删除和搜索等常用接口的使用。
+
+### 使用说明
+
+1、启动应用时连接融合搜索服务。
+
+2、点击“构造定位索引”构造定位信息索引,返回成功后点击“读取索引”,返回构造的定位信息的索引,包括title,tag,bucket\_id,latitude,longitude,device\_id。
+
+3、点击“插入定位数据”插入10条定位信息,返回成功。
+
+4、点击“更新定位数据”来更新位置信息。
+
+5、点击“获取查询索引条数”,假设用户输入是“定位”,要在"title", "tag"这两个域上发起搜索,搜索在bucket\_id和CommonItem.IDENTIFIER在0-5之间,在"tag"或者CommonItem.TITLE上命中"位置",纬度必须在\[-80.0f, 80.0f\],经度必须在\[-90.0, 90.0\]进行搜索,先在CommonItem.CATEGORY字段上升序排序,只有在CommonItem.CATEGORY上相同时,才会继续在"tag"上降序排序。此处返回满足查询条件的索引数据的条数。
+
+6、点击“分组搜索”和“分页搜索”分别进行定位索引数据的查询,查询条件同上,这里返回查询到的数据。
+
+7、操作完成可以点击“删除索引数据”或“通过查询语句删除索引数据”来完成删除索引数据。
+
+### 约束与限制
+
+本示例支持在大型设备上运行。
+
diff --git a/data/Search/build.gradle b/data/Search/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..c9499304b51dd3090343af95ffd321db4e833d17
--- /dev/null
+++ b/data/Search/build.gradle
@@ -0,0 +1,35 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+apply plugin: 'com.huawei.ohos.app'
+
+//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
+ohos {
+ compileSdkVersion 6
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+}
+
+buildscript {
+ repositories {
+ maven {
+ url 'https://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ }
+ dependencies {
+ classpath 'com.huawei.ohos:hap:2.4.5.0'
+ }
+}
+
+allprojects {
+ repositories {
+ maven {
+ url 'https://repo.huaweicloud.com/repository/maven/'
+ }
+ maven {
+ url 'https://developer.huawei.com/repo/'
+ }
+ }
+}
diff --git a/data/Search/entry/build.gradle b/data/Search/entry/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..b1b882781763d89e6ecfc352a0b382a7efb80354
--- /dev/null
+++ b/data/Search/entry/build.gradle
@@ -0,0 +1,20 @@
+apply plugin: 'com.huawei.ohos.hap'
+//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510
+ohos {
+ compileSdkVersion 6
+ defaultConfig {
+ compatibleSdkVersion 4
+ }
+ buildTypes {
+ release {
+ proguardOpt {
+ proguardEnabled false
+ rulesFiles 'proguard-rules.pro'
+ }
+ }
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar', '*.har'])
+}
diff --git a/data/Search/entry/src/main/config.json b/data/Search/entry/src/main/config.json
new file mode 100644
index 0000000000000000000000000000000000000000..c8437170c397af749b221b909a52c778b9bcc5e4
--- /dev/null
+++ b/data/Search/entry/src/main/config.json
@@ -0,0 +1,51 @@
+{
+ "app": {
+ "bundleName": "ohos.samples.search",
+ "vendor": "samples",
+ "version": {
+ "code": 1000000,
+ "name": "1.0.0"
+ }
+ },
+ "deviceConfig": {},
+ "module": {
+ "package": "ohos.samples.search",
+ "name": ".MyApplication",
+ "mainAbility": "ohos.samples.search.MainAbility",
+ "deviceType": [
+ "phone"
+ ],
+ "distro": {
+ "deliveryWithInstall": true,
+ "moduleName": "entry",
+ "moduleType": "entry",
+ "installationFree": false
+ },
+ "abilities": [
+ {
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ],
+ "orientation": "unspecified",
+ "name": ".MainAbility",
+ "icon": "$media:icon",
+ "description": "$string:mainability_description",
+ "label": "$string:app_name",
+ "type": "page",
+ "launchType": "standard"
+ }
+ ],
+ "reqPermissions": [
+ {
+ "name": "ohos.permission.ACCESS_SEARCH_SERVICE"
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/data/Search/entry/src/main/java/ohos/samples/search/MainAbility.java b/data/Search/entry/src/main/java/ohos/samples/search/MainAbility.java
new file mode 100644
index 0000000000000000000000000000000000000000..dcb676223d0977d1ac356b8591e56c5e16af6bfb
--- /dev/null
+++ b/data/Search/entry/src/main/java/ohos/samples/search/MainAbility.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.search;
+
+import ohos.samples.search.slice.MainAbilitySlice;
+import ohos.aafwk.ability.Ability;
+import ohos.aafwk.content.Intent;
+
+/**
+ * MainAbility
+ *
+ * @since 2021-07-23
+ */
+public class MainAbility extends Ability {
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setMainRoute(MainAbilitySlice.class.getName());
+ }
+}
diff --git a/data/Search/entry/src/main/java/ohos/samples/search/MyApplication.java b/data/Search/entry/src/main/java/ohos/samples/search/MyApplication.java
new file mode 100644
index 0000000000000000000000000000000000000000..bcca90f3bac22cccc6b777180ebfc362e4e2c893
--- /dev/null
+++ b/data/Search/entry/src/main/java/ohos/samples/search/MyApplication.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.search;
+
+import ohos.aafwk.ability.AbilityPackage;
+
+/**
+ * MyApplication
+ *
+ * @since 2021-07-23
+ */
+public class MyApplication extends AbilityPackage {
+ @Override
+ public void onInitialize() {
+ super.onInitialize();
+ }
+}
diff --git a/data/Search/entry/src/main/java/ohos/samples/search/slice/MainAbilitySlice.java b/data/Search/entry/src/main/java/ohos/samples/search/slice/MainAbilitySlice.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8758423709566111b7b66704dea55560ca6aa31
--- /dev/null
+++ b/data/Search/entry/src/main/java/ohos/samples/search/slice/MainAbilitySlice.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.search.slice;
+
+import ohos.agp.components.Component;
+import ohos.agp.components.Text;
+import ohos.app.dispatcher.TaskDispatcher;
+import ohos.app.dispatcher.task.TaskPriority;
+import ohos.data.search.SearchAbility;
+import ohos.data.search.connect.ServiceConnectCallback;
+import ohos.samples.search.ResourceTable;
+import ohos.aafwk.ability.AbilitySlice;
+import ohos.aafwk.content.Intent;
+import ohos.samples.search.utils.LogUtils;
+import ohos.samples.search.utils.SearchUtils;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * MainAbilitySlice
+ *
+ * @since 2021-07-23
+ */
+public class MainAbilitySlice extends AbilitySlice {
+ private static final String TAG = MainAbilitySlice.class.getSimpleName();
+
+ private SearchAbility searchAbility;
+
+ private SearchUtils searUtils;
+
+ private Text searchResult;
+
+ @Override
+ public void onStart(Intent intent) {
+ super.onStart(intent);
+ super.setUIContent(ResourceTable.Layout_ability_main);
+ initComponents();
+ connectService();
+ }
+
+ private void connectService() {
+ LogUtils.info(TAG, "connect search service");
+ TaskDispatcher task = getGlobalTaskDispatcher(TaskPriority.DEFAULT);
+ searchAbility = new SearchAbility(getContext());
+ searUtils = new SearchUtils(getContext(), searchAbility);
+ task.asyncDispatch(() -> {
+ CountDownLatch lock = new CountDownLatch(1);
+
+ // connect to SearchService
+ searchAbility.connect(new ServiceConnectCallback() {
+ @Override
+ public void onConnect() {
+ lock.countDown();
+ }
+
+ @Override
+ public void onDisconnect() {
+ }
+ });
+ try {
+ lock.await(3000, TimeUnit.MILLISECONDS);
+ if (searchAbility.hasConnected()) {
+ searchResult.setText(ResourceTable.String_connect_service_succeed);
+ } else {
+ searchResult.setText(ResourceTable.String_connect_service_failed);
+ }
+ } catch (InterruptedException e) {
+ LogUtils.info(TAG, "connect search service failed");
+ }
+ });
+ }
+
+ private void initComponents() {
+ Component btnBuildIndexForms = findComponentById(ResourceTable.Id_btnBuildIndexForms);
+ btnBuildIndexForms.setClickedListener(this::buildIndexForms);
+ Component btnReadIndexForms = findComponentById(ResourceTable.Id_btnReadIndexForms);
+ btnReadIndexForms.setClickedListener(this::readIndexForms);
+ Component btnInsertIndexData = findComponentById(ResourceTable.Id_btnInsertIndexData);
+ btnInsertIndexData.setClickedListener(this::insertIndexData);
+ Component btnUpdateIndexData = findComponentById(ResourceTable.Id_btnUpdateIndexData);
+ btnUpdateIndexData.setClickedListener(this::updateIndexData);
+ Component btnDeleteIndexData = findComponentById(ResourceTable.Id_btnDeleteIndexData);
+ btnDeleteIndexData.setClickedListener(this::deleteIndexData);
+ Component btnDeleteIndexDataByQuery = findComponentById(ResourceTable.Id_btnDeleteIndexDataByQuery);
+ btnDeleteIndexDataByQuery.setClickedListener(this::deleteByQuery);
+ Component btnGetSearchHitCount = findComponentById(ResourceTable.Id_btnGetHitCount);
+ btnGetSearchHitCount.setClickedListener(this::getSearchHitCount);
+ Component btnSearchByGroup = findComponentById(ResourceTable.Id_btnSearchByGroup);
+ btnSearchByGroup.setClickedListener(this::searchByGroup);
+ Component btnSearchByPage = findComponentById(ResourceTable.Id_btnSearchByPage);
+ btnSearchByPage.setClickedListener(this::searchByPage);
+
+ Component searchComponent = findComponentById(ResourceTable.Id_searchResult);;
+ if (searchComponent instanceof Text) {
+ searchResult = (Text) searchComponent;
+ }
+ }
+
+ private void searchByPage(Component component) {
+ searchResult.setText(searUtils.searchByPage());
+ }
+
+ private void searchByGroup(Component component) {
+ searchResult.setText(searUtils.searchByGroup());
+ }
+
+ private void getSearchHitCount(Component component) {
+ searchResult.setText(searUtils.getSearchHitCount());
+ }
+
+ private void deleteByQuery(Component component) {
+ int result = searUtils.deleteIndexByQuery();
+ if (result == 1) {
+ LogUtils.info(TAG, "updateIndexData succeed");
+ searchResult.setText(ResourceTable.String_succeed);
+ } else {
+ LogUtils.error(TAG, "updateIndexData failed");
+ searchResult.setText(ResourceTable.String_failed);
+ }
+ }
+
+ private void deleteIndexData(Component component) {
+ int result = searUtils.deleteIndexData();
+ if (result > 0) {
+ LogUtils.error(TAG, "updateIndexData failed num=" + result);
+ searchResult.setText(ResourceTable.String_failed);
+ } else {
+ LogUtils.info(TAG, "updateIndexData succeed");
+ searchResult.setText(ResourceTable.String_succeed);
+ }
+ }
+
+ private void updateIndexData(Component component) {
+ int result = searUtils.updateIndexData();
+ if (result > 0) {
+ LogUtils.error(TAG, "updateIndexData failed num=" + result);
+ searchResult.setText(ResourceTable.String_failed);
+ } else {
+ LogUtils.info(TAG, "updateIndexData succeed");
+ searchResult.setText(ResourceTable.String_succeed);
+ }
+ }
+
+ private void insertIndexData(Component component) {
+ int result = searUtils.insertIndexData();
+ if (result > 0) {
+ LogUtils.error(TAG, "insertIndexData failed num=" + result);
+ searchResult.setText(ResourceTable.String_failed);
+ } else {
+ LogUtils.info(TAG, "insertIndexData succeed");
+ searchResult.setText(ResourceTable.String_succeed);
+ }
+ }
+
+ private void readIndexForms(Component component) {
+ searchResult.setText(searUtils.readIndexForms());
+ }
+
+ private void buildIndexForms(Component component) {
+ int result = searUtils.buildIndexForms();
+ if (result == 1) {
+ LogUtils.info(TAG, "buildIndexForms succeed");
+ searchResult.setText(ResourceTable.String_succeed);
+ } else {
+ LogUtils.error(TAG, "buildIndexForms failed");
+ searchResult.setText(ResourceTable.String_failed);
+ }
+ }
+
+ @Override
+ public void onActive() {
+ super.onActive();
+ }
+
+ @Override
+ public void onForeground(Intent intent) {
+ super.onForeground(intent);
+ }
+}
diff --git a/data/Search/entry/src/main/java/ohos/samples/search/utils/LogUtils.java b/data/Search/entry/src/main/java/ohos/samples/search/utils/LogUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..60efd17f44cbec4a0717550bb0256ef9671503b3
--- /dev/null
+++ b/data/Search/entry/src/main/java/ohos/samples/search/utils/LogUtils.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.search.utils;
+
+import ohos.hiviewdfx.HiLog;
+import ohos.hiviewdfx.HiLogLabel;
+
+import java.util.Objects;
+
+/**
+ * LogUtils
+ *
+ * @since 2021-07-23
+ */
+public class LogUtils {
+ private static final String APP_NAME = "search";
+ private static final HiLogLabel LABAL_LOG = new HiLogLabel(3, 0xD000f00, APP_NAME);
+ private static final String LOG_FORMAT = "%{public}s:%{public}s";
+
+ private LogUtils() {
+ }
+
+ /**
+ * log info
+ *
+ * @param className String
+ * @param msg String
+ */
+ public static void info(String className, String msg) {
+ HiLog.info(LABAL_LOG, LOG_FORMAT, getLogPrefix(className), msg);
+ }
+
+ /**
+ * log error
+ *
+ * @param className String
+ * @param msg String
+ */
+ public static void error(String className, String msg) {
+ HiLog.error(LABAL_LOG, LOG_FORMAT, getLogPrefix(className), msg);
+ }
+
+ private static String getLogPrefix(String tag) {
+ Thread currentThread = Thread.currentThread();
+ String threadName = currentThread.getName();
+ StackTraceElement[] stackTraceElements = currentThread.getStackTrace();
+ int lineNum = 0;
+ for (int index = 0; index < stackTraceElements.length; index++) {
+ if (Objects.equals(stackTraceElements[index].getClassName(), LogUtils.class.getName())
+ && stackTraceElements.length > index + 1
+ && !Objects.equals(stackTraceElements[index + 1].getClassName(), LogUtils.class.getName())) {
+ lineNum = stackTraceElements[index + 1].getLineNumber();
+ }
+ }
+ return "[" + threadName + "]" + "(" + tag + ".java" + lineNum + ")";
+ }
+}
diff --git a/data/Search/entry/src/main/java/ohos/samples/search/utils/SearchUtils.java b/data/Search/entry/src/main/java/ohos/samples/search/utils/SearchUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..3eef5411f87b5aa1056d7bdb4c490e94d01567ec
--- /dev/null
+++ b/data/Search/entry/src/main/java/ohos/samples/search/utils/SearchUtils.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ohos.samples.search.utils;
+
+import ohos.app.Context;
+import ohos.data.search.SearchAbility;
+import ohos.data.search.SearchSession;
+import ohos.data.search.model.*;
+import ohos.data.search.schema.CommonItem;
+import ohos.data.search.schema.IndexSchemaType;
+import ohos.utils.zson.ZSONArray;
+import ohos.utils.zson.ZSONObject;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * SearchUtils
+ *
+ * @since 2021-07-23
+ */
+public class SearchUtils {
+ private final String LOCAL_DEVICE_ID = "";
+ private final String FILE_PATH;
+ private final Context context;
+ private final SearchAbility searchAbility;
+
+ public SearchUtils(Context context, SearchAbility searchAbility) {
+ this.context = context;
+ this.searchAbility = searchAbility;
+ FILE_PATH = context.getFilesDir().getPath();
+ }
+
+ /**
+ * build indexfroms
+ *
+ * @return int
+ */
+ public int buildIndexForms() {
+ searchAbility.clearIndex(SearchParameter.DEFAULT_GROUP, context.getBundleName(), null);
+ searchAbility.clearIndexForm(context.getBundleName());
+
+ // constructing custom index attributes
+ List indexFormList = new ArrayList<>();
+ indexFormList.add( // Word segmentation, while supporting sorting and grouping
+ new IndexForm("tag", IndexType.SORTED, false, true, false));
+ indexFormList.add( // Support sorting and range query
+ new IndexForm("bucket_id", IndexType.INTEGER, false, true, false));
+ indexFormList.add( // Support range search
+ new IndexForm("latitude", IndexType.FLOAT, false, true, false));
+ indexFormList.add( // Support range search
+ new IndexForm("longitude", IndexType.FLOAT, false, true, false));
+ indexFormList.add( // Support search
+ new IndexForm("device_id", IndexType.NO_ANALYZED, false, true, false));
+
+ // constructing index attributes using a generic template
+ return searchAbility.setIndexForm(context.getBundleName(), 1, indexFormList, IndexSchemaType.COMMON);
+ }
+
+ /**
+ * readIndexForms
+ *
+ * @return String
+ */
+ public String readIndexForms() {
+ StringBuilder result = new StringBuilder("Result:");
+ List indexFormList = searchAbility.getIndexForm(context.getBundleName());
+ for (IndexForm indexForm : indexFormList) {
+ result.append(indexForm.toString()).append(System.lineSeparator());
+ }
+ return result.toString();
+ }
+
+ /**
+ * insert index data
+ *
+ * @return int
+ */
+ public int insertIndexData() {
+ // Create an IndexData instance.
+ List indexDataList = new ArrayList<>();
+ for (int i = 0; i < 10; i++) {
+ CommonItem commonItem = new CommonItem().setIdentifier(LOCAL_DEVICE_ID + i)
+ .setTitle("position")
+ .setSubtitle("subtitle")
+ .setCategory("things")
+ .setDescription("is description")
+ .setName("name")
+ .setAlternateName("othername")
+ .setDateCreate(System.currentTimeMillis())
+ .setKeywords("key")
+ .setPotentialAction("com.sample.search.TestAbility")
+ .setThumbnailUrl(FILE_PATH)
+ .setUrl(FILE_PATH)
+ .setReserved1("reserved1")
+ .setReserved2("reserved2");
+ commonItem.put("tag", "location" + i);
+ commonItem.put("bucket_id", i);
+ commonItem.put("latitude", i / 10.0 * 180);
+ commonItem.put("longitude", i / 10.0 * 360);
+ commonItem.put("device_id", "localDeviceId");
+ indexDataList.add(commonItem);
+ }
+
+ // Insert a list of indexes.
+ List failedList = searchAbility.insert(SearchParameter.DEFAULT_GROUP,
+ context.getBundleName(), indexDataList);
+ // If some indexes fail to be inserted, try again later.
+ return failedList.size();
+ }
+
+ /**
+ * update index data
+ *
+ * @return int
+ */
+ public int updateIndexData() {
+ // constructing index data
+ List indexDataList = new ArrayList<>();
+ for (int i = 0; i < 10; i++) {
+ CommonItem commonItem = new CommonItem().setIdentifier(LOCAL_DEVICE_ID + i).setTitle("position update");
+ commonItem.put("tag", "location update" + i);
+ commonItem.put("bucket_id", i + 1);
+ commonItem.put("latitude", i / 10.0 * 100);
+ commonItem.put("longitude", i / 10.0 * 300);
+ commonItem.put("device_id", "localDeviceId");
+ indexDataList.add(commonItem);
+ }
+
+ List failedList = searchAbility.update(SearchParameter.DEFAULT_GROUP,
+ context.getBundleName(), indexDataList);
+ return failedList.size();
+ }
+
+ /**
+ * delete index data
+ *
+ * @return int
+ */
+ public int deleteIndexData() {
+ // constructing index data
+ List indexDataList = new ArrayList<>();
+ for (int i = 0; i < 5; i++) {
+ CommonItem commonItem = new CommonItem().setIdentifier(LOCAL_DEVICE_ID + i);
+ indexDataList.add(commonItem);
+ }
+
+ List failedList = searchAbility.delete(SearchParameter.DEFAULT_GROUP,
+ context.getBundleName(), indexDataList);
+ return failedList.size();
+ }
+
+ /**
+ * deleteIndexByQuery
+ *
+ * @return int
+ */
+ public int deleteIndexByQuery() {
+ return searchAbility.deleteByQuery(SearchParameter.DEFAULT_GROUP,
+ context.getBundleName(), buildQueryString().toString());
+ }
+
+ /**
+ * getSearchHitCount
+ *
+ * @return int
+ */
+ public String getSearchHitCount() {
+ SearchSession session = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName());
+ String result = "SearchHitCount:" + System.lineSeparator();
+ if (session == null) {
+ return result;
+ }
+ try {
+ String query = buildQueryString().toString();
+ return result + session.getSearchHitCount(query);
+ } finally {
+ searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName(), session);
+ }
+ }
+
+ /**
+ * searchByGroup
+ *
+ * @return String
+ */
+ public String searchByGroup() {
+ // Start a search session.
+ SearchSession session = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName());
+ StringBuilder result = new StringBuilder("searchByGroup:" + System.lineSeparator());
+ if (session == null) {
+ return result.toString();
+ }
+ try {
+ ZSONObject query = buildQueryString();
+ // SearchParameter.GROUP_FIELD_LIST indicates the field list you need to specify when calling the groupSearch method.
+ query.put(SearchParameter.GROUP_FIELD_LIST, new ZSONArray(Arrays.asList("tag", CommonItem.CATEGORY)));
+
+ int limit = 10; // A maximum of 10 groups (recommendations) are returned for each field.
+ List recommendationList = session.groupSearch(query.toString(), limit);
+
+ // Process recommendations.
+ for (Recommendation recommendation : recommendationList) {
+ result.append(recommendation.toString()).append(System.lineSeparator());
+ }
+ return result.toString();
+ } finally {
+ searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName(), session);
+ }
+ }
+
+ /**
+ * searchByPage
+ *
+ * @return String
+ */
+ public String searchByPage() {
+ // Start a search session.
+ SearchSession session = searchAbility.beginSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName());
+ StringBuilder result = new StringBuilder("searchByPage:" + System.lineSeparator());
+ if (session == null) {
+ return result.toString();
+ }
+ try {
+ String query = buildQueryString().toString();
+ int count = session.getSearchHitCount(query);
+ int batch = 50; // A maximum of 50 results are allowed on each page.
+ for (int i = 0; i < count; i += batch) {
+ List indexDataList = session.search(query, i, batch);
+ for (IndexData indexData : indexDataList) {
+ result.append("tag:").append(indexData.get("tag")).append(", latitude:")
+ .append(indexData.get("latitude")).append(", longitude:")
+ .append(indexData.get("longitude")).append(System.lineSeparator());
+ }
+ }
+ return result.toString();
+ } finally {
+ searchAbility.endSearch(SearchParameter.DEFAULT_GROUP, context.getBundleName(), session);
+ }
+ }
+
+ /**
+ * buildQueryString
+ *
+ * @return ZSONObject
+ */
+ public ZSONObject buildQueryString() {
+ // Create a JSONObject.
+ ZSONObject zsonObject = new ZSONObject();
+
+ // SearchParameter.QUERY indicates the user input. It is recommended that the search fields be analyzed.
+ // Assume that the user inputs location and starts a search for the title and tag fields.
+ ZSONObject query = new ZSONObject();
+ query.put("location", new ZSONArray(Arrays.asList(CommonItem.TITLE, "tag")));
+ zsonObject.put(SearchParameter.QUERY, query);
+
+ /*
+ * Search criteria can be added to ZSONArray of the SearchParameter.FILTER_CONDITION.
+ * An index in the index library is hit only if the search criteria of each ZSONObject in the ZSONArray is met.
+ * The search criteria of a ZSONArray is met as long as one of the conditions in the search criteria is met.
+ */
+ ZSONArray filterCondition = new ZSONArray();
+
+ // For the first condition, a field may have multiple values.
+ ZSONObject filter1 = new ZSONObject();
+ filter1.put("bucket_id", new ZSONArray(Arrays.asList(0, 1, 2, 3, 4, 5))); // An index is hit if its value is 0, 1, 2, 3, 4, or 5 for the bucket_id field.
+ filter1.put(CommonItem.IDENTIFIER, new ZSONArray(Arrays.asList(0, 1, 2, 3, 4, 5))); // The index is also hit if its value is 0 , 1, 2, 3, 4 or 5 for the CommonItem.IDENTIFIER field.
+ filterCondition.add(filter1);
+ ZSONObject filter2 = new ZSONObject();
+ filter2.put("tag", new ZSONArray(Arrays.asList("position")));
+ filter2.put(CommonItem.TITLE, new ZSONArray(Arrays.asList("position"))); // An index is hit if the value of the tag or CommonItem.TITLE field is position.
+ filterCondition.add(filter2);
+ zsonObject.put(SearchParameter.FILTER_CONDITION, filterCondition); // An index is hit only if both the first and second conditions are met.
+
+ // SearchParameter.DEVICE_ID_LIST indicates the device ID list. Indexes with the specified IDs are hit.
+ ZSONObject deviceId = new ZSONObject();
+ deviceId.put("device_id", new ZSONArray(Arrays.asList("localDeviceId"))); // Specify the local device.
+ zsonObject.put(SearchParameter.DEVICE_ID_LIST, deviceId);
+
+ // Start a search by specifying the value range of a specified index field.
+ // Indexes whose values fall within the value range of the specified index field are hit.
+ ZSONObject latitudeObject = new ZSONObject();
+ latitudeObject.put(SearchParameter.LOWER, -80.0f);
+ latitudeObject.put(SearchParameter.UPPER, 80.0f);
+ zsonObject.put("latitude", latitudeObject); // The latitude must be in the range of [-80.0f, 80.0f].
+ ZSONObject longitudeObject = new ZSONObject();
+ longitudeObject.put(SearchParameter.LOWER, -90.0);
+ longitudeObject.put(SearchParameter.UPPER, 90.0);
+ zsonObject.put("longitude", longitudeObject); // The longitude must be in the range of [-90.0, 90.0].
+
+ /*
+ * SearchParameter.ORDER_BY indicates how the search results are sorted.
+ * The value can be SearchParameter.ASC or SearchParameter.DESC.
+ * The sequence of the fields matters.
+ * In the following example, indexes are first sorted in ascending order of the CommonItem.CATEGORY field.
+ * If they are equal on the CommonItem.CATEGORY field, they will be sorted in descending order of the tag field.
+ */
+ ZSONObject order = new ZSONObject();
+ order.put(CommonItem.CATEGORY, SearchParameter.ASC);
+ order.put("tag", SearchParameter.DESC);
+ zsonObject.put(SearchParameter.ORDER_BY, order);
+
+ // Obtain the string for search.
+ return zsonObject;
+ }
+}
diff --git a/data/Search/entry/src/main/resources/base/element/float.json b/data/Search/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..2bf7c116831d70625af020dc8593e92f60c4bfdb
--- /dev/null
+++ b/data/Search/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,12 @@
+{
+ "float": [
+ {
+ "name": "layout_padding",
+ "value": "10vp"
+ },
+ {
+ "name": "button_height",
+ "value": "40vp"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/base/element/pattern.json b/data/Search/entry/src/main/resources/base/element/pattern.json
new file mode 100644
index 0000000000000000000000000000000000000000..7f142da1745d40ad16cd648a7235e6f42b1fe715
--- /dev/null
+++ b/data/Search/entry/src/main/resources/base/element/pattern.json
@@ -0,0 +1,58 @@
+{
+ "pattern": [
+ {
+ "name": "button_blue",
+ "value": [
+ {
+ "name": "text_size",
+ "value": "18fp"
+ },
+ {
+ "name": "margin",
+ "value": "5vp"
+ },
+ {
+ "name": "background_element",
+ "value": "$graphic:button_blue"
+ },
+ {
+ "name": "text_color",
+ "value": "#FFFFFF"
+ }
+ ]
+ },
+ {
+ "name": "content_text",
+ "value": [
+ {
+ "name": "text_size",
+ "value": "17fp"
+ },
+ {
+ "name": "text_color",
+ "value": "#000000"
+ },
+ {
+ "name": "background_element",
+ "value": "#F0F0F0"
+ },
+ {
+ "name": "multiple_lines",
+ "value": "true"
+ },
+ {
+ "name": "padding",
+ "value": "5vp"
+ },
+ {
+ "name": "margin",
+ "value": "5vp"
+ },
+ {
+ "name": "text_alignment",
+ "value": "start"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/base/element/string.json b/data/Search/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..a8147d72c872dbd2cdaa3c9adcbf4e0cd78ce661
--- /dev/null
+++ b/data/Search/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,68 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "search"
+ },
+ {
+ "name": "mainability_description",
+ "value": "Search Ability"
+ },
+ {
+ "name": "result",
+ "value": "result:"
+ },
+ {
+ "name": "btn_build_index_forms",
+ "value": "build location indexForm"
+ },
+ {
+ "name": "btn_read_index_forms",
+ "value": "read indexForm"
+ },
+ {
+ "name": "btn_insert_index_data",
+ "value": "insert indexData"
+ },
+ {
+ "name": "btn_update_index_data",
+ "value": "update indexData"
+ },
+ {
+ "name": "btn_delete_indexdata",
+ "value": "delete indexData"
+ },
+ {
+ "name": "btn_delete_indexdata_by_query",
+ "value": "delete indexData by query"
+ },
+ {
+ "name": "btn_get_search_hint_count",
+ "value": "get search hint count"
+ },
+ {
+ "name": "btn_search_by_group",
+ "value": "search by group"
+ },
+ {
+ "name": "btn_search_by_page",
+ "value": "search by page"
+ },
+ {
+ "name": "connect_service_succeed",
+ "value": "connect service succeed"
+ },
+ {
+ "name": "connect_service_failed",
+ "value": "connect service failed"
+ },
+ {
+ "name": "succeed",
+ "value": "succeed"
+ },
+ {
+ "name": "failed",
+ "value": "failed"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/base/graphic/button_blue.xml b/data/Search/entry/src/main/resources/base/graphic/button_blue.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c7ac8a58fa538cb49c2002099764577c5465bfe3
--- /dev/null
+++ b/data/Search/entry/src/main/resources/base/graphic/button_blue.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/base/graphic/button_blue_empty.xml b/data/Search/entry/src/main/resources/base/graphic/button_blue_empty.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e90b693d2efa580d4767d55250f0e5a2c6ab5958
--- /dev/null
+++ b/data/Search/entry/src/main/resources/base/graphic/button_blue_empty.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/base/graphic/button_blue_pressed.xml b/data/Search/entry/src/main/resources/base/graphic/button_blue_pressed.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fe2343b5ec2010eb2435bcee605b37b0c3f29d97
--- /dev/null
+++ b/data/Search/entry/src/main/resources/base/graphic/button_blue_pressed.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/base/layout/ability_main.xml b/data/Search/entry/src/main/resources/base/layout/ability_main.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b62d8a0c1c2d7d9766b3bc2154f2d02bd46c22ed
--- /dev/null
+++ b/data/Search/entry/src/main/resources/base/layout/ability_main.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/base/media/icon.png b/data/Search/entry/src/main/resources/base/media/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/data/Search/entry/src/main/resources/base/media/icon.png differ
diff --git a/data/Search/entry/src/main/resources/en/element/string.json b/data/Search/entry/src/main/resources/en/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..a8147d72c872dbd2cdaa3c9adcbf4e0cd78ce661
--- /dev/null
+++ b/data/Search/entry/src/main/resources/en/element/string.json
@@ -0,0 +1,68 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "search"
+ },
+ {
+ "name": "mainability_description",
+ "value": "Search Ability"
+ },
+ {
+ "name": "result",
+ "value": "result:"
+ },
+ {
+ "name": "btn_build_index_forms",
+ "value": "build location indexForm"
+ },
+ {
+ "name": "btn_read_index_forms",
+ "value": "read indexForm"
+ },
+ {
+ "name": "btn_insert_index_data",
+ "value": "insert indexData"
+ },
+ {
+ "name": "btn_update_index_data",
+ "value": "update indexData"
+ },
+ {
+ "name": "btn_delete_indexdata",
+ "value": "delete indexData"
+ },
+ {
+ "name": "btn_delete_indexdata_by_query",
+ "value": "delete indexData by query"
+ },
+ {
+ "name": "btn_get_search_hint_count",
+ "value": "get search hint count"
+ },
+ {
+ "name": "btn_search_by_group",
+ "value": "search by group"
+ },
+ {
+ "name": "btn_search_by_page",
+ "value": "search by page"
+ },
+ {
+ "name": "connect_service_succeed",
+ "value": "connect service succeed"
+ },
+ {
+ "name": "connect_service_failed",
+ "value": "connect service failed"
+ },
+ {
+ "name": "succeed",
+ "value": "succeed"
+ },
+ {
+ "name": "failed",
+ "value": "failed"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/Search/entry/src/main/resources/zh/element/string.json b/data/Search/entry/src/main/resources/zh/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..e4211e249915e32142f49986149111962a9df45f
--- /dev/null
+++ b/data/Search/entry/src/main/resources/zh/element/string.json
@@ -0,0 +1,72 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "搜索"
+ },
+ {
+ "name": "mainability_description",
+ "value": "搜索界面"
+ },
+ {
+ "name": "result",
+ "value": "结果:"
+ },
+ {
+ "name": "btn_build_index_forms",
+ "value": "构造定位索引"
+ },
+ {
+ "name": "btn_read_index_forms",
+ "value": "读取索引"
+ },
+ {
+ "name": "btn_insert_index_data",
+ "value": "插入定位数据"
+ },
+ {
+ "name": "btn_update_index_data",
+ "value": "更新定位数据"
+ },
+ {
+ "name": "btn_delete_indexdata",
+ "value": "删除索引数据"
+ },
+ {
+ "name": "btn_delete_indexdata_by_query",
+ "value": "通过查询语句删除索引数据"
+ },
+ {
+ "name": "btn_get_search_hint_count",
+ "value": "获取查询索引条数"
+ },
+ {
+ "name": "btn_search_by_group",
+ "value": "分组搜索"
+ },
+ {
+ "name": "btn_search_by_page",
+ "value": "分页搜索"
+ },
+ {
+ "name": "connect_service_succeed",
+ "value": "连接服务成功"
+ },
+ {
+ "name": "connect_service_failed",
+ "value": "连接服务失败"
+ },
+ {
+ "name": "succeed",
+ "value": "成功"
+ },
+ {
+ "name": "failed",
+ "value": "失败"
+ },
+ {
+ "name": "doing",
+ "value": "正在进行..."
+ }
+ ]
+}
\ No newline at end of file
diff --git a/data/Search/screenshots/device/main.png b/data/Search/screenshots/device/main.png
new file mode 100644
index 0000000000000000000000000000000000000000..b9f66e07e2f8d52435877ac156841e5cc0ef37a7
Binary files /dev/null and b/data/Search/screenshots/device/main.png differ
diff --git a/data/Search/settings.gradle b/data/Search/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..4773db73233a570c2d0c01a22e75321acfbf7a07
--- /dev/null
+++ b/data/Search/settings.gradle
@@ -0,0 +1 @@
+include ':entry'