com.aslanoba.hwc.UiHybridAppContainer.java Source code

Java tutorial

Introduction

Here is the source code for com.aslanoba.hwc.UiHybridAppContainer.java

Source

/*
 Copyright (c) Sybase, Inc. 2012 All rights reserved. 
     
 In addition to the license terms set out in the Sybase License Agreement for 
 the Sybase Unwired Platform ("Program"), the following additional or different 
 rights and accompanying obligations and restrictions shall apply to the source 
 code in this file ("Code"). Sybase grants you a limited, non-exclusive, 
 non-transferable, revocable license to use, reproduce, and modify the Code 
 solely for purposes of (i) maintaining the Code as reference material to better 
 understand the operation of the Program, and (ii) development and testing of 
 applications created in connection with your licensed use of the Program. 
 The Code may not be transferred, sold, assigned, sublicensed or otherwise 
 conveyed (whether by operation of law or otherwise) to another party without 
 Sybase's prior written consent. The following provisions shall apply to any 
 modifications you make to the Code: (i) Sybase will not provide any maintenance 
 or support for modified Code or problems that result from use of modified Code; 
 (ii) Sybase expressly disclaims any warranties and conditions, express or 
 implied, relating to modified Code or any problems that result from use of the 
 modified Code; (iii) SYBASE SHALL NOT BE LIABLE FOR ANY LOSS OR DAMAGE RELATING 
 TO MODIFICATIONS MADE TO THE CODE OR FOR ANY DAMAGES RESULTING FROM USE OF THE 
 MODIFIED CODE, INCLUDING, WITHOUT LIMITATION, ANY INACCURACY OF DATA, LOSS OF 
 PROFITS OR DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, EVEN 
 IF SYBASE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES; (iv) you agree 
 to indemnify, hold harmless, and defend Sybase from and against any claims or 
 lawsuits, including attorney's fees, that arise from or are related to the 
 modified Code or from use of the modified Code.
 */
package com.aslanoba.hwc;

import org.apache.cordova.CordovaChromeClient;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaWebViewClient;
import org.apache.cordova.DroidGap;
import org.apache.cordova.api.CordovaInterface;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.webkit.ConsoleMessage;
import android.webkit.ConsoleMessage.MessageLevel;
import android.webkit.GeolocationPermissions;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

import com.google.android.gcm.GCMRegistrar;
import com.sybase.hybridApp.AndroidHybridAppHelper;
import com.sybase.hybridApp.HybridAppDb;
import com.sybase.hybridApp.UiHybridAppController;
import com.sybase.hybridApp.amp.Consts;
import com.sybase.mo.MocaLog;
import com.sybase.mo.MocaLog.eMocaLogLevel;

/**
 * HybridAppContainer is the activity that displays the WebView hosting the
 * hybrid app.
 */
public class UiHybridAppContainer extends DroidGap {

    private static final String LOG_TAG = "HybridAppContainer";

    // Receiver for challenges
    private ChallengeListener m_oChallengeListener = new ChallengeListener(this);

    private UiHybridAppController m_oHybridAppController = null;
    private WebView m_oWebView;
    private String m_sProgressText = "";

    private ViewTreeObserver.OnGlobalLayoutListener m_oLayoutListener;
    private boolean m_bOrientationChanged = false;

    private boolean m_bInitialized = false;

    // Helper to turn PhoneGap integration on/off
    private static final boolean USE_PHONEGAP = true;
    private boolean m_errorLoading = false;

