39 private static WeakReference<Activity> m_activity =
null;
40 private static WeakReference<Service> m_service =
null;
41 private static final Object m_mainActivityMutex =
new Object();
43 private static final ApplicationStateDetails m_stateDetails =
new ApplicationStateDetails();
45 static final String QtTAG =
"Qt JAVA";
48 private static final BackgroundActionsTracker m_backgroundActionsTracker =
new BackgroundActionsTracker();
49 private static QtThread m_qtThread =
null;
50 private static final Object m_qtThreadLock =
new Object();
51 private static ClassLoader m_classLoader =
null;
53 private static final Runnable runPendingCppRunnablesRunnable = QtNative::runPendingCppRunnables;
54 private static final ArrayList<AppStateDetailsListener> m_appStateListeners =
new ArrayList<>();
55 private static final Object m_appStateListenersLock =
new Object();
58 static ClassLoader classLoader()
63 static void setClassLoader(ClassLoader classLoader)
65 m_classLoader = classLoader;
68 static void setActivity(Activity qtMainActivity)
70 synchronized (m_mainActivityMutex) {
71 m_activity =
new WeakReference<>(qtMainActivity);
73 if (m_stateDetails.isStarted)
74 updateNativeActivity();
75 }
catch (UnsatisfiedLinkError ignored) {
83 static void setService(Service qtMainService)
85 synchronized (m_mainActivityMutex) {
86 m_service =
new WeakReference<>(qtMainService);
91 static Activity activity()
93 synchronized (m_mainActivityMutex) {
94 return m_activity !=
null ? m_activity.get() :
null;
98 static boolean isActivityValid()
100 return m_activity !=
null && m_activity.get() !=
null;
104 static Service service()
106 synchronized (m_mainActivityMutex) {
107 return m_service !=
null ? m_service.get() :
null;
111 static boolean isServiceValid()
113 return m_service !=
null && m_service.get() !=
null;
118 if (isActivityValid())
119 return m_activity.get();
126 return joinedString.split(
",");
129 private static String getCurrentMethodNameLog()
131 return new Exception().getStackTrace()[1].getMethodName() +
": ";
139 parsedUri = Uri.parse(uri);
140 }
catch (NullPointerException e) {
146 String scheme = parsedUri.getScheme();
149 if (scheme !=
null && scheme.compareTo(
"content") != 0)
153 String uriStr = parsedUri.getPath();
155 for (
int i = 0; i < permissions.size(); ++i) {
156 Uri iterUri = permissions.get(i).getUri();
157 boolean isRequestPermission = permissions.get(i).isReadPermission();
159 if (!openMode.equals(
"r"))
160 isRequestPermission = permissions.get(i).isWritePermission();
162 if (Objects.equals(iterUri.getPath(), uriStr) && isRequestPermission)
170 }
catch (SecurityException e) {
171 Log.e(QtTAG, getCurrentMethodNameLog() + e);
179 final Uri uri = getUriWithValidPermission(
context,
url,
"r");
181 Log.e(QtTAG, getCurrentMethodNameLog() +
"received invalid/null Uri");
186 Intent intent =
new Intent(Intent.ACTION_VIEW, uri);
187 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
189 intent.setDataAndType(uri, mime);
191 Activity activity = activity();
192 if (activity ==
null) {
193 Log.w(QtTAG,
"openURL(): The activity reference is null");
197 activity.startActivity(intent);
200 }
catch (Exception e) {
201 Log.e(QtTAG, getCurrentMethodNameLog() + e);
206 static QtThread getQtThread() {
207 if (m_qtThread !=
null && m_qtThread.isAlive())
210 synchronized (m_qtThreadLock) {
211 if (m_qtThread ==
null || !m_qtThread.isAlive())
212 m_qtThread =
new QtThread();
224 static class ApplicationState {
225 static final int ApplicationSuspended = 0x0;
226 static final int ApplicationHidden = 0x1;
227 static final int ApplicationInactive = 0x2;
228 static final int ApplicationActive = 0x4;
231 static class ApplicationStateDetails {
232 int state = ApplicationState.ApplicationSuspended;
233 boolean nativePluginIntegrationReady =
false;
234 boolean isStarted =
false;
237 static ApplicationStateDetails getStateDetails()
239 return m_stateDetails;
242 static void setStarted(
boolean started)
244 m_stateDetails.isStarted = started;
245 notifyAppStateDetailsChanged(m_stateDetails);
249 static void notifyNativePluginIntegrationReady(
boolean ready)
251 m_stateDetails.nativePluginIntegrationReady = ready;
252 notifyNativePluginIntegrationReadyChanged(ready);
253 notifyAppStateDetailsChanged(m_stateDetails);
256 final String bufferSize = Os.getenv(
"QT_ANDROID_BACKGROUND_ACTIONS_QUEUE_SIZE");
257 if (bufferSize !=
null) {
260 m_backgroundActionsTracker.setMaxAllowedActions(
size);
261 }
catch (NumberFormatException exception) {
262 Log.e(QtTAG,
"Parsing failed, QT_ANDROID_BACKGROUND_ACTIONS_QUEUE_SIZE value is not an integer");
267 static void setApplicationState(
int state)
269 synchronized (m_mainActivityMutex) {
270 m_stateDetails.state =
state;
271 if (
state == ApplicationState.ApplicationActive)
272 m_backgroundActionsTracker.processActions();
274 updateApplicationState(
state);
275 notifyAppStateDetailsChanged(m_stateDetails);
279 synchronized (m_appStateListenersLock) {
280 if (!m_appStateListeners.contains(listener))
281 m_appStateListeners.add(listener);
286 synchronized (m_appStateListenersLock) {
287 m_appStateListeners.remove(listener);
291 static void notifyNativePluginIntegrationReadyChanged(
boolean ready) {
292 synchronized (m_appStateListenersLock) {
294 listener.onNativePluginIntegrationReadyChanged(ready);
298 static void notifyAppStateDetailsChanged(ApplicationStateDetails details) {
299 synchronized (m_appStateListenersLock) {
301 listener.onAppStateDetailsChanged(details);
307 static void runAction(Runnable action)
309 runAction(action,
true);
312 static void runAction(Runnable action,
boolean queueWhenInactive)
314 synchronized (m_mainActivityMutex) {
315 final Looper mainLooper = Looper.getMainLooper();
318 if (queueWhenInactive) {
319 final boolean isStateVisible =
320 (m_stateDetails.state != ApplicationState.ApplicationSuspended)
321 && (m_stateDetails.state != ApplicationState.ApplicationHidden);
322 final boolean active = (isActivityValid() && isStateVisible) || isServiceValid();
323 if (!active || !
handler.post(action))
324 m_backgroundActionsTracker.enqueue(action);
332 private static void runPendingCppRunnablesOnAndroidThread()
334 synchronized (m_mainActivityMutex) {
335 if (isActivityValid()) {
336 if (m_stateDetails.state == ApplicationState.ApplicationActive)
337 m_activity.get().runOnUiThread(runPendingCppRunnablesRunnable);
339 runAction(runPendingCppRunnablesRunnable);
341 final Looper mainLooper = Looper.getMainLooper();
342 final Thread looperThread = mainLooper.getThread();
343 if (looperThread.equals(Thread.currentThread())) {
344 runPendingCppRunnablesRunnable.run();
347 handler.post(runPendingCppRunnablesRunnable);
354 private static void setViewVisibility(
final View
view,
final boolean visible)
356 runAction(() ->
view.setVisibility(visible ? View.VISIBLE : View.GONE));
361 if (m_stateDetails.isStarted)
365 getQtThread().post(() -> { startQtNativeApplication(qtParams); });
369 static int checkSelfPermission(
String permission)
371 synchronized (m_mainActivityMutex) {
373 PackageManager pm =
context.getPackageManager();
374 return pm.checkPermission(permission,
context.getPackageName());
379 private static byte[][] getSSLCertificates()
381 ArrayList<byte[]> certificateList =
new ArrayList<>();
384 TrustManagerFactory
factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
388 if (
manager instanceof X509TrustManager) {
389 X509TrustManager trustManager = (X509TrustManager)
manager;
391 for (X509Certificate certificate : trustManager.getAcceptedIssuers()) {
392 byte[]
buffer = certificate.getEncoded();
393 certificateList.add(
buffer);
397 }
catch (Exception e) {
398 Log.e(QtTAG,
"Failed to get certificates", e);
401 byte[][] certificateArray =
new byte[certificateList.size()][];
402 certificateArray = certificateList.toArray(certificateArray);
403 return certificateArray;
407 private static String[] listAssetContent(android.content.res.AssetManager asset,
String path) {
409 ArrayList<String>
res =
new ArrayList<>();
416 if (isDir !=
null && isDir.length > 0)
419 }
catch (Exception e) {
424 }
catch (Exception e) {
431 static native
void startQtNativeApplication(
String params);
432 static native
void terminateQtNativeApplication();
433 static native
boolean updateNativeActivity();
437 static native
void updateApplicationState(
int state);
438 static native
void updateLocale();
441 static native
boolean onPrepareOptionsMenu(Menu
menu);
442 static native
boolean onOptionsItemSelected(
int itemId,
boolean checked);
443 static native
void onOptionsMenuClosed(Menu
menu);
445 static native
void onCreateContextMenu(ContextMenu
menu);
446 static native
void fillContextMenu(Menu
menu);
447 static native
boolean onContextItemSelected(
int itemId,
boolean checked);
448 static native
void onContextMenuClosed(Menu
menu);
452 static native
void onActivityResult(
int requestCode,
int resultCode, Intent
data);
455 static native
void runPendingCppRunnables();
457 static native
void sendRequestPermissionsResult(
int requestCode,
int[] grantResults);
461 static native IBinder onBind(Intent intent);