Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
QtActivityBase.java
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4package org.qtproject.qt.android;
5
6import android.annotation.SuppressLint;
7import android.app.Activity;
8import android.app.AlertDialog;
9import android.app.Dialog;
10import android.content.Intent;
11import android.content.pm.ActivityInfo;
12import android.content.res.Configuration;
13import android.content.res.Resources;
14import android.net.Uri;
15import android.os.Build;
16import android.os.Bundle;
17import android.provider.Browser;
18import android.view.ContextMenu;
19import android.view.ContextMenu.ContextMenuInfo;
20import android.view.KeyEvent;
21import android.view.Menu;
22import android.view.MenuItem;
23import android.view.MotionEvent;
24import android.view.View;
25import android.view.Window;
26import java.lang.IllegalArgumentException;
27
28import android.widget.Toast;
29
30public class QtActivityBase extends Activity
31{
32 public static final String EXTRA_SOURCE_INFO = "org.qtproject.qt.android.sourceInfo";
33
34 private String m_applicationParams = "";
35 private boolean m_isCustomThemeSet = false;
36 private boolean m_retainNonConfigurationInstance = false;
37 private Configuration m_prevConfig;
38 private final QtActivityDelegate m_delegate;
39 private boolean m_onCreateSucceeded = false;
40
41 private void addReferrer(Intent intent)
42 {
43 Bundle extras = intent.getExtras();
44 if (extras != null && extras.getString(EXTRA_SOURCE_INFO) != null)
45 return;
46
47 if (extras == null) {
48 Uri referrer = getReferrer();
49 if (referrer != null) {
50 String cleanReferrer = referrer.toString().replaceFirst("android-app://", "");
51 intent.putExtra(EXTRA_SOURCE_INFO, cleanReferrer);
52 }
53 } else {
54 String applicationId = extras.getString(Browser.EXTRA_APPLICATION_ID);
55 if (applicationId != null)
56 intent.putExtra(EXTRA_SOURCE_INFO, applicationId);
57 }
58 }
59
67 @SuppressWarnings("unused")
69 {
70 if (params == null || params.isEmpty())
71 return;
72
73 if (!m_applicationParams.isEmpty())
74 m_applicationParams += " ";
75 m_applicationParams += params;
76 }
77
78 @Override
79 public void setTheme(int resId) {
80 super.setTheme(resId);
81 m_isCustomThemeSet = true;
82 }
83
84 private void restartApplication() {
85 Intent intent = Intent.makeRestartActivityTask(getComponentName());
86 startActivity(intent);
87 QtNative.setStarted(false);
88 // FIXME: calling exit() right after this gives no time to get onDestroy().
89 finish();
90 Runtime.getRuntime().exit(0);
91 }
92
94 {
95 m_delegate = new QtActivityDelegate(this);
96 }
97
98 @Override
99 protected void onCreate(Bundle savedInstanceState)
100 {
101 super.onCreate(savedInstanceState);
102 requestWindowFeature(Window.FEATURE_ACTION_BAR);
103
104 if (!m_isCustomThemeSet) {
105 setTheme(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q ?
106 android.R.style.Theme_DeviceDefault_DayNight :
107 android.R.style.Theme_Holo_Light);
108 }
109
110 if (QtNative.getStateDetails().isStarted) {
111 // We don't yet have a reliable way to keep the app
112 // running properly in case of an Activity only restart,
113 // so for now restart the whole app.
114 restartApplication();
115 }
116
117 QtNative.registerAppStateListener(m_delegate);
118 addReferrer(getIntent());
119
120 try {
121 QtActivityLoader loader = QtActivityLoader.getActivityLoader(this);
122 loader.appendApplicationParameters(m_applicationParams);
123
124 QtLoader.LoadingResult result = loader.loadQtLibraries();
125 if (result == QtLoader.LoadingResult.Succeeded) {
126 m_delegate.startNativeApplication(loader.getApplicationParameters(),
127 loader.getMainLibraryPath());
128 } else if (result == QtLoader.LoadingResult.Failed) {
129 showFatalFinishingToast();
130 return;
131 }
132 } catch (IllegalArgumentException e) {
133 e.printStackTrace();
134 showFatalFinishingToast();
135 return;
136 }
137
138 m_prevConfig = new Configuration(getResources().getConfiguration());
139 m_onCreateSucceeded = true;
140 }
141
142 private void showFatalFinishingToast() {
143 Resources resources = getResources();
144 String packageName = getPackageName();
145 @SuppressLint("DiscouragedApi") int id = resources.getIdentifier(
146 "fatal_error_msg", "string", packageName);
147 String message = resources.getString(id);
148 Toast.makeText(this, message, Toast.LENGTH_LONG).show();
149
150 finish();
151 }
152
153 @Override
154 protected void onPause()
155 {
156 super.onPause();
157 if (Build.VERSION.SDK_INT < 24 || !isInMultiWindowMode())
158 QtNative.setApplicationState(QtNative.ApplicationState.ApplicationInactive);
159 m_delegate.displayManager().unregisterDisplayListener();
160 }
161
162 @Override
163 protected void onResume()
164 {
165 super.onResume();
166 QtNative.setApplicationState(QtNative.ApplicationState.ApplicationActive);
167 if (QtNative.getStateDetails().isStarted) {
168 m_delegate.displayManager().registerDisplayListener();
169 QtWindow.updateWindows();
170 // Suspending the app clears the immersive mode, so we need to set it again.
171 m_delegate.displayManager().reinstateFullScreen();
172 }
173 }
174
175 @Override
176 protected void onStop()
177 {
178 super.onStop();
179 QtNative.setApplicationState(QtNative.ApplicationState.ApplicationSuspended);
180 }
181
182 @Override
183 protected void onDestroy()
184 {
185 super.onDestroy();
186
187 if (!m_onCreateSucceeded)
188 System.exit(-1);
189
190 if (!m_retainNonConfigurationInstance) {
191 QtNative.unregisterAppStateListener(m_delegate);
192 QtNative.terminateQtNativeApplication();
193 QtNative.setActivity(null);
194 System.exit(0);
195 }
196 }
197
198 @Override
199 public void onConfigurationChanged(Configuration newConfig)
200 {
201 super.onConfigurationChanged(newConfig);
202
203 int diff = newConfig.diff(m_prevConfig);
204 if ((diff & ActivityInfo.CONFIG_UI_MODE) != 0)
205 m_delegate.handleUiModeChange();
206
207 if ((diff & ActivityInfo.CONFIG_LOCALE) != 0)
208 QtNative.updateLocale();
209
210 m_prevConfig = new Configuration(newConfig);
211 }
212
213 @Override
214 public boolean onContextItemSelected(MenuItem item)
215 {
216 m_delegate.setContextMenuVisible(false);
217 return QtNative.onContextItemSelected(item.getItemId(), item.isChecked());
218 }
219
220 @Override
221 public void onContextMenuClosed(Menu menu)
222 {
223 if (!m_delegate.isContextMenuVisible())
224 return;
225 m_delegate.setContextMenuVisible(false);
226 QtNative.onContextMenuClosed(menu);
227 }
228
229 @Override
230 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
231 {
232 menu.clearHeader();
233 QtNative.onCreateContextMenu(menu);
234 m_delegate.setContextMenuVisible(true);
235 }
236
237 @Override
239 {
240 boolean handleResult = m_delegate.getInputDelegate().handleDispatchKeyEvent(event);
241 if (QtNative.getStateDetails().isStarted && handleResult)
242 return true;
243
244 return super.dispatchKeyEvent(event);
245 }
246
247 @Override
248 public boolean dispatchGenericMotionEvent(MotionEvent event)
249 {
250 boolean handled = m_delegate.getInputDelegate().handleDispatchGenericMotionEvent(event);
251 if (QtNative.getStateDetails().isStarted && handled)
252 return true;
253
254 return super.dispatchGenericMotionEvent(event);
255 }
256
257 @Override
258 public boolean onKeyDown(int keyCode, KeyEvent event)
259 {
260 QtNative.ApplicationStateDetails stateDetails = QtNative.getStateDetails();
261 if (!stateDetails.isStarted || !stateDetails.nativePluginIntegrationReady)
262 return false;
263
264 return m_delegate.getInputDelegate().onKeyDown(keyCode, event);
265 }
266
267 @Override
268 public boolean onKeyUp(int keyCode, KeyEvent event)
269 {
270 QtNative.ApplicationStateDetails stateDetails = QtNative.getStateDetails();
271 if (!stateDetails.isStarted || !stateDetails.nativePluginIntegrationReady)
272 return false;
273
274 return m_delegate.getInputDelegate().onKeyUp(keyCode, event);
275 }
276
277 @Override
278 public boolean onCreateOptionsMenu(Menu menu)
279 {
280 menu.clear();
281 return true;
282 }
283
284 @Override
285 public boolean onPrepareOptionsMenu(Menu menu)
286 {
287 boolean res = QtNative.onPrepareOptionsMenu(menu);
288 m_delegate.setActionBarVisibility(res && menu.size() > 0);
289 return res;
290 }
291
292 @Override
293 public boolean onOptionsItemSelected(MenuItem item)
294 {
295 return QtNative.onOptionsItemSelected(item.getItemId(), item.isChecked());
296 }
297
298 @Override
299 public void onOptionsMenuClosed(Menu menu)
300 {
301 QtNative.onOptionsMenuClosed(menu);
302 }
303
304 @Override
305 protected void onRestoreInstanceState(Bundle savedInstanceState)
306 {
307 super.onRestoreInstanceState(savedInstanceState);
308
309 // only restore when this Activity is being recreated for a config change
310 if (getLastNonConfigurationInstance() == null)
311 return;
312
313 QtNative.setStarted(savedInstanceState.getBoolean("Started"));
314 boolean isFullScreen = savedInstanceState.getBoolean("isFullScreen");
315 boolean expandedToCutout = savedInstanceState.getBoolean("expandedToCutout");
316 m_delegate.displayManager().setSystemUiVisibility(isFullScreen, expandedToCutout);
317 // FIXME restore all surfaces
318 }
319
320 @Override
322 {
323 super.onRetainNonConfigurationInstance();
324 m_retainNonConfigurationInstance = true;
325 return true;
326 }
327
328 @Override
329 protected void onSaveInstanceState(Bundle outState)
330 {
331 super.onSaveInstanceState(outState);
332 outState.putBoolean("isFullScreen", m_delegate.displayManager().isFullScreen());
333 outState.putBoolean("expandedToCutout", m_delegate.displayManager().expandedToCutout());
334 outState.putBoolean("Started", QtNative.getStateDetails().isStarted);
335 }
336
337 @Override
338 public void onWindowFocusChanged(boolean hasFocus)
339 {
340 super.onWindowFocusChanged(hasFocus);
341 if (hasFocus)
342 m_delegate.displayManager().reinstateFullScreen();
343 }
344
345 @Override
346 protected void onNewIntent(Intent intent)
347 {
348 addReferrer(intent);
349 QtNative.onNewIntent(intent);
350 }
351
352 @Override
353 protected void onActivityResult(int requestCode, int resultCode, Intent data)
354 {
355 super.onActivityResult(requestCode, resultCode, data);
356 QtNative.onActivityResult(requestCode, resultCode, data);
357 }
358
359 @Override
360 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
361 {
362 QtNative.sendRequestPermissionsResult(requestCode, grantResults);
363 }
364
366 public void hideSplashScreen(final int duration)
367 {
368 m_delegate.hideSplashScreen(duration);
369 }
370}
[Window class with invokable method]
Definition window.h:11
void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
boolean dispatchGenericMotionEvent(MotionEvent event)
boolean onKeyDown(int keyCode, KeyEvent event)
void onCreate(Bundle savedInstanceState)
void onActivityResult(int requestCode, int resultCode, Intent data)
void onConfigurationChanged(Configuration newConfig)
boolean onKeyUp(int keyCode, KeyEvent event)
void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
void onRestoreInstanceState(Bundle savedInstanceState)
static native void onNewIntent(Intent data)
#define this
Definition dialogs.cpp:8
QMap< Name, StatePointer > Bundle
Definition lalr.h:46
[vector_of_multirole_objects_0]
Definition main.cpp:188
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
[0]
GLuint GLsizei const GLchar * message
GLsizei const GLfloat * v
void ** params
struct _cl_event * event
GLuint res
GLuint64EXT * result
[6]
static QStringList getResources(const QString &resourceFile, QMakeVfs *vfs)
Definition main.cpp:99
static QString getString(IMFActivate *device, const IID &id)
view show()
[18] //! [19]
void handleResult(const QFuture< T > &future)
QGraphicsItem * item
QMenu menu
[5]
if(foo.startsWith("("+type+") 0x")) ... QString hello("hello")
[0]