txa-settings-permission 1.0.0
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/LICENSE +22 -0
- package/README.md +391 -0
- package/android/build.gradle +57 -0
- package/android/src/main/AndroidManifest.xml +42 -0
- package/android/src/main/java/online/txa/settingspermission/TxaSettingsPermissionPlugin.java +744 -0
- package/dist/cjs/definitions.d.ts +114 -0
- package/dist/cjs/definitions.js +7 -0
- package/dist/cjs/index.d.ts +9 -0
- package/dist/cjs/index.js +50 -0
- package/dist/cjs/web.d.ts +35 -0
- package/dist/cjs/web.js +82 -0
- package/dist/esm/definitions.d.ts +114 -0
- package/dist/esm/definitions.js +6 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/web.d.ts +35 -0
- package/dist/esm/web.js +78 -0
- package/dist/plugin.cjs.js +98 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +101 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +67 -0
- package/src/definitions.ts +151 -0
- package/src/index.ts +18 -0
- package/src/web.ts +103 -0
|
@@ -0,0 +1,744 @@
|
|
|
1
|
+
package online.txa.settingspermission;
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TXA Settings Permission Plugin
|
|
5
|
+
* Author: TXA (txa@nrotxa.online)
|
|
6
|
+
* GitHub: https://github.com/TXAVLOG/txa-settings-permission
|
|
7
|
+
*
|
|
8
|
+
* Hỗ trợ mở tất cả các màn hình Settings cấp quyền trên Android,
|
|
9
|
+
* tự động tương thích theo Android version.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import android.Manifest;
|
|
13
|
+
import android.app.Activity;
|
|
14
|
+
import android.content.Context;
|
|
15
|
+
import android.content.Intent;
|
|
16
|
+
import android.content.pm.PackageManager;
|
|
17
|
+
import android.net.Uri;
|
|
18
|
+
import android.os.Build;
|
|
19
|
+
import android.os.Environment;
|
|
20
|
+
import android.os.PowerManager;
|
|
21
|
+
import android.provider.Settings;
|
|
22
|
+
import android.util.Log;
|
|
23
|
+
|
|
24
|
+
import androidx.core.app.ActivityCompat;
|
|
25
|
+
import androidx.core.content.ContextCompat;
|
|
26
|
+
|
|
27
|
+
import com.getcapacitor.JSArray;
|
|
28
|
+
import com.getcapacitor.JSObject;
|
|
29
|
+
import com.getcapacitor.Plugin;
|
|
30
|
+
import com.getcapacitor.PluginCall;
|
|
31
|
+
import com.getcapacitor.PluginMethod;
|
|
32
|
+
import com.getcapacitor.annotation.CapacitorPlugin;
|
|
33
|
+
|
|
34
|
+
import org.json.JSONArray;
|
|
35
|
+
import org.json.JSONException;
|
|
36
|
+
|
|
37
|
+
import java.util.ArrayList;
|
|
38
|
+
import java.util.List;
|
|
39
|
+
|
|
40
|
+
@CapacitorPlugin(name = "TxaSettingsPermission")
|
|
41
|
+
public class TxaSettingsPermissionPlugin extends Plugin {
|
|
42
|
+
|
|
43
|
+
private static final String TAG = "TxaSettingsPermission";
|
|
44
|
+
|
|
45
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
46
|
+
// HELPER: build log object đẹp trả về JS
|
|
47
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
48
|
+
|
|
49
|
+
private JSObject buildLog(String level, String message, String action, boolean success) {
|
|
50
|
+
JSObject log = new JSObject();
|
|
51
|
+
log.put("level", level);
|
|
52
|
+
log.put("message", message);
|
|
53
|
+
log.put("action", action);
|
|
54
|
+
log.put("success", success);
|
|
55
|
+
log.put("androidVersion", Build.VERSION.SDK_INT);
|
|
56
|
+
log.put("androidRelease", Build.VERSION.RELEASE);
|
|
57
|
+
log.put("timestamp", System.currentTimeMillis());
|
|
58
|
+
return log;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private void logInfo(String msg) {
|
|
62
|
+
Log.i(TAG, "✅ " + msg);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private void logWarn(String msg) {
|
|
66
|
+
Log.w(TAG, "⚠️ " + msg);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private void logError(String msg) {
|
|
70
|
+
Log.e(TAG, "❌ " + msg);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
74
|
+
// getDeviceInfo: thông tin thiết bị + Android version
|
|
75
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
@PluginMethod
|
|
78
|
+
public void getDeviceInfo(PluginCall call) {
|
|
79
|
+
JSObject result = new JSObject();
|
|
80
|
+
result.put("androidSdk", Build.VERSION.SDK_INT);
|
|
81
|
+
result.put("androidRelease", Build.VERSION.RELEASE);
|
|
82
|
+
result.put("manufacturer", Build.MANUFACTURER);
|
|
83
|
+
result.put("model", Build.MODEL);
|
|
84
|
+
result.put("brand", Build.BRAND);
|
|
85
|
+
result.put("device", Build.DEVICE);
|
|
86
|
+
result.put("packageName", getContext().getPackageName());
|
|
87
|
+
|
|
88
|
+
// Feature flags theo version
|
|
89
|
+
result.put("supportsManageAllFiles", Build.VERSION.SDK_INT >= Build.VERSION_CODES.R);
|
|
90
|
+
result.put("supportsNotificationPolicy", Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
|
|
91
|
+
result.put("supportsOverlay", Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
|
|
92
|
+
result.put("supportsBatteryOptimization", Build.VERSION.SDK_INT >= Build.VERSION_CODES.M);
|
|
93
|
+
result.put("supportsMediaPermissions", Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU);
|
|
94
|
+
result.put("supportsInstallUnknownApps", Build.VERSION.SDK_INT >= Build.VERSION_CODES.O);
|
|
95
|
+
result.put("supportsUsageStats", Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1);
|
|
96
|
+
result.put("supportsAccessibility", true);
|
|
97
|
+
result.put("supportsDeviceAdmin", true);
|
|
98
|
+
|
|
99
|
+
logInfo("getDeviceInfo → SDK " + Build.VERSION.SDK_INT + " (" + Build.MANUFACTURER + " " + Build.MODEL + ")");
|
|
100
|
+
call.resolve(result);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
104
|
+
// openSettings: mở màn hình Settings tổng quát của app
|
|
105
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
@PluginMethod
|
|
108
|
+
public void openSettings(PluginCall call) {
|
|
109
|
+
try {
|
|
110
|
+
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
|
111
|
+
intent.setData(Uri.parse("package:" + getContext().getPackageName()));
|
|
112
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
113
|
+
getActivity().startActivity(intent);
|
|
114
|
+
|
|
115
|
+
logInfo("openSettings → Opened app settings");
|
|
116
|
+
JSObject result = new JSObject();
|
|
117
|
+
result.put("opened", true);
|
|
118
|
+
result.put("screen", "APP_SETTINGS");
|
|
119
|
+
result.put("log", buildLog("info", "Đã mở màn hình cài đặt ứng dụng", "APP_SETTINGS", true));
|
|
120
|
+
call.resolve(result);
|
|
121
|
+
} catch (Exception e) {
|
|
122
|
+
logError("openSettings → " + e.getMessage());
|
|
123
|
+
call.reject("TXA_ERR_OPEN_SETTINGS: Không thể mở Settings → " + e.getMessage(), "OPEN_SETTINGS_FAILED", e);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
128
|
+
// openManageAllFiles: MANAGE_EXTERNAL_STORAGE (Android 11+)
|
|
129
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
130
|
+
|
|
131
|
+
@PluginMethod
|
|
132
|
+
public void openManageAllFiles(PluginCall call) {
|
|
133
|
+
JSObject result = new JSObject();
|
|
134
|
+
|
|
135
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
136
|
+
if (Environment.isExternalStorageManager()) {
|
|
137
|
+
logInfo("openManageAllFiles → Already granted");
|
|
138
|
+
result.put("granted", true);
|
|
139
|
+
result.put("opened", false);
|
|
140
|
+
result.put("log", buildLog("info", "Đã có quyền MANAGE_EXTERNAL_STORAGE", "MANAGE_ALL_FILES", true));
|
|
141
|
+
call.resolve(result);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
Intent intent = new Intent(
|
|
146
|
+
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
|
|
147
|
+
Uri.parse("package:" + getContext().getPackageName())
|
|
148
|
+
);
|
|
149
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
150
|
+
getActivity().startActivity(intent);
|
|
151
|
+
logInfo("openManageAllFiles → Opened per-app screen");
|
|
152
|
+
result.put("granted", false);
|
|
153
|
+
result.put("opened", true);
|
|
154
|
+
result.put("screen", "MANAGE_APP_ALL_FILES_ACCESS");
|
|
155
|
+
result.put("log", buildLog("info", "Đã mở màn hình 'Truy cập tất cả các file'", "MANAGE_APP_ALL_FILES", true));
|
|
156
|
+
call.resolve(result);
|
|
157
|
+
} catch (Exception e) {
|
|
158
|
+
logWarn("openManageAllFiles → Per-app failed, trying global → " + e.getMessage());
|
|
159
|
+
try {
|
|
160
|
+
Intent fallback = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
|
|
161
|
+
fallback.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
162
|
+
getActivity().startActivity(fallback);
|
|
163
|
+
result.put("granted", false);
|
|
164
|
+
result.put("opened", true);
|
|
165
|
+
result.put("screen", "MANAGE_ALL_FILES_ACCESS_PERMISSION");
|
|
166
|
+
result.put("log", buildLog("warn", "Fallback: Đã mở màn hình All Files Access chung", "MANAGE_ALL_FILES_FALLBACK", true));
|
|
167
|
+
call.resolve(result);
|
|
168
|
+
} catch (Exception e2) {
|
|
169
|
+
logError("openManageAllFiles → Both failed: " + e2.getMessage());
|
|
170
|
+
call.reject("TXA_ERR_MANAGE_ALL_FILES: Không thể mở màn hình quản lý file → " + e2.getMessage(), "MANAGE_ALL_FILES_FAILED", e2);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
} else {
|
|
174
|
+
logInfo("openManageAllFiles → Android < 11, permission not needed");
|
|
175
|
+
result.put("granted", true);
|
|
176
|
+
result.put("opened", false);
|
|
177
|
+
result.put("log", buildLog("info", "Android " + Build.VERSION.RELEASE + " < 11, không cần quyền MANAGE_EXTERNAL_STORAGE", "MANAGE_ALL_FILES_NOT_NEEDED", true));
|
|
178
|
+
call.resolve(result);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
183
|
+
// checkManageAllFiles
|
|
184
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
@PluginMethod
|
|
187
|
+
public void checkManageAllFiles(PluginCall call) {
|
|
188
|
+
JSObject result = new JSObject();
|
|
189
|
+
boolean granted;
|
|
190
|
+
|
|
191
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
|
192
|
+
granted = Environment.isExternalStorageManager();
|
|
193
|
+
} else {
|
|
194
|
+
granted = true;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
result.put("granted", granted);
|
|
198
|
+
result.put("androidSdk", Build.VERSION.SDK_INT);
|
|
199
|
+
result.put("log", buildLog(granted ? "info" : "warn",
|
|
200
|
+
granted ? "Đã có quyền MANAGE_EXTERNAL_STORAGE" : "Chưa có quyền MANAGE_EXTERNAL_STORAGE",
|
|
201
|
+
"CHECK_MANAGE_ALL_FILES", granted));
|
|
202
|
+
logInfo("checkManageAllFiles → " + granted);
|
|
203
|
+
call.resolve(result);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
207
|
+
// openOverlaySettings: Hiển thị trên ứng dụng khác (Android 6+)
|
|
208
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
209
|
+
|
|
210
|
+
@PluginMethod
|
|
211
|
+
public void openOverlaySettings(PluginCall call) {
|
|
212
|
+
JSObject result = new JSObject();
|
|
213
|
+
|
|
214
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
215
|
+
if (Settings.canDrawOverlays(getContext())) {
|
|
216
|
+
logInfo("openOverlaySettings → Already granted");
|
|
217
|
+
result.put("granted", true);
|
|
218
|
+
result.put("opened", false);
|
|
219
|
+
result.put("log", buildLog("info", "Đã có quyền hiển thị trên ứng dụng khác", "OVERLAY", true));
|
|
220
|
+
call.resolve(result);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
try {
|
|
224
|
+
Intent intent = new Intent(
|
|
225
|
+
Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
|
|
226
|
+
Uri.parse("package:" + getContext().getPackageName())
|
|
227
|
+
);
|
|
228
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
229
|
+
getActivity().startActivity(intent);
|
|
230
|
+
logInfo("openOverlaySettings → Opened");
|
|
231
|
+
result.put("granted", false);
|
|
232
|
+
result.put("opened", true);
|
|
233
|
+
result.put("screen", "MANAGE_OVERLAY_PERMISSION");
|
|
234
|
+
result.put("log", buildLog("info", "Đã mở màn hình 'Hiển thị trên ứng dụng khác'", "OVERLAY", true));
|
|
235
|
+
call.resolve(result);
|
|
236
|
+
} catch (Exception e) {
|
|
237
|
+
logError("openOverlaySettings → " + e.getMessage());
|
|
238
|
+
call.reject("TXA_ERR_OVERLAY: Không thể mở màn hình Overlay → " + e.getMessage(), "OVERLAY_FAILED", e);
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
logInfo("openOverlaySettings → Android < 6, not needed");
|
|
242
|
+
result.put("granted", true);
|
|
243
|
+
result.put("opened", false);
|
|
244
|
+
result.put("log", buildLog("info", "Android < 6, không cần quyền Overlay", "OVERLAY_NOT_NEEDED", true));
|
|
245
|
+
call.resolve(result);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
250
|
+
// checkOverlay
|
|
251
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
252
|
+
|
|
253
|
+
@PluginMethod
|
|
254
|
+
public void checkOverlay(PluginCall call) {
|
|
255
|
+
boolean granted = Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|
|
256
|
+
|| Settings.canDrawOverlays(getContext());
|
|
257
|
+
JSObject result = new JSObject();
|
|
258
|
+
result.put("granted", granted);
|
|
259
|
+
result.put("log", buildLog(granted ? "info" : "warn",
|
|
260
|
+
granted ? "Đã có quyền Overlay" : "Chưa có quyền Overlay",
|
|
261
|
+
"CHECK_OVERLAY", granted));
|
|
262
|
+
call.resolve(result);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
266
|
+
// openInstallUnknownApps: Cài từ nguồn không rõ (Android 8+)
|
|
267
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
268
|
+
|
|
269
|
+
@PluginMethod
|
|
270
|
+
public void openInstallUnknownApps(PluginCall call) {
|
|
271
|
+
JSObject result = new JSObject();
|
|
272
|
+
|
|
273
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
274
|
+
if (getContext().getPackageManager().canRequestPackageInstalls()) {
|
|
275
|
+
logInfo("openInstallUnknownApps → Already granted");
|
|
276
|
+
result.put("granted", true);
|
|
277
|
+
result.put("opened", false);
|
|
278
|
+
result.put("log", buildLog("info", "Đã có quyền cài ứng dụng từ nguồn không rõ", "INSTALL_UNKNOWN_APPS", true));
|
|
279
|
+
call.resolve(result);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
try {
|
|
283
|
+
Intent intent = new Intent(
|
|
284
|
+
Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
|
|
285
|
+
Uri.parse("package:" + getContext().getPackageName())
|
|
286
|
+
);
|
|
287
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
288
|
+
getActivity().startActivity(intent);
|
|
289
|
+
logInfo("openInstallUnknownApps → Opened");
|
|
290
|
+
result.put("granted", false);
|
|
291
|
+
result.put("opened", true);
|
|
292
|
+
result.put("screen", "MANAGE_UNKNOWN_APP_SOURCES");
|
|
293
|
+
result.put("log", buildLog("info", "Đã mở màn hình 'Cài ứng dụng không rõ nguồn'", "INSTALL_UNKNOWN_APPS", true));
|
|
294
|
+
call.resolve(result);
|
|
295
|
+
} catch (Exception e) {
|
|
296
|
+
logError("openInstallUnknownApps → " + e.getMessage());
|
|
297
|
+
call.reject("TXA_ERR_INSTALL_UNKNOWN: Không thể mở màn hình → " + e.getMessage(), "INSTALL_UNKNOWN_FAILED", e);
|
|
298
|
+
}
|
|
299
|
+
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
300
|
+
// Android 5-7: chỉ mở settings chung
|
|
301
|
+
try {
|
|
302
|
+
Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
|
|
303
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
304
|
+
getActivity().startActivity(intent);
|
|
305
|
+
logWarn("openInstallUnknownApps → Android < 8, opened Security Settings");
|
|
306
|
+
result.put("granted", false);
|
|
307
|
+
result.put("opened", true);
|
|
308
|
+
result.put("screen", "SECURITY_SETTINGS");
|
|
309
|
+
result.put("log", buildLog("warn", "Android < 8: Mở Security Settings để bật 'Nguồn không xác định'", "INSTALL_UNKNOWN_LEGACY", true));
|
|
310
|
+
call.resolve(result);
|
|
311
|
+
} catch (Exception e) {
|
|
312
|
+
call.reject("TXA_ERR_SECURITY_SETTINGS: " + e.getMessage(), "SECURITY_SETTINGS_FAILED", e);
|
|
313
|
+
}
|
|
314
|
+
} else {
|
|
315
|
+
result.put("granted", true);
|
|
316
|
+
result.put("log", buildLog("info", "Android quá cũ, mặc định cho phép", "INSTALL_UNKNOWN_OLD", true));
|
|
317
|
+
call.resolve(result);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
322
|
+
// checkInstallUnknownApps
|
|
323
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
324
|
+
|
|
325
|
+
@PluginMethod
|
|
326
|
+
public void checkInstallUnknownApps(PluginCall call) {
|
|
327
|
+
boolean granted;
|
|
328
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
329
|
+
granted = getContext().getPackageManager().canRequestPackageInstalls();
|
|
330
|
+
} else {
|
|
331
|
+
granted = true;
|
|
332
|
+
}
|
|
333
|
+
JSObject result = new JSObject();
|
|
334
|
+
result.put("granted", granted);
|
|
335
|
+
result.put("log", buildLog(granted ? "info" : "warn",
|
|
336
|
+
granted ? "Đã có quyền cài APK ngoài" : "Chưa có quyền cài APK ngoài",
|
|
337
|
+
"CHECK_INSTALL_UNKNOWN", granted));
|
|
338
|
+
call.resolve(result);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
342
|
+
// openBatteryOptimization: Bỏ qua tối ưu hóa pin (Android 6+)
|
|
343
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
344
|
+
|
|
345
|
+
@PluginMethod
|
|
346
|
+
public void openBatteryOptimization(PluginCall call) {
|
|
347
|
+
JSObject result = new JSObject();
|
|
348
|
+
|
|
349
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
350
|
+
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
|
|
351
|
+
if (pm != null && pm.isIgnoringBatteryOptimizations(getContext().getPackageName())) {
|
|
352
|
+
logInfo("openBatteryOptimization → Already ignoring");
|
|
353
|
+
result.put("granted", true);
|
|
354
|
+
result.put("opened", false);
|
|
355
|
+
result.put("log", buildLog("info", "App đã được bỏ qua tối ưu hóa pin", "BATTERY_OPTIMIZATION", true));
|
|
356
|
+
call.resolve(result);
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
try {
|
|
360
|
+
Intent intent = new Intent(
|
|
361
|
+
Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
|
|
362
|
+
Uri.parse("package:" + getContext().getPackageName())
|
|
363
|
+
);
|
|
364
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
365
|
+
getActivity().startActivity(intent);
|
|
366
|
+
logInfo("openBatteryOptimization → Opened");
|
|
367
|
+
result.put("granted", false);
|
|
368
|
+
result.put("opened", true);
|
|
369
|
+
result.put("screen", "REQUEST_IGNORE_BATTERY_OPTIMIZATIONS");
|
|
370
|
+
result.put("log", buildLog("info", "Đã mở màn hình bỏ qua tối ưu hóa pin", "BATTERY_OPTIMIZATION", true));
|
|
371
|
+
call.resolve(result);
|
|
372
|
+
} catch (Exception e) {
|
|
373
|
+
logWarn("openBatteryOptimization → Direct failed, opening battery settings: " + e.getMessage());
|
|
374
|
+
try {
|
|
375
|
+
Intent fallback = new Intent(Settings.ACTION_BATTERY_SAVER_SETTINGS);
|
|
376
|
+
fallback.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
377
|
+
getActivity().startActivity(fallback);
|
|
378
|
+
result.put("opened", true);
|
|
379
|
+
result.put("screen", "BATTERY_SAVER_SETTINGS");
|
|
380
|
+
result.put("log", buildLog("warn", "Fallback: Đã mở Battery Saver Settings", "BATTERY_OPTIMIZATION_FALLBACK", true));
|
|
381
|
+
call.resolve(result);
|
|
382
|
+
} catch (Exception e2) {
|
|
383
|
+
call.reject("TXA_ERR_BATTERY: Không thể mở màn hình pin → " + e2.getMessage(), "BATTERY_FAILED", e2);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
logInfo("openBatteryOptimization → Android < 6, not needed");
|
|
388
|
+
result.put("granted", true);
|
|
389
|
+
result.put("log", buildLog("info", "Android < 6, không cần xử lý Battery Optimization", "BATTERY_NOT_NEEDED", true));
|
|
390
|
+
call.resolve(result);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
395
|
+
// checkBatteryOptimization
|
|
396
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
397
|
+
|
|
398
|
+
@PluginMethod
|
|
399
|
+
public void checkBatteryOptimization(PluginCall call) {
|
|
400
|
+
boolean ignoring = true;
|
|
401
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
402
|
+
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
|
|
403
|
+
ignoring = pm != null && pm.isIgnoringBatteryOptimizations(getContext().getPackageName());
|
|
404
|
+
}
|
|
405
|
+
JSObject result = new JSObject();
|
|
406
|
+
result.put("ignoring", ignoring);
|
|
407
|
+
result.put("granted", ignoring);
|
|
408
|
+
result.put("log", buildLog(ignoring ? "info" : "warn",
|
|
409
|
+
ignoring ? "App đang được bỏ qua tối ưu hóa pin" : "App vẫn bị tối ưu hóa pin",
|
|
410
|
+
"CHECK_BATTERY", ignoring));
|
|
411
|
+
call.resolve(result);
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
415
|
+
// openNotificationSettings: Cài đặt thông báo
|
|
416
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
417
|
+
|
|
418
|
+
@PluginMethod
|
|
419
|
+
public void openNotificationSettings(PluginCall call) {
|
|
420
|
+
try {
|
|
421
|
+
Intent intent;
|
|
422
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
423
|
+
intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
|
|
424
|
+
intent.putExtra(Settings.EXTRA_APP_PACKAGE, getContext().getPackageName());
|
|
425
|
+
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
426
|
+
intent = new Intent("android.settings.APP_NOTIFICATION_SETTINGS");
|
|
427
|
+
intent.putExtra("app_package", getContext().getPackageName());
|
|
428
|
+
intent.putExtra("app_uid", getContext().getApplicationInfo().uid);
|
|
429
|
+
} else {
|
|
430
|
+
intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
|
431
|
+
intent.setData(Uri.parse("package:" + getContext().getPackageName()));
|
|
432
|
+
}
|
|
433
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
434
|
+
getActivity().startActivity(intent);
|
|
435
|
+
logInfo("openNotificationSettings → Opened (SDK " + Build.VERSION.SDK_INT + ")");
|
|
436
|
+
JSObject result = new JSObject();
|
|
437
|
+
result.put("opened", true);
|
|
438
|
+
result.put("screen", "APP_NOTIFICATION_SETTINGS");
|
|
439
|
+
result.put("log", buildLog("info", "Đã mở màn hình cài đặt thông báo", "NOTIFICATION_SETTINGS", true));
|
|
440
|
+
call.resolve(result);
|
|
441
|
+
} catch (Exception e) {
|
|
442
|
+
logError("openNotificationSettings → " + e.getMessage());
|
|
443
|
+
call.reject("TXA_ERR_NOTIFICATION: Không thể mở cài đặt thông báo → " + e.getMessage(), "NOTIFICATION_FAILED", e);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
448
|
+
// openNotificationPolicyAccess: Chế độ không làm phiền (Android 6+)
|
|
449
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
450
|
+
|
|
451
|
+
@PluginMethod
|
|
452
|
+
public void openNotificationPolicyAccess(PluginCall call) {
|
|
453
|
+
JSObject result = new JSObject();
|
|
454
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
455
|
+
try {
|
|
456
|
+
Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS);
|
|
457
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
458
|
+
getActivity().startActivity(intent);
|
|
459
|
+
logInfo("openNotificationPolicyAccess → Opened");
|
|
460
|
+
result.put("opened", true);
|
|
461
|
+
result.put("screen", "NOTIFICATION_POLICY_ACCESS_SETTINGS");
|
|
462
|
+
result.put("log", buildLog("info", "Đã mở màn hình quyền truy cập chính sách thông báo (DND)", "NOTIFICATION_POLICY", true));
|
|
463
|
+
call.resolve(result);
|
|
464
|
+
} catch (Exception e) {
|
|
465
|
+
logError("openNotificationPolicyAccess → " + e.getMessage());
|
|
466
|
+
call.reject("TXA_ERR_NOTIFICATION_POLICY: " + e.getMessage(), "NOTIFICATION_POLICY_FAILED", e);
|
|
467
|
+
}
|
|
468
|
+
} else {
|
|
469
|
+
result.put("granted", true);
|
|
470
|
+
result.put("log", buildLog("info", "Android < 6, không cần quyền Notification Policy", "NOTIFICATION_POLICY_NOT_NEEDED", true));
|
|
471
|
+
call.resolve(result);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
476
|
+
// openAccessibilitySettings: Quyền trợ năng
|
|
477
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
478
|
+
|
|
479
|
+
@PluginMethod
|
|
480
|
+
public void openAccessibilitySettings(PluginCall call) {
|
|
481
|
+
try {
|
|
482
|
+
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
|
|
483
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
484
|
+
getActivity().startActivity(intent);
|
|
485
|
+
logInfo("openAccessibilitySettings → Opened");
|
|
486
|
+
JSObject result = new JSObject();
|
|
487
|
+
result.put("opened", true);
|
|
488
|
+
result.put("screen", "ACCESSIBILITY_SETTINGS");
|
|
489
|
+
result.put("log", buildLog("info", "Đã mở màn hình Trợ năng (Accessibility)", "ACCESSIBILITY", true));
|
|
490
|
+
call.resolve(result);
|
|
491
|
+
} catch (Exception e) {
|
|
492
|
+
logError("openAccessibilitySettings → " + e.getMessage());
|
|
493
|
+
call.reject("TXA_ERR_ACCESSIBILITY: " + e.getMessage(), "ACCESSIBILITY_FAILED", e);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
498
|
+
// openUsageStatsSettings: Quyền sử dụng dữ liệu (Android 5.1+)
|
|
499
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
500
|
+
|
|
501
|
+
@PluginMethod
|
|
502
|
+
public void openUsageStatsSettings(PluginCall call) {
|
|
503
|
+
JSObject result = new JSObject();
|
|
504
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
|
|
505
|
+
try {
|
|
506
|
+
Intent intent = new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS);
|
|
507
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
508
|
+
getActivity().startActivity(intent);
|
|
509
|
+
logInfo("openUsageStatsSettings → Opened");
|
|
510
|
+
result.put("opened", true);
|
|
511
|
+
result.put("screen", "USAGE_ACCESS_SETTINGS");
|
|
512
|
+
result.put("log", buildLog("info", "Đã mở màn hình quyền truy cập dữ liệu sử dụng", "USAGE_STATS", true));
|
|
513
|
+
call.resolve(result);
|
|
514
|
+
} catch (Exception e) {
|
|
515
|
+
logError("openUsageStatsSettings → " + e.getMessage());
|
|
516
|
+
call.reject("TXA_ERR_USAGE_STATS: " + e.getMessage(), "USAGE_STATS_FAILED", e);
|
|
517
|
+
}
|
|
518
|
+
} else {
|
|
519
|
+
result.put("granted", true);
|
|
520
|
+
result.put("log", buildLog("info", "Android < 5.1, không cần quyền Usage Stats", "USAGE_STATS_NOT_NEEDED", true));
|
|
521
|
+
call.resolve(result);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
526
|
+
// openDeviceAdminSettings: Quản trị thiết bị
|
|
527
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
528
|
+
|
|
529
|
+
@PluginMethod
|
|
530
|
+
public void openDeviceAdminSettings(PluginCall call) {
|
|
531
|
+
try {
|
|
532
|
+
Intent intent = new Intent(Settings.ACTION_DEVICE_INFO_SETTINGS);
|
|
533
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
534
|
+
getActivity().startActivity(intent);
|
|
535
|
+
logInfo("openDeviceAdminSettings → Opened");
|
|
536
|
+
JSObject result = new JSObject();
|
|
537
|
+
result.put("opened", true);
|
|
538
|
+
result.put("screen", "DEVICE_INFO_SETTINGS");
|
|
539
|
+
result.put("log", buildLog("info", "Đã mở màn hình thông tin thiết bị", "DEVICE_ADMIN", true));
|
|
540
|
+
call.resolve(result);
|
|
541
|
+
} catch (Exception e) {
|
|
542
|
+
logError("openDeviceAdminSettings → " + e.getMessage());
|
|
543
|
+
call.reject("TXA_ERR_DEVICE_ADMIN: " + e.getMessage(), "DEVICE_ADMIN_FAILED", e);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
548
|
+
// openWifiSettings / openLocationSettings / openBluetoothSettings
|
|
549
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
550
|
+
|
|
551
|
+
@PluginMethod
|
|
552
|
+
public void openWifiSettings(PluginCall call) {
|
|
553
|
+
openSimpleSettings(call, Settings.ACTION_WIFI_SETTINGS, "WIFI_SETTINGS", "Đã mở cài đặt WiFi");
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
@PluginMethod
|
|
557
|
+
public void openLocationSettings(PluginCall call) {
|
|
558
|
+
openSimpleSettings(call, Settings.ACTION_LOCATION_SOURCE_SETTINGS, "LOCATION_SETTINGS", "Đã mở cài đặt Vị trí");
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
@PluginMethod
|
|
562
|
+
public void openBluetoothSettings(PluginCall call) {
|
|
563
|
+
openSimpleSettings(call, Settings.ACTION_BLUETOOTH_SETTINGS, "BLUETOOTH_SETTINGS", "Đã mở cài đặt Bluetooth");
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
@PluginMethod
|
|
567
|
+
public void openNfcSettings(PluginCall call) {
|
|
568
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
|
569
|
+
openSimpleSettings(call, Settings.ACTION_NFC_SETTINGS, "NFC_SETTINGS", "Đã mở cài đặt NFC");
|
|
570
|
+
} else {
|
|
571
|
+
openSimpleSettings(call, Settings.ACTION_WIRELESS_SETTINGS, "WIRELESS_SETTINGS", "Đã mở cài đặt Wireless (NFC fallback)");
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
@PluginMethod
|
|
576
|
+
public void openDateTimeSettings(PluginCall call) {
|
|
577
|
+
openSimpleSettings(call, Settings.ACTION_DATE_SETTINGS, "DATE_SETTINGS", "Đã mở cài đặt Ngày giờ");
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
@PluginMethod
|
|
581
|
+
public void openLanguageSettings(PluginCall call) {
|
|
582
|
+
openSimpleSettings(call, Settings.ACTION_LOCALE_SETTINGS, "LOCALE_SETTINGS", "Đã mở cài đặt Ngôn ngữ");
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
@PluginMethod
|
|
586
|
+
public void openStorageSettings(PluginCall call) {
|
|
587
|
+
openSimpleSettings(call, Settings.ACTION_INTERNAL_STORAGE_SETTINGS, "STORAGE_SETTINGS", "Đã mở cài đặt Bộ nhớ");
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
@PluginMethod
|
|
591
|
+
public void openDisplaySettings(PluginCall call) {
|
|
592
|
+
openSimpleSettings(call, Settings.ACTION_DISPLAY_SETTINGS, "DISPLAY_SETTINGS", "Đã mở cài đặt Màn hình");
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
@PluginMethod
|
|
596
|
+
public void openSoundSettings(PluginCall call) {
|
|
597
|
+
openSimpleSettings(call, Settings.ACTION_SOUND_SETTINGS, "SOUND_SETTINGS", "Đã mở cài đặt Âm thanh");
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
601
|
+
// checkRuntimePermission: kiểm tra bất kỳ runtime permission nào
|
|
602
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
603
|
+
|
|
604
|
+
@PluginMethod
|
|
605
|
+
public void checkRuntimePermission(PluginCall call) {
|
|
606
|
+
String permission = call.getString("permission");
|
|
607
|
+
if (permission == null || permission.isEmpty()) {
|
|
608
|
+
call.reject("TXA_ERR_PARAM: Thiếu tham số 'permission'", "MISSING_PARAM");
|
|
609
|
+
return;
|
|
610
|
+
}
|
|
611
|
+
boolean granted = ContextCompat.checkSelfPermission(getContext(), permission)
|
|
612
|
+
== PackageManager.PERMISSION_GRANTED;
|
|
613
|
+
JSObject result = new JSObject();
|
|
614
|
+
result.put("permission", permission);
|
|
615
|
+
result.put("granted", granted);
|
|
616
|
+
result.put("log", buildLog(granted ? "info" : "warn",
|
|
617
|
+
granted ? "Đã có quyền: " + permission : "Chưa có quyền: " + permission,
|
|
618
|
+
"CHECK_RUNTIME_PERMISSION", granted));
|
|
619
|
+
call.resolve(result);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
623
|
+
// checkMultiplePermissions: check nhiều quyền 1 lúc
|
|
624
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
625
|
+
|
|
626
|
+
@PluginMethod
|
|
627
|
+
public void checkMultiplePermissions(PluginCall call) {
|
|
628
|
+
JSArray permsArray = call.getArray("permissions");
|
|
629
|
+
if (permsArray == null) {
|
|
630
|
+
call.reject("TXA_ERR_PARAM: Thiếu tham số 'permissions' (array)", "MISSING_PARAM");
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
JSObject result = new JSObject();
|
|
635
|
+
JSObject permResults = new JSObject();
|
|
636
|
+
boolean allGranted = true;
|
|
637
|
+
List<String> missing = new ArrayList<>();
|
|
638
|
+
|
|
639
|
+
try {
|
|
640
|
+
JSONArray arr = permsArray.toJSONArray();
|
|
641
|
+
if (arr != null) {
|
|
642
|
+
for (int i = 0; i < arr.length(); i++) {
|
|
643
|
+
String perm = arr.getString(i);
|
|
644
|
+
boolean granted = ContextCompat.checkSelfPermission(getContext(), perm)
|
|
645
|
+
== PackageManager.PERMISSION_GRANTED;
|
|
646
|
+
permResults.put(perm, granted);
|
|
647
|
+
if (!granted) {
|
|
648
|
+
allGranted = false;
|
|
649
|
+
missing.add(perm);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
} catch (JSONException e) {
|
|
654
|
+
call.reject("TXA_ERR_PARSE: Lỗi parse permissions array → " + e.getMessage(), "PARSE_ERROR", e);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
result.put("results", permResults);
|
|
659
|
+
result.put("allGranted", allGranted);
|
|
660
|
+
try {
|
|
661
|
+
result.put("missing", new JSArray(missing));
|
|
662
|
+
} catch (Exception ignore) {}
|
|
663
|
+
result.put("log", buildLog(allGranted ? "info" : "warn",
|
|
664
|
+
allGranted ? "Tất cả quyền đã được cấp" : "Thiếu " + missing.size() + " quyền: " + missing,
|
|
665
|
+
"CHECK_MULTIPLE_PERMISSIONS", allGranted));
|
|
666
|
+
call.resolve(result);
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
670
|
+
// checkAllRequired: kiểm tra toàn bộ các permission cần thiết của app
|
|
671
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
672
|
+
|
|
673
|
+
@PluginMethod
|
|
674
|
+
public void checkAllRequired(PluginCall call) {
|
|
675
|
+
JSObject result = new JSObject();
|
|
676
|
+
JSObject checks = new JSObject();
|
|
677
|
+
|
|
678
|
+
// MANAGE_EXTERNAL_STORAGE
|
|
679
|
+
boolean manageFiles = Build.VERSION.SDK_INT < Build.VERSION_CODES.R
|
|
680
|
+
|| Environment.isExternalStorageManager();
|
|
681
|
+
checks.put("manageAllFiles", manageFiles);
|
|
682
|
+
|
|
683
|
+
// Overlay
|
|
684
|
+
boolean overlay = Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|
|
685
|
+
|| Settings.canDrawOverlays(getContext());
|
|
686
|
+
checks.put("overlay", overlay);
|
|
687
|
+
|
|
688
|
+
// Install unknown apps
|
|
689
|
+
boolean installUnknown = Build.VERSION.SDK_INT < Build.VERSION_CODES.O
|
|
690
|
+
|| getContext().getPackageManager().canRequestPackageInstalls();
|
|
691
|
+
checks.put("installUnknownApps", installUnknown);
|
|
692
|
+
|
|
693
|
+
// Battery optimization
|
|
694
|
+
boolean batteryIgnoring = true;
|
|
695
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
696
|
+
PowerManager pm = (PowerManager) getContext().getSystemService(Context.POWER_SERVICE);
|
|
697
|
+
batteryIgnoring = pm != null && pm.isIgnoringBatteryOptimizations(getContext().getPackageName());
|
|
698
|
+
}
|
|
699
|
+
checks.put("batteryOptimization", batteryIgnoring);
|
|
700
|
+
|
|
701
|
+
// Runtime permissions thường gặp
|
|
702
|
+
checks.put("camera", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED);
|
|
703
|
+
checks.put("microphone", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED);
|
|
704
|
+
checks.put("location", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED);
|
|
705
|
+
|
|
706
|
+
// Media permissions (Android 13+)
|
|
707
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
|
708
|
+
checks.put("readMediaImages", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_MEDIA_IMAGES) == PackageManager.PERMISSION_GRANTED);
|
|
709
|
+
checks.put("readMediaVideo", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_MEDIA_VIDEO) == PackageManager.PERMISSION_GRANTED);
|
|
710
|
+
checks.put("readMediaAudio", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_MEDIA_AUDIO) == PackageManager.PERMISSION_GRANTED);
|
|
711
|
+
checks.put("postNotifications", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED);
|
|
712
|
+
} else {
|
|
713
|
+
checks.put("readExternalStorage", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
|
|
714
|
+
checks.put("writeExternalStorage", ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
result.put("checks", checks);
|
|
718
|
+
result.put("androidSdk", Build.VERSION.SDK_INT);
|
|
719
|
+
result.put("androidRelease", Build.VERSION.RELEASE);
|
|
720
|
+
logInfo("checkAllRequired → SDK " + Build.VERSION.SDK_INT + " | checks done");
|
|
721
|
+
call.resolve(result);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
725
|
+
// PRIVATE HELPER
|
|
726
|
+
// ─────────────────────────────────────────────────────────────────────────
|
|
727
|
+
|
|
728
|
+
private void openSimpleSettings(PluginCall call, String action, String screenName, String logMsg) {
|
|
729
|
+
try {
|
|
730
|
+
Intent intent = new Intent(action);
|
|
731
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
732
|
+
getActivity().startActivity(intent);
|
|
733
|
+
logInfo(screenName + " → Opened");
|
|
734
|
+
JSObject result = new JSObject();
|
|
735
|
+
result.put("opened", true);
|
|
736
|
+
result.put("screen", screenName);
|
|
737
|
+
result.put("log", buildLog("info", logMsg, screenName, true));
|
|
738
|
+
call.resolve(result);
|
|
739
|
+
} catch (Exception e) {
|
|
740
|
+
logError(screenName + " → " + e.getMessage());
|
|
741
|
+
call.reject("TXA_ERR_" + screenName + ": Không thể mở → " + e.getMessage(), screenName + "_FAILED", e);
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
}
|