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