1 /*
2     Copyright (c) 2012-2013, BogDan Vatra <bogdan@kde.org>
3     Contact: http://www.qt-project.org/legal
4 
5     Redistribution and use in source and binary forms, with or without
6     modification, are permitted provided that the following conditions
7     are met:
8 
9     1. Redistributions of source code must retain the above copyright
10     notice, this list of conditions and the following disclaimer.
11     2. Redistributions in binary form must reproduce the above copyright
12     notice, this list of conditions and the following disclaimer in the
13     documentation and/or other materials provided with the distribution.
14 
15     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26 package org.qtproject.qt5.android.bindings;
27 
28 import com.arieslabs.assetbridge.Assetbridge;
29 
30 import java.io.File;
31 import java.io.IOException;
32 import java.io.OutputStream;
33 import java.io.InputStream;
34 import java.io.FileOutputStream;
35 import java.io.FileInputStream;
36 import java.io.DataOutputStream;
37 import java.io.DataInputStream;
38 import java.lang.reflect.Field;
39 import java.lang.reflect.Method;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.lang.Math;
43 import java.util.concurrent.Semaphore;
44 import java.util.StringTokenizer;
45 
46 import com.google.android.gms.common.GoogleApiAvailability;
47 
48 import org.kde.necessitas.ministro.IMinistro;
49 import org.kde.necessitas.ministro.IMinistroCallback;
50 
51 import android.os.SystemClock;
52 import android.os.Environment;
53 import android.app.Activity;
54 import android.app.ProgressDialog;
55 import android.app.AlertDialog;
56 import android.app.Dialog;
57 import android.app.ActionBar;
58 import android.app.ActionBar.Tab;
59 import android.app.FragmentTransaction;
60 import android.content.ComponentName;
61 import android.content.Context;
62 import android.content.DialogInterface;
63 import android.content.Intent;
64 import android.content.ServiceConnection;
65 import android.content.pm.ActivityInfo;
66 import android.content.pm.ApplicationInfo;
67 import android.content.DialogInterface.OnCancelListener;
68 import android.media.AudioManager;
69 import android.media.MediaPlayer;
70 
71 import android.app.DownloadManager;
72 import android.app.DownloadManager.Query;
73 import android.app.DownloadManager.Request;
74 import android.content.BroadcastReceiver;
75 import android.database.Cursor;
76 import android.content.IntentFilter;
77 
78 import android.app.ActivityManager;
79 import android.app.ActivityManager.MemoryInfo;
80 import android.content.pm.PackageManager;
81 import android.content.pm.PackageManager.NameNotFoundException;
82 import android.content.pm.PackageInfo;
83 import android.content.res.Configuration;
84 import android.content.res.Resources.Theme;
85 import android.content.res.AssetManager;
86 import android.graphics.Bitmap;
87 import android.graphics.Canvas;
88 import android.graphics.drawable.Drawable;
89 import android.graphics.drawable.ColorDrawable;
90 import android.graphics.Point;
91 import android.net.Uri;
92 import android.os.Build;
93 import android.os.Bundle;
94 import android.os.IBinder;
95 import android.os.RemoteException;
96 import android.util.AttributeSet;
97 import android.util.Log;
98 import android.util.DisplayMetrics;
99 import android.widget.Toast;
100 import android.widget.ListView;
101 import android.widget.ArrayAdapter;
102 import android.widget.Button;
103 
104 import android.view.ContextMenu;
105 import android.view.ContextMenu.ContextMenuInfo;
106 import android.view.KeyEvent;
107 import android.view.Menu;
108 import android.view.MenuItem;
109 import android.view.MotionEvent;
110 import android.view.View;
111 import android.view.Window;
112 import android.view.WindowManager;
113 import android.view.WindowManager.LayoutParams;
114 import android.view.accessibility.AccessibilityEvent;
115 import android.view.Display;
116 import android.view.MenuInflater;
117 import android.view.InputDevice;
118 
119 import dalvik.system.DexClassLoader;
120 import android.app.AlertDialog;
121 import android.content.DialogInterface;
122 import android.provider.Settings;
123 
124 import android.os.Bundle;
125 import android.os.Handler;
126 import android.os.Looper;
127 import android.preference.Preference;
128 import android.preference.PreferenceFragment;
129 import org.opencpn.opencpn.R;
130 
131 //ANDROID-11
132 import android.app.Fragment;
133 import android.view.ActionMode;
134 import android.view.ActionMode.Callback;
135 //ANDROID-11
136 
137 import android.net.wifi.WifiManager;
138 import android.net.wifi.WifiManager.MulticastLock;
139 import java.util.concurrent.atomic.AtomicReference;
140 
141 import android.bluetooth.BluetoothAdapter;
142 
143 import org.opencpn.GPSServer;
144 import org.opencpn.OCPNNativeLib;
145 
146 import org.qtproject.qt5.android.QtNative;
147 import org.qtproject.qt5.android.QtActivityDelegate;
148 
149 import android.bluetooth.BluetoothDevice;
150 import org.opencpn.BTScanHelper;
151 import app.akexorcist.bluetotohspp.library.BluetoothSPP;
152 import app.akexorcist.bluetotohspp.library.BluetoothState;
153 import app.akexorcist.bluetotohspp.library.BluetoothSPP.OnDataReceivedListener;
154 
155 import org.opencpn.SpinnerNavItem;
156 import org.opencpn.TitleNavigationAdapter;
157 import org.opencpn.WebViewActivity;
158 
159 import ar.com.daidalos.afiledialog.*;
160 
161 import com.google.android.vending.licensing.LicenseChecker;
162 import com.google.android.vending.licensing.LicenseCheckerCallback;
163 import com.google.android.vending.licensing.Policy;
164 import com.google.android.vending.licensing.ServerManagedPolicy;
165 import com.google.android.vending.licensing.AESObfuscator;
166 import android.provider.Settings.Secure;
167 import android.accounts.AccountManager;
168 
169 public class QtActivity extends Activity implements ActionBar.OnNavigationListener
170 {
171     private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished
172     private final static int OCPN_SETTINGS_REQUEST_CODE = 0xf3ef; // request code used to know when OCPNsettings dialog activity is done
173     private final static int OCPN_GOOGLEMAPS_REQUEST_CODE = 0xf3ed; // request code used to know when GoogleMaps activity is done
174 
175     private static final int MINISTRO_API_LEVEL = 4; // Ministro api level (check IMinistro.aidl file)
176     private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin
177     private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0
178 
179     private final static int OCPN_FILECHOOSER_REQUEST_CODE = 0x5555;
180     private final static int OCPN_AFILECHOOSER_REQUEST_CODE = 0x5556;
181 
182     private final static int OCPN_ACTION_FOLLOW = 0x1000;
183     private final static int OCPN_ACTION_ROUTE = 0x1001;
184     private final static int OCPN_ACTION_RMD = 0x1002;
185     private final static int OCPN_ACTION_SETTINGS_BASIC = 0x1003;
186     private final static int OCPN_ACTION_SETTINGS_EXPERT = 0x1004;
187     private final static int OCPN_ACTION_TRACK_TOGGLE = 0x1005;
188     private final static int OCPN_ACTION_MOB = 0x1006;
189     private final static int OCPN_ACTION_TIDES_TOGGLE = 0x1007;
190     private final static int OCPN_ACTION_CURRENTS_TOGGLE = 0x1008;
191     private final static int OCPN_ACTION_ENCTEXT_TOGGLE = 0x1009;
192     private final static int OCPN_ACTION_TRACK_ON = 0x100a;
193     private final static int OCPN_ACTION_TRACK_OFF = 0x100b;
194 
195 
196     //  Definitions found in OCPN "chart1.h"
197     private final static int ID_CMD_APPLY_SETTINGS = 300;
198     private final static int ID_CMD_NULL_REFRESH = 301;
199     private final static int ID_CMD_TRIGGER_RESIZE  = 302;
200     private final static int ID_CMD_SETVP = 303;
201 
202     private final static int CHART_TYPE_CM93COMP = 7;       // must line up with OCPN types
203     private final static int CHART_FAMILY_RASTER = 1;
204     private final static int CHART_FAMILY_VECTOR = 2;
205 
206 
207     private static final String ERROR_CODE_KEY = "error.code";
208     private static final String ERROR_MESSAGE_KEY = "error.message";
209     private static final String DEX_PATH_KEY = "dex.path";
210     private static final String LIB_PATH_KEY = "lib.path";
211     private static final String LOADER_CLASS_NAME_KEY = "loader.class.name";
212     private static final String NATIVE_LIBRARIES_KEY = "native.libraries";
213     private static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
214     private static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
215     private static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
216     private static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id";
217     private static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id";
218     private static final String MAIN_LIBRARY_KEY = "main.library";
219     private static final String STATIC_INIT_CLASSES_KEY = "static.init.classes";
220     private static final String NECESSITAS_API_LEVEL_KEY = "necessitas.api.level";
221 
222     /// Ministro server parameter keys
223     private static final String REQUIRED_MODULES_KEY = "required.modules";
224     private static final String APPLICATION_TITLE_KEY = "application.title";
225     private static final String MINIMUM_MINISTRO_API_KEY = "minimum.ministro.api";
226     private static final String MINIMUM_QT_VERSION_KEY = "minimum.qt.version";
227     private static final String SOURCES_KEY = "sources";               // needs MINISTRO_API_LEVEL >=3 !!!
228                                                                        // Use this key to specify any 3rd party sources urls
229                                                                        // Ministro will download these repositories into their
230                                                                        // own folders, check http://community.kde.org/Necessitas/Ministro
231                                                                        // for more details.
232 
233     private static final String REPOSITORY_KEY = "repository";         // use this key to overwrite the default ministro repsitory
234     private static final String ANDROID_THEMES_KEY = "android.themes"; // themes that your application uses
235 
236 
237     public String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application,
238                                                                // the parameters must not contain any white spaces
239                                                                // and must be separated with "\t"
240                                                                // e.g "-param1\t-param2=value2\t-param3\tvalue3"
241 
242     public String ENVIRONMENT_VARIABLES = "QT_USE_ANDROID_NATIVE_STYLE=1\tQT_USE_ANDROID_NATIVE_DIALOGS=1\t";
243                                                                // use this variable to add any environment variables to your application.
244                                                                // the env vars must be separated with "\t"
245                                                                // e.g. "ENV_VAR1=1\tENV_VAR2=2\t"
246                                                                // Currently the following vars are used by the android plugin:
247                                                                // * QT_USE_ANDROID_NATIVE_STYLE - 1 to use the android widget style if available.
248                                                                // * QT_USE_ANDROID_NATIVE_DIALOGS -1 to use the android native dialogs.
249 
250     public String[] QT_ANDROID_THEMES = null;     // A list with all themes that your application want to use.
251                                                   // The name of the theme must be the same with any theme from
252                                                   // http://developer.android.com/reference/android/R.style.html
253                                                   // The most used themes are:
254                                                   //  * "Theme" - (fallback) check http://developer.android.com/reference/android/R.style.html#Theme
255                                                   //  * "Theme_Black" - check http://developer.android.com/reference/android/R.style.html#Theme_Black
256                                                   //  * "Theme_Light" - (default for API <=10) check http://developer.android.com/reference/android/R.style.html#Theme_Light
257                                                   //  * "Theme_Holo" - check http://developer.android.com/reference/android/R.style.html#Theme_Holo
258                                                   //  * "Theme_Holo_Light" - (default for API 11-13) check http://developer.android.com/reference/android/R.style.html#Theme_Holo_Light
259                                                   //  * "Theme_DeviceDefault" - check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault
260                                                   //  * "Theme_DeviceDefault_Light" - (default for API 14+) check http://developer.android.com/reference/android/R.style.html#Theme_DeviceDefault_Light
261 
262     public String QT_ANDROID_DEFAULT_THEME = null; // sets the default theme.
263 
264     private static Activity m_activity = null;
265 
266     private static final int INCOMPATIBLE_MINISTRO_VERSION = 1; // Incompatible Ministro version. Ministro needs to be upgraded.
267     private static final int BUFFER_SIZE = 1024;
268 
269     private ActivityInfo m_activityInfo = null; // activity info object, used to access the libs and the strings
270     private DexClassLoader m_classLoader = null; // loader object
271     private String[] m_sources = {"https://download.qt-project.org/ministro/android/qt5/qt-5.2"}; // Make sure you are using ONLY secure locations
272     private String m_repository = "default"; // Overwrites the default Ministro repository
273                                                         // Possible values:
274                                                         // * default - Ministro default repository set with "Ministro configuration tool".
275                                                         // By default the stable version is used. Only this or stable repositories should
276                                                         // be used in production.
277                                                         // * stable - stable repository, only this and default repositories should be used
278                                                         // in production.
279                                                         // * testing - testing repository, DO NOT use this repository in production,
280                                                         // this repository is used to push a new release, and should be used to test your application.
281                                                         // * unstable - unstable repository, DO NOT use this repository in production,
282                                                         // this repository is used to push Qt snapshots.
283     private String[] m_qtLibs = null; // required qt libs
284 
285     private DownloadManager m_dm;
286     private long m_enqueue;
287 
288     private static ActivityManager activityManager;
289 
290     private Float lastX;
291     private Float lastY;
292 
293     private Boolean m_GPSServiceStarted = false;
294     private GPSServer m_GPSServer;
295     public ProgressDialog ringProgressDialog;
296     public boolean m_hasGPS;
297     private boolean m_backButtonEnable = true;
298 
299     private BTScanHelper scanHelper;
300     private Boolean m_ScanHelperStarted = false;
301     private BluetoothSPP m_BTSPP;
302     private Boolean m_BTServiceCreated = false;
303     private String m_BTStat;
304     private Boolean m_FileChooserDone = false;
305     private String m_filechooserString;
306 
307     private String m_downloadRet = "";
308 
309     OCPNNativeLib nativeLib;
310 
311     // action bar
312     private ActionBar actionBar;
313 
314         // Title navigation Spinner data
315     private ArrayList<SpinnerNavItem> navSpinner;
316     private SpinnerNavItem spinnerItemRaster;
317     private SpinnerNavItem spinnerItemVector;
318     private SpinnerNavItem spinnerItemcm93;
319 
320         // Navigation adapter
321     private TitleNavigationAdapter adapter;
322 
323         // Menu item used to indicate "RouteCreate" is active
324     MenuItem itemRouteAnnunciator;
325     MenuItem itemRouteMenuItem;
326     private boolean m_showRouteAnnunciator = false;
327 
328     MenuItem itemFollowInActive;
329     MenuItem itemFollowActive;
330     private boolean m_isFollowActive = false;
331 
332     MenuItem itemTrackInActive;
333     MenuItem itemTrackActive;
334     private boolean m_isTrackActive = false;
335 
336     private static AudioManager audioManager;
337     private MediaPlayer mediaPlayer; // The media player to play the sounds, even in background
338 
339     BroadcastReceiver downloadBCReceiver = null;
340 
341     private double m_gminitialLat;
342     private double m_gminitialLon;
343     private double m_gminitialZoom;
344 
345     private boolean m_fullScreen;
346 
347     private LicenseCheckerCallback mLicenseCheckerCallback;
348     private LicenseChecker mChecker = null;
349     private Handler mLicenseHandler;
350     private boolean m_licenseOK = true;
351     private static final byte[] SALT = new byte[] {
352      -46, 65, 30, -128, -103, -57, 74, -64, 51, 88, -95,
353      -45, 77, -117, -36, -113, -11, 32, -64, 89
354      };
355 
356     private static final String BASE64_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoMqiYIxHmwC+qVcD0KE1xnOA/RJDgOHvnsrSKAvIMJl3P7twBcybJ+/xzjtEXSvNXU0KME9P4r/q1j/A1ST6HFGvzZx90MipX9449LkZmUUlT0MwCX9BqB7Beq5VWOb6hzpoKRFnZHJVoHaJdAfNlg0AYpGosaOM7WiKZX0uHy2y5m5QsF3S+KYoJYzucKqRp39mCBl/zg7osZwSm5HoY9FbRw2D2/MAFwl8YycMYisEqLFlacGNkHYxvdh0x9uY4amo6nn5UndICXdBGBYTghA41hSUrQrDqnAgLy6Uw+/d54j+jezlJcuiUpcfkJECzxYAT6NS3OBEI+2FaVP6XwIDAQAB";
357 
QtActivity()358     public QtActivity()
359     {
360         if (Build.VERSION.SDK_INT <= 10) {
361             QT_ANDROID_THEMES = new String[] {"Theme_Light"};
362             QT_ANDROID_DEFAULT_THEME = "Theme_Light";
363         }
364         else if (Build.VERSION.SDK_INT >= 11 && Build.VERSION.SDK_INT <= 13) {
365             QT_ANDROID_THEMES = new String[] {"Theme_Holo_Light"};
366             QT_ANDROID_DEFAULT_THEME = "Theme_Holo_Light";
367         } else {
368             QT_ANDROID_THEMES = new String[] {"Theme_DeviceDefault_Light"};
369             QT_ANDROID_DEFAULT_THEME = "Theme_DeviceDefault_Light";
370         }
371         m_activity = QtActivity.this;
372 
373 
374     }
375 
376 //    public static QtActivity activity()
377 //    {
378 //        return QtActivity.this;
379 //    }
380 
381 
382 //    public static  String appData()
383 //    {
384 //        Log.d("App Data is ", "Working");
385 //        return data;
386 //    }
387 
388 // This really never gets called, and so dont need m_activity
activity()389     public static Activity activity()
390     {
391 //        synchronized (m_mainActivityMutex)
392         //Log.i("DEBUGGER_TAG", "activity()");
393 
394         {
395             return m_activity;
396         }
397     }
398 
399     private String m_settingsReturn;
400 
launchHelpView()401     public String launchHelpView(){
402         Intent intent = new Intent(this, WebViewActivity.class);
403         startActivity(intent);
404         return "OK";
405     }
406 
toggleFullscreen()407     private void toggleFullscreen(){
408         m_fullScreen = !m_fullScreen;
409         setFullscreen(m_fullScreen);
410         nativeLib.notifyFullscreenChange(m_fullScreen);
411     }
412 
setFullscreen( final boolean bfull)413     public void setFullscreen( final boolean bfull){
414 
415         final QtActivityDelegate delegate = QtNative.activityDelegate();
416 
417         if(null != delegate){
418             runOnUiThread(new Runnable() {
419                 @Override
420                 public void run() {
421                     delegate.setFullScreen( bfull );
422 
423                 }});
424         }
425     }
426 
setFullscreen( final int bfull)427     public String setFullscreen( final int bfull){
428  //       String aa = String.format("%d", bfull);
429 //        Log.i("DEBUGGER_TAG", "setFullscreen " + aa);
430         setFullscreen(bfull != 0);
431         m_fullScreen = (bfull != 0);
432         return "OK";
433     }
434 
435 
getFullscreen( )436     public String getFullscreen( ){
437         if(m_fullScreen)
438             return "YES";
439         else
440             return "NO";
441     }
442 
443 
444 
invokeGoogleMaps()445     public String invokeGoogleMaps(){
446         Log.i("DEBUGGER_TAG", "invokeGoogleMaps");
447 
448 
449         Intent intent = new Intent(QtActivity.this, org.opencpn.OCPNMapsActivity.class);
450 
451         String s = nativeLib.getVPCorners();
452 
453         String v = nativeLib.getVPS();
454         Log.i("DEBUGGER_TAG", "initialPositionString" + v);
455 
456         StringTokenizer tkz = new StringTokenizer(v, ";");
457 
458         String initialLat = "";
459         String initialLon = "";
460         String initialZoom = "";
461 
462         if(tkz.hasMoreTokens()){
463             initialLat = tkz.nextToken();
464             initialLon = tkz.nextToken();
465             initialZoom = tkz.nextToken();
466         }
467 
468         m_gminitialZoom = Double.parseDouble(initialZoom);
469 
470 
471         intent.putExtra("VP_CORNERS", s);
472         intent.putExtra("VPS", v);
473 
474         int height = this.getWindow().getDecorView().getHeight();
475         int width = this.getWindow().getDecorView().getWidth();
476         intent.putExtra("WIDTH", width);
477         intent.putExtra("HEIGHT", height);
478 
479         startActivityForResult(intent, OCPN_GOOGLEMAPS_REQUEST_CODE);
480 
481         int pss = 55;
482         String ret;
483         ret = String.format("%d", pss);
484         return ret;
485     }
486 
doAndroidSettings(String settings)487     public String doAndroidSettings(String settings){
488         //Log.i("DEBUGGER_TAG", "doAndroidSettings");
489         //Log.i("DEBUGGER_TAG", settings);
490 
491         m_settingsReturn = new String();
492 
493         Intent intent = new Intent(QtActivity.this, org.opencpn.OCPNSettingsActivity.class);
494         intent.putExtra("SETTINGS_STRING",settings);
495         startActivityForResult(intent, OCPN_SETTINGS_REQUEST_CODE);
496 
497         //Log.i("DEBUGGER_TAG", "after start activity");
498 
499         int pss = 55;
500         String ret;
501         ret = String.format("%d", pss);
502         return ret;
503     }
504 
505 
checkAndroidSettings( )506     public String checkAndroidSettings(  ){
507 //        Log.i("DEBUGGER_TAG", "checkAndroidSettings");
508 //        Log.i("DEBUGGER_TAG", m_settingsReturn);
509 
510         return m_settingsReturn;
511     }
512 
513 
514 
515 
callFromCpp(int pid)516     public String callFromCpp(int pid){
517         //Log.i("DEBUGGER_TAG", "callFromCpp");
518 
519 //        Intent intent = new Intent(QtActivity.this, org.opencpn.OCPNSettingsActivity.class);
520 //        startActivity(intent);
521 
522 
523         MemoryInfo mi = new MemoryInfo();
524 //        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
525 //        activityManager.getMemoryInfo(mi);
526         int pids[] = new int[1];
527         pids[0] = pid;
528 
529         //MemoryInfo[] memoryInfoArray;
530         //memoryInfoArray = activityManager.getProcessMemoryInfo( pids );
531 
532         android.os.Debug.MemoryInfo[] memoryInfoArray= activityManager.getProcessMemoryInfo( pids );
533         int pss = memoryInfoArray[0].getTotalPss();
534 
535         String ret;
536         ret = String.format("%d", pss);
537         return ret;
538 
539 
540     }
541 
getMemInfo(int pid)542     public String getMemInfo(int pid){
543 //        Log.i("DEBUGGER_TAG", "getMemInfo");
544         int pids[] = new int[1];
545         pids[0] = pid;
546 
547         ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
548         android.os.Debug.MemoryInfo[] memoryInfoArray= activityManager.getProcessMemoryInfo( pids );
549         int pss = memoryInfoArray[0].getTotalPss();
550 
551         String ret;
552         ret = String.format("%d", pss);
553         return ret;
554     }
555 
556 
getJniString()557     public native String getJniString();
test()558     public native int test();
559 
getDisplayMetrics()560     public String getDisplayMetrics(){
561         //Log.i("DEBUGGER_TAG", "getDisplayDPI");
562 /*
563         int i = nativeLib.test();
564         String aa;
565         aa = String.format("%d", i);
566         Log.i("DEBUGGER_TAG", aa);
567 
568         String bb = "$GPRMC...";
569         int j = nativeLib.processNMEA(bb);
570 //      int j = nativeLib.processNMEA( 44);
571         aa = String.format("%d", j);
572         Log.i("DEBUGGER_TAG", aa);
573 */
574         DisplayMetrics dm = new DisplayMetrics();
575         getWindowManager().getDefaultDisplay().getMetrics(dm);
576         int statusBarHeight = 0;
577 
578         int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
579         if (resourceId > 0) {
580             statusBarHeight = getResources().getDimensionPixelSize(resourceId);
581         }
582 
583 //        TypedValue typedValue = new TypedValue();
584 //        if(getTheme().resolveAttribute(android.R.attr.actionBarSize, typedValue, true)){
585 //            screen_h -= getResources().getDimensionPixelSize(typedValue.resourceId);
586 //        }
587 
588         int actionBarHeight = 0;
589         ActionBar actionBar = getActionBar();
590         if(actionBar.isShowing())
591             actionBarHeight = actionBar.getHeight();
592 
593 //            float getTextSize() //pixels
594         int width = 600;
595         int height = 400;
596 
597         Display display = getWindowManager().getDefaultDisplay();
598 
599 
600         if (Build.VERSION.SDK_INT >= 13) {
601 
602             if(Build.VERSION.SDK_INT >= 17){
603                 //Log.i("DEBUGGER_TAG", "VERSION.SDK_INT >= 17");
604                 width = dm.widthPixels;
605                 height = dm.heightPixels;
606             }
607             else{
608 
609                 switch (Build.VERSION.SDK_INT){
610 
611                     case 16:
612                         //Log.i("DEBUGGER_TAG", "VERSION.SDK_INT == 16");
613                         width = dm.widthPixels;
614                         height = dm.heightPixels;
615                         break;
616 
617                     case 15:
618                     case 14:
619                         Point outPoint = new Point();
620                         display.getRealSize(outPoint);
621                         if (outPoint != null){
622                             width = outPoint.x;
623                             height = outPoint.y;
624                         }
625                     break;
626 
627                     default:
628                         width = dm.widthPixels;
629                         height = dm.heightPixels;
630                         break;
631 
632                 }
633             }
634         }
635         else{
636             //Log.i("DEBUGGER_TAG", "VERSION.SDK_INT < 13");
637             width = display.getWidth();
638             height = display.getHeight();
639         }
640 
641 
642 
643 //  In FullScreen immersive mode, height needs a fixup...
644         if(m_fullScreen){
645             Point outPoint = new Point();
646             display.getRealSize(outPoint);
647             if (outPoint != null){
648                 width = outPoint.x;
649                 height = outPoint.y;
650             }
651             height += statusBarHeight;
652         }
653 
654 
655         float tsize = new Button(this).getTextSize();       // in pixels
656 
657         String ret;
658 
659         ret = String.format("%f;%f;%d;%d;%d;%d;%d;%d;%d;%d;%f", dm.xdpi, dm.density, dm.densityDpi,
660                width, height - statusBarHeight,
661                width, height,
662                dm.widthPixels, dm.heightPixels, actionBarHeight, tsize);
663 
664         //Log.i("DEBUGGER_TAG", ret);
665 
666 
667 
668         return ret;
669     }
670 
getDeviceInfo()671     public String getDeviceInfo(){
672         String s="Device Info:";
673                 s += "\n OS Version: " + System.getProperty("os.version") + "(" + android.os.Build.VERSION.INCREMENTAL + ")";
674                 s += "\n OS API Level: "+android.os.Build.VERSION.RELEASE + "("+android.os.Build.VERSION.SDK_INT+")";
675                 s += "\n Device: " + android.os.Build.DEVICE;
676                 s += "\n Model (and Product): " + android.os.Build.MODEL + " ("+ android.os.Build.PRODUCT + ")";
677 
678         //Log.i("DEBUGGER_TAG", s);
679 
680         return s;
681     }
682 
683 
showBusyCircle()684     public String showBusyCircle(){
685     //if(!m_fullScreen)
686     {
687         runOnUiThread(new Runnable() {
688             @Override
689             public void run() {
690 
691 //                 QtActivity.this.ringProgressDialog.show(QtActivity.this, "", "", true);
692 
693                  ringProgressDialog = new ProgressDialog(QtActivity.this,R.style.MyTheme);
694                  ringProgressDialog.setCancelable(false);
695                  ringProgressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
696 
697                  Drawable myIcon = getResources().getDrawable( R.drawable.progressbar_custom );
698                  ringProgressDialog.setIndeterminateDrawable(myIcon);
699 
700                  //  THIS IS IMPORTANT...Keeps the busy spinner from surfacing the hidden navigation buttons.
701                  ringProgressDialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
702                             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
703                  QtActivity.this.ringProgressDialog.show();
704          }});
705      }
706 
707         String ret = "";
708         return ret;
709     }
710 
hideBusyCircle()711     public String hideBusyCircle(){
712 
713         mutex = new Semaphore(0);
714 
715         runOnUiThread(new Runnable() {
716             @Override
717             public void run() {
718 
719                  ringProgressDialog.dismiss();
720 
721                  mutex.release();
722              }});
723 
724 /*
725              // One way to wait for the runnable to be done...
726       try {
727              mutex.acquire();            // Cannot get mutex until runnable above exits.
728       } catch (InterruptedException e) {
729              e.printStackTrace();
730       }
731 
732         this.getWindow().getDecorView().requestFocus();
733 */
734         String ret = "";
735         return ret;
736     }
737 
738 
739 
740 
741 
742 
setRouteAnnunciator( final int viz)743     public String setRouteAnnunciator( final int viz){
744      //Log.i("DEBUGGER_TAG", "setRouteAnnunciator");
745 
746      m_showRouteAnnunciator = (viz != 0);
747 
748 //    if( null != itemRouteAnnunciator)
749     {
750 
751         runOnUiThread(new Runnable() {
752                 @Override
753                 public void run() {
754 
755 //                    itemRouteAnnunciator.setVisible(viz != 0);
756                     QtActivity.this.invalidateOptionsMenu();
757 
758                  }});
759 
760 //        itemRouteAnnunciator.setVisible(viz != 0);
761 //        this.invalidateOptionsMenu();
762         return "OK";
763      }
764 //     else
765 //        return "NO";
766     }
767 
768     private boolean m_showAction = false;
769 
setFollowIconState( final int isActive)770     public String setFollowIconState( final int isActive){
771         m_isFollowActive = (isActive != 0);
772 
773         //if(isActive == 0)
774             //Log.i("DEBUGGER_TAG", "setFollowIconStateA");
775         //else
776             //Log.i("DEBUGGER_TAG", "setFollowIconStateB");
777 
778            runOnUiThread(new Runnable() {
779                    @Override
780                    public void run() {
781 
782 
783                        QtActivity.this.invalidateOptionsMenu();
784 
785                     }});
786 
787            // testing playSound("/data/data/org.opencpn.opencpn/files/sounds/2bells.wav");
788 
789            m_showAction = (isActive != 0);
790 
791            return "OK";
792        }
793 
setTrackIconState( final int isActive)794        public String setTrackIconState( final int isActive){
795            m_isTrackActive = (isActive != 0);
796 
797            //if(isActive == 0)
798                //Log.i("DEBUGGER_TAG", "setTrackIconStateA");
799            //else
800                //Log.i("DEBUGGER_TAG", "setTrackIconStateB");
801 
802               runOnUiThread(new Runnable() {
803                       @Override
804                       public void run() {
805 
806 
807                           QtActivity.this.invalidateOptionsMenu();
808 
809                        }});
810 
811               return "OK";
812           }
813 
814 
815 
setBackButtonState( final int isActive)816        public String setBackButtonState( final int isActive){
817            //Log.i("DEBUGGER_TAG", "setBackButtonState");
818            m_backButtonEnable = (isActive != 0);
819            return "OK";
820           }
821 
822 
queryGPSServer( final int parm )823     public String queryGPSServer( final int parm ){
824 
825         if( GPSServer.GPS_PROVIDER_AVAILABLE == parm){
826             String ret_string = "NO";
827             if( m_hasGPS )
828                 ret_string = "YES";
829             return ret_string;
830         }
831 
832 
833 
834         if(!m_GPSServiceStarted){
835             //Log.i("DEBUGGER_TAG", "Start GPS Server");
836             m_GPSServer = new GPSServer(getApplicationContext(), nativeLib, this);
837             m_GPSServiceStarted = true;
838         }
839 
840         return m_GPSServer.doService( parm );
841     }
842 
hasBluetooth( final int parm )843     public String hasBluetooth( final int parm ){
844         String ret = "Yes";
845         BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
846         if (mBluetoothAdapter == null) {
847             ret = "No";
848         }
849 
850 //        PackageManager pm = context.getPackageManager();
851 //        boolean hasBluetooth = pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
852         return ret;
853     }
854 
startBlueToothScan( final int parm )855     public String startBlueToothScan( final int parm ){
856         Log.i("DEBUGGER_TAG", "startBlueToothScan");
857 
858         runOnUiThread(new Runnable() {
859             @Override
860             public void run() {
861 
862                 if(!m_ScanHelperStarted){
863                     scanHelper = new BTScanHelper(QtActivity.this);
864                     m_ScanHelperStarted = true;
865                 }
866 
867                 scanHelper.doDiscovery();
868 
869              }});
870 
871 
872         return( "OK" );
873 
874     }
875 
stopBlueToothScan( final int parm )876     public String stopBlueToothScan( final int parm ){
877 //        Log.i("DEBUGGER_TAG", "stopBlueToothScan");
878 
879         runOnUiThread(new Runnable() {
880             @Override
881             public void run() {
882 
883                 if(m_ScanHelperStarted){
884                     scanHelper.doDiscovery();
885                     scanHelper.stopDiscovery();
886                 }
887 
888 
889              }});
890 
891 
892         return( "OK" );
893 
894     }
895 
getBlueToothScanResults( final int parm )896     public String getBlueToothScanResults( final int parm ){
897         String ret_str = "";
898 
899         runOnUiThread(new Runnable() {
900             @Override
901             public void run() {
902 
903                 if(!m_ScanHelperStarted){
904                     scanHelper = new BTScanHelper(QtActivity.this);
905                     m_ScanHelperStarted = true;
906                 }
907 
908 
909              }});
910 
911         if(m_ScanHelperStarted)
912             ret_str = scanHelper.getDiscoveredDevices();;
913 
914 //        Log.i("DEBUGGER_TAG", "results");
915 //        Log.i("DEBUGGER_TAG", ret_str);
916 
917         return ret_str;
918 
919    //     return ("line A;line B;"); //scanHelper.getDiscoveredDevices();
920 
921 
922     }
923 
924 
startBTService( final String address)925     public String startBTService( final String address){
926         Log.i("DEBUGGER_TAG", "startBTService");
927         Log.i("DEBUGGER_TAG", address);
928         m_BTStat = "Unknown";
929 
930         runOnUiThread(new Runnable() {
931             @Override
932             public void run() {
933 
934 ///
935                 if(!m_BTServiceCreated){
936 //                    Log.i("DEBUGGER_TAG", "Bluetooth createBTService");
937                     m_BTSPP = new BluetoothSPP(getApplicationContext());
938 
939                     if(!m_BTSPP.isBluetoothAvailable() || !m_BTSPP.isBluetoothEnabled()) {
940  //                           Toast.makeText(getApplicationContext()
941  //                                           , "Bluetooth is not available"
942  //                                           , Toast.LENGTH_SHORT).show();
943                     }
944 
945                     else {
946                         m_BTSPP.setupService();
947                         m_BTServiceCreated = true;
948                     }
949                 }
950 
951 
952                 m_BTSPP.setOnDataReceivedListener(new OnDataReceivedListener() {
953                     public void onDataReceived(byte[] data, String message) {
954 //                        Log.i("DEBUGGER_TAG", message);
955                         // Do something when data incoming
956                         nativeLib.processBTNMEA( message );
957 
958                     }
959                 });
960 
961                 if(m_BTSPP.isServiceAvailable()){
962 //                    Log.i("DEBUGGER_TAG", "Bluetooth startService");
963                     m_BTSPP.startService(BluetoothState.DEVICE_OTHER);
964 
965 //                    Log.i("DEBUGGER_TAG", "Bluetooth connectA");
966 //                    m_BTSPP.connect(address);
967                     m_BTSPP.resetAutoConnect();
968                     m_BTSPP.autoConnectAddress(address);
969 
970                 }
971 
972                 if(!m_BTSPP.isBluetoothEnabled())
973                     m_BTStat = "NOK.BTNotEnabled";
974                 else if(!m_BTSPP.isServiceAvailable())
975                     m_BTStat = "NOK.ServiceNotAvailable";
976                 else
977                     m_BTStat = "OK";
978 
979 
980 
981              }});
982 
983 
984         Log.i("DEBUGGER_TAG", "startBTService return: " + m_BTStat);
985         return m_BTStat;
986     }
987 
988 
stopBTService( final int parm)989     public String stopBTService( final int parm){
990         Log.i("DEBUGGER_TAG", "stopBTService");
991         String ret_str = "";
992 
993         runOnUiThread(new Runnable() {
994             @Override
995             public void run() {
996 
997                 if(m_BTServiceCreated){
998                     Log.i("DEBUGGER_TAG", "Bluetooth stopService");
999                     m_BTSPP.stopService();
1000                 }
1001 
1002 
1003              }});
1004 
1005         ret_str = "OK";
1006         return ret_str;
1007     }
1008 
1009     private Semaphore mutex = new Semaphore(0);
1010     private Query m_query = new Query();
1011 
downloadFile( final String url, final String destination )1012     public String downloadFile( final String url, final String destination )
1013     {
1014         m_downloadRet = "";
1015 
1016 
1017         if( downloadBCReceiver == null){
1018           downloadBCReceiver = new BroadcastReceiver() {
1019             @Override
1020             public void onReceive(Context context, Intent intent) {
1021                 String action = intent.getAction();
1022                 Log.i("DEBUGGER_TAG", "onReceive: " + action);
1023 
1024                 if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
1025                     long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
1026 
1027                     m_query = new Query();
1028                     m_query.setFilterById(m_enqueue);
1029                     Cursor c = m_dm.query(m_query);
1030 
1031 
1032                     if (c.moveToFirst()) {
1033                         String uriString = c.getString(c.getColumnIndex(DownloadManager.COLUMN_URI));
1034 
1035                         int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
1036                         if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
1037                             Log.i("DEBUGGER_TAG", "Download successful");
1038                         }
1039 
1040                         nativeLib.setDownloadStatus( c.getInt(columnIndex), uriString);
1041 
1042 
1043                     }
1044                     c.close();
1045                 }
1046             }
1047           };
1048         }
1049 
1050         registerReceiver(downloadBCReceiver, new IntentFilter(
1051                 DownloadManager.ACTION_DOWNLOAD_COMPLETE));
1052 
1053 
1054         mutex = new Semaphore(0);
1055 
1056         runOnUiThread(new Runnable() {
1057             @Override
1058             public void run() {
1059                 m_dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
1060 
1061                 Request request = new Request( Uri.parse(url) );
1062                 request.setDestinationUri( Uri.parse(destination) );
1063 
1064                 Log.i("DEBUGGER_TAG", "enqueue");
1065                 m_downloadRet = "PENDING";
1066                 try{
1067                      m_enqueue = m_dm.enqueue(request);
1068                      String result = "OK;" + String.valueOf(m_enqueue);
1069                      Log.i("DEBUGGER_TAG", result);
1070                      m_downloadRet = result;
1071                  }
1072                  catch(Exception e){
1073                      m_downloadRet = "NOK";
1074                      Log.i("DEBUGGER_TAG", "exception");
1075                  }
1076 
1077 
1078                  mutex.release();
1079 
1080 
1081              }});
1082 
1083         // One way to wait for the runnable to be done...
1084         try {
1085             mutex.acquire();            // Cannot get mutex until runnable above exits.
1086         } catch (InterruptedException e) {
1087             e.printStackTrace();
1088         }
1089 
1090 
1091         Log.i("DEBUGGER_TAG", "m_downloadRet " + m_downloadRet);
1092         return m_downloadRet;
1093     }
1094 
getDownloadStatus( final int ID )1095     public String getDownloadStatus( final int ID )
1096     {
1097         Log.i("DEBUGGER_TAG", "getDownloadStatus "  + String.valueOf(ID));
1098 
1099         String ret = "NOSTAT";
1100         if(m_dm != null){
1101             //Log.i("DEBUGGER_TAG", "mdm");
1102 
1103             m_query.setFilterById(ID);
1104             Cursor c = m_dm.query(m_query);
1105 
1106             if (c.moveToFirst()) {
1107                 //Log.i("DEBUGGER_TAG", "cmtf");
1108                 int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
1109                 int stat = c.getInt(columnIndex);
1110                 String sstat = String.valueOf(stat);
1111 
1112                 String sofarBytes = c.getString(c.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR ));
1113                 String totalBytes = c.getString(c.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
1114 
1115                 ret =  sstat + ";" + sofarBytes + ";" + totalBytes;
1116 
1117             }
1118             c.close();
1119 
1120         }
1121 
1122         Log.i("DEBUGGER_TAG", ret);
1123         return ret;
1124     }
1125 
1126 
cancelDownload( final int ID )1127     public String cancelDownload( final int ID )
1128     {
1129         Log.i("DEBUGGER_TAG", "cancelDownload "  + String.valueOf(ID));
1130         if(m_dm != null){
1131             m_dm.remove( ID );
1132         }
1133 
1134         return "OK";
1135     }
1136 
1137 
getGMAPILicense( )1138     public String getGMAPILicense( )
1139     {
1140         String ret = "";
1141 
1142         GoogleApiAvailability av = GoogleApiAvailability.getInstance();
1143         if(av != null)
1144             ret = av.getOpenSourceSoftwareLicenseInfo (this);
1145 
1146         return ret;
1147     }
1148 
1149 
1150 
1151     /**
1152      * it will play the given file, when it finishes, or fails, it will play the next from the list
1153      *
1154      * @param fileName: the file name to start playing from it
1155      */
playSound(final String fileName)1156     public String playSound(final String fileName) {
1157         Log.i("DEBUGGER_TAG", "playSound " + fileName);
1158         if (mediaPlayer == null) {
1159             mediaPlayer = new MediaPlayer();
1160             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
1161 
1162         }
1163 
1164 
1165         if (mediaPlayer != null) {
1166             //if (!mediaPlayer.isPlaying())
1167 
1168             runOnUiThread(new Runnable() {
1169                 @Override
1170                 public void run() {
1171                     try {
1172                         mediaPlayer.reset();
1173                         mediaPlayer.setDataSource(fileName);
1174                         mediaPlayer.prepare();
1175                         mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
1176                             @Override
1177                             public void onCompletion(MediaPlayer mp) {
1178                                 //playNextSoundTrack();
1179                             }
1180                         });
1181                         //Log.i("DEBUGGER_TAG", "playSoundStart");
1182                         mediaPlayer.start();
1183                     } catch (Exception e) {
1184                         // TODO: Remove this error checking before publishing
1185                     }
1186 
1187 
1188                  }});
1189 
1190         }
1191 
1192         return "OK";
1193     }
1194 
FileChooserDialog(final String initialDir, final String Title, final String Suggestion, final String wildcard)1195     public String FileChooserDialog(final String initialDir, final String Title, final String Suggestion, final String wildcard)
1196     {
1197         //Log.i("DEBUGGER_TAG", "FileChooserDialog");
1198         //Log.i("DEBUGGER_TAG", initialDir);
1199 
1200         m_FileChooserDone = false;
1201 
1202         boolean buseDialog = true;
1203         if(!buseDialog){
1204             Intent intent = new Intent(this, FileChooserActivity.class);
1205             intent.putExtra(FileChooserActivity.INPUT_START_FOLDER, initialDir);
1206             intent.putExtra(FileChooserActivity.INPUT_FOLDER_MODE, false);
1207             intent.putExtra(FileChooserActivity.INPUT_SHOW_FULL_PATH_IN_TITLE, true);
1208             intent.putExtra(FileChooserActivity.INPUT_TITLE_STRING, Title);
1209 
1210 
1211         //  Creating a file?
1212             if(!Suggestion.isEmpty()){
1213                 //Log.i("DEBUGGER_TAG", "FileChooserDialog Creating");
1214                 intent.putExtra(FileChooserActivity.INPUT_CAN_CREATE_FILES, true);
1215             }
1216 
1217             this.startActivityForResult(intent, OCPN_AFILECHOOSER_REQUEST_CODE);
1218         }
1219 
1220         //Log.i("DEBUGGER_TAG", "FileChooserDialog create and show " + initialDir);
1221 
1222         Thread thread = new Thread() {
1223             @Override
1224             public void run() {
1225 
1226         // Block this thread for 20 msec.
1227                 try {
1228                     Thread.sleep(20);
1229                 } catch (InterruptedException e) {
1230                 }
1231 
1232 // After sleep finishes blocking, create a Runnable to run on the UI Thread.
1233                 runOnUiThread(new Runnable() {
1234                     @Override
1235                     public void run() {
1236                         FileChooserDialog dialog = new FileChooserDialog(m_activity, initialDir);
1237 
1238                         dialog.setShowFullPath( true );
1239                         dialog.setTitle( Title );
1240 
1241                         dialog.addListener(new FileChooserDialog.OnFileSelectedListener() {
1242                             public void onFileSelected(Dialog source, File file) {
1243                                 source.hide();
1244                                 //Toast toast = Toast.makeText(source.getContext(), "File selected: " + file.getName(), Toast.LENGTH_LONG);
1245                                 //toast.show();
1246 
1247                                 m_filechooserString = "file:" + file.getPath();
1248                                 m_FileChooserDone = true;
1249 
1250                             }
1251                             public void onFileSelected(Dialog source, File folder, String name) {
1252                                 source.hide();
1253                                 //Toast toast = Toast.makeText(source.getContext(), "File created: " + folder.getName() + "/" + name, Toast.LENGTH_LONG);
1254                                 //toast.show();
1255 
1256                                 m_filechooserString = "file:" + folder.getPath() + "/" + name;
1257                                 m_FileChooserDone = true;
1258 
1259                             }
1260                         });
1261 
1262                         dialog.setOnCancelListener(new OnCancelListener() {
1263                             public void onCancel(DialogInterface dialog) {
1264                                 //Log.i("DEBUGGER_TAG", "FileChooserDialog Cancel");
1265                                 m_filechooserString = "cancel:";
1266                                 m_FileChooserDone = true;
1267                             }
1268                         });
1269 
1270 
1271                         dialog.setCanCreateFiles(true);
1272                         dialog.show();
1273 
1274                         //Log.i("DEBUGGER_TAG", "FileChooserDialog Back from show");
1275 
1276                     }
1277                 });
1278             }
1279         };
1280 
1281         // Don't forget to start the thread.
1282         thread.start();
1283 
1284         //Log.i("DEBUGGER_TAG", "FileChooserDialog Returning");
1285 
1286         return "OK";
1287    }
1288 
DirChooserDialog(final String initialDir, final String Title)1289    public String DirChooserDialog(final String initialDir, final String Title)
1290    {
1291        m_FileChooserDone = false;
1292 
1293        boolean buseDialog = true;
1294        if(!buseDialog){
1295             Intent intent = new Intent(this, FileChooserActivity.class);
1296             intent.putExtra(FileChooserActivity.INPUT_START_FOLDER, initialDir);
1297             intent.putExtra(FileChooserActivity.INPUT_FOLDER_MODE, true);
1298             this.startActivityForResult(intent, OCPN_AFILECHOOSER_REQUEST_CODE);
1299         }
1300 
1301         //Log.i("DEBUGGER_TAG", "DirChooserDialog create and show " + initialDir);
1302 
1303         Thread thread = new Thread() {
1304             @Override
1305             public void run() {
1306 
1307         // Block this thread for 20 msec.
1308                 try {
1309                     Thread.sleep(20);
1310                 } catch (InterruptedException e) {
1311                 }
1312 
1313 // After sleep finishes blocking, create a Runnable to run on the UI Thread.
1314                 runOnUiThread(new Runnable() {
1315                     @Override
1316                     public void run() {
1317                         FileChooserDialog dialog = new FileChooserDialog(m_activity, initialDir);
1318 
1319                         dialog.setShowFullPath( true );
1320                         dialog.setFolderMode( true );
1321                         dialog.setCanCreateFiles( true );
1322 
1323 
1324                         dialog.setTitle( Title );
1325 
1326                         dialog.addListener(new FileChooserDialog.OnFileSelectedListener() {
1327                             public void onFileSelected(Dialog source, File file) {
1328                                 source.hide();
1329                                 //Toast toast = Toast.makeText(source.getContext(), "File selected: " + file.getName(), Toast.LENGTH_LONG);
1330                                 //toast.show();
1331 
1332                                 m_filechooserString = "file:" + file.getPath();
1333                                 m_FileChooserDone = true;
1334 
1335                             }
1336                             public void onFileSelected(Dialog source, File folder, String name) {
1337                                 source.hide();
1338                                 m_FileChooserDone = true;
1339                             }
1340 
1341                         });
1342 
1343                         dialog.setOnCancelListener(new OnCancelListener() {
1344                             public void onCancel(DialogInterface dialog) {
1345                                 //Log.i("DEBUGGER_TAG", "DirChooserDialog Cancel");
1346                                 m_filechooserString = "cancel:";
1347                                 m_FileChooserDone = true;
1348                             }
1349                         });
1350 
1351 
1352                         dialog.show();
1353 
1354                         //Log.i("DEBUGGER_TAG", "DirChooserDialog Back from show");
1355 
1356                     }
1357                 });
1358             }
1359         };
1360 
1361         // Don't forget to start the thread.
1362         thread.start();
1363 
1364         //Log.i("DEBUGGER_TAG", "DirChooserDialog Returning");
1365 
1366        return "OK";
1367   }
1368 
isFileChooserFinished()1369    public String isFileChooserFinished()
1370    {
1371        if(m_FileChooserDone){
1372             return m_filechooserString;
1373        }
1374        else{
1375            return "no";
1376        }
1377    }
1378 
1379    // ActionBar Spinner navigation to select chart display type
1380 
1381    //  Thread safe version, callable from another thread
configureNavSpinnerTS(final int flag, final int sel)1382    public String configureNavSpinnerTS(final int flag, final int sel){
1383        Thread thread = new Thread() {
1384             @Override
1385             public void run() {
1386 
1387        // Block this thread for 20 msec.
1388                 try {
1389                     Thread.sleep(20);
1390                 } catch (InterruptedException e) {
1391                 }
1392 
1393        // After sleep finished blocking, create a Runnable to run on the UI Thread.
1394                 runOnUiThread(new Runnable() {
1395                     @Override
1396                     public void run() {
1397                         configureNavSpinner(flag, sel);
1398                     }
1399                 });
1400             }
1401        };
1402 
1403        // Don't forget to start the thread.
1404        thread.start();
1405 
1406        return "OK";
1407    }
1408 
1409 
1410 
configureNavSpinner(int flag, int sel)1411    public String configureNavSpinner(int flag, int sel){
1412        //Log.i("DEBUGGER_TAG", "configureNavSpinner");
1413        //String aa; aa = String.format("%d %d", flag, sel ); Log.i("DEBUGGER_TAG", aa);
1414 
1415        navSpinner.clear();
1416        int nbits = 0;
1417        int n93 = -1;
1418        int nraster = -1;
1419        int nvector = -1;
1420 
1421        if((flag & 1) == 1){
1422            nraster = nbits;
1423            navSpinner.add(spinnerItemRaster);
1424            nbits++;
1425        }
1426        if((flag & 2) == 2){
1427            nvector = nbits;
1428            navSpinner.add(spinnerItemVector);
1429            nbits++;
1430        }
1431        if((flag & 4) == 4){
1432            n93 = nbits;
1433            navSpinner.add(spinnerItemcm93);
1434            nbits++;
1435        }
1436 
1437 
1438 
1439        // Select the proper item as directed
1440        int to_sel = 0;
1441        if(sel == 1)
1442             to_sel = nraster;
1443        else if(sel == 2)
1444             to_sel = nvector;
1445        else if(sel == 4)
1446             to_sel = n93;
1447 
1448        // Any bits set?
1449        if(nbits > 1){
1450            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
1451            actionBar.setSelectedNavigationItem(to_sel);
1452        }
1453        else
1454            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
1455 
1456        return "OK";
1457    }
1458 
getSystemDirs()1459    public String getSystemDirs(){
1460        String result = "";
1461 
1462        ApplicationInfo ai = getApplicationInfo();
1463        if((ai.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) ==  ApplicationInfo.FLAG_EXTERNAL_STORAGE){
1464            //Log.i("DEBUGGER_TAG", "External");
1465            result = "EXTAPP;";
1466        }
1467        else{
1468            //Log.i("DEBUGGER_TAG", "Internal");
1469            result = "INTAPP;";
1470        }
1471 
1472 
1473 
1474        result = result.concat(getFilesDir().getPath() + ";");
1475        result = result.concat(getCacheDir().getPath() + ";");
1476        result = result.concat(getExternalFilesDir(null).getPath() + ";");
1477        result = result.concat(getExternalCacheDir().getPath() + ";");
1478        result = result.concat(Environment.getExternalStorageDirectory().getPath() + ";");
1479 
1480        //Log.i("DEBUGGER_TAG", result);
1481 
1482        return result;
1483    }
1484 
1485 
1486 
1487 
1488 //   @Override
1489 //   public void onTabSelected(ActionBar.Tab tab,
1490 //       FragmentTransaction fragmentTransaction) {
1491 
1492 //   Log.i("DEBUGGER_TAG", "onTabSelected");
1493 //   Log.i("DEBUGGER_TAG", tab.getText().toString());
1494 
1495      // When the given tab is selected, show the tab contents in the
1496      // container view.
1497 //     Fragment fragment = new DummySectionFragment();
1498 //     Bundle args = new Bundle();
1499 //     args.putInt(DummySectionFragment.ARG_SECTION_NUMBER,
1500 //         tab.getPosition() + 1);
1501 //     fragment.setArguments(args);
1502 //     getFragmentManager().beginTransaction()
1503 //         .replace(R.id.container, fragment).commit();
1504 //   }
1505 
1506 //   @Override
1507 //   public void onTabUnselected(ActionBar.Tab tab,
1508 //       FragmentTransaction fragmentTransaction) {
1509 //   }
1510 
1511 //   @Override
1512 //   public void onTabReselected(ActionBar.Tab tab,
1513 //       FragmentTransaction fragmentTransaction) {
1514 //   }
1515 
1516 
1517    //  ActionBar drop-down spinner navigation
1518    @Override
onNavigationItemSelected(int itemPosition, long itemId)1519    public boolean onNavigationItemSelected(int itemPosition, long itemId) {
1520    // Action to be taken after selecting a spinner item from action bar
1521 
1522    //Log.i("DEBUGGER_TAG", "onNavigationItemSelected");
1523    String aa;
1524    aa = String.format("%d", itemPosition);
1525    //Log.i("DEBUGGER_TAG", aa);
1526 
1527         SpinnerNavItem item = navSpinner.get(itemPosition);
1528         if(item.getTitle().equalsIgnoreCase("cm93")){
1529             nativeLib.selectChartDisplay(CHART_TYPE_CM93COMP, -1);
1530             return true;
1531         }
1532         else if(item.getTitle().equalsIgnoreCase("raster")){
1533             nativeLib.selectChartDisplay(-1, CHART_FAMILY_RASTER);
1534             //Log.i("DEBUGGER_TAG", "onNavigationItemSelectedA");
1535             return true;
1536         }
1537         else if(item.getTitle().equalsIgnoreCase("vector")){
1538             nativeLib.selectChartDisplay(-1, CHART_FAMILY_VECTOR);
1539             return true;
1540         }
1541 
1542 
1543        return false;
1544    }
1545 
relocateOCPNPlugins( )1546    private void relocateOCPNPlugins( )
1547    {
1548        // We need to relocate the PlugIns that have been included as "assets"
1549 
1550        // Reason:  PlugIns can only load from the apps dataDir, which is like:
1551        //          "/data/data/org.opencpn.opencpn"
1552        //          This is due to some policy in the system loader....
1553        //
1554        //           There is no need to relocate any data files needed by the PlugIns
1555        //           since they will have been added as assets and moved to the file system
1556        //           by assetbridge elsewhere.
1557        //
1558        //          Since this method runs on every restart, it may be used to condition manually installed
1559        //          PlugIns as well.  Just somehow install the PlugIn .so file into ".../files/plugins" dir,
1560        //          and it will be moved to the proper load location on restart.
1561 
1562        Log.i("DEBUGGER_TAG", "relocateOCPNPlugins");
1563 
1564        // On Moto G
1565        // This produces "/data/data/org.opencpn.opencpn/files"
1566        //  Which is where the app files would be with default load
1567        String iDir = getFilesDir().getPath();
1568        Log.i("DEBUGGER_TAG", "iDir: " + iDir);
1569 
1570        // This produces "/storage/emulated/0/Android/data/org.opencpn.opencpn/files"
1571        //  Which is where the app files would be if the app were "moved to SDCARD"
1572        String xDir = getExternalFilesDir(null).getPath();
1573        Log.i("DEBUGGER_TAG", "xDir: " + xDir);
1574 
1575 
1576        //   If the app is installed on external media, then that is where the assets have been stored...
1577        String ssd = iDir + "/plugins";
1578        ApplicationInfo ai = getApplicationInfo();
1579        if((ai.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) ==  ApplicationInfo.FLAG_EXTERNAL_STORAGE)
1580             ssd = xDir + "/plugins/";
1581 
1582 
1583        File sourceDir = new File( ssd );
1584 
1585        // The PlugIn .so files are always relocated to here, which looks like:
1586        // "/data/data/org.opencpn.opencpn"
1587        String finalDestination = getApplicationInfo().dataDir;
1588 
1589        File[] dirs = sourceDir.listFiles();
1590        if (dirs != null) {
1591            for (int j=0; j < dirs.length; j++){
1592                File sfile = dirs[j];
1593                Log.i("DEBUGGER_TAG", "sfile: " + sfile.getName());
1594 
1595                if (sfile.isFile()){
1596 
1597                               String source = sfile.getAbsolutePath();
1598                               String dest = finalDestination + "/" + sfile.getName();
1599 
1600 
1601                               try {
1602                                   InputStream inputStream = new FileInputStream(source);
1603                                   OutputStream outputStream = new FileOutputStream(dest);
1604                                   copyFile(inputStream, outputStream);
1605                                   inputStream.close();
1606                                   outputStream.close();
1607                                  Log.i("DEBUGGER_TAG", "copyFile OK: " + source + " to " + dest);
1608                               }
1609                               catch (Exception e) {
1610                                   e.printStackTrace();
1611                                   Log.i("DEBUGGER_TAG", "copyFile Exception");
1612                               }
1613               }
1614           }
1615       }
1616    }
1617 
1618 
1619     // this function is used to load and start the loader
loadApplication(Bundle loaderParams)1620     private void loadApplication(Bundle loaderParams)
1621     {
1622         Log.i("DEBUGGER_TAG", "LoadApplication");
1623 
1624         relocateOCPNPlugins();
1625 
1626 
1627         try {
1628             final int errorCode = loaderParams.getInt(ERROR_CODE_KEY);
1629             if (errorCode != 0) {
1630                 if (errorCode == INCOMPATIBLE_MINISTRO_VERSION) {
1631                     downloadUpgradeMinistro(loaderParams.getString(ERROR_MESSAGE_KEY));
1632                     return;
1633                 }
1634 
1635                 // fatal error, show the error and quit
1636                 AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create();
1637                 errorDialog.setMessage(loaderParams.getString(ERROR_MESSAGE_KEY));
1638                 errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
1639                     @Override
1640                     public void onClick(DialogInterface dialog, int which) {
1641                         finish();
1642                     }
1643                 });
1644                 errorDialog.show();
1645                 return;
1646             }
1647 
1648             // add all bundled Qt libs to loader params
1649             ArrayList<String> libs = new ArrayList<String>();
1650             if ( m_activityInfo.metaData.containsKey("android.app.bundled_libs_resource_id") )
1651                 libs.addAll(Arrays.asList(getResources().getStringArray(m_activityInfo.metaData.getInt("android.app.bundled_libs_resource_id"))));
1652 
1653                 //  We want the default OCPN plugins bundled into the APK and installed
1654                 //  into the proper app-lib.  So they are listed in ANDROID_EXTRA_LIBS.
1655                 //  But we do not want to pre-load them.  So take them out of the DexClassLoader list.
1656 
1657 //                libs.remove("dashboard_pi");
1658 //                libs.remove("grib_pi");
1659 
1660 
1661 
1662 
1663             String libName = null;
1664             if ( m_activityInfo.metaData.containsKey("android.app.lib_name") ) {
1665                 libName = m_activityInfo.metaData.getString("android.app.lib_name");
1666                 loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function
1667             }
1668 
1669             loaderParams.putStringArrayList(BUNDLED_LIBRARIES_KEY, libs);
1670             loaderParams.putInt(NECESSITAS_API_LEVEL_KEY, NECESSITAS_API_LEVEL);
1671 
1672             // load and start QtLoader class
1673             m_classLoader = new DexClassLoader(loaderParams.getString(DEX_PATH_KEY), // .jar/.apk files
1674                                                getDir("outdex", Context.MODE_PRIVATE).getAbsolutePath(), // directory where optimized DEX files should be written.
1675                                                loaderParams.containsKey(LIB_PATH_KEY) ? loaderParams.getString(LIB_PATH_KEY) : null, // libs folder (if exists)
1676                                                getClassLoader()); // parent loader
1677 
1678             @SuppressWarnings("rawtypes")
1679             Class loaderClass = m_classLoader.loadClass(loaderParams.getString(LOADER_CLASS_NAME_KEY)); // load QtLoader class
1680             Object qtLoader = loaderClass.newInstance(); // create an instance
1681             Method perpareAppMethod = qtLoader.getClass().getMethod("loadApplication",
1682                                                                     Activity.class,
1683                                                                     ClassLoader.class,
1684                                                                     Bundle.class);
1685             if (!(Boolean)perpareAppMethod.invoke(qtLoader, this, m_classLoader, loaderParams))
1686                 throw new Exception("");
1687 
1688             QtApplication.setQtActivityDelegate(qtLoader);
1689 
1690             // now load the application library so it's accessible from this class loader
1691             if (libName != null)
1692                 System.loadLibrary(libName);
1693 
1694             Method startAppMethod=qtLoader.getClass().getMethod("startApplication");
1695             if (!(Boolean)startAppMethod.invoke(qtLoader))
1696                 throw new Exception("");
1697 
1698 
1699         } catch (Exception e) {
1700             e.printStackTrace();
1701             AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create();
1702             if (m_activityInfo.metaData.containsKey("android.app.fatal_error_msg"))
1703                 errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.fatal_error_msg"));
1704             else
1705                 errorDialog.setMessage("Fatal error, your application can't be started.");
1706 
1707             errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
1708                 @Override
1709                 public void onClick(DialogInterface dialog, int which) {
1710                     finish();
1711                 }
1712             });
1713             errorDialog.show();
1714         }
1715     }
1716 
1717     private ServiceConnection m_ministroConnection=new ServiceConnection() {
1718         private IMinistro m_service = null;
1719         @Override
1720         public void onServiceConnected(ComponentName name, IBinder service)
1721         {
1722             m_service = IMinistro.Stub.asInterface(service);
1723             try {
1724                 if (m_service != null) {
1725                     Bundle parameters = new Bundle();
1726                     parameters.putStringArray(REQUIRED_MODULES_KEY, m_qtLibs);
1727                     parameters.putString(APPLICATION_TITLE_KEY, (String)QtActivity.this.getTitle());
1728                     parameters.putInt(MINIMUM_MINISTRO_API_KEY, MINISTRO_API_LEVEL);
1729                     parameters.putInt(MINIMUM_QT_VERSION_KEY, QT_VERSION);
1730                     parameters.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES);
1731                     if (APPLICATION_PARAMETERS != null)
1732                         parameters.putString(APPLICATION_PARAMETERS_KEY, APPLICATION_PARAMETERS);
1733                     parameters.putStringArray(SOURCES_KEY, m_sources);
1734                     parameters.putString(REPOSITORY_KEY, m_repository);
1735                     if (QT_ANDROID_THEMES != null)
1736                         parameters.putStringArray(ANDROID_THEMES_KEY, QT_ANDROID_THEMES);
1737                     m_service.requestLoader(m_ministroCallback, parameters);
1738                 }
1739             } catch (RemoteException e) {
1740                     e.printStackTrace();
1741             }
1742         }
1743 
1744         private IMinistroCallback m_ministroCallback = new IMinistroCallback.Stub() {
1745             // this function is called back by Ministro.
1746             @Override
1747             public void loaderReady(final Bundle loaderParams) throws RemoteException {
1748                 runOnUiThread(new Runnable() {
1749                     @Override
1750                     public void run() {
1751                         unbindService(m_ministroConnection);
1752                         loadApplication(loaderParams);
1753                     }
1754                 });
1755             }
1756         };
1757 
1758         @Override
1759         public void onServiceDisconnected(ComponentName name) {
1760             m_service = null;
1761         }
1762     };
1763 
downloadUpgradeMinistro(String msg)1764     private void downloadUpgradeMinistro(String msg)
1765     {
1766         AlertDialog.Builder downloadDialog = new AlertDialog.Builder(this);
1767         downloadDialog.setMessage(msg);
1768         downloadDialog.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
1769             @Override
1770             public void onClick(DialogInterface dialogInterface, int i) {
1771                 try {
1772                     Uri uri = Uri.parse("market://search?q=pname:org.kde.necessitas.ministro");
1773                     Intent intent = new Intent(Intent.ACTION_VIEW, uri);
1774                     startActivityForResult(intent, MINISTRO_INSTALL_REQUEST_CODE);
1775                 } catch (Exception e) {
1776                     e.printStackTrace();
1777                     ministroNotFound();
1778                 }
1779             }
1780         });
1781 
1782         downloadDialog.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
1783             @Override
1784             public void onClick(DialogInterface dialogInterface, int i) {
1785                 QtActivity.this.finish();
1786             }
1787         });
1788         downloadDialog.show();
1789     }
1790 
ministroNotFound()1791     private void ministroNotFound()
1792     {
1793         AlertDialog errorDialog = new AlertDialog.Builder(QtActivity.this).create();
1794 
1795         if (m_activityInfo.metaData.containsKey("android.app.ministro_not_found_msg"))
1796             errorDialog.setMessage(m_activityInfo.metaData.getString("android.app.ministro_not_found_msg"));
1797         else
1798             errorDialog.setMessage("Can't find Ministro service.\nThe application can't start.");
1799 
1800         errorDialog.setButton(getResources().getString(android.R.string.ok), new DialogInterface.OnClickListener() {
1801             @Override
1802             public void onClick(DialogInterface dialog, int which) {
1803                 finish();
1804             }
1805         });
1806         errorDialog.show();
1807     }
1808 
copyFile(InputStream inputStream, OutputStream outputStream)1809     static private void copyFile(InputStream inputStream, OutputStream outputStream)
1810         throws IOException
1811     {
1812         byte[] buffer = new byte[BUFFER_SIZE];
1813 
1814         int count;
1815         while ((count = inputStream.read(buffer)) > 0)
1816             outputStream.write(buffer, 0, count);
1817     }
1818 
1819 
copyAsset(String source, String destination)1820     private void copyAsset(String source, String destination)
1821         throws IOException
1822     {
1823         // Already exists, we don't have to do anything
1824         File destinationFile = new File(destination);
1825         if (destinationFile.exists())
1826             return;
1827 
1828         File parentDirectory = destinationFile.getParentFile();
1829         if (!parentDirectory.exists())
1830             parentDirectory.mkdirs();
1831 
1832         destinationFile.createNewFile();
1833 
1834         AssetManager assetsManager = getAssets();
1835         InputStream inputStream = assetsManager.open(source);
1836         OutputStream outputStream = new FileOutputStream(destinationFile);
1837         copyFile(inputStream, outputStream);
1838 
1839         inputStream.close();
1840         outputStream.close();
1841     }
1842 
createBundledBinary(String source, String destination)1843     private static void createBundledBinary(String source, String destination)
1844         throws IOException
1845     {
1846         // Already exists, we don't have to do anything
1847         File destinationFile = new File(destination);
1848         if (destinationFile.exists())
1849             return;
1850 
1851         File parentDirectory = destinationFile.getParentFile();
1852         if (!parentDirectory.exists())
1853             parentDirectory.mkdirs();
1854 
1855         destinationFile.createNewFile();
1856 
1857         InputStream inputStream = new FileInputStream(source);
1858         OutputStream outputStream = new FileOutputStream(destinationFile);
1859         copyFile(inputStream, outputStream);
1860 
1861         inputStream.close();
1862         outputStream.close();
1863     }
1864 
cleanCacheIfNecessary(String prefix, long packageVersion, String cacheName)1865     private boolean cleanCacheIfNecessary(String prefix, long packageVersion, String cacheName)
1866     {
1867         Log.i("DEBUGGER_TAG", "cleanCacheIfNecessary " + prefix);
1868         File versionFile = new File(prefix + cacheName);
1869 
1870         Log.i("DEBUGGER_TAG", "version file: " + prefix + cacheName);
1871 
1872         long cacheVersion = 0;
1873         if (versionFile.exists() && versionFile.canRead()) {
1874             Log.i("DEBUGGER_TAG", "version file exists ");
1875             try {
1876                 DataInputStream inputStream = new DataInputStream(new FileInputStream(versionFile));
1877                 cacheVersion = inputStream.readLong();
1878                 inputStream.close();
1879              } catch (Exception e) {
1880                 e.printStackTrace();
1881              }
1882         }
1883 
1884         if (cacheVersion != packageVersion) {
1885             //deleteRecursively(new File(prefix));
1886  //           Log.i("DEBUGGER_TAG", "cleanCacheIfNecessary return true");
1887             return true;
1888         } else {
1889  //           Log.i("DEBUGGER_TAG", "cleanCacheIfNecessary return false");
1890 
1891             return false;
1892         }
1893     }
1894 
extractBundledPluginsAndImports(String pluginsPrefix)1895     private void extractBundledPluginsAndImports(String pluginsPrefix)
1896         throws IOException
1897     {
1898         ArrayList<String> libs = new ArrayList<String>();
1899 
1900         String dataDir = getApplicationInfo().dataDir + "/";
1901 
1902         long packageVersion = -1;
1903         try {
1904             PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
1905             packageVersion = packageInfo.lastUpdateTime;
1906         } catch (Exception e) {
1907             e.printStackTrace();
1908         }
1909 
1910         if (!cleanCacheIfNecessary(pluginsPrefix, packageVersion, "cache.version"))
1911             return;
1912 
1913         {
1914             File versionFile = new File(pluginsPrefix + "cache.version");
1915 
1916             File parentDirectory = versionFile.getParentFile();
1917             if (!parentDirectory.exists())
1918                 parentDirectory.mkdirs();
1919 
1920             versionFile.createNewFile();
1921 
1922             DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(versionFile));
1923             outputStream.writeLong(packageVersion);
1924             outputStream.close();
1925         }
1926 
1927         {
1928             String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
1929             java.util.Set<String> keys = m_activityInfo.metaData.keySet();
1930             if (m_activityInfo.metaData.containsKey(key)) {
1931                 String[] list = getResources().getStringArray(m_activityInfo.metaData.getInt(key));
1932 
1933                 for (String bundledImportBinary : list) {
1934                     String[] split = bundledImportBinary.split(":");
1935                     String sourceFileName = dataDir + "lib/" + split[0];
1936                     String destinationFileName = pluginsPrefix + split[1];
1937                     createBundledBinary(sourceFileName, destinationFileName);
1938                 }
1939             }
1940         }
1941 
1942         {
1943             String key = BUNDLED_IN_ASSETS_RESOURCE_ID_KEY;
1944             if (m_activityInfo.metaData.containsKey(key)) {
1945                 String[] list = getResources().getStringArray(m_activityInfo.metaData.getInt(key));
1946 
1947                 for (String fileName : list) {
1948                     String[] split = fileName.split(":");
1949                     String sourceFileName = split[0];
1950                     String destinationFileName = pluginsPrefix + split[1];
1951                     copyAsset(sourceFileName, destinationFileName);
1952                 }
1953             }
1954 
1955         }
1956     }
1957 
deleteRecursively(File directory)1958     private void deleteRecursively(File directory)
1959     {
1960         File[] files = directory.listFiles();
1961         if (files != null) {
1962             for (File file : files) {
1963                 if (file.isDirectory())
1964                     deleteRecursively(file);
1965                 else
1966                     file.delete();
1967             }
1968 
1969             directory.delete();
1970         }
1971     }
1972 
cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix)1973     private void cleanOldCacheIfNecessary(String oldLocalPrefix, String localPrefix)
1974     {
1975         File newCache = new File(localPrefix);
1976         if (!newCache.exists()) {
1977             {
1978                 File oldPluginsCache = new File(oldLocalPrefix + "plugins/");
1979                 if (oldPluginsCache.exists() && oldPluginsCache.isDirectory())
1980                     deleteRecursively(oldPluginsCache);
1981             }
1982 
1983             {
1984                 File oldImportsCache = new File(oldLocalPrefix + "imports/");
1985                 if (oldImportsCache.exists() && oldImportsCache.isDirectory())
1986                     deleteRecursively(oldImportsCache);
1987             }
1988 
1989             {
1990                 File oldQmlCache = new File(oldLocalPrefix + "qml/");
1991                 if (oldQmlCache.exists() && oldQmlCache.isDirectory())
1992                     deleteRecursively(oldQmlCache);
1993             }
1994         }
1995     }
1996 
startApp(final boolean firstStart)1997     private void startApp(final boolean firstStart)
1998     {
1999         try {
2000             if (m_activityInfo.metaData.containsKey("android.app.qt_sources_resource_id")) {
2001                 int resourceId = m_activityInfo.metaData.getInt("android.app.qt_sources_resource_id");
2002                 m_sources = getResources().getStringArray(resourceId);
2003             }
2004 
2005             if (m_activityInfo.metaData.containsKey("android.app.repository"))
2006                 m_repository = m_activityInfo.metaData.getString("android.app.repository");
2007 
2008             if (m_activityInfo.metaData.containsKey("android.app.qt_libs_resource_id")) {
2009                 int resourceId = m_activityInfo.metaData.getInt("android.app.qt_libs_resource_id");
2010                 m_qtLibs = getResources().getStringArray(resourceId);
2011             }
2012 
2013             if (m_activityInfo.metaData.containsKey("android.app.use_local_qt_libs")
2014                     && m_activityInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) {
2015                 ArrayList<String> libraryList = new ArrayList<String>();
2016 
2017 
2018                 String localPrefix = "/data/local/tmp/qt/";
2019                 if (m_activityInfo.metaData.containsKey("android.app.libs_prefix"))
2020                     localPrefix = m_activityInfo.metaData.getString("android.app.libs_prefix");
2021 
2022                 String pluginsPrefix = localPrefix;
2023 
2024                 boolean bundlingQtLibs = false;
2025                 if (m_activityInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
2026                     && m_activityInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
2027                     localPrefix = getApplicationInfo().dataDir + "/";
2028                     pluginsPrefix = localPrefix + "qt-reserved-files/";
2029                     cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
2030                     extractBundledPluginsAndImports(pluginsPrefix);
2031                     bundlingQtLibs = true;
2032                 }
2033 
2034                 if (m_qtLibs != null) {
2035                     for (int i=0;i<m_qtLibs.length;i++) {
2036                         libraryList.add(localPrefix
2037                                         + "lib/lib"
2038                                         + m_qtLibs[i]
2039                                         + ".so");
2040                     }
2041                 }
2042 
2043                 if (m_activityInfo.metaData.containsKey("android.app.load_local_libs")) {
2044                     String[] extraLibs = m_activityInfo.metaData.getString("android.app.load_local_libs").split(":");
2045                     for (String lib : extraLibs) {
2046                         if (lib.length() > 0) {
2047                             if (lib.startsWith("lib/"))
2048                                 libraryList.add(localPrefix + lib);
2049                             else
2050                                 libraryList.add(pluginsPrefix + lib);
2051                         }
2052                     }
2053                 }
2054 
2055 
2056                 String dexPaths = new String();
2057                 String pathSeparator = System.getProperty("path.separator", ":");
2058                 if (!bundlingQtLibs && m_activityInfo.metaData.containsKey("android.app.load_local_jars")) {
2059                     String[] jarFiles = m_activityInfo.metaData.getString("android.app.load_local_jars").split(":");
2060                     for (String jar:jarFiles) {
2061                         if (jar.length() > 0) {
2062                             if (dexPaths.length() > 0)
2063                                 dexPaths += pathSeparator;
2064                             dexPaths += localPrefix + jar;
2065                         }
2066                     }
2067                 }
2068 
2069                 Bundle loaderParams = new Bundle();
2070                 loaderParams.putInt(ERROR_CODE_KEY, 0);
2071                 loaderParams.putString(DEX_PATH_KEY, dexPaths);
2072                 loaderParams.putString(LOADER_CLASS_NAME_KEY, "org.qtproject.qt5.android.QtActivityDelegate");
2073                 if (m_activityInfo.metaData.containsKey("android.app.static_init_classes")) {
2074                     loaderParams.putStringArray(STATIC_INIT_CLASSES_KEY,
2075                                                 m_activityInfo.metaData.getString("android.app.static_init_classes").split(":"));
2076                 }
2077                 loaderParams.putStringArrayList(NATIVE_LIBRARIES_KEY, libraryList);
2078                 loaderParams.putString(ENVIRONMENT_VARIABLES_KEY, ENVIRONMENT_VARIABLES
2079                                                                   + "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml"
2080                                                                   + "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports"
2081                                                                   + "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins");
2082 
2083                 Intent intent = getIntent();
2084                 if (intent != null) {
2085                     String parameters = intent.getStringExtra("applicationArguments");
2086                     if (parameters != null)
2087                         loaderParams.putString(APPLICATION_PARAMETERS_KEY, parameters.replace(' ', '\t'));
2088                 }
2089 
2090                 loadApplication(loaderParams);
2091 
2092                 activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
2093 
2094                 PackageManager packMan = getPackageManager();
2095                 m_hasGPS = packMan.hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
2096 
2097                 return;
2098             }
2099 
2100             try {
2101                 if (!bindService(new Intent(org.kde.necessitas.ministro.IMinistro.class.getCanonicalName()),
2102                                  m_ministroConnection,
2103                                  Context.BIND_AUTO_CREATE)) {
2104                     throw new SecurityException("");
2105                 }
2106             } catch (Exception e) {
2107                 if (firstStart) {
2108                     String msg = "This application requires Ministro service. Would you like to install it?";
2109                     if (m_activityInfo.metaData.containsKey("android.app.ministro_needed_msg"))
2110                         msg = m_activityInfo.metaData.getString("android.app.ministro_needed_msg");
2111                     downloadUpgradeMinistro(msg);
2112                 } else {
2113                     ministroNotFound();
2114                 }
2115             }
2116         } catch (Exception e) {
2117             Log.e(QtApplication.QtTAG, "Can't create main activity", e);
2118         }
2119     }
2120 
2121     /////////////////////////// forward all notifications ////////////////////////////
2122     /////////////////////////// Super class calls ////////////////////////////////////
2123     /////////////// PLEASE DO NOT CHANGE THE FOLLOWING CODE //////////////////////////
2124     //////////////////////////////////////////////////////////////////////////////////
2125 
2126     @Override
dispatchKeyEvent(KeyEvent event)2127     public boolean dispatchKeyEvent(KeyEvent event)
2128     {
2129         if (QtApplication.m_delegateObject != null && QtApplication.dispatchKeyEvent != null)
2130             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchKeyEvent, event);
2131         else
2132             return super.dispatchKeyEvent(event);
2133     }
super_dispatchKeyEvent(KeyEvent event)2134     public boolean super_dispatchKeyEvent(KeyEvent event)
2135     {
2136         return super.dispatchKeyEvent(event);
2137     }
2138     //---------------------------------------------------------------------------
2139 
2140     @Override
dispatchPopulateAccessibilityEvent(AccessibilityEvent event)2141     public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event)
2142     {
2143         if (QtApplication.m_delegateObject != null && QtApplication.dispatchPopulateAccessibilityEvent != null)
2144             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchPopulateAccessibilityEvent, event);
2145         else
2146             return super.dispatchPopulateAccessibilityEvent(event);
2147     }
super_dispatchPopulateAccessibilityEvent(AccessibilityEvent event)2148     public boolean super_dispatchPopulateAccessibilityEvent(AccessibilityEvent event)
2149     {
2150         return super_dispatchPopulateAccessibilityEvent(event);
2151     }
2152     //---------------------------------------------------------------------------
2153 
2154     @Override
dispatchTouchEvent(MotionEvent ev)2155     public boolean dispatchTouchEvent(MotionEvent ev)
2156     {
2157         //Toast.makeText(getApplicationContext(), "dispatchTouchEvent",Toast.LENGTH_LONG).show();
2158 
2159         if( (ev.getAction() == MotionEvent.ACTION_MOVE) && (Math.abs(ev.getRawX() - lastX) < 1.0f) && (Math.abs(ev.getRawY() - lastY) < 1.0f))
2160             return true;
2161 
2162         lastX = ev.getRawX();
2163         lastY = ev.getRawY();
2164 
2165         if(ev.getAction() == MotionEvent.ACTION_UP){
2166             lastX = -1.0f;
2167             lastY = -1.0f;
2168         }
2169 //        Log.i("Sending", String.format("%d  x = %5.2f, y=%5.2f", ev.getAction(), ev.getRawX(), ev.getRawY()));
2170 
2171         if (QtApplication.m_delegateObject != null && QtApplication.dispatchTouchEvent != null)
2172             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchTouchEvent, ev);
2173         else
2174             return super.dispatchTouchEvent(ev);
2175     }
super_dispatchTouchEvent(MotionEvent event)2176     public boolean super_dispatchTouchEvent(MotionEvent event)
2177     {
2178         return super.dispatchTouchEvent(event);
2179     }
2180     //---------------------------------------------------------------------------
2181 
2182     @Override
dispatchTrackballEvent(MotionEvent ev)2183     public boolean dispatchTrackballEvent(MotionEvent ev)
2184     {
2185         if (QtApplication.m_delegateObject != null && QtApplication.dispatchTrackballEvent != null)
2186             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchTrackballEvent, ev);
2187         else
2188             return super.dispatchTrackballEvent(ev);
2189     }
super_dispatchTrackballEvent(MotionEvent event)2190     public boolean super_dispatchTrackballEvent(MotionEvent event)
2191     {
2192         return super.dispatchTrackballEvent(event);
2193     }
2194     //---------------------------------------------------------------------------
2195 
2196     @Override
onActivityResult(int requestCode, int resultCode, Intent data)2197     protected void onActivityResult(int requestCode, int resultCode, Intent data)
2198     {
2199 //        Log.i("DEBUGGER_TAG", "onActivityResultA");
2200         if (requestCode == OCPN_SETTINGS_REQUEST_CODE) {
2201 //            Log.i("DEBUGGER_TAG", "onqtActivityResultC");
2202             // Make sure the request was successful
2203             if (resultCode == RESULT_OK)
2204             {
2205 //                Log.i("DEBUGGER_TAG", "onqtActivityResultD");
2206                 m_settingsReturn = data.getStringExtra("SettingsString");
2207                 nativeLib.invokeCmdEventCmdString( ID_CMD_NULL_REFRESH, m_settingsReturn);
2208 
2209                 // defer hte application of settings until the screen refreshes
2210                 Handler handler = new Handler();
2211                 handler.postDelayed(new Runnable() {
2212                      public void run() {
2213                           nativeLib.invokeCmdEventCmdString( ID_CMD_APPLY_SETTINGS, m_settingsReturn);
2214                      }
2215                 }, 100);
2216 //                Log.i("DEBUGGER_TAG", m_settingsReturn);
2217             }
2218             else if (resultCode == RESULT_CANCELED){
2219 //                Log.i("DEBUGGER_TAG", "onqtActivityResultE");
2220             }
2221 
2222             super.onActivityResult(requestCode, resultCode, data);
2223 
2224             return;
2225         }
2226 
2227         if (requestCode == OCPN_FILECHOOSER_REQUEST_CODE) {
2228             //Log.i("DEBUGGER_TAG", "onqtActivityResultCf");
2229             // Make sure the request was successful
2230             if (resultCode == RESULT_OK)
2231             {
2232                  //Log.i("DEBUGGER_TAG", "onqtActivityResultDf");
2233                  m_filechooserString = "file:" + data.getStringExtra("itemSelected");
2234                  //Log.i("DEBUGGER_TAG", m_filechooserString);
2235             }
2236             else if (resultCode == RESULT_CANCELED){
2237                 //Log.i("DEBUGGER_TAG", "onqtActivityResultEf");
2238                 m_filechooserString = "cancel:";
2239             }
2240 
2241             m_FileChooserDone = true;
2242 
2243             super.onActivityResult(requestCode, resultCode, data);
2244 
2245             return;
2246         }
2247 
2248         if (requestCode == OCPN_AFILECHOOSER_REQUEST_CODE) {
2249             //Log.i("DEBUGGER_TAG", "onqtActivityResultCa");
2250             // Make sure the request was successful
2251             if (resultCode == Activity.RESULT_OK) {
2252                 //Log.i("DEBUGGER_TAG", "onqtActivityResultDa");
2253                 boolean fileCreated = false;
2254                 String filePath = "";
2255 
2256                 Bundle bundle = data.getExtras();
2257                 if(bundle != null)
2258                 {
2259                     if(bundle.containsKey(FileChooserActivity.OUTPUT_NEW_FILE_NAME)) {
2260                             fileCreated = true;
2261                             File folder = (File) bundle.get(FileChooserActivity.OUTPUT_FILE_OBJECT);
2262                             String name = bundle.getString(FileChooserActivity.OUTPUT_NEW_FILE_NAME);
2263                             filePath = folder.getAbsolutePath() + "/" + name;
2264                     } else {
2265                             fileCreated = false;
2266                             File file = (File) bundle.get(FileChooserActivity.OUTPUT_FILE_OBJECT);
2267                             filePath = file.getAbsolutePath();
2268                     }
2269 
2270                     m_filechooserString = "file:" + filePath;
2271 
2272                 }
2273             }
2274             else if (resultCode == Activity.RESULT_CANCELED){
2275                 //Log.i("DEBUGGER_TAG", "onqtActivityResultEa");
2276                 m_filechooserString = "cancel:";
2277             }
2278 
2279             m_FileChooserDone = true;
2280 
2281             super.onActivityResult(requestCode, resultCode, data);
2282 
2283             return;
2284         }
2285 
2286         if (requestCode == OCPN_GOOGLEMAPS_REQUEST_CODE) {
2287             // Make sure the request was successful
2288             if (resultCode == RESULT_OK)
2289             {
2290                 String finalPosition = data.getStringExtra("finalPosition");
2291 //                Log.i("DEBUGGER_TAG", "finalPositionFromMaps " + finalPosition);
2292 
2293                 StringTokenizer tkz = new StringTokenizer(finalPosition, ";");
2294 
2295                 String finalLat = finalPosition.valueOf(m_gminitialLat);
2296                 String finalLon = finalPosition.valueOf(m_gminitialLon);
2297                 String finalZoom = finalPosition.valueOf(m_gminitialZoom);
2298                 String zoomFactor = "1.0";
2299 
2300                 if(tkz.hasMoreTokens()){
2301                     finalLat = tkz.nextToken();
2302                     finalLon = tkz.nextToken();
2303                     finalZoom = tkz.nextToken();
2304                     zoomFactor = tkz.nextToken();
2305                 }
2306 
2307                 double zoomF = Double.parseDouble(zoomFactor);
2308                 finalZoom = String.valueOf(m_gminitialZoom * zoomF);
2309 
2310 
2311                 String vpSet = "";
2312 
2313                 vpSet = vpSet.concat(finalLat);
2314                 vpSet = vpSet.concat(";");
2315                 vpSet = vpSet.concat(finalLon);
2316                 vpSet = vpSet.concat(";");
2317                 vpSet = vpSet.concat(finalZoom);
2318                 vpSet = vpSet.concat(";");
2319 
2320 
2321                 Log.i("DEBUGGER_TAG", "finalPositionString " + vpSet);
2322 
2323                 nativeLib.invokeCmdEventCmdString( ID_CMD_SETVP, vpSet);
2324 
2325             }
2326             else if (resultCode == RESULT_CANCELED){
2327 //                Log.i("DEBUGGER_TAG", "onqtActivityResultE");
2328             }
2329 
2330             super.onActivityResult(requestCode, resultCode, data);
2331 
2332             return;
2333         }
2334 
2335         if (QtApplication.m_delegateObject != null && QtApplication.onActivityResult != null) {
2336             QtApplication.invokeDelegateMethod(QtApplication.onActivityResult, requestCode, resultCode, data);
2337             return;
2338         }
2339         //Log.i("DEBUGGER_TAG", "onqtActivityResultB");
2340         if (requestCode == MINISTRO_INSTALL_REQUEST_CODE)
2341             startApp(false);
2342 
2343         super.onActivityResult(requestCode, resultCode, data);
2344     }
super_onActivityResult(int requestCode, int resultCode, Intent data)2345     public void super_onActivityResult(int requestCode, int resultCode, Intent data)
2346     {
2347         super.onActivityResult(requestCode, resultCode, data);
2348     }
2349 
doLicenseCheck()2350     private void doLicenseCheck() {
2351         mChecker.checkAccess(mLicenseCheckerCallback);
2352     }
2353 
2354     private class MyLicenseCheckerCallback implements LicenseCheckerCallback {
allow(int reason)2355         public void allow(int reason) {
2356             Log.i("OpenCPN", "License allow()");
2357             if (isFinishing()) {
2358                 // Don't update UI if Activity is finishing.
2359                 return;
2360             }
2361             // Should allow user access.
2362 
2363             m_licenseOK = true;
2364         }
2365 
dontAllow(int reason)2366         public void dontAllow(int reason) {
2367             if (isFinishing()) {
2368                 // Don't update UI if Activity is finishing.
2369                 return;
2370             }
2371 
2372             if (reason == Policy.RETRY) {
2373                 // If the reason received from the policy is RETRY, it was probably
2374                 // due to a loss of connection with the service, so we should give the
2375                 // user a chance to retry. So show a dialog to retry.
2376                 mLicenseHandler.post(new Runnable() {
2377                     public void run() {
2378                         Log.i("OpenCPN", "License: dontAllow(), RETRY");
2379                         m_licenseOK = true;
2380                     }
2381                 });
2382 
2383             } else {
2384                 // Otherwise, the user is not licensed to use this app.
2385                 // Your response should always inform the user that the application
2386                 // is not licensed, but your behavior at that point can vary. You might
2387                 // provide the user a limited access version of your app or you can
2388                 // take them to Google Play to purchase the app.
2389                 mLicenseHandler.post(new Runnable() {
2390                     public void run() {
2391                         Log.i("OpenCPN", "License: dontAllow(), NOT LICENSED");
2392 
2393                         m_licenseOK = false;
2394                         ShowTextDialog("OpenCPN is not licensed on this device.\nPlease visit the Google Play Store to install a valid copy.");
2395 
2396                     }
2397                 });
2398 
2399             }
2400         }
2401 
applicationError(int errorCode)2402         public void applicationError(int errorCode) {
2403 /*
2404             private static final int LICENSED = 0x0;
2405             private static final int NOT_LICENSED = 0x1;
2406             private static final int LICENSED_OLD_KEY = 0x2;
2407             private static final int ERROR_NOT_MARKET_MANAGED = 0x3;
2408             private static final int ERROR_SERVER_FAILURE = 0x4;
2409             private static final int ERROR_OVER_QUOTA = 0x5;
2410 
2411             private static final int ERROR_CONTACTING_SERVER = 0x101;
2412             private static final int ERROR_INVALID_PACKAGE_NAME = 0x102;
2413             private static final int ERROR_NON_MATCHING_UID = 0x103;
2414 */
2415             Log.i("OpenCPN", "License: applicationError() "  + String.valueOf(errorCode));
2416 
2417             ShowTextDialog("License: applicationError() "  + String.valueOf(errorCode) );
2418 
2419             if (isFinishing()) {
2420                 // Don't update UI if Activity is finishing.
2421                 return;
2422             }
2423        }
2424 
2425     }
2426 
ShowTextDialog(final String message)2427     private void ShowTextDialog(final String message){
2428         AlertDialog.Builder builder1 = new AlertDialog.Builder(this);
2429                 builder1.setMessage(message);
2430                 builder1.setCancelable(true);
2431                 builder1.setNeutralButton("OK",
2432                         new DialogInterface.OnClickListener() {
2433                     public void onClick(DialogInterface dialog, int id) {
2434                         dialog.cancel();
2435                         if(!m_licenseOK)
2436                             finish();
2437                     }
2438                 });
2439 /*
2440                 builder1.setNegativeButton("No",
2441                         new DialogInterface.OnClickListener() {
2442                     public void onClick(DialogInterface dialog, int id) {
2443                         dialog.cancel();
2444                     }
2445                 });
2446 */
2447                 AlertDialog alert11 = builder1.create();
2448                 alert11.show();
2449         }
2450 
2451 
2452 
2453 
2454     //---------------------------------------------------------------------------
2455 
2456     @Override
onApplyThemeResource(Theme theme, int resid, boolean first)2457     protected void onApplyThemeResource(Theme theme, int resid, boolean first)
2458     {
2459         if (!QtApplication.invokeDelegate(theme, resid, first).invoked)
2460             super.onApplyThemeResource(theme, resid, first);
2461     }
super_onApplyThemeResource(Theme theme, int resid, boolean first)2462     public void super_onApplyThemeResource(Theme theme, int resid, boolean first)
2463     {
2464         super.onApplyThemeResource(theme, resid, first);
2465     }
2466     //---------------------------------------------------------------------------
2467 
2468 
2469     @Override
onChildTitleChanged(Activity childActivity, CharSequence title)2470     protected void onChildTitleChanged(Activity childActivity, CharSequence title)
2471     {
2472         if (!QtApplication.invokeDelegate(childActivity, title).invoked)
2473             super.onChildTitleChanged(childActivity, title);
2474     }
super_onChildTitleChanged(Activity childActivity, CharSequence title)2475     public void super_onChildTitleChanged(Activity childActivity, CharSequence title)
2476     {
2477         super.onChildTitleChanged(childActivity, title);
2478     }
2479     //---------------------------------------------------------------------------
2480 
2481     @Override
onConfigurationChanged(Configuration newConfig)2482     public void onConfigurationChanged(Configuration newConfig)
2483     {
2484         //Log.i("DEBUGGER_TAG", "onConfigurationChanged");
2485 
2486         int i = nativeLib.onConfigChange();
2487 
2488         if (!QtApplication.invokeDelegate(newConfig).invoked)
2489             super.onConfigurationChanged(newConfig);
2490     }
super_onConfigurationChanged(Configuration newConfig)2491     public void super_onConfigurationChanged(Configuration newConfig)
2492     {
2493         super.onConfigurationChanged(newConfig);
2494     }
2495     //---------------------------------------------------------------------------
2496 
2497     @Override
onContentChanged()2498     public void onContentChanged()
2499     {
2500         if (!QtApplication.invokeDelegate().invoked)
2501             super.onContentChanged();
2502     }
super_onContentChanged()2503     public void super_onContentChanged()
2504     {
2505         super.onContentChanged();
2506     }
2507     //---------------------------------------------------------------------------
2508 
2509     @Override
onContextItemSelected(MenuItem item)2510     public boolean onContextItemSelected(MenuItem item)
2511     {
2512         QtApplication.InvokeResult res = QtApplication.invokeDelegate(item);
2513         if (res.invoked)
2514             return (Boolean)res.methodReturns;
2515         else
2516             return super.onContextItemSelected(item);
2517     }
super_onContextItemSelected(MenuItem item)2518     public boolean super_onContextItemSelected(MenuItem item)
2519     {
2520         return super.onContextItemSelected(item);
2521     }
2522     //---------------------------------------------------------------------------
2523 
2524     @Override
onContextMenuClosed(Menu menu)2525     public void onContextMenuClosed(Menu menu)
2526     {
2527         if (!QtApplication.invokeDelegate(menu).invoked)
2528             super.onContextMenuClosed(menu);
2529     }
super_onContextMenuClosed(Menu menu)2530     public void super_onContextMenuClosed(Menu menu)
2531     {
2532         super.onContextMenuClosed(menu);
2533     }
2534     //---------------------------------------------------------------------------
2535 
2536     private ListView mDrawerList;
2537     private ArrayAdapter<String> mAdapter;
2538 
2539     @Override
onCreate(Bundle savedInstanceState)2540     public void onCreate(Bundle savedInstanceState)
2541     {
2542 //        Log.i("DEBUGGER_TAG", "onCreate");
2543         //Toast.makeText(getApplicationContext(), "onCreate",Toast.LENGTH_LONG).show();
2544 
2545         super.onCreate(savedInstanceState);
2546 
2547         //  Bug fix, see http://code.google.com/p/android/issues/detail?id=26658
2548         if(!isTaskRoot()) {
2549             finish();
2550             return;
2551         }
2552 
2553 //        setContentView(R.layout.activity_main);
2554 
2555 
2556         // Validate Google Licensing plan...
2557 
2558         // This device must have a Google Play Services account...
2559         AccountManager am = AccountManager.get(this);
2560         int numAccounts = am.getAccountsByType("com.google").length;
2561 
2562         if(numAccounts == 0) {
2563             Log.i("OpenCPN", "No Google account...");
2564 
2565             ShowTextDialog( "OpenCPN is not licensed on this device. Please create a Google Play Services / Play Store account.");
2566 
2567             finish();
2568             return;
2569 
2570        } else {
2571              // Do the license check as you have an account
2572 
2573         // Try to use more data here. ANDROID_ID is a single point of attack.
2574             String deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
2575 
2576         // Construct the LicenseCheckerCallback.
2577             mLicenseCheckerCallback = new MyLicenseCheckerCallback();
2578 
2579         // Construct the LicenseChecker with a Policy.
2580             mChecker = new LicenseChecker(
2581                 this, new ServerManagedPolicy(this,
2582                     new AESObfuscator(SALT, getPackageName(), deviceId)),
2583                 BASE64_PUBLIC_KEY  // Your public licensing key.
2584                 );
2585 
2586 
2587         // We need a Handler to manage license server responses
2588             mLicenseHandler = new Handler();
2589 
2590         // Initiate a license check
2591             doLicenseCheck();
2592         }
2593 
2594 
2595         try {
2596             m_activityInfo = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
2597             for (Field f : Class.forName("android.R$style").getDeclaredFields()) {
2598                 if (f.getInt(null) == m_activityInfo.getThemeResource()) {
2599                     QT_ANDROID_THEMES = new String[] {f.getName()};
2600                     QT_ANDROID_DEFAULT_THEME = f.getName();
2601                 }
2602             }
2603         } catch (Exception e) {
2604             e.printStackTrace();
2605             finish();
2606             return;
2607         }
2608 
2609         try {
2610             setTheme(Class.forName("android.R$style").getDeclaredField(QT_ANDROID_DEFAULT_THEME).getInt(null));
2611         } catch (Exception e) {
2612             e.printStackTrace();
2613         }
2614 
2615         if (Build.VERSION.SDK_INT > 10) {
2616             try {
2617 //                requestWindowFeature(Window.class.getField("FEATURE_ACTION_BAR").getInt(null));
2618             } catch (Exception e) {
2619                 e.printStackTrace();
2620             }
2621         } else {
2622             requestWindowFeature(Window.FEATURE_NO_TITLE);
2623         }
2624 
2625         nativeLib = new OCPNNativeLib();
2626 
2627 
2628         if (QtApplication.m_delegateObject != null && QtApplication.onCreate != null) {
2629             QtApplication.invokeDelegateMethod(QtApplication.onCreate, savedInstanceState);
2630             return;
2631         }
2632 
2633 
2634  //----------------------------------------------------------------------------
2635         // Set up ActionBar spinner navigation
2636         actionBar = getActionBar();
2637 
2638         // Setup Spinner title navigation data
2639         navSpinner = new ArrayList<SpinnerNavItem>();
2640 
2641         spinnerItemRaster = new SpinnerNavItem("Raster", R.drawable.ic_action_map);
2642         spinnerItemVector = new SpinnerNavItem("Vector", R.drawable.ic_action_map);
2643         spinnerItemcm93 = new SpinnerNavItem("cm93", R.drawable.ic_action_map);
2644 
2645         // title drop down adapter
2646         adapter = new TitleNavigationAdapter(getApplicationContext(), navSpinner);
2647         // assigning the spinner navigation
2648         actionBar.setListNavigationCallbacks(adapter, this);
2649 
2650         configureNavSpinner(7, 0);
2651 
2652 //----------------------------------------------------------------------------
2653 
2654         ENVIRONMENT_VARIABLES += "\tQT_ANDROID_THEME=" + QT_ANDROID_DEFAULT_THEME
2655                               + "/\tQT_ANDROID_THEME_DISPLAY_DPI=" + getResources().getDisplayMetrics().densityDpi + "\t";
2656 
2657     //Log.i("DEBUGGER_TAG", "splash Screen??");
2658 
2659         if (null == getLastNonConfigurationInstance()) {
2660             // if splash screen is defined, then show it
2661             if (m_activityInfo.metaData.containsKey("android.app.splash_screen") )
2662                 setContentView(m_activityInfo.metaData.getInt("android.app.splash_screen"));
2663 
2664     String tmpdir = "";
2665     ApplicationInfo ai = getApplicationInfo();
2666     if((ai.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) ==  ApplicationInfo.FLAG_EXTERNAL_STORAGE)
2667         tmpdir = getExternalFilesDir(null).getPath();
2668     else
2669         tmpdir = getFilesDir().getPath();
2670 
2671 
2672         long packageVersion = -1;
2673         try {
2674             PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
2675             packageVersion = packageInfo.lastUpdateTime;
2676         } catch (Exception e) {
2677             e.printStackTrace();
2678         }
2679 
2680         boolean b_needcopy = false;
2681         if (cleanCacheIfNecessary(tmpdir + "/", packageVersion, "OCPNcache.version"))
2682             b_needcopy = true;
2683 
2684 
2685         try{
2686             File versionFile = new File(tmpdir + "/OCPNcache.version");
2687 
2688             File parentDirectory = versionFile.getParentFile();
2689             if (!parentDirectory.exists())
2690                 parentDirectory.mkdirs();
2691 
2692             versionFile.createNewFile();
2693 
2694             DataOutputStream outputStream = new DataOutputStream(new FileOutputStream(versionFile));
2695             outputStream.writeLong(packageVersion);
2696             outputStream.close();
2697         } catch (Exception e) {
2698             e.printStackTrace();
2699         }
2700 
2701 
2702         if(b_needcopy){
2703             Log.i("DEBUGGER_TAG", "b_needcopy true");
2704         }
2705         else{
2706             Log.i("DEBUGGER_TAG", "b_needcopy false");
2707         }
2708 
2709 
2710 
2711 
2712     if (b_needcopy){
2713       Log.i("DEBUGGER_TAG", "asset bridge start unpack");
2714       Assetbridge.unpack(this);
2715       Log.i("DEBUGGER_TAG", "asset bridge finish unpack");
2716     }
2717 
2718 
2719 
2720 
2721    /* Turn off multicast filter */
2722    WifiManager wifi = (WifiManager)getSystemService(Context.WIFI_SERVICE);
2723    if (wifi != null){
2724         WifiManager.MulticastLock lock = wifi.createMulticastLock("mylock");
2725         lock.acquire();
2726    }
2727 
2728 
2729             startApp(true);
2730 
2731 
2732 
2733         }
2734     }
2735     //---------------------------------------------------------------------------
2736 
2737 
2738     @Override
onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)2739     public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
2740     {
2741         if (!QtApplication.invokeDelegate(menu, v, menuInfo).invoked)
2742             super.onCreateContextMenu(menu, v, menuInfo);
2743     }
super_onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)2744     public void super_onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)
2745     {
2746         super.onCreateContextMenu(menu, v, menuInfo);
2747     }
2748     //---------------------------------------------------------------------------
2749 
2750     @Override
onCreateDescription()2751     public CharSequence onCreateDescription()
2752     {
2753         QtApplication.InvokeResult res = QtApplication.invokeDelegate();
2754         if (res.invoked)
2755             return (CharSequence)res.methodReturns;
2756         else
2757             return super.onCreateDescription();
2758     }
super_onCreateDescription()2759     public CharSequence super_onCreateDescription()
2760     {
2761         return super.onCreateDescription();
2762     }
2763     //---------------------------------------------------------------------------
2764 
2765     @Override
onCreateDialog(int id)2766     protected Dialog onCreateDialog(int id)
2767     {
2768         QtApplication.InvokeResult res = QtApplication.invokeDelegate(id);
2769         if (res.invoked)
2770             return (Dialog)res.methodReturns;
2771         else
2772             return super.onCreateDialog(id);
2773     }
super_onCreateDialog(int id)2774     public Dialog super_onCreateDialog(int id)
2775     {
2776         return super.onCreateDialog(id);
2777     }
2778     //---------------------------------------------------------------------------
2779 
2780     @Override
onCreateOptionsMenu(Menu menu)2781     public boolean onCreateOptionsMenu(Menu menu)
2782     {
2783         //Log.i("DEBUGGER_TAG", "onCreateOptionsMenu");
2784 
2785 //      We don't use Qt menu system, since it does not support ActionBar.
2786 //      We handle ActionBar here, in standard Android manner
2787 //
2788 //        QtApplication.InvokeResult res = QtApplication.invokeDelegate(menu);
2789 //        if (res.invoked)
2790 //            return (Boolean)res.methodReturns;
2791 //        else
2792 //            return super.onCreateOptionsMenu(menu);
2793 
2794 
2795         MenuInflater inflater = getMenuInflater();
2796         inflater.inflate(R.menu.activity_main_actions, menu);
2797 
2798         itemRouteAnnunciator = menu.findItem(R.id.ocpn_route_create_active);
2799         if( null != itemRouteAnnunciator) {
2800             itemRouteAnnunciator.setVisible(m_showRouteAnnunciator);
2801         }
2802 
2803          itemRouteMenuItem = menu.findItem(R.id.ocpn_action_createroute);
2804          if( null != itemRouteMenuItem) {
2805              itemRouteMenuItem.setVisible(!m_showRouteAnnunciator);
2806          }
2807 
2808 
2809         // Auto follow icon
2810          itemFollowActive = menu.findItem(R.id.ocpn_action_follow_active);
2811          if( null != itemFollowActive) {
2812              itemFollowActive.setVisible(m_isFollowActive);
2813 
2814           }
2815          itemFollowInActive = menu.findItem(R.id.ocpn_action_follow);
2816          if( null != itemFollowInActive) {
2817               itemFollowInActive.setVisible(!m_isFollowActive);
2818            }
2819 
2820          // Track icon
2821          itemTrackActive = menu.findItem(R.id.ocpn_action_track_toggle_ison);
2822          if( null != itemTrackActive) {
2823              itemTrackActive.setVisible(m_isTrackActive);
2824          }
2825          itemTrackInActive = menu.findItem(R.id.ocpn_action_track_toggle_isoff);
2826          if( null != itemTrackInActive) {
2827              itemTrackInActive.setVisible(!m_isTrackActive);
2828          }
2829 
2830 
2831 
2832         return super.onCreateOptionsMenu(menu);
2833 
2834 
2835     }
super_onCreateOptionsMenu(Menu menu)2836     public boolean super_onCreateOptionsMenu(Menu menu)
2837     {
2838         return super.onCreateOptionsMenu(menu);
2839     }
2840     //---------------------------------------------------------------------------
2841 
2842     @Override
onCreatePanelMenu(int featureId, Menu menu)2843     public boolean onCreatePanelMenu(int featureId, Menu menu)
2844     {
2845         QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, menu);
2846         if (res.invoked)
2847             return (Boolean)res.methodReturns;
2848         else
2849             return super.onCreatePanelMenu(featureId, menu);
2850     }
super_onCreatePanelMenu(int featureId, Menu menu)2851     public boolean super_onCreatePanelMenu(int featureId, Menu menu)
2852     {
2853         return super.onCreatePanelMenu(featureId, menu);
2854     }
2855     //---------------------------------------------------------------------------
2856 
2857 
2858     @Override
onCreatePanelView(int featureId)2859     public View onCreatePanelView(int featureId)
2860     {
2861         QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId);
2862         if (res.invoked)
2863             return (View)res.methodReturns;
2864         else
2865             return super.onCreatePanelView(featureId);
2866     }
super_onCreatePanelView(int featureId)2867     public View super_onCreatePanelView(int featureId)
2868     {
2869         return super.onCreatePanelView(featureId);
2870     }
2871     //---------------------------------------------------------------------------
2872 
2873     @Override
onCreateThumbnail(Bitmap outBitmap, Canvas canvas)2874     public boolean onCreateThumbnail(Bitmap outBitmap, Canvas canvas)
2875     {
2876         QtApplication.InvokeResult res = QtApplication.invokeDelegate(outBitmap, canvas);
2877         if (res.invoked)
2878             return (Boolean)res.methodReturns;
2879         else
2880             return super.onCreateThumbnail(outBitmap, canvas);
2881     }
super_onCreateThumbnail(Bitmap outBitmap, Canvas canvas)2882     public boolean super_onCreateThumbnail(Bitmap outBitmap, Canvas canvas)
2883     {
2884         return super.onCreateThumbnail(outBitmap, canvas);
2885     }
2886     //---------------------------------------------------------------------------
2887 
2888     @Override
onCreateView(String name, Context context, AttributeSet attrs)2889     public View onCreateView(String name, Context context, AttributeSet attrs)
2890     {
2891 //        Toast.makeText(getApplicationContext(), "onCreateView " + name,Toast.LENGTH_LONG).show();
2892 
2893         QtApplication.InvokeResult res = QtApplication.invokeDelegate(name, context, attrs);
2894         if (res.invoked)
2895             return (View)res.methodReturns;
2896         else
2897             return super.onCreateView(name, context, attrs);
2898     }
super_onCreateView(String name, Context context, AttributeSet attrs)2899     public View super_onCreateView(String name, Context context, AttributeSet attrs)
2900     {
2901         return super.onCreateView(name, context, attrs);
2902     }
2903     //---------------------------------------------------------------------------
2904 
2905     @Override
onDestroy()2906     protected void onDestroy()
2907     {
2908         //Toast.makeText(getApplicationContext(), "onDestroy",Toast.LENGTH_LONG).show();
2909 
2910         super.onDestroy();
2911         if(null != mChecker)
2912             mChecker.onDestroy();
2913 
2914         QtApplication.invokeDelegate();
2915     }
2916     //---------------------------------------------------------------------------
2917 
2918 
2919     @Override
onKeyDown(int keyCode, KeyEvent event)2920     public boolean onKeyDown(int keyCode, KeyEvent event)
2921     {
2922 
2923         audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
2924         audioManager.playSoundEffect(AudioManager.FX_KEY_CLICK);
2925 
2926 
2927         if(keyCode==KeyEvent.KEYCODE_BACK){
2928             //Toast.makeText(getApplicationContext(), "back press",Toast.LENGTH_LONG).show();
2929             if(!m_backButtonEnable)
2930                 return false;
2931         }
2932 
2933 /*
2934         if (keyCode == KeyEvent.KEYCODE_MENU) {
2935             //Log.i("DEBUGGER_TAG", "KEYCODE_MENU");
2936 
2937             int i = nativeLib.onMenuKey();
2938 
2939             return true;
2940         }
2941 */
2942 
2943         if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null)
2944             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyDown, keyCode, event);
2945         else
2946             return super.onKeyDown(keyCode, event);
2947     }
super_onKeyDown(int keyCode, KeyEvent event)2948     public boolean super_onKeyDown(int keyCode, KeyEvent event)
2949     {
2950         return super.onKeyDown(keyCode, event);
2951     }
2952     //---------------------------------------------------------------------------
2953 
2954 
2955     @Override
onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)2956     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
2957     {
2958         if (QtApplication.m_delegateObject != null && QtApplication.onKeyMultiple != null)
2959             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyMultiple, keyCode, repeatCount, event);
2960         else
2961             return super.onKeyMultiple(keyCode, repeatCount, event);
2962     }
super_onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)2963     public boolean super_onKeyMultiple(int keyCode, int repeatCount, KeyEvent event)
2964     {
2965         return super.onKeyMultiple(keyCode, repeatCount, event);
2966     }
2967     //---------------------------------------------------------------------------
2968 
2969     @Override
onKeyUp(int keyCode, KeyEvent event)2970     public boolean onKeyUp(int keyCode, KeyEvent event)
2971     {
2972         if (QtApplication.m_delegateObject != null  && QtApplication.onKeyDown != null)
2973             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyUp, keyCode, event);
2974         else
2975             return super.onKeyUp(keyCode, event);
2976     }
super_onKeyUp(int keyCode, KeyEvent event)2977     public boolean super_onKeyUp(int keyCode, KeyEvent event)
2978     {
2979         return super.onKeyUp(keyCode, event);
2980     }
2981     //---------------------------------------------------------------------------
2982 
2983     @Override
onLowMemory()2984     public void onLowMemory()
2985     {
2986         if (!QtApplication.invokeDelegate().invoked)
2987             super.onLowMemory();
2988     }
2989     //---------------------------------------------------------------------------
2990 
2991     @Override
onMenuItemSelected(int featureId, MenuItem item)2992     public boolean onMenuItemSelected(int featureId, MenuItem item)
2993     {
2994         QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, item);
2995         if (res.invoked)
2996             return (Boolean)res.methodReturns;
2997         else
2998             return super.onMenuItemSelected(featureId, item);
2999     }
super_onMenuItemSelected(int featureId, MenuItem item)3000     public boolean super_onMenuItemSelected(int featureId, MenuItem item)
3001     {
3002         return super.onMenuItemSelected(featureId, item);
3003     }
3004     //---------------------------------------------------------------------------
3005 
3006     @Override
onMenuOpened(int featureId, Menu menu)3007     public boolean onMenuOpened(int featureId, Menu menu)
3008     {
3009         QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, menu);
3010         if (res.invoked)
3011             return (Boolean)res.methodReturns;
3012         else
3013             return super.onMenuOpened(featureId, menu);
3014     }
super_onMenuOpened(int featureId, Menu menu)3015     public boolean super_onMenuOpened(int featureId, Menu menu)
3016     {
3017         return super.onMenuOpened(featureId, menu);
3018     }
3019     //---------------------------------------------------------------------------
3020 
3021     @Override
onNewIntent(Intent intent)3022     protected void onNewIntent(Intent intent)
3023     {
3024         if (!QtApplication.invokeDelegate(intent).invoked)
3025             super.onNewIntent(intent);
3026     }
super_onNewIntent(Intent intent)3027     public void super_onNewIntent(Intent intent)
3028     {
3029         super.onNewIntent(intent);
3030     }
3031     //---------------------------------------------------------------------------
3032 
3033     @Override
onOptionsItemSelected(MenuItem item)3034     public boolean onOptionsItemSelected(MenuItem item)
3035     {
3036 //        QtApplication.InvokeResult res = QtApplication.invokeDelegate(item);
3037 //        if (res.invoked)
3038 //            return (Boolean)res.methodReturns;
3039 //        else
3040 //            return super.onOptionsItemSelected(item);
3041 
3042         // Take appropriate action for each action item click
3043         switch (item.getItemId()) {
3044             case R.id.ocpn_action_follow:
3045                 //Log.i("DEBUGGER_TAG", "Invoke OCPN_ACTION_FOLLOW while in-active");
3046                 nativeLib.invokeMenuItem(OCPN_ACTION_FOLLOW);
3047                 return true;
3048 
3049                 case R.id.ocpn_action_follow_active:
3050                     //Log.i("DEBUGGER_TAG", "Invoke OCPN_ACTION_FOLLOW while active");
3051                     nativeLib.invokeMenuItem(OCPN_ACTION_FOLLOW);
3052                     return true;
3053 
3054                 case R.id.ocpn_action_settings_basic:
3055                     nativeLib.invokeMenuItem(OCPN_ACTION_SETTINGS_BASIC);
3056                     return true;
3057 
3058                 case R.id.ocpn_action_routemanager:
3059                     nativeLib.invokeMenuItem(OCPN_ACTION_RMD);
3060                     return true;
3061 
3062                 case R.id.ocpn_action_track_toggle_ison:
3063                     nativeLib.invokeMenuItem(OCPN_ACTION_TRACK_TOGGLE);
3064                     return true;
3065 
3066                 case R.id.ocpn_action_track_toggle_isoff:
3067                     nativeLib.invokeMenuItem(OCPN_ACTION_TRACK_TOGGLE);
3068                     return true;
3069 
3070                 case R.id.ocpn_action_createroute:              // entering Route Create Mode
3071                     nativeLib.invokeMenuItem(OCPN_ACTION_ROUTE);
3072                     return true;
3073 
3074                 case R.id.ocpn_route_create_active:             // exiting Route Create mode
3075                     nativeLib.invokeMenuItem(OCPN_ACTION_ROUTE);
3076                     return true;
3077 
3078                 case R.id.ocpn_action_mob:
3079                     nativeLib.invokeMenuItem(OCPN_ACTION_MOB);
3080                     return true;
3081 
3082                 case R.id.ocpn_action_tides:
3083                     nativeLib.invokeMenuItem(OCPN_ACTION_TIDES_TOGGLE);
3084                     return true;
3085 
3086                 case R.id.ocpn_action_currents:
3087                     nativeLib.invokeMenuItem(OCPN_ACTION_CURRENTS_TOGGLE);
3088                     return true;
3089 
3090                 case R.id.ocpn_action_encText:
3091                     nativeLib.invokeMenuItem(OCPN_ACTION_ENCTEXT_TOGGLE);
3092                     return true;
3093 
3094                 case R.id.ocpn_action_googlemaps:
3095                         invokeGoogleMaps();
3096                         return true;
3097 
3098                 case R.id.ocpn_action_toggle_fullscreen:
3099                         toggleFullscreen();
3100                         return true;
3101 
3102             default:
3103                 return super.onOptionsItemSelected(item);
3104             }
3105 
3106     }
super_onOptionsItemSelected(MenuItem item)3107     public boolean super_onOptionsItemSelected(MenuItem item)
3108     {
3109         return super.onOptionsItemSelected(item);
3110     }
3111     //---------------------------------------------------------------------------
3112 
3113     @Override
onOptionsMenuClosed(Menu menu)3114     public void onOptionsMenuClosed(Menu menu)
3115     {
3116         if (!QtApplication.invokeDelegate(menu).invoked)
3117             super.onOptionsMenuClosed(menu);
3118     }
super_onOptionsMenuClosed(Menu menu)3119     public void super_onOptionsMenuClosed(Menu menu)
3120     {
3121         super.onOptionsMenuClosed(menu);
3122     }
3123     //---------------------------------------------------------------------------
3124 
3125     @Override
onPanelClosed(int featureId, Menu menu)3126     public void onPanelClosed(int featureId, Menu menu)
3127     {
3128         if (!QtApplication.invokeDelegate(featureId, menu).invoked)
3129             super.onPanelClosed(featureId, menu);
3130     }
super_onPanelClosed(int featureId, Menu menu)3131     public void super_onPanelClosed(int featureId, Menu menu)
3132     {
3133         super.onPanelClosed(featureId, menu);
3134     }
3135     //---------------------------------------------------------------------------
3136 
3137     @Override
onPause()3138     protected void onPause()
3139     {
3140         //Log.i("DEBUGGER_TAG", "onPause");
3141 
3142         int i = nativeLib.onPause();
3143         String aa;
3144         aa = String.format("%d", i);
3145         //Log.i("DEBUGGER_TAG", aa);
3146 
3147         super.onPause();
3148         QtApplication.invokeDelegate();
3149     }
3150     //---------------------------------------------------------------------------
3151 
3152     @Override
onPostCreate(Bundle savedInstanceState)3153     protected void onPostCreate(Bundle savedInstanceState)
3154     {
3155         super.onPostCreate(savedInstanceState);
3156         QtApplication.invokeDelegate(savedInstanceState);
3157     }
3158     //---------------------------------------------------------------------------
3159 
3160     @Override
onPostResume()3161     protected void onPostResume()
3162     {
3163         super.onPostResume();
3164         QtApplication.invokeDelegate();
3165     }
3166     //---------------------------------------------------------------------------
3167 
3168     @Override
onPrepareDialog(int id, Dialog dialog)3169     protected void onPrepareDialog(int id, Dialog dialog)
3170     {
3171         if (!QtApplication.invokeDelegate(id, dialog).invoked)
3172             super.onPrepareDialog(id, dialog);
3173     }
super_onPrepareDialog(int id, Dialog dialog)3174     public void super_onPrepareDialog(int id, Dialog dialog)
3175     {
3176         super.onPrepareDialog(id, dialog);
3177     }
3178     //---------------------------------------------------------------------------
3179 
3180     @Override
onPrepareOptionsMenu(Menu menu)3181     public boolean onPrepareOptionsMenu(Menu menu)
3182     {
3183         //Log.i("DEBUGGER_TAG", "onPrepareOptionsMenu");
3184 
3185 
3186 // Use native instead og Qt
3187 //        QtApplication.InvokeResult res = QtApplication.invokeDelegate(menu);
3188 //        if (res.invoked)
3189 //            return (Boolean)res.methodReturns;
3190 //        else
3191 //            return super.onPrepareOptionsMenu(menu);
3192         ActionBar actionBar = getActionBar();
3193         if(actionBar != null){
3194             // set the icon
3195             //actionBar.setIcon(R.drawable.opencpn_mobile);
3196             actionBar.setLogo(R.drawable.opencpn_mobile);
3197             actionBar.setDisplayUseLogoEnabled(true);
3198 
3199             //  Use transparent ActionBar background?
3200             //getWindow().requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY);//or add in style.xml
3201             //ColorDrawable newColor = new ColorDrawable(getResources().getColor(R.color.action_bar_color));//your color from res
3202             //newColor.setAlpha(0);//from 0(0%) to 256(100%)
3203             //getActionBar().setBackgroundDrawable(newColor);
3204 
3205             actionBar.show();
3206         }
3207 
3208 
3209         return super.onPrepareOptionsMenu(menu);
3210     }
super_onPrepareOptionsMenu(Menu menu)3211     public boolean super_onPrepareOptionsMenu(Menu menu)
3212     {
3213         return super.onPrepareOptionsMenu(menu);
3214     }
3215     //---------------------------------------------------------------------------
3216 
3217     @Override
onPreparePanel(int featureId, View view, Menu menu)3218     public boolean onPreparePanel(int featureId, View view, Menu menu)
3219     {
3220         QtApplication.InvokeResult res = QtApplication.invokeDelegate(featureId, view, menu);
3221         if (res.invoked)
3222             return (Boolean)res.methodReturns;
3223         else
3224             return super.onPreparePanel(featureId, view, menu);
3225     }
super_onPreparePanel(int featureId, View view, Menu menu)3226     public boolean super_onPreparePanel(int featureId, View view, Menu menu)
3227     {
3228         return super.onPreparePanel(featureId, view, menu);
3229     }
3230     //---------------------------------------------------------------------------
3231 
3232     @Override
onRestart()3233     protected void onRestart()
3234     {
3235         //Log.i("DEBUGGER_TAG", "onRestart");
3236         super.onRestart();
3237         QtApplication.invokeDelegate();
3238     }
3239     //---------------------------------------------------------------------------
3240 
3241     @Override
onRestoreInstanceState(Bundle savedInstanceState)3242     protected void onRestoreInstanceState(Bundle savedInstanceState)
3243     {
3244         if (!QtApplication.invokeDelegate(savedInstanceState).invoked)
3245             super.onRestoreInstanceState(savedInstanceState);
3246     }
super_onRestoreInstanceState(Bundle savedInstanceState)3247     public void super_onRestoreInstanceState(Bundle savedInstanceState)
3248     {
3249         super.onRestoreInstanceState(savedInstanceState);
3250     }
3251     //---------------------------------------------------------------------------
3252 
3253     @Override
onResume()3254     protected void onResume()
3255     {
3256         //Log.i("DEBUGGER_TAG", "onResume");
3257 
3258         if(null != nativeLib)
3259             nativeLib.onResume();
3260 
3261         super.onResume();
3262         QtApplication.invokeDelegate();
3263     }
3264     //---------------------------------------------------------------------------
3265 
3266     @Override
onRetainNonConfigurationInstance()3267     public Object onRetainNonConfigurationInstance()
3268     {
3269         QtApplication.InvokeResult res = QtApplication.invokeDelegate();
3270         if (res.invoked)
3271             return res.methodReturns;
3272         else
3273             return super.onRetainNonConfigurationInstance();
3274     }
super_onRetainNonConfigurationInstance()3275     public Object super_onRetainNonConfigurationInstance()
3276     {
3277         return super.onRetainNonConfigurationInstance();
3278     }
3279     //---------------------------------------------------------------------------
3280 
3281     @Override
onSaveInstanceState(Bundle outState)3282     protected void onSaveInstanceState(Bundle outState)
3283     {
3284         if (!QtApplication.invokeDelegate(outState).invoked)
3285             super.onSaveInstanceState(outState);
3286     }
super_onSaveInstanceState(Bundle outState)3287     public void super_onSaveInstanceState(Bundle outState)
3288     {
3289         super.onSaveInstanceState(outState);
3290 
3291     }
3292     //---------------------------------------------------------------------------
3293 
3294     @Override
onSearchRequested()3295     public boolean onSearchRequested()
3296     {
3297         QtApplication.InvokeResult res = QtApplication.invokeDelegate();
3298         if (res.invoked)
3299             return (Boolean)res.methodReturns;
3300         else
3301             return super.onSearchRequested();
3302     }
super_onSearchRequested()3303     public boolean super_onSearchRequested()
3304     {
3305         return super.onSearchRequested();
3306     }
3307     //---------------------------------------------------------------------------
3308 
3309     @Override
onStart()3310     protected void onStart()
3311     {
3312         Log.i("DEBUGGER_TAG", "onStart");
3313 
3314 //        int i = nativeLib.onStart();
3315 //        String aa;
3316 //        aa = String.format("%d", i);
3317 //        Log.i("DEBUGGER_TAG", aa);
3318 
3319         super.onStart();
3320         QtApplication.invokeDelegate();
3321     }
3322     //---------------------------------------------------------------------------
3323 
3324     @Override
onStop()3325     protected void onStop()
3326     {
3327         //Log.i("DEBUGGER_TAG", "onStop");
3328 
3329         int i = nativeLib.onStop();
3330         String aa;
3331         aa = String.format("%d", i);
3332         //Log.i("DEBUGGER_TAG", aa);
3333 
3334         super.onStop();
3335         QtApplication.invokeDelegate();
3336     }
3337     //---------------------------------------------------------------------------
3338 
3339     @Override
onTitleChanged(CharSequence title, int color)3340     protected void onTitleChanged(CharSequence title, int color)
3341     {
3342         if (!QtApplication.invokeDelegate(title, color).invoked)
3343             super.onTitleChanged(title, color);
3344     }
super_onTitleChanged(CharSequence title, int color)3345     public void super_onTitleChanged(CharSequence title, int color)
3346     {
3347         super.onTitleChanged(title, color);
3348     }
3349     //---------------------------------------------------------------------------
3350 
3351     @Override
onTouchEvent(MotionEvent event)3352     public boolean onTouchEvent(MotionEvent event)
3353     {
3354         if (QtApplication.m_delegateObject != null  && QtApplication.onTouchEvent != null)
3355             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onTouchEvent, event);
3356         else
3357             return super.onTouchEvent(event);
3358     }
super_onTouchEvent(MotionEvent event)3359     public boolean super_onTouchEvent(MotionEvent event)
3360     {
3361         return super.onTouchEvent(event);
3362     }
3363     //---------------------------------------------------------------------------
3364 
3365     @Override
onTrackballEvent(MotionEvent event)3366     public boolean onTrackballEvent(MotionEvent event)
3367     {
3368         if (QtApplication.m_delegateObject != null  && QtApplication.onTrackballEvent != null)
3369             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onTrackballEvent, event);
3370         else
3371             return super.onTrackballEvent(event);
3372     }
super_onTrackballEvent(MotionEvent event)3373     public boolean super_onTrackballEvent(MotionEvent event)
3374     {
3375         return super.onTrackballEvent(event);
3376     }
3377     //---------------------------------------------------------------------------
3378 
3379     @Override
onUserInteraction()3380     public void onUserInteraction()
3381     {
3382         if (!QtApplication.invokeDelegate().invoked)
3383             super.onUserInteraction();
3384     }
super_onUserInteraction()3385     public void super_onUserInteraction()
3386     {
3387         super.onUserInteraction();
3388     }
3389     //---------------------------------------------------------------------------
3390 
3391     @Override
onUserLeaveHint()3392     protected void onUserLeaveHint()
3393     {
3394         if (!QtApplication.invokeDelegate().invoked)
3395             super.onUserLeaveHint();
3396     }
super_onUserLeaveHint()3397     public void super_onUserLeaveHint()
3398     {
3399         super.onUserLeaveHint();
3400     }
3401     //---------------------------------------------------------------------------
3402 
3403     @Override
onWindowAttributesChanged(LayoutParams params)3404     public void onWindowAttributesChanged(LayoutParams params)
3405     {
3406         if (!QtApplication.invokeDelegate(params).invoked)
3407             super.onWindowAttributesChanged(params);
3408     }
super_onWindowAttributesChanged(LayoutParams params)3409     public void super_onWindowAttributesChanged(LayoutParams params)
3410     {
3411         super.onWindowAttributesChanged(params);
3412     }
3413     //---------------------------------------------------------------------------
3414 
3415     @Override
onWindowFocusChanged(boolean hasFocus)3416     public void onWindowFocusChanged(boolean hasFocus)
3417     {
3418         if (!QtApplication.invokeDelegate(hasFocus).invoked)
3419             super.onWindowFocusChanged(hasFocus);
3420 
3421         if (hasFocus) {
3422             if(m_fullScreen){
3423 /*
3424                  getWindow ().getDecorView().setSystemUiVisibility(
3425                          View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3426                          | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
3427                          | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
3428                          | View.SYSTEM_UI_FLAG_FULLSCREEN
3429                          | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
3430 */
3431                 int flags =  View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3432                 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
3433                 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
3434                 | View.SYSTEM_UI_FLAG_FULLSCREEN
3435                 | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
3436 
3437 
3438 //                if(!m_showAction){
3439 //                    flags |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
3440 //                }
3441 
3442                 getWindow ().getDecorView().setSystemUiVisibility( flags );
3443 
3444 
3445 
3446 
3447                      }
3448  //           else{
3449  //               getWindow ().getDecorView().setSystemUiVisibility(0);
3450  //           }
3451         }
3452 
3453     }
super_onWindowFocusChanged(boolean hasFocus)3454     public void super_onWindowFocusChanged(boolean hasFocus)
3455     {
3456         super.onWindowFocusChanged(hasFocus);
3457     }
3458     //---------------------------------------------------------------------------
3459 
3460     //////////////// Activity API 5 /////////////
3461 //ANDROID-5
3462     @Override
onAttachedToWindow()3463     public void onAttachedToWindow()
3464     {
3465         if (!QtApplication.invokeDelegate().invoked)
3466             super.onAttachedToWindow();
3467     }
super_onAttachedToWindow()3468     public void super_onAttachedToWindow()
3469     {
3470         super.onAttachedToWindow();
3471     }
3472     //---------------------------------------------------------------------------
3473 
3474     @Override
onBackPressed()3475     public void onBackPressed()
3476     {
3477 
3478         if (!QtApplication.invokeDelegate().invoked)
3479             super.onBackPressed();
3480     }
super_onBackPressed()3481     public void super_onBackPressed()
3482     {
3483         super.onBackPressed();
3484     }
3485     //---------------------------------------------------------------------------
3486 
3487     @Override
onDetachedFromWindow()3488     public void onDetachedFromWindow()
3489     {
3490         if (!QtApplication.invokeDelegate().invoked)
3491             super.onDetachedFromWindow();
3492     }
super_onDetachedFromWindow()3493     public void super_onDetachedFromWindow()
3494     {
3495         super.onDetachedFromWindow();
3496     }
3497     //---------------------------------------------------------------------------
3498 
3499     @Override
onKeyLongPress(int keyCode, KeyEvent event)3500     public boolean onKeyLongPress(int keyCode, KeyEvent event)
3501     {
3502         if (QtApplication.m_delegateObject != null  && QtApplication.onKeyLongPress != null)
3503             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyLongPress, keyCode, event);
3504         else
3505             return super.onKeyLongPress(keyCode, event);
3506     }
super_onKeyLongPress(int keyCode, KeyEvent event)3507     public boolean super_onKeyLongPress(int keyCode, KeyEvent event)
3508     {
3509         return super.onKeyLongPress(keyCode, event);
3510     }
3511     //---------------------------------------------------------------------------
3512 //ANDROID-5
3513 
3514 //////////////// Activity API 8 /////////////
3515 //ANDROID-8
3516 @Override
onCreateDialog(int id, Bundle args)3517     protected Dialog onCreateDialog(int id, Bundle args)
3518     {
3519         QtApplication.InvokeResult res = QtApplication.invokeDelegate(id, args);
3520         if (res.invoked)
3521             return (Dialog)res.methodReturns;
3522         else
3523             return super.onCreateDialog(id, args);
3524     }
super_onCreateDialog(int id, Bundle args)3525     public Dialog super_onCreateDialog(int id, Bundle args)
3526     {
3527         return super.onCreateDialog(id, args);
3528     }
3529     //---------------------------------------------------------------------------
3530 
3531     @Override
onPrepareDialog(int id, Dialog dialog, Bundle args)3532     protected void onPrepareDialog(int id, Dialog dialog, Bundle args)
3533     {
3534         if (!QtApplication.invokeDelegate(id, dialog, args).invoked)
3535             super.onPrepareDialog(id, dialog, args);
3536     }
super_onPrepareDialog(int id, Dialog dialog, Bundle args)3537     public void super_onPrepareDialog(int id, Dialog dialog, Bundle args)
3538     {
3539         super.onPrepareDialog(id, dialog, args);
3540     }
3541     //---------------------------------------------------------------------------
3542 //ANDROID-8
3543     //////////////// Activity API 11 /////////////
3544 
3545 //ANDROID-11
3546     @Override
dispatchKeyShortcutEvent(KeyEvent event)3547     public boolean dispatchKeyShortcutEvent(KeyEvent event)
3548     {
3549         if (QtApplication.m_delegateObject != null  && QtApplication.dispatchKeyShortcutEvent != null)
3550             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchKeyShortcutEvent, event);
3551         else
3552             return super.dispatchKeyShortcutEvent(event);
3553     }
super_dispatchKeyShortcutEvent(KeyEvent event)3554     public boolean super_dispatchKeyShortcutEvent(KeyEvent event)
3555     {
3556         return super.dispatchKeyShortcutEvent(event);
3557     }
3558     //---------------------------------------------------------------------------
3559 
3560     @Override
onActionModeFinished(ActionMode mode)3561     public void onActionModeFinished(ActionMode mode)
3562     {
3563         if (!QtApplication.invokeDelegate(mode).invoked)
3564             super.onActionModeFinished(mode);
3565     }
super_onActionModeFinished(ActionMode mode)3566     public void super_onActionModeFinished(ActionMode mode)
3567     {
3568         super.onActionModeFinished(mode);
3569     }
3570     //---------------------------------------------------------------------------
3571 
3572     @Override
onActionModeStarted(ActionMode mode)3573     public void onActionModeStarted(ActionMode mode)
3574     {
3575         if (!QtApplication.invokeDelegate(mode).invoked)
3576             super.onActionModeStarted(mode);
3577     }
super_onActionModeStarted(ActionMode mode)3578     public void super_onActionModeStarted(ActionMode mode)
3579     {
3580         super.onActionModeStarted(mode);
3581     }
3582     //---------------------------------------------------------------------------
3583 
3584     @Override
onAttachFragment(Fragment fragment)3585     public void onAttachFragment(Fragment fragment)
3586     {
3587         if (!QtApplication.invokeDelegate(fragment).invoked)
3588             super.onAttachFragment(fragment);
3589     }
super_onAttachFragment(Fragment fragment)3590     public void super_onAttachFragment(Fragment fragment)
3591     {
3592         super.onAttachFragment(fragment);
3593     }
3594     //---------------------------------------------------------------------------
3595 
3596     @Override
onCreateView(View parent, String name, Context context, AttributeSet attrs)3597     public View onCreateView(View parent, String name, Context context, AttributeSet attrs)
3598     {
3599         QtApplication.InvokeResult res = QtApplication.invokeDelegate(parent, name, context, attrs);
3600         if (res.invoked)
3601             return (View)res.methodReturns;
3602         else
3603             return super.onCreateView(parent, name, context, attrs);
3604     }
super_onCreateView(View parent, String name, Context context, AttributeSet attrs)3605     public View super_onCreateView(View parent, String name, Context context,
3606             AttributeSet attrs) {
3607         return super.onCreateView(parent, name, context, attrs);
3608     }
3609     //---------------------------------------------------------------------------
3610 
3611     @Override
onKeyShortcut(int keyCode, KeyEvent event)3612     public boolean onKeyShortcut(int keyCode, KeyEvent event)
3613     {
3614         if (QtApplication.m_delegateObject != null  && QtApplication.onKeyShortcut != null)
3615             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onKeyShortcut, keyCode,event);
3616         else
3617             return super.onKeyShortcut(keyCode, event);
3618     }
super_onKeyShortcut(int keyCode, KeyEvent event)3619     public boolean super_onKeyShortcut(int keyCode, KeyEvent event)
3620     {
3621         return super.onKeyShortcut(keyCode, event);
3622     }
3623     //---------------------------------------------------------------------------
3624 
3625     @Override
onWindowStartingActionMode(Callback callback)3626     public ActionMode onWindowStartingActionMode(Callback callback)
3627     {
3628         QtApplication.InvokeResult res = QtApplication.invokeDelegate(callback);
3629         if (res.invoked)
3630             return (ActionMode)res.methodReturns;
3631         else
3632             return super.onWindowStartingActionMode(callback);
3633     }
super_onWindowStartingActionMode(Callback callback)3634     public ActionMode super_onWindowStartingActionMode(Callback callback)
3635     {
3636         return super.onWindowStartingActionMode(callback);
3637     }
3638     //---------------------------------------------------------------------------
3639 //ANDROID-11
3640     //////////////// Activity API 12 /////////////
3641 
3642 //ANDROID-12
3643     @Override
dispatchGenericMotionEvent(MotionEvent ev)3644     public boolean dispatchGenericMotionEvent(MotionEvent ev)
3645     {
3646         //Toast.makeText(getApplicationContext(), "dispatchGenericMotionEvent",Toast.LENGTH_LONG).show();
3647 
3648         if (QtApplication.m_delegateObject != null  && QtApplication.dispatchGenericMotionEvent != null)
3649             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.dispatchGenericMotionEvent, ev);
3650         else
3651             return super.dispatchGenericMotionEvent(ev);
3652     }
super_dispatchGenericMotionEvent(MotionEvent event)3653     public boolean super_dispatchGenericMotionEvent(MotionEvent event)
3654     {
3655         return super.dispatchGenericMotionEvent(event);
3656     }
3657     //---------------------------------------------------------------------------
3658 
3659     @Override
onGenericMotionEvent(MotionEvent event)3660     public boolean onGenericMotionEvent(MotionEvent event)
3661     {
3662 //        Log.i("DEBUGGER_TAG", "onGenericMotionEvent");
3663 //        Toast.makeText(getApplicationContext(), "onGenericMotionEvent",Toast.LENGTH_LONG).show();
3664 
3665         if (0 != (event.getSource() & InputDevice.SOURCE_CLASS_POINTER)) {
3666             switch (event.getAction()) {
3667               case MotionEvent.ACTION_SCROLL:
3668               if (event.getAxisValue(MotionEvent.AXIS_VSCROLL) < 0.0f){
3669                   Log.i("DEBUGGER_TAG", "Scroll Up");
3670                   nativeLib.onMouseWheel(-1);
3671               }
3672               else{
3673                   Log.i("DEBUGGER_TAG", "Scroll Down");
3674                   nativeLib.onMouseWheel(1);
3675               }
3676             }
3677           }
3678 
3679         if (QtApplication.m_delegateObject != null  && QtApplication.onGenericMotionEvent != null)
3680             return (Boolean) QtApplication.invokeDelegateMethod(QtApplication.onGenericMotionEvent, event);
3681         else
3682             return super.onGenericMotionEvent(event);
3683     }
super_onGenericMotionEvent(MotionEvent event)3684     public boolean super_onGenericMotionEvent(MotionEvent event)
3685     {
3686         return super.onGenericMotionEvent(event);
3687     }
3688     //---------------------------------------------------------------------------
3689 //ANDROID-12
3690 
3691 
3692 
3693 
3694 }
3695