├── .gitattributes ├── index.js ├── android ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── rnlocktask │ │ ├── MyAdmin.java │ │ ├── RNLockTaskPackage.java │ │ └── RNLockTaskModule.java └── build.gradle ├── package.json ├── .gitignore ├── LICENSE └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | import { NativeModules } from 'react-native'; 3 | 4 | const { RNLockTask } = NativeModules; 5 | 6 | export default RNLockTask; 7 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/java/com/rnlocktask/MyAdmin.java: -------------------------------------------------------------------------------- 1 | package com.rnlocktask; 2 | 3 | import android.app.admin.DeviceAdminReceiver; 4 | 5 | 6 | public class MyAdmin extends DeviceAdminReceiver{ 7 | 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "react-native-lock-task", 4 | "version": "1.4.1", 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/fast0490f/react-native-lock-taskt" 13 | }, 14 | "license": "MIT", 15 | "keywords": [ 16 | "react-native" 17 | ], 18 | "author": "" 19 | } 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | 34 | # Android/IntelliJ 35 | # 36 | build/ 37 | .idea 38 | .gradle 39 | local.properties 40 | *.iml 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | -------------------------------------------------------------------------------- /android/src/main/java/com/rnlocktask/RNLockTaskPackage.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rnlocktask; 3 | 4 | import com.facebook.react.ReactPackage; 5 | import com.facebook.react.bridge.JavaScriptModule; 6 | import com.facebook.react.bridge.NativeModule; 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.uimanager.ViewManager; 9 | 10 | import java.util.Arrays; 11 | import java.util.Collections; 12 | import java.util.List; 13 | public class RNLockTaskPackage implements ReactPackage { 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | return Arrays.asList(new RNLockTaskModule(reactContext)); 17 | } 18 | 19 | // Deprecated from RN 0.47 20 | public List> createJSModules() { 21 | return Collections.emptyList(); 22 | } 23 | 24 | @Override 25 | public List createViewManagers(ReactApplicationContext reactContext) { 26 | return Collections.emptyList(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Artem Ivanov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | def safeExtGet(prop, fallback) { 4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 5 | } 6 | 7 | buildscript { 8 | repositories { 9 | google() 10 | } 11 | 12 | dependencies { 13 | classpath("com.android.tools.build:gradle") 14 | } 15 | } 16 | 17 | android { 18 | def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION 19 | // Check AGP version for backward compatibility reasons (for RN < 0.71) 20 | if (agpVersion.tokenize('.')[0].toInteger() >= 7) { 21 | namespace "com.rnlocktask" 22 | } 23 | 24 | compileSdkVersion safeExtGet('compileSdkVersion', 35) 25 | 26 | defaultConfig { 27 | minSdkVersion safeExtGet('minSdkVersion', 21) 28 | targetSdkVersion safeExtGet('targetSdkVersion', 35) 29 | versionCode 1 30 | versionName "1.0" 31 | } 32 | lintOptions { 33 | abortOnError false 34 | } 35 | } 36 | 37 | repositories { 38 | mavenCentral() 39 | google() 40 | } 41 | 42 | dependencies { 43 | implementation 'com.facebook.react:react-native:+' 44 | } 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # react-native-lock-task 3 | 4 | ## Getting started 5 | 6 | `$ npm install react-native-lock-task --save` 7 | 8 | ### Mostly automatic installation 9 | 10 | `$ react-native link react-native-lock-task` 11 | 12 | ### Settings 13 | 14 | **`yourProject/android/app/src/main/AndroidManifest.xml`** 15 | 16 | ```diff 17 | 18 | 20 | + 21 | + 22 | 31 | 32 | 33 | 34 | 35 | + 36 | 37 | 38 | 39 | 40 | + 44 | + 46 | + 47 | + 48 | + 49 | + 50 | 51 | 52 | ``` 53 | 54 | 55 | **`yourProject/android/app/src/main/res/values/strings.xml`** 56 | 57 | ```diff 58 | 59 | yourNameApp 60 | + yourNameApp 61 | + yourNameAppTitle 62 | 63 | 64 | ``` 65 | 66 | **`yourProject/android/app/src/main/res/xml/my_admin.xml`** 67 | 68 | ```diff 69 | + 70 | + 71 | + 72 | + 73 | + 74 | + 75 | + 76 | + 77 | + 78 | 79 | ``` 80 | 81 | Add the library types to your project by creating (or editing) a `index.d.ts` in your project root directory with the line: 82 | ``` 83 | declare module 'react-native-lock-task'; 84 | ``` 85 | and then add it to your `tsconfig.json` 86 | ``` 87 | { 88 | ... 89 | "include" : ["index.d.ts"] 90 | } 91 | ``` 92 | 93 | ## Reinstall application 94 | * Start your emulator 95 | * Install project 96 | 97 | ## Set owner device adb 98 | * Settings --> Accounts --> Delete All 99 | * `adb shell dpm set-device-owner com.yourProject/com.rnlocktask.MyAdmin` 100 | 101 | ## Usage 102 | ```javascript 103 | import RNLockTask from 'react-native-lock-task'; 104 | RNLockTask.isAppInLockTaskMode(); 105 | RNLockTask.startLockTask(); 106 | RNLockTask.startLockTaskWith(["com.google.android.youtube", "com.sega.sonicdash"]); 107 | RNLockTask.stopLockTask(); 108 | RNLockTask.clearDeviceOwnerApp(); 109 | ``` 110 | -------------------------------------------------------------------------------- /android/src/main/java/com/rnlocktask/RNLockTaskModule.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rnlocktask; 3 | 4 | import android.app.Activity; 5 | import android.app.ActivityManager; 6 | import android.app.admin.DevicePolicyManager; 7 | import android.content.ComponentName; 8 | import android.content.Context; 9 | import android.os.Build; 10 | 11 | import com.facebook.react.bridge.Promise; 12 | import com.facebook.react.bridge.ReactApplicationContext; 13 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 14 | import com.facebook.react.bridge.ReactMethod; 15 | import com.facebook.react.bridge.ReadableArray; 16 | 17 | import java.util.ArrayList; 18 | 19 | public class RNLockTaskModule extends ReactContextBaseJavaModule { 20 | 21 | 22 | private static final String ACTIVITY_GONE = "ACTIVITY_GONE"; 23 | private static final String DEVICE_OWNER_CLEARED = "DEVICE_OWNER_CLEARED"; 24 | private static final String LOCKED_TASK = "LOCKED_TASK"; 25 | private static final String LOCKED_TASK_AS_OWNER = "LOCKED_TASK_AS_OWNER"; 26 | private static final String UNLOCKED_TASK = "UNLOCKED_TASK"; 27 | private static final String TAG = "RNLockTaskModule"; 28 | 29 | public RNLockTaskModule(ReactApplicationContext reactContext) { 30 | super(reactContext); 31 | } 32 | 33 | @Override 34 | public String getName() { 35 | return "RNLockTask"; 36 | } 37 | 38 | @ReactMethod 39 | public void isAppInLockTaskMode(Promise promise) { 40 | try { 41 | Activity mActivity = getCurrentActivity(); 42 | if (mActivity != null) { 43 | ActivityManager activityManager = (ActivityManager) mActivity.getSystemService(Context.ACTIVITY_SERVICE); 44 | 45 | // When SDK version is 23 46 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { 47 | int lockTaskMode = activityManager.getLockTaskModeState(); 48 | promise.resolve(lockTaskMode == ActivityManager.LOCK_TASK_MODE_PINNED); 49 | } 50 | 51 | //When SDK version <=21 and <23. This API is deprecated in 23. 52 | else { 53 | promise.resolve(activityManager.isInLockTaskMode()); 54 | } 55 | } 56 | } catch (Exception e) { 57 | promise.reject(e); 58 | } 59 | } 60 | 61 | @ReactMethod 62 | public void clearDeviceOwnerApp(Promise promise) { 63 | try { 64 | Activity mActivity = getCurrentActivity(); 65 | if (mActivity != null) { 66 | DevicePolicyManager myDevicePolicyManager = (DevicePolicyManager) mActivity.getSystemService(Context.DEVICE_POLICY_SERVICE); 67 | myDevicePolicyManager.clearDeviceOwnerApp(mActivity.getPackageName()); 68 | promise.resolve(DEVICE_OWNER_CLEARED); 69 | } 70 | promise.reject(ACTIVITY_GONE, "Activity gone or mismatch"); 71 | } catch (Exception e) { 72 | promise.reject(e); 73 | } 74 | } 75 | 76 | @ReactMethod 77 | public void startLockTaskWith(ReadableArray additionalPackages, Promise promise) { 78 | try { 79 | Activity mActivity = getCurrentActivity(); 80 | if (mActivity != null) { 81 | DevicePolicyManager myDevicePolicyManager = (DevicePolicyManager) mActivity.getSystemService(Context.DEVICE_POLICY_SERVICE); 82 | ComponentName mDPM = new ComponentName(mActivity, MyAdmin.class); 83 | 84 | if (myDevicePolicyManager.isDeviceOwnerApp(mActivity.getPackageName())) { 85 | ArrayList packages = new ArrayList<>(); 86 | packages.add(mActivity.getPackageName()); 87 | if(additionalPackages != null){ 88 | for (int i = 0; i < additionalPackages.size(); i++) { 89 | packages.add(additionalPackages.getString(i)); 90 | } 91 | } 92 | myDevicePolicyManager.setLockTaskPackages(mDPM, packages.toArray(new String[0])); 93 | mActivity.startLockTask(); 94 | promise.resolve(LOCKED_TASK_AS_OWNER); 95 | } else { 96 | mActivity.startLockTask(); 97 | promise.resolve(LOCKED_TASK); 98 | } 99 | } else{ 100 | promise.reject(ACTIVITY_GONE, "Activity gone or mismatch"); 101 | } 102 | } catch (Exception e) { 103 | promise.reject(e); 104 | } 105 | } 106 | 107 | @ReactMethod 108 | public void startLockTask(Promise promise) { 109 | startLockTaskWith(null, promise); 110 | } 111 | 112 | @ReactMethod 113 | public void stopLockTask(Promise promise) { 114 | try { 115 | Activity mActivity = getCurrentActivity(); 116 | if (mActivity != null) { 117 | mActivity.stopLockTask(); 118 | promise.resolve(UNLOCKED_TASK); 119 | } else { 120 | promise.reject(ACTIVITY_GONE, "Activity gone or mismatch"); 121 | } 122 | } catch (Exception e) { 123 | promise.reject(e); 124 | } 125 | } 126 | } 127 | --------------------------------------------------------------------------------