@maximilien0405/capacitor-android-launcher 0.0.3 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,13 @@
2
2
 
3
3
  This Capacitor plugin allows you to open the launcher settings to set your app as the default launcher on Android.
4
4
 
5
- It can also, if needed, start (and stop) and immersive mode that hides all UI elements and prevents your user from leaving the app. This is usefull for an Kiosk App, or for children or seniors.
5
+ It can also, if needed, start (and stop) and immersive mode that hides the all UI elements (status bar and navigation bar). This is usefull for an Kiosk App, or for special apps made for childrens or seniors.
6
+
7
+ ## Support
8
+
9
+ ANDROID Only.
10
+
11
+ - v7.X.X supports Capacitor V7 (Android minSdkVersion 23+).
6
12
 
7
13
  ## Installation
8
14
 
@@ -14,7 +20,7 @@ npx cap sync
14
20
  ## Usage
15
21
 
16
22
 
17
- #### Request Launcher Role
23
+ #### Open Launcher Settings
18
24
 
19
25
  This method opens the settings page where the user can set your app as the default launcher.
20
26
 
@@ -24,7 +30,7 @@ await AndroidLauncher.openLauncherSettings();
24
30
 
25
31
  #### Start Immersive Mode
26
32
 
27
- This method hides all system controls and prevents the user from leaving the app.
33
+ This method hides all system controls.
28
34
 
29
35
  > ⚠️ The app must be set as the launcher for it to work.
30
36
 
@@ -34,28 +40,17 @@ await AndroidLauncher.startImmersiveMode();
34
40
 
35
41
  #### Stop Immersive Mode
36
42
 
37
- This method restores the system controls and allows the user to exit the app.
43
+ This method restores the system controls.
38
44
 
39
45
  ```ts
40
46
  await AndroidLauncher.stopImmersiveMode();
41
47
  ```
42
48
 
43
- #### Check if the App is the Launcher
49
+ #### Check if is the Launcher
44
50
 
45
51
  This method checks if your app is currently set as the default launcher.
46
52
 
47
53
  ```ts
48
54
  const isLauncher = await AndroidLauncher.isLauncherApp();
49
55
  console.log(isLauncher); // true or false
50
- ```
51
-
52
- ## API
53
-
54
- ```ts
55
- interface AndroidLauncherPlugin {
56
- openLauncherSettings(): Promise<void>;
57
- startImmersiveMode(): Promise<void>;
58
- stopImmersiveMode(): Promise<void>;
59
- isLauncherApp(): Promise<boolean>;
60
- }
61
56
  ```
@@ -1,25 +1,30 @@
1
1
  package com.maximilien0405.androidlauncher;
2
2
 
3
- import android.view.View;
4
3
  import android.content.Intent;
5
- import android.provider.Settings;
6
4
  import android.content.pm.PackageManager;
7
5
  import android.content.pm.ResolveInfo;
8
- import android.widget.Toast;
6
+ import android.os.Handler;
7
+ import android.os.Build;
8
+ import android.os.Looper;
9
+ import android.view.View;
10
+ import android.view.WindowInsetsController;
9
11
  import androidx.appcompat.app.AppCompatActivity;
10
-
11
- import com.getcapacitor.JSObject;
12
+ import androidx.annotation.RequiresApi;
12
13
  import com.getcapacitor.Plugin;
13
14
  import com.getcapacitor.PluginCall;
14
- import com.getcapacitor.annotation.CapacitorPlugin;
15
15
  import com.getcapacitor.PluginMethod;
16
+ import com.getcapacitor.Bridge;
17
+ import android.provider.Settings;
16
18
 
