5package org.qtproject.qt.android;
7import android.app.Activity;
8import android.app.Service;
9import android.content.Context;
10import android.content.Intent;
11import android.content.UriPermission;
12import android.content.pm.PackageManager;
13import android.net.Uri;
14import android.os.Handler;
15import android.os.IBinder;
16import android.os.Looper;
17import android.util.Log;
18import android.view.ContextMenu;
19import android.view.Menu;
20import android.view.View;
22import java.lang.ref.WeakReference;
23import java.security.KeyStore;
24import java.security.cert.X509Certificate;
25import java.util.ArrayList;
27import java.util.Objects;
29import javax.net.ssl.TrustManager;
30import javax.net.ssl.TrustManagerFactory;
31import javax.net.ssl.X509TrustManager;
35 private static WeakReference<Activity> m_activity =
null;
36 private static WeakReference<Service> m_service =
null;
37 public static final Object m_mainActivityMutex =
new Object();
39 private static final ApplicationStateDetails m_stateDetails =
new ApplicationStateDetails();
41 public static final String QtTAG =
"Qt JAVA";
44 private static final ArrayList<Runnable> m_lostActions =
new ArrayList<>();
46 private static final QtThread m_qtThread =
new QtThread();
47 private static ClassLoader m_classLoader =
null;
49 private static final Runnable runPendingCppRunnablesRunnable = QtNative::runPendingCppRunnables;
50 private static final ArrayList<AppStateDetailsListener> m_appStateListeners =
new ArrayList<>();
51 private static final Object m_appStateListenersLock =
new Object();
54 public static ClassLoader classLoader()
59 public static void setClassLoader(ClassLoader classLoader)
64 public static void setActivity(Activity qtMainActivity)
66 synchronized (m_mainActivityMutex) {
67 m_activity =
new WeakReference<>(qtMainActivity);
71 public static void setService(Service qtMainService)
73 synchronized (m_mainActivityMutex) {
74 m_service =
new WeakReference<>(qtMainService);
79 public static Activity activity()
81 synchronized (m_mainActivityMutex) {
82 return m_activity !=
null ? m_activity.get() :
null;
86 public static boolean isActivityValid()
88 return m_activity !=
null && m_activity.get() !=
null;
92 public static Service service()
94 synchronized (m_mainActivityMutex) {
95 return m_service !=
null ? m_service.get() :
null;
99 public static boolean isServiceValid()
101 return m_service !=
null && m_service.get() !=
null;
105 public static Context getContext() {
106 if (isActivityValid())
107 return m_activity.get();
112 public static String[] getStringArray(String joinedString)
114 return joinedString.split(
",");
117 private static String getCurrentMethodNameLog()
119 return new Exception().getStackTrace()[1].getMethodName() +
": ";
123 private static Uri getUriWithValidPermission(Context
context, String uri, String openMode)
127 parsedUri = Uri.parse(uri);
128 }
catch (NullPointerException e) {
134 String scheme = parsedUri.getScheme();
137 if (scheme !=
null && scheme.compareTo(
"content") != 0)
140 List<UriPermission> permissions =
context.getContentResolver().getPersistedUriPermissions();
141 String uriStr = parsedUri.getPath();
143 for (
int i = 0;
i < permissions.size(); ++
i) {
144 Uri iterUri = permissions.get(
i).getUri();
145 boolean isRequestPermission = permissions.get(
i).isReadPermission();
147 if (!openMode.equals(
"r"))
148 isRequestPermission = permissions.get(
i).isWritePermission();
150 if (Objects.equals(iterUri.getPath(), uriStr) && isRequestPermission)
158 }
catch (SecurityException e) {
159 Log.e(QtTAG, getCurrentMethodNameLog() + e);
165 public static boolean openURL(Context
context, String
url, String
mime)
167 final Uri uri = getUriWithValidPermission(
context,
url,
"r");
169 Log.e(QtTAG, getCurrentMethodNameLog() +
"received invalid/null Uri");
174 Intent intent =
new Intent(Intent.ACTION_VIEW, uri);
175 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
177 intent.setDataAndType(uri,
mime);
180 if (activity ==
null) {
181 Log.w(QtTAG,
"openURL(): The activity reference is null");
188 }
catch (Exception e) {
189 Log.e(QtTAG, getCurrentMethodNameLog() + e);
194 static QtThread getQtThread() {
205 static final int ApplicationSuspended = 0x0;
206 static final int ApplicationHidden = 0x1;
207 static final int ApplicationInactive = 0x2;
208 static final int ApplicationActive = 0x4;
213 boolean nativePluginIntegrationReady =
false;
214 boolean isStarted =
false;
219 return m_stateDetails;
222 public static void setStarted(
boolean started)
224 m_stateDetails.isStarted = started;
225 notifyAppStateDetailsChanged(m_stateDetails);
229 public static void notifyNativePluginIntegrationReady(
boolean ready)
231 m_stateDetails.nativePluginIntegrationReady = ready;
232 notifyNativePluginIntegrationReadyChanged(ready);
233 notifyAppStateDetailsChanged(m_stateDetails);
236 public static void setApplicationState(
int state)
238 synchronized (m_mainActivityMutex) {
239 m_stateDetails.state =
state;
240 if (
state == ApplicationState.ApplicationActive) {
241 for (Runnable mLostAction : m_lostActions)
242 runAction(mLostAction);
243 m_lostActions.clear();
246 updateApplicationState(
state);
247 notifyAppStateDetailsChanged(m_stateDetails);
250 static void registerAppStateListener(AppStateDetailsListener listener) {
251 synchronized (m_appStateListenersLock) {
252 if (!m_appStateListeners.contains(listener))
253 m_appStateListeners.add(listener);
257 static void unregisterAppStateListener(AppStateDetailsListener listener) {
258 synchronized (m_appStateListenersLock) {
259 m_appStateListeners.remove(listener);
263 static void notifyNativePluginIntegrationReadyChanged(
boolean ready) {
264 synchronized (m_appStateListenersLock) {
265 for (
final AppStateDetailsListener listener : m_appStateListeners)
266 listener.onNativePluginIntegrationReadyChanged(ready);
270 static void notifyAppStateDetailsChanged(ApplicationStateDetails details) {
271 synchronized (m_appStateListenersLock) {
272 for (AppStateDetailsListener listener : m_appStateListeners)
273 listener.onAppStateDetailsChanged(details);
279 public static void runAction(Runnable action)
281 runAction(action,
true);
284 public static void runAction(Runnable action,
boolean queueWhenInactive)
286 synchronized (m_mainActivityMutex) {
287 final Looper mainLooper = Looper.getMainLooper();
288 final Handler handler =
new Handler(mainLooper);
290 if (queueWhenInactive) {
291 final boolean isStateVisible =
294 final boolean active = (isActivityValid() && isStateVisible) || isServiceValid();
295 if (!active || !handler.post(action))
296 m_lostActions.add(action);
298 handler.post(action);
304 private static void runPendingCppRunnablesOnAndroidThread()
306 synchronized (m_mainActivityMutex) {
307 if (isActivityValid()) {
309 m_activity.get().runOnUiThread(runPendingCppRunnablesRunnable);
311 runAction(runPendingCppRunnablesRunnable);
313 final Looper mainLooper = Looper.getMainLooper();
314 final Thread looperThread = mainLooper.getThread();
315 if (looperThread.equals(Thread.currentThread())) {
316 runPendingCppRunnablesRunnable.run();
318 final Handler handler =
new Handler(mainLooper);
319 handler.post(runPendingCppRunnablesRunnable);
326 private static void setViewVisibility(
final View view,
final boolean visible)
328 runAction(() ->
view.setVisibility(visible ?
View.VISIBLE :
View.GONE));
331 public static void startApplication(String
params, String mainLib)
333 synchronized (m_mainActivityMutex) {
334 m_qtThread.run(() -> {
335 final String qtParams = mainLib +
" " +
params;
336 if (!startQtAndroidPlugin(qtParams))
337 Log.e(QtTAG,
"An error occurred while starting the Qt Android plugin");
339 m_qtThread.post(QtNative::startQtApplication);
340 waitForServiceSetup();
341 m_stateDetails.isStarted =
true;
342 notifyAppStateDetailsChanged(m_stateDetails);
346 public static void quitApp()
349 quitQtAndroidPlugin();
350 if (isActivityValid())
351 m_activity.get().finish();
352 if (isServiceValid())
353 m_service.get().stopSelf();
354 m_stateDetails.isStarted =
false;
355 notifyAppStateDetailsChanged(m_stateDetails);
360 public static int checkSelfPermission(String permission)
362 synchronized (m_mainActivityMutex) {
363 Context
context = getContext();
364 PackageManager pm =
context.getPackageManager();
365 return pm.checkPermission(permission,
context.getPackageName());
370 private static byte[][] getSSLCertificates()
372 ArrayList<byte[]> certificateList =
new ArrayList<>();
375 TrustManagerFactory
factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
379 if (
manager instanceof X509TrustManager) {
380 X509TrustManager trustManager = (X509TrustManager)
manager;
382 for (X509Certificate certificate : trustManager.getAcceptedIssuers()) {
383 byte[]
buffer = certificate.getEncoded();
384 certificateList.add(
buffer);
388 }
catch (Exception e) {
389 Log.e(QtTAG,
"Failed to get certificates", e);
392 byte[][] certificateArray =
new byte[certificateList.size()][];
393 certificateArray = certificateList.toArray(certificateArray);
394 return certificateArray;
398 private static String[] listAssetContent(android.content.res.AssetManager asset, String
path) {
400 ArrayList<String>
res =
new ArrayList<>();
407 if (isDir !=
null && isDir.length > 0)
410 }
catch (Exception e) {
415 }
catch (Exception e) {
418 return res.toArray(
new String[0]);
422 public static native
boolean startQtAndroidPlugin(String
params);
423 public static native
void startQtApplication();
424 public static native
void waitForServiceSetup();
425 public static native
void quitQtCoreApplication();
426 public static native
void quitQtAndroidPlugin();
427 public static native
void terminateQt();
428 public static native
boolean updateNativeActivity();
432 public static native
void setSurface(
int id,
Object surface);
436 public static native
void updateWindow();
440 public static native
void updateApplicationState(
int state);
443 public static native
boolean onPrepareOptionsMenu(Menu
menu);
444 public static native
boolean onOptionsItemSelected(
int itemId,
boolean checked);
445 public static native
void onOptionsMenuClosed(Menu
menu);
447 public static native
void onCreateContextMenu(ContextMenu
menu);
448 public static native
void fillContextMenu(Menu
menu);
449 public static native
boolean onContextItemSelected(
int itemId,
boolean checked);
450 public static native
void onContextMenuClosed(Menu
menu);
454 public static native
void onActivityResult(
int requestCode,
int resultCode, Intent
data);
455 public static native
void onNewIntent(Intent
data);
457 public static native
void runPendingCppRunnables();
459 public static native
void sendRequestPermissionsResult(
int requestCode, String[] permissions,
int[] grantResults);
463 public static native IBinder onBind(Intent intent);
default void onNativePluginIntegrationReadyChanged(boolean ready)
default void onAppStateDetailsChanged(ApplicationStateDetails details)
Q_CORE_EXPORT QtJniTypes::Activity activity()
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei const GLchar *const * path
QUrl url("example.com")
[constructor-url-reference]
application x qt windows mime
[2]
QItemEditorFactory * factory
QNetworkAccessManager manager