@Override protected void onResume() { super.onResume(); if (ProxySettings.checkSystemProxyProperties()) { ProxySettings.shouldSetProxySetting = true; } // Save the context for further access AndroidServiceLocator.setContext(this, activityManager); if (extras != null) { NotificationManager nMngr = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); nMngr.cancelAll(); // nMngr.cancel(Integer.parseInt(id)); } LOG.Log(Module.GUI, "onResume"); /* * // security reasons if(splashShownOnBackground) { * activityManager.dismissSplashScreen(); splashShownOnBackground = * false; } */ if (!performSecurityChecks((AndroidServiceLocator) AndroidServiceLocator.GetInstance())) return; LOG.Log(Module.GUI, "Security checks passed... beaking up Appverse..."); ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()) .sendApplicationEvent(AndroidApplicationEvent.onResume); // Start HTTP server startServer(); this.activityManager.loadUrlIntoWebView("javascript:try{Appverse._toForeground()}catch(e){}"); // TESTING getExtras(); if (this.getIntent() != null) { LOG.Log(Module.GUI, "Processing intent data and extras... "); this.lastIntentExtras = this.getIntent().getExtras(); Bundle nullExtras = null; this.getIntent().replaceExtras(nullExtras); this.lastIntentData = this.getIntent().getData(); Uri nullData = null; this.getIntent().setData(nullData); } }
@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); AndroidSystem system = (AndroidSystem) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_TYPE_SYSTEM); boolean locked = system.IsOrientationLocked(); if (locked) { int configOrientation; DisplayOrientation lockedOrientation = system.GetLockedOrientation(); if (DisplayOrientation.Portrait.equals(lockedOrientation)) { configOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; } else if (DisplayOrientation.Landscape.equals(lockedOrientation)) { configOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } else { // Portrait as default orientation configOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; } if (newConfig.orientation != configOrientation) { LOG.Log( Module.GUI, "Main Activity onConfigurationChanged setting requested orientation: " + configOrientation); setRequestedOrientation(configOrientation); } } else { activityManager.layoutSplashscreen(); appView.requestLayout(); } }
private void startServer() { if (server == null) { AssetManager am = (AssetManager) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_ANDROID_ASSET_MANAGER); if (serverProperties == null) { serverProperties = new Properties(); try { serverProperties.load(am.open(SERVER_PROPERTIES)); } catch (IOException ex) { LOG.Log(Module.GUI, ex.toString()); } } LOG.Log( Module.GUI, "The Port is: " + serverProperties.getProperty(SERVER_PORT_PROPERTY, "Missing")); try { serverPort = Integer.parseInt(serverProperties.getProperty(SERVER_PORT_PROPERTY)); server = new HttpServer(serverPort, this, this.appView); server.start(); } catch (Exception ex) { LOG.Log(Module.GUI, ex.toString()); } LOG.Log(Module.GUI, "Server started."); } }
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { AndroidActivityManager aam = (AndroidActivityManager) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_ANDROID_ACTIVITY_MANAGER); if (aam != null) { aam.publishActivityResult(requestCode, resultCode, data); } }
@Override protected void onStop() { LOG.Log(Module.GUI, "onStop"); ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()) .sendApplicationEvent(AndroidApplicationEvent.onStop); // Stop HTTP server stopServer(); super.onStop(); }
@Override protected void onPause() { LOG.Log(Module.GUI, "onPause"); ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()) .sendApplicationEvent(AndroidApplicationEvent.onPause); // Stop HTTP server, and send to background later stopServer(true); super.onPause(); }
protected void RegisterResultReceiver(int[] resultCodes, ResultReceiver resultReceiver) { try { ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()) .RegisterResultReceiver(resultCodes, resultReceiver); } catch (Exception ex) { LOG.LogDebug( Module.GUI, "************* Exception registering result receiver, exception message: " + ex.getMessage()); } }
protected void RegisterService(Object service, String key) { try { LOG.LogDebug(Module.GUI, "************* REGISTERING SERVICE: " + key); ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()).RegisterService(service, key); } catch (Exception ex) { LOG.LogDebug( Module.GUI, "************* Exception registering service [" + key + "], exception message: " + ex.getMessage()); } }
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // this method is invoked with an CANCELED result code if the activity is a "singleInstance" // (launchMode) // that is the reason that we removed that launch mode for the AndroidManifest (see SVN logs) LOG.LogDebug( Module.GUI, "******** onActivityResult # requestCode " + requestCode + ", resultCode: " + resultCode); AndroidActivityManager aam = (AndroidActivityManager) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_ANDROID_ACTIVITY_MANAGER); boolean handleResult = false; if (aam != null) { handleResult = aam.publishActivityResult(requestCode, resultCode, data); } if (!handleResult) { ResultReceiver resultReceiver = ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()) .getResultReceiver(requestCode); if (resultReceiver != null) { LOG.LogDebug( Module.GUI, "******** Calling ResultReceiver send (probably from a module)..."); Bundle bundle = (data == null ? new Bundle() : data.getExtras()); bundle.putInt(IAppDelegate.ACTIVITY_RESULT_CODE_BUNDLE_KEY, resultCode); resultReceiver.send(requestCode, bundle); } else { LOG.LogDebug(Module.GUI, "******** Calling super.onActivityResult()"); super.onActivityResult(requestCode, resultCode, data); } } }
@Override protected void onDestroy() { LOG.Log(Module.GUI, "onDestroy"); ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()) .sendApplicationEvent(AndroidApplicationEvent.onDestroy); // Stop HTTP server stopServer(); super.onDestroy(); LOG.Log(Module.GUI, "killing process..."); android.os.Process.killProcess(android.os.Process.myPid()); }
@Override public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults) { // this method is invoked with an CANCELED result code if the activity is a "singleInstance" // (launchMode) // that is the reason that we removed that launch mode for the AndroidManifest (see SVN logs) LOG.LogDebug( Module.GUI, "******** onActivityResult # requestCode " + requestCode + ", grantResults: " + grantResults); AndroidActivityManager aam = (AndroidActivityManager) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_ANDROID_ACTIVITY_MANAGER); boolean handleResult = false; if (aam != null) { handleResult = aam.publishPermissionResult(requestCode, permissions, grantResults); } }
/** Initializes the appverse context exposing data to the WebView Javascript DOM. */ private void InitializeAppverseContext(int networkType) { long startTime = System.currentTimeMillis(); try { LOG.Log( Module.GUI, "Before loading the main HTML, platform will expose some information directly to javascript..."); AndroidSystem systemService = (AndroidSystem) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_TYPE_SYSTEM); AndroidI18N i18nService = (AndroidI18N) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_TYPE_I18N); AndroidIO ioService = (AndroidIO) AndroidServiceLocator.GetInstance().GetService(AndroidServiceLocator.SERVICE_TYPE_IO); IActivityManager am = (IActivityManager) AndroidServiceLocator.GetInstance() .GetService(AndroidServiceLocator.SERVICE_ANDROID_ACTIVITY_MANAGER); // 1. Appverse Context (Appverse.is) UnityContext unityContext = systemService.GetUnityContext(); String unityContextJsonString = JSONSerializer.serialize(unityContext); unityContextJsonString = "_AppverseContext = " + unityContextJsonString; LOG.LogDebug(Module.GUI, "InitializeAppverseContext: " + unityContextJsonString); am.executeJS(unityContextJsonString); // 2. OS Info (Appverse.OSInfo) OSInfo osInfo = systemService.GetOSInfo(); String osInfoJsonString = JSONSerializer.serialize(osInfo); osInfoJsonString = "_OSInfo = " + osInfoJsonString; LOG.LogDebug(Module.GUI, "InitializeAppverseContext: " + osInfoJsonString); am.executeJS(osInfoJsonString); // 3. Hardware Info (Appverse.HardwareInfo) HardwareInfo hwInfo = systemService.GetOSHardwareInfo(); String hwInfoJsonString = JSONSerializer.serialize(hwInfo); hwInfoJsonString = "_HwInfo = " + hwInfoJsonString; LOG.LogDebug(Module.GUI, "InitializeAppverseContext: " + hwInfoJsonString); am.executeJS(hwInfoJsonString); try { // 4. Get all configured localized keys (Appverse.i18n) Locale[] supportedLocales = i18nService.GetLocaleSupported(); String localizedStrings = "_i18n = {}; _i18n['default'] = '" + i18nService.getDefaultLocale() + "'; "; String localeLiterals = ""; for (Locale supportedLocale : supportedLocales) { ResourceLiteralDictionary literals = i18nService.GetResourceLiterals(supportedLocale); String literalsJsonString = JSONSerializer.serialize(literals); localeLiterals = localeLiterals + " _i18n['" + supportedLocale.toString() + "'] = " + literalsJsonString + "; "; } localizedStrings = localizedStrings + localeLiterals; LOG.LogDebug(Module.GUI, "InitializeAppverseContext: " + localizedStrings); am.executeJS(localizedStrings); } catch (Exception ex) { LOG.LogDebug( Module.GUI, "Unable to load all languages. Exception message: " + ex.getMessage()); } // 5. Current device locale com.gft.unity.core.system.Locale currentLocale = systemService.GetLocaleCurrent(); String currentLocaleJsonString = JSONSerializer.serialize(currentLocale); currentLocaleJsonString = "_CurrentDeviceLocale = " + currentLocaleJsonString; LOG.LogDebug(Module.GUI, "InitializeAppverseContext: " + currentLocaleJsonString); am.executeJS(currentLocaleJsonString); try { // 6. Configured IO services endpoints IOService[] services = ioService.GetServices(); String servicesJsonString = "_IOServices = {}; "; for (IOService service : services) { String serviceJson = JSONSerializer.serialize(service); servicesJsonString = servicesJsonString + " _IOServices['" + service.getName() + "-" + JSONSerializer.serialize(service.getType()) + "'] = " + serviceJson + "; "; } LOG.LogDebug(Module.GUI, "InitializeAppverseContext: " + servicesJsonString); am.executeJS(servicesJsonString); } catch (Exception ex) { LOG.LogDebug( Module.GUI, "Unable to load all services. Exception message: " + ex.getMessage()); } String networkStatusString = "_NetworkStatus = " + networkType + ";"; LOG.LogDebug(Module.GUI, "InitializeAppverseContext: networkType: " + networkType); am.executeJS(networkStatusString); } catch (Exception ex) { LOG.LogDebug( Module.GUI, "Unable to load Appverse Context. Exception message: " + ex.getMessage()); } long timetaken = System.currentTimeMillis() - startTime; LOG.Log(Module.GUI, "# Time elapsed initializing Appverse Context: " + timetaken); }
/** ACTIVITY OVERRIDEN METHODS * */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LOG.Log(Module.GUI, "onCreate"); if (getIntent() != null && getIntent().getExtras() != null) { extras = getIntent().getExtras(); LOG.LogDebug(Module.GUI, "[K] notification Extra:" + extras.getString("item_id")); } // GUI initialization code getWindow().requestFeature(Window.FEATURE_NO_TITLE); getWindow() .setFlags( WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); /*disableThumbnails = checkUnityProperty("Unity_DisableThumbnails"); blockRooted = checkUnityProperty("Appverse_BlockRooted"); blockROMModified = checkUnityProperty("Appverse_BlockROMModified");*/ // security reasons; don't allow screen shots while this window is displayed /* not valid for builds under level 14 */ // TODO DISABLETHUMBNAILS_1 // @@DISABLETHUMBNAILS_1@@ // Initialize Webview component and provide specific settings this.initialiazeWebViewSettings(); // create the application logger LogManager.setDelegate(new AndroidLoggerDelegate()); // initialize the service locator activityManager = initialiazeActivityManager(); // save the context for further access AndroidServiceLocator.setContext(this, activityManager); // killing previous background processes from the same package activityManager.killBackgroundProcesses(); AndroidServiceLocator serviceLocator = (AndroidServiceLocator) AndroidServiceLocator.GetInstance(); serviceLocator.RegisterService( this.getAssets(), AndroidServiceLocator.SERVICE_ANDROID_ASSET_MANAGER); serviceLocator.RegisterService( activityManager, AndroidServiceLocator.SERVICE_ANDROID_ACTIVITY_MANAGER); // registering Appverse modules (if any) this.registerModulesServices(); // initialize config data files for app delegates serviceLocator.initConfigDataForServices(); if (Build.VERSION.SDK_INT >= 17) { // Only used for JELLY_BEAN_MR1 or higher /** * INJECT SCRIPT MESSAGE HANDLER (new in Appverse 5) ** */ /** * From Android documentation: * * <p>This method can be used to allow JavaScript to control the host application. This is a * powerful feature, but also presents a security risk for apps targeting JELLY_BEAN or * earlier. Apps that target a version later than JELLY_BEAN are still vulnerable if the app * runs on a device running Android earlier than 4.2. The most secure way to use this method * is to target JELLY_BEAN_MR1 and to ensure the method is called only when running on Android * 4.2 or later. With these older versions, JavaScript could use reflection to access an * injected object's public fields. Use of this method in a WebView containing untrusted * content could allow an attacker to manipulate the host application in unintended ways, * executing Java code with the permissions of the host application. Use extreme care when * using this method in a WebView which could contain untrusted content. * * <p>JavaScript interacts with Java object on a private, background thread of this WebView. * Care is therefore required to maintain thread safety. The Java object's fields are not * accessible. For applications targeted to API level LOLLIPOP and above, methods of injected * Java objects are enumerable from JavaScript. */ this.addJavascriptIntefaceToWebView(serviceLocator, "appverseJSBridge"); } if (performSecurityChecks(serviceLocator)) { LOG.Log(Module.GUI, "Security checks passed... initializing Appverse..."); startServer(); /* THIS COULD NOT BE CHECKED ON API LEVEL < 11; NO suchmethodexception * boolean hwAccelerated = appView.isHardwareAccelerated(); * if(hwAccelerated) * LOG.Log(Module.GUI,"Application View is HARDWARE ACCELERATED"); else * LOG.Log(Module.GUI,"Application View is NOT hardware accelerated"); */ final IntentFilter actionFilter = new IntentFilter(); actionFilter.addAction(android.net.ConnectivityManager.CONNECTIVITY_ACTION); // actionFilter.addAction("android.intent.action.SERVICE_STATE"); registerReceiver(this.initialiazeNetworkReceiver(), actionFilter); ConnectivityManager conMan = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE); NetworkInfo networkInfo = conMan.getActiveNetworkInfo(); com.gft.unity.core.net.NetworkType type = NetworkType.Unknown; if (networkInfo != null) { boolean isWiFi = networkInfo.getType() == ConnectivityManager.TYPE_WIFI; boolean isMobile = networkInfo.getType() == ConnectivityManager.TYPE_MOBILE; boolean isConnected = networkInfo.isConnected(); if (isWiFi) { if (isConnected) { LOG.Log(Module.GUI, "Wi-Fi - CONNECTED (" + networkInfo.getType() + ")"); type = NetworkType.Wifi; } else { LOG.Log(Module.GUI, "Wi-Fi - DISCONNECTED (" + networkInfo.getType() + ")"); } } else if (isMobile) { if (isConnected) { LOG.Log(Module.GUI, "Mobile - CONNECTED (" + networkInfo.getType() + ")"); type = NetworkType.Carrier_3G; } else { LOG.Log(Module.GUI, "Mobile - DISCONNECTED (" + networkInfo.getType() + ")"); } } else { if (isConnected) { LOG.Log( Module.GUI, networkInfo.getTypeName() + " - CONNECTED (" + networkInfo.getType() + ")"); } else { LOG.Log( Module.GUI, networkInfo.getTypeName() + " - DISCONNECTED (" + networkInfo.getType() + ")"); } } } else { LOG.Log(Module.GUI, "DISCONNECTED"); } final int typeOrdinal = type.ordinal(); final Activity currentContext = this; new Thread( new Runnable() { public void run() { currentContext.runOnUiThread( new Runnable() { public void run() { InitializeAppverseContext(typeOrdinal); String networkStatusListener = "javascript:try{if(Appverse&&Appverse.Net){Appverse.Net.NetworkStatus = " + typeOrdinal + ";Appverse.Net.onConnectivityChange(Appverse.Net.NetworkStatus);}else{console.log('Appverse is not defined');}}catch(e){console.log('Error setting network status (please check onConnectivityChange method): '+e);}"; queueJSStatementsForWebviewClient(networkStatusListener); loadMainURLIntoWebview(); } }); } }) .start(); } holdSplashScreenOnStartup = checkUnityProperty("Unity_HoldSplashScreenOnStartup"); this.showSplashScreen(); LocalNotificationReceiver.initialize(this.activityManager, this); // notify app delegates about the onCreate event ((AndroidServiceLocator) AndroidServiceLocator.GetInstance()) .sendApplicationEvent(AndroidApplicationEvent.onCreate); }
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LOG.Log(Module.GUI, "onCreate"); // GUI initialization code getWindow().requestFeature(Window.FEATURE_NO_TITLE); getWindow() .setFlags( WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN, WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN); disableThumbnails = checkUnityProperty("Unity_DisableThumbnails"); // security reasons; don't allow screen shots while this window is displayed /* not valid for builds under level 14 */ if (disableThumbnails && Build.VERSION.SDK_INT >= 14) { getWindow() .setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE); } appView = new WebView(this); appView.enablePlatformNotifications(); setGlobalProxy(); appView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); appView.setId(APPVIEW_ID); appView.setWebViewClient(new UnityWebViewClient()); appView.getSettings().setJavaScriptEnabled(true); appView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); appView.getSettings().setAllowFileAccess(true); appView.getSettings().setSupportZoom(false); appView.getSettings().setAppCacheEnabled(false); appView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE); appView.getSettings().setAppCacheMaxSize(0); appView.getSettings().setSavePassword(false); appView.getSettings().setSaveFormData(false); appView.getSettings().setDefaultTextEncodingName("UTF-8"); appView.getSettings().setGeolocationEnabled(true); appView.getSettings().setLightTouchEnabled(true); appView.getSettings().setRenderPriority(RenderPriority.HIGH); appView.getSettings().setDomStorageEnabled(true); // [MOBPLAT-129] enable HTML5 local storage appView.setVerticalScrollBarEnabled(false); // Required settings to enable HTML5 database storage appView.getSettings().setDatabaseEnabled(true); String databasePath = this.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); appView.getSettings().setDatabasePath(databasePath); webChromeClient = new WebChromeClient() { // Required settings to enable HTML5 database storage @Override public void onExceededDatabaseQuota( String url, String databaseIdentifier, long currentQuota, long estimatedSize, long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) { quotaUpdater.updateQuota(estimatedSize * 2); }; @Override public void onReachedMaxAppCacheSize( long spaceNeeded, long totalUsedQuota, android.webkit.WebStorage.QuotaUpdater quotaUpdater) { quotaUpdater.updateQuota(0); }; @Override public boolean onConsoleMessage(ConsoleMessage cm) { LOG.Log( Module.GUI, cm.message() + " -- From line " + cm.lineNumber() + " of " + cm.sourceId()); return true; } }; appView.setWebChromeClient(webChromeClient); // create the application logger LogManager.setDelegate(new AndroidLoggerDelegate()); // save the context for further access AndroidServiceLocator.setContext(this); // initialize the service locator activityManager = new AndroidActivityManager(this, appView); // killing previous background processes from the same package activityManager.killBackgroundProcesses(); AndroidServiceLocator serviceLocator = (AndroidServiceLocator) AndroidServiceLocator.GetInstance(); serviceLocator.RegisterService( this.getAssets(), AndroidServiceLocator.SERVICE_ANDROID_ASSET_MANAGER); serviceLocator.RegisterService( activityManager, AndroidServiceLocator.SERVICE_ANDROID_ACTIVITY_MANAGER); startServer(); /* THIS COULD NOT BE CHECKED ON API LEVEL < 11; NO suchmethodexception boolean hwAccelerated = appView.isHardwareAccelerated(); if(hwAccelerated) LOG.Log(Module.GUI,"Application View is HARDWARE ACCELERATED"); else LOG.Log(Module.GUI,"Application View is NOT hardware accelerated"); */ final IntentFilter actionFilter = new IntentFilter(); actionFilter.addAction(android.net.ConnectivityManager.CONNECTIVITY_ACTION); // actionFilter.addAction("android.intent.action.SERVICE_STATE"); registerReceiver(new AndroidNetworkReceiver(appView), actionFilter); final Activity currentContext = this; new Thread( new Runnable() { public void run() { currentContext.runOnUiThread( new Runnable() { public void run() { appView.loadUrl(WEBVIEW_MAIN_URL); } }); } }) .start(); holdSplashScreenOnStartup = checkUnityProperty("Unity_HoldSplashScreenOnStartup"); hasSplash = activityManager.showSplashScreen(appView); RemoteNotificationIntentService.loadNotificationOptions(getResources(), appView, this); LocalNotificationReceiver.initialize(appView, this); }