17
19
  public class AndroidLauncher {
18
-
19
20
  private AppCompatActivity activity;
21
+ private Bridge bridge;
22
+ private boolean immersiveModeEnabled = false;
20
23
 
21
- public AndroidLauncher(AppCompatActivity activity) {
22
- this.activity = activity;
24
+ public AndroidLauncher(AppCompatActivity activity, Bridge bridge) {
25
+ this.activity = activity;
26
+ this.bridge = bridge;
27
+ setupSystemUiVisibilityListener();
23
28
  }
24
29
 
25
30
  // Opens the settings to allow the user to set the app as launcher
@@ -35,32 +40,88 @@ public class AndroidLauncher {
35
40
 
36
41
  // Starts immersive mode and prevents the user from leaving the app (if it's the launcher)
37
42
  public void startImmersiveMode(PluginCall call) {
38
- if (!isLauncherApp()) {
39
- call.reject("App is not set as the launcher.");
40
- return;
41
- }
42
-
43
43
  try {
44
- // Hide the status bar and navigation bar
45
- activity.getWindow().getDecorView().setSystemUiVisibility(
46
- View.SYSTEM_UI_FLAG_IMMERSIVE |
47
- View.SYSTEM_UI_FLAG_FULLSCREEN |
48
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
49
- call.resolve();
44
+ if (Looper.myLooper() == Looper.getMainLooper()) {
45
+ enableImmersiveMode();
46
+ call.resolve();
47
+ } else {
48
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
49
+ @Override
50
+ public void run() {
51
+ enableImmersiveMode();
52
+ call.resolve();
53
+ }
54
+ });
55
+ }
50
56
  } catch (Exception e) {
51
57
  call.reject("Error starting immersive mode", e);
52
58
  }
53
59
  }
54
60
 
55
- // Stops immersive mode and allows the user to interact with the controls again
61
+ private void enableImmersiveMode() {
62
+ try {
63
+ immersiveModeEnabled = true;
64
+ View decorView = this.bridge.getActivity().getWindow().getDecorView();
65
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
66
+ WindowInsetsController insetsController = decorView.getWindowInsetsController();
67
+ if (insetsController != null) {
68
+ insetsController.hide(android.view.WindowInsets.Type.statusBars()
69
+ | android.view.WindowInsets.Type.navigationBars());
70
+
71
+ insetsController.setSystemBarsBehavior(
72
+ WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
73
+ }
74
+ } else {
75
+ int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
76
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
77
+ | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
78
+ | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
79
+ | View.SYSTEM_UI_FLAG_FULLSCREEN
80
+ | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
81
+ decorView.setSystemUiVisibility(flags);
82
+ }
83
+ } catch (Exception e) {
84
+ e.printStackTrace();
85
+ }
86
+ }
87
+
56
88
  public void stopImmersiveMode(PluginCall call) {
89
+ try {
90
+ if (Looper.myLooper() == Looper.getMainLooper()) {
91
+ clearImmersiveMode();
92
+ call.resolve();
93
+ } else {
94
+ new Handler(Looper.getMainLooper()).post(new Runnable() {
95
+ @Override
96
+ public void run() {
97
+ clearImmersiveMode();
98
+ call.resolve();
99
+ }
100
+ });
101
+ }
102
+ } catch (Exception e) {
103
+ call.reject("Error stopping immersive mode", e);
104
+ }
105
+ }
106
+
107
+ private void clearImmersiveMode() {
57
108
  try {
58
- // Reset system UI visibility
59
- activity.getWindow().getDecorView().setSystemUiVisibility(
60
- View.SYSTEM_UI_FLAG_VISIBLE);
61
- call.resolve();
109
+ immersiveModeEnabled = false;
110
+ View decorView = this.bridge.getActivity().getWindow().getDecorView();
111
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
112
+ WindowInsetsController insetsController = decorView.getWindowInsetsController();
113
+ if (insetsController != null) {
114
+ insetsController.hide(WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_SWIPE);
115
+ insetsController.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH);
116
+ }
117
+ } else {
118
+ int uiOptions = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
119
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
120
+ View.SYSTEM_UI_FLAG_FULLSCREEN;
121
+ decorView.setSystemUiVisibility(uiOptions);
122
+ }
62
123
  } catch (Exception e) {
63
- call.reject("Error stopping immersive mode", e);
124
+ e.printStackTrace();
64
125
  }
65
126
  }
66
127
 
@@ -72,4 +133,32 @@ public class AndroidLauncher {
72
133
  ResolveInfo resolveInfo = packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
73
134
  return resolveInfo.activityInfo.packageName.equals(activity.getPackageName());
74
135
  }
136
+
137
+ // Listen to system UI changes and hide UI if swiped
138
+ private void setupSystemUiVisibilityListener() {
139
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
140
+ // For Android 11+, use a window focus change listener instead
141
+ activity.getWindow().getDecorView().setOnApplyWindowInsetsListener(
142
+ (view, windowInsets) -> {
143
+ if (immersiveModeEnabled &&
144
+ windowInsets.isVisible(android.view.WindowInsets.Type.statusBars() | android.view.WindowInsets.Type.navigationBars())) {
145
+ if (immersiveModeEnabled) {
146
+ enableImmersiveMode();
147
+ }
148
+ }
149
+ return view.onApplyWindowInsets(windowInsets);
150
+ });
151
+ } else {
152
+ // For older Android versions
153
+ activity.getWindow().getDecorView().setOnSystemUiVisibilityChangeListener(
154
+ visibility -> {
155
+ if (immersiveModeEnabled && (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
156
+ if (immersiveModeEnabled) {
157
+ enableImmersiveMode();
158
+ }
159
+ }
160
+ }
161
+ );
162
+ }
163
+ }
75
164
  }
@@ -14,7 +14,7 @@ public class AndroidLauncherPlugin extends Plugin {
14
14
  @Override
15
15
  public void load() {
16
16
  super.load();
17
- androidLauncher = new AndroidLauncher(getActivity());
17
+ androidLauncher = new AndroidLauncher(getActivity(), getBridge());
18
18
  }
19
19
 
20
20
  // Opens the launcher settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maximilien0405/capacitor-android-launcher",
3
- "version": "0.0.3",
3
+ "version": "7.0.1",
4
4
  "description": "Capacitor plugin to request your app to be the main launcher.",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",