    @Override
    public boolean onPrepareOptionsMenu(Menu oMenu) {
        m_oHybridAppController.onPrepareOptionsMenu(oMenu);

        //SMPONP-12445   Android: Menbar almost covered the whole screen after calling hwc.removeAllMenuItems()
        //If this is no Menu item added, the menu won't be shown. 
        if (oMenu != null && oMenu.size() <= 0) {
            return false;
        }
        return super.onPrepareOptionsMenu(oMenu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem oItem) {
        m_oHybridAppController.onOptionsItemSelected(oItem);

        return super.onOptionsItemSelected(oItem);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.setBooleanProperty("showTitle", true);
        super.onCreate(savedInstanceState);
        GCMRegistrar.checkManifest(this);
        final String regid = GCMRegistrar.getRegistrationId(this);
        Log.i("GCM Started - onCreate", "Check registration :" + regid);
        String SENDER_ID = "741064895497";
        if (regid.equals("")) {
            GCMRegistrar.register(this, SENDER_ID);
        }
    }

    @Override
    public void onResume() {
        super.onResume();

        GCMRegistrar.checkManifest(this);
        final String regid = GCMRegistrar.getRegistrationId(this);
        Log.i("GCM Started - onResume", "Check registration :" + regid);
        String SENDER_ID = "741064895497";
        if (regid.equals("")) {
            GCMRegistrar.register(this, SENDER_ID);
        }

        // check to see if we need to redirect to the password entry or
        // change screen
        if (PasswordPolicyMgr.redirect(this))
            return;

        if (!m_bInitialized) {
            try {
                initWebView();
            } finally {
                m_bInitialized = true;
            }
        }

        m_oHybridAppController.onResume();

        // Register challenge listener
        HybridWebApplication.getInstance().setChallengeListener(m_oChallengeListener);
    }

    private void initWebView() {
        Intent oIntent = getIntent();
        m_errorLoading = false;

        // PhoneGap Change: Layout provided by PhoneGap
        if (USE_PHONEGAP) {
            // PhoneGap Change: We must call DroidGap.init right away
            // so that the WebView is created
            CordovaWebView webView = new CordovaWebView(this);
            CordovaWebViewClient webViewClient = new HybridAppCordovaWebViewClient(this);
            CordovaChromeClient chromeClient = new HybridAppCordovaChromeClient(this, webView);
            super.init(webView, webViewClient, chromeClient); // <----- must
                                                              // comment this out
                                                              // if we no longer
                                                              // inherit from
                                                              // PhoneGap
            m_oWebView = this.appView;
        } else {
            setContentView(R.layout.hybridappcontainer);
            m_oWebView = (WebView) findViewById(R.id.webview);
        }

        int iStartMode = oIntent.getIntExtra(Consts.INTENT_PARAM_HYBRIDAPP_START_MODE, Consts.START_MODE_INVALID);

        if (iStartMode == Consts.START_MODE_MESSAGE) {
            int iMessageID = oIntent.getIntExtra(Consts.INTENT_PARAM_HYBRIDAPP_MSG_ID, 0);
            int iModuleID = oIntent.getIntExtra(Consts.INTENT_PARAM_HYBRIDAPP_MODULE_ID, 0);
            int iModuleVersion = oIntent.getIntExtra(Consts.INTENT_PARAM_HYBRIDAPP_MODULE_VERSION, -1);
            m_sProgressText = oIntent.getStringExtra(Consts.INTENT_PARAM_HYBRIDAPP_PROGRESS_TEXT);

            m_oHybridAppController = new UiHybridAppController(this, m_oWebView, iMessageID, iModuleID,
                    iModuleVersion);
        } else if (iStartMode == Consts.START_MODE_HYBRIDAPP) {
            int iHybridAppID = oIntent.getIntExtra(Consts.INTENT_PARAM_HYBRIDAPP_ID, 0);
            m_sProgressText = oIntent.getStringExtra(Consts.INTENT_PARAM_HYBRIDAPP_PROGRESS_TEXT);

            m_oHybridAppController = new UiHybridAppController(this, m_oWebView, iHybridAppID);
        } else {
            setResult(Activity.RESULT_OK, null);
            finish();
            return;
        }

        // Check that controller was initialized. This could fail if the HybridApp
        // or message is missing
        if (!m_oHybridAppController.isInitialized()) {
            setResult(Activity.RESULT_OK, null);
            finish();
            return;
        }

        // Register a layout changed listener to capture screen orientation
        // event(after orientation happens)
        View root = findViewById(android.R.id.content);
        ViewTreeObserver obs = root.getViewTreeObserver();
        m_oLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (m_bOrientationChanged) {
                    // call into javascript to notify an orientation change
                    m_oWebView.loadUrl("javascript:onFrameResize();");
                    m_bOrientationChanged = false;
                }
            }
        };
        obs.addOnGlobalLayoutListener(m_oLayoutListener);

        // Already set in the xml but due to Android bug in 2.2, must be
        // re-applied here.
        m_oWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        WebSettings webSettings = m_oWebView.getSettings();
        webSettings.setSavePassword(false);
        webSettings.setSaveFormData(false);
        webSettings.setJavaScriptEnabled(true);

        // Setup localStorage
        webSettings.setDomStorageEnabled(true);
        AndroidHybridAppHelper.getInstance().setWebSettingsDatabasePath(webSettings, m_oHybridAppController);

        // Setup geolocation
        webSettings.setGeolocationEnabled(true);
        AndroidHybridAppHelper.getInstance().setWebSettingsGeolocationDatabasePath(webSettings,
                m_oHybridAppController);

        // PhoneGap Change: We use the PhoneGap version of these clients
        if (!USE_PHONEGAP) {
            m_oWebView.setWebChromeClient(new HybridAppWebChromeClient(m_oWebView));
            m_oWebView.setWebViewClient(new HybridAppWebViewClient());
        }

        String sBaseURL = m_oHybridAppController.getLaunchURL();

        // We can't directly load the url as some devices(Xoom) don't like having
        // a query string on the content provider url
        // Instead we provide the html data and url and let the content provider
        // handle any resources(js,css) that are linked in
        byte[] abData = m_oHybridAppController.getLaunchURLData();

        // PhoneGap Change: We must call through PhoneGap to load the URL
        if (USE_PHONEGAP) {
            // PhoneGap takes cares of the loading spinner
            super.setStringProperty("loadingDialog", m_sProgressText);

            // PhoneGap may timeout loading the web page
            super.setIntegerProperty("loadUrlTimeoutValue", 300000);

            // PhoneGap will load the URL
            super.loadUrlWithData(sBaseURL, abData);
        } else {
            m_oWebView.loadDataWithBaseURL(sBaseURL, new String(abData), null, "utf-8", null);
        }
    }

    @Override
    protected void onPause() {
        // Unregister challenge listener
        HybridWebApplication.getInstance().setChallengeListener(null);

        if (m_oHybridAppController != null)
            m_oHybridAppController.onPause();

        super.onPause();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        View root = findViewById(android.R.id.content);
        ViewTreeObserver obs = root.getViewTreeObserver();
        obs.removeGlobalOnLayoutListener(m_oLayoutListener);

        if (m_oWebView != null) {
            // Need to explicitly wipe the state of the webview
            // so the scriptable objects are GC
            m_oWebView.destroy();
            m_oWebView = null;
        }

        if (m_oHybridAppController != null)
            m_oHybridAppController.onDestroy();
        m_oHybridAppController = null;
    }

    @Override
    public void onUserInteraction() {
        // check to see if we need to redirect to the password entry or
        // change screen
        PasswordPolicyMgr.redirect(this);
        PasswordPolicyMgr.resetIdleCounter();
    }

    @Override
    public void onActivityResult(final int iRequest, final int iResult, final Intent oData) {
        // Process platform onActivityResult in another thread to avoid dead lock.
        Thread tRunner = new Thread(new Runnable() {
            @Override
            public void run() {
                processActivityResult(iRequest, iResult, oData);
            }
        });
        tRunner.start();
    }

    /**
     * Process platform onActivityResult
     * 
     * @param iRequest
     * @param iResult
     * @param oData
     */
    private void processActivityResult(int iRequest, int iResult, Intent oData) {
        super.onActivityResult(iRequest, iResult, oData);
        m_oHybridAppController.onActivityResult(iRequest, iResult, oData);
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (m_oHybridAppController.onKeyDown(keyCode, event)) {
            return true;
        }

        // Default behavior
        return super.onKeyDown(keyCode, event);
    }

    class HybridAppWebChromeClient extends WebChromeClient {
        private WebView m_webView;

        HybridAppWebChromeClient(WebView webView) {
            m_webView = webView;
        }

        public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
            new AlertDialog.Builder(UiHybridAppContainer.this).setTitle("HybridApp").setMessage(message)
                    .setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            result.confirm();
                        }
                    }).setCancelable(false).create().show();
            return true;
        }

        public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
            // Allow access to geolocation
            callback.invoke(origin, true, true);
        }

        @Override
        public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
            if (handleJSConsoleMessage(consoleMessage, m_webView) == false) {
                return super.onConsoleMessage(consoleMessage);
            }
            return true;
        }
    }

    /**
     * HybridAppWebViewClient extends the WebViewClient The purpose of this class
     * is to provide any possible actions when the web page is loading. Currently
     * this displays the progress dialog when a page is being loaded
     * 
     */
    class HybridAppWebViewClient extends WebViewClient {
        private ProgressDialog m_oProgressDlg = null;

        /**
         * Shows a spinner on the screen
         */
        private void showProgressDialog(final String sMessage) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (m_oProgressDlg == null) {
                        // Create progress dialog that cannot be canceled
                        m_oProgressDlg = ProgressDialog.show(UiHybridAppContainer.this, null, sMessage, false);
                    }
                }
            });
        }

        /**
         * Hides the spinner on the screen
         */
        private void hideProgressDialog() {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    try {
                        if (m_oProgressDlg != null) {

                            // when you dismiss the dialog the spinner stops and will
                            // not spin if you show it again
                            m_oProgressDlg.dismiss();
                            m_oProgressDlg = null;
                        }
                    } catch (Exception ex) {
                        MocaLog.getAmpHostLog().logMessage("Dismiss progress exception: " + ex.getMessage(),
                                MocaLog.eMocaLogLevel.Normal);
                    }
                }
            });
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Log.d(LOG_TAG, "shouldOverrideUrlLoading" + url);

            // Fix for 3.x devices.  On first touch event we may receive an about:blank navigation.
            if (url.equals("about:blank")) {
                return true;
            }
            // Local content we load within the browser. This may be an iframe.
            else if (url.indexOf(m_oHybridAppController.getProviderURL().toString()) == 0) {
                return false;
            } else {
                // We don't want to load any external links in our browser
                // Open these with an external viewer (mailto, tel, ...)
                Intent oIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                startActivity(oIntent);

                return true;
            }
        }

        @Override
        public void onLoadResource(WebView view, String url) {
            Log.d(LOG_TAG, "onLoadResource" + url);
            MocaLog.getAmpHostLog().logMessage(
                    Consts.LOG_PREFIX_HYBRIDAPP_CONTAINER + "WebViewClient onloadresource: " + url,
                    MocaLog.eMocaLogLevel.Normal);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap favicon) {
            showProgressDialog(m_sProgressText);
            Log.d(LOG_TAG, "onPageStarted" + url);
            MocaLog.getAmpHostLog().logMessage(
                    Consts.LOG_PREFIX_HYBRIDAPP_CONTAINER + "WebViewClient onpagestarted: " + url,
                    MocaLog.eMocaLogLevel.Normal);

        }

        @Override
        public void onPageFinished(WebView view, String url) {
            hideProgressDialog();
            Log.d(LOG_TAG, "onPageFinished" + url);
            MocaLog.getAmpHostLog().logMessage(
                    Consts.LOG_PREFIX_HYBRIDAPP_CONTAINER + "WebViewClient onpageFinished: " + url,
                    MocaLog.eMocaLogLevel.Normal);

        }

        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            Log.d(LOG_TAG, "onReceivedError" + failingUrl);
            MocaLog.getAmpHostLog().logMessage(
                    Consts.LOG_PREFIX_HYBRIDAPP_CONTAINER + "WebViewClient onReceiveError: " + failingUrl
                            + ", description: " + description + ", errorCode: " + errorCode,
                    MocaLog.eMocaLogLevel.Normal);

        }
    }

    /**
     * PhoneGap web view client to indicate when the hybrid app javascript is
     * loaded for receiving javascript call
     */
    class HybridAppCordovaWebViewClient extends CordovaWebViewClient {
        public HybridAppCordovaWebViewClient(DroidGap ctx) {
            super(ctx);
        }

        @Override
        public void onPageStarted(WebView view, String url, Bitmap bitmap) {
            try {
                super.onPageStarted(view, url, bitmap);
            } catch (Exception ex) {
                MocaLog.getAmpHostLog().logMessage(
                        Consts.LOG_PREFIX_HYBRIDAPP_CONTAINER + "WebViewClient onPageStarted: " + ex.getMessage(),
                        MocaLog.eMocaLogLevel.Normal);
            }
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            if (!m_errorLoading) {
                super.onPageFinished(view, url);
                m_oHybridAppController.setIsHybridAppLoaded(true);
            }
        }

        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            super.onReceivedError(view, errorCode, description, failingUrl);
        }

        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            Log.d(LOG_TAG, "shouldOverrideUrlLoading" + url);

            // Fix for 3.x devices.  On first touch event we may receive an about:blank navigation.
            if (url.equals("about:blank")) {
                return true;
            } else {
                return super.shouldOverrideUrlLoading(view, url);
            }
        }
    }

    /**
     * Class that handles callbacks from the Javascript engine.
     */
    class HybridAppCordovaChromeClient extends CordovaChromeClient {
        private WebView m_webView;

        public HybridAppCordovaChromeClient(CordovaInterface client, WebView webView) {
            super(client);
            m_webView = webView;
        }

        /**
         * Handle any javascript errors during hybridapp loading.
         */
        @Override
        public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
            if (handleJSConsoleMessage(consoleMessage, m_webView) == false) {
                return super.onConsoleMessage(consoleMessage);
            }
            return true;
        }

    }

    /**
     * Handles any javascript errors during HybridApp loading. If the
     * consoleMessage is an error, this method displays an alert dialog to inform
     * the user about the error. When the user clicks the OK button, the current
     * activity is terminated by calling the finish() method and control goes
     * back to the previous activity.
     * 
     * @param consoleMessage
     * @return true if the message is handled by this method.
     */
    private boolean handleJSConsoleMessage(ConsoleMessage consoleMessage, WebView webView) {
        if (consoleMessage != null && consoleMessage.messageLevel() == MessageLevel.ERROR) {
            MocaLog.getAmpHostLog().logMessage(
                    "Captured Javascript error. Details: " + consoleMessage.message() + " at "
                            + consoleMessage.lineNumber() + " in " + consoleMessage.sourceId(),
                    eMocaLogLevel.Normal);

            if (showAlertOnJavaScriptError()) {
                if (m_errorLoading) {
                    // this is the another error that is being caught.
                    // There is no point displaying another dialog as the user is
                    // seeing one more dialog on the screen.
                    // so, lets just swallow this.
                    return true;
                }

                m_errorLoading = true;
                // signal to the webview to stop loading.
                webView.stopLoading();

                new AlertDialog.Builder(UiHybridAppContainer.this).setTitle(android.R.string.dialog_alert_title)
                        .setMessage("(Javascript)" + consoleMessage.message())
                        .setPositiveButton(android.R.string.ok, new AlertDialog.OnClickListener() {
                            public void onClick(DialogInterface dialog, int which) {
                                m_oHybridAppController.setIsHybridAppLoaded(false);
                                // causes the activity to be removed from the history
                                // stack
                                // & control goes back to the earlier activity.
                                // DroidGap specific method that invokes finish(). It
                                // is better to call this method to let PhoneGap
                                // handle cleanup as well.
                                endActivity();
                            }
                        }).setCancelable(false).create().show();

                return true;
            }
        }
        return false;
    }

    /**
     * To check whether show alert when there is JavaScript error.
     * @return true show alert box when there is error. Otherwise false.
     */
    private boolean showAlertOnJavaScriptError() {
        // default don't show alert box, just log error message.
        // there is backward compatibility issues if we show alert message
        // on every java script error. As android platform is more tolerable on
        // some JavaScript errors, some applications still works fine under
        // JavaScript errors.
        return false;
    }

    /**
     * Let web client get the orientation change notification after the
     * orientation happens, ViewTreeObserver.OnGlobalLayoutListener is hooked up
     * in onCreate and will be triggered after orientation event.
     */
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

        Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
        int currOrientation = display.getOrientation();
        // check if the orientation is changed, filtering out other type of
        // changes
        if (newConfig.orientation != currOrientation) {
            m_bOrientationChanged = true;
        }
    }

    /**
     * open client initiated default hybrid app if available
     * 
     * @param iTimeoutInMillseconds
     *           timeout to wait for opening the hybrid app
     * @return true if hybrid app is opened, otherwise false
     */
    public static boolean openClientInitiatedDefaultHybridAppIfAvailable(int iTimeoutInMillseconds)
            throws Exception {
        boolean bReturn = false;
        // Auto start for default app
        HybridAppDb oHybridApp = (HybridAppDb) HybridAppDb.getDefaultHybridApp();

        if (oHybridApp != null && oHybridApp.isUserViewable())

        {
            Intent oIntentHybridAppContainer = new Intent(HybridWebApplication.getInstance(),
                    UiHybridAppContainer.class);
            oIntentHybridAppContainer.putExtra(Consts.INTENT_PARAM_HYBRIDAPP_START_MODE,
                    Consts.START_MODE_HYBRIDAPP);
            oIntentHybridAppContainer.putExtra(Consts.INTENT_PARAM_HYBRIDAPP_ID,
                    (((HybridAppDb) oHybridApp).getHybridAppId()));
            oIntentHybridAppContainer.putExtra(Consts.INTENT_PARAM_HYBRIDAPP_PROGRESS_TEXT,
                    oHybridApp.getDisplayName());
            oIntentHybridAppContainer.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            HybridWebApplication.getInstance().startActivity(oIntentHybridAppContainer);

            // wait the hybrid app is loaded so that it can accept javascript push
            // notification requests
            while (true) {
                // wait until the hybrid app is fully loaded to handle the push
                // notification by javascript listener
                if (AndroidHybridAppHelper.getInstance().getHybridAppController() != null) {
                    if (AndroidHybridAppHelper.getInstance().getHybridAppController().getIsHybridAppLoaded()) {
                        bReturn = true;
                        break;
                    }
                }
                if (iTimeoutInMillseconds < 0) {
                    throw new Exception("Timeout when starting hybrid app by push notification");
                }
                // sleep 200ms
                Thread.sleep(200);
                iTimeoutInMillseconds -= 200;
            }
        }
        return bReturn;
    }
}