Sqlite-Plugin, DB-Copy plugin added und integriert

This commit is contained in:
2016-01-15 00:59:23 +01:00
parent 337215938a
commit 7c683d7450
243 changed files with 308639 additions and 253 deletions

View File

@@ -0,0 +1,9 @@
<component name="libraryTable">
<library name="sqlite-connector">
<CLASSES>
<root url="jar://$PROJECT_DIR$/libs/sqlite-connector.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

View File

@@ -1,7 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AndroidLogFilters">
<option name="TOOL_WINDOW_CUSTOM_FILTER" value="raataar_wrk.db" />
<option name="TOOL_WINDOW_LOG_LEVEL" value="INFO" />
<option name="TOOL_WINDOW_CONFIGURED_FILTER" value="Show only selected application" />
</component>
<component name="ChangeListManager">
<list default="true" id="e7d7b196-7dbe-4017-ac13-28cca15e160a" name="Default" comment="" />
<list default="true" id="1a60bf2a-41b9-42f3-a21a-2b8a537063de" name="Default" comment="" />
<ignored path="android.iws" />
<ignored path=".idea/workspace.xml" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
@@ -19,10 +24,19 @@
<component name="FavoritesManager">
<favorites_list name="android" />
</component>
<component name="GenerateSignedApkSettings">
<option name="KEY_STORE_PATH" value="D:\_PROJEKTE_\Android_NAS\android-playstore-stuff\KeyStoreAPK\raataar.jks" />
<option name="KEY_ALIAS" value="wollerosenkaufen" />
<option name="REMEMBER_PASSWORDS" value="true" />
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="app.js" pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/assets/www/js/app.js">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.46703297">
<caret line="50" column="48" selection-start-line="50" selection-start-column="48" selection-end-line="50" selection-end-column="48" />
<folding />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="GradleLocalSettings">
<option name="availableProjects">
@@ -945,7 +959,7 @@
</option>
<option name="modificationStamps">
<map>
<entry key="C:\Ionic\Ionic\wollerosenkaufen\platforms\android" value="5801013707543" />
<entry key="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android" value="5805882473891" />
</map>
</option>
<option name="projectBuildClasspath">
@@ -960,6 +974,7 @@
<ExternalModuleBuildClasspathPojo>
<option name="entries">
<list>
<option value="$MODULE_DIR$/libs/sqlite-connector.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/1.0.0/cc834d833ada2ae95c63eedfc87efcd2d842f3d6/gradle-1.0.0-sources.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/1.0.0/79f4ed9b6582ecec4d7b35aecfa45fbc48dadb96/gradle-1.0.0.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/1.0.0/5937e1bdf4c807a0c2adf3e1269838238d05da2b/builder-1.0.0-sources.jar" />
@@ -1035,6 +1050,7 @@
<ExternalModuleBuildClasspathPojo>
<option name="entries">
<list>
<option value="$MODULE_DIR$/libs/sqlite-connector.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/1.0.0/cc834d833ada2ae95c63eedfc87efcd2d842f3d6/gradle-1.0.0-sources.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/gradle/1.0.0/79f4ed9b6582ecec4d7b35aecfa45fbc48dadb96/gradle-1.0.0.jar" />
<option value="$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.android.tools.build/builder/1.0.0/5937e1bdf4c807a0c2adf3e1269838238d05da2b/builder-1.0.0-sources.jar" />
@@ -1225,13 +1241,21 @@
<projects_view />
</option>
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/assets/www/js/app.js" />
</list>
</option>
</component>
<component name="NamedScopeManager">
<order />
</component>
<component name="ProjectFrameBounds">
<option name="x" value="1" />
<option name="width" value="1678" />
<option name="height" value="1010" />
<option name="x" value="1912" />
<option name="y" value="-8" />
<option name="width" value="1696" />
<option name="height" value="1066" />
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
@@ -1256,6 +1280,8 @@
<sortByType />
</navigator>
<panes>
<pane id="ProjectPane" />
<pane id="Scratches" />
<pane id="AndroidView">
<subPane>
<PATH>
@@ -1273,23 +1299,68 @@
<option name="myItemId" value="android" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="assets" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidSourceTypeNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="www" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidPsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="android" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="android" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidModuleNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="assets" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidSourceTypeNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="www" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidPsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="js" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="android" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="android" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidModuleNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="android" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="CordovaLib" />
<option name="myItemType" value="com.android.tools.idea.navigator.nodes.AndroidModuleNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="Scratches" />
<pane id="PackagesPane" />
<pane id="Scope" />
<pane id="ProjectPane" />
<pane id="PackagesPane" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="android.sdk.path" value="C:/Program Files (x86)/Android/android-sdk" />
<property name="recentsLimit" value="5" />
<property name="last_opened_file_path" value="D:/_PROJEKTE_/Android_NAS/android-playstore-stuff/KeyStoreAPK/raataar.jks" />
<property name="ExportApk.ApkPath" value="C:\Ionic\Ionic\wollerosenkaufen\platforms\android" />
<property name="ExportApk.Flavors" value="" />
<property name="ExportApk.BuildType" value="release" />
<property name="FullScreen" value="false" />
<property name="ANDROID_EXTENDED_DEVICE_CHOOSER_SERIALS" value="CB5A1UMZYM" />
<property name="ANDROID_EXTENDED_DEVICE_CHOOSER_AVD" value="MyAvd0" />
</component>
<component name="RunManager" selected="Android Application.android">
<configuration default="true" type="AndroidRunConfigurationType" factoryName="Android Application">
@@ -1321,6 +1392,36 @@
<option name="CLOUD_DEVICE_SERIAL_NUMBER" value="" />
<method />
</configuration>
<configuration default="true" type="AndroidTestRunConfigurationType" factoryName="Android Tests">
<module name="" />
<option name="TESTING_TYPE" value="0" />
<option name="INSTRUMENTATION_RUNNER_CLASS" value="" />
<option name="METHOD_NAME" value="" />
<option name="CLASS_NAME" value="" />
<option name="PACKAGE_NAME" value="" />
<option name="TARGET_SELECTION_MODE" value="EMULATOR" />
<option name="USE_LAST_SELECTED_DEVICE" value="false" />
<option name="PREFERRED_AVD" value="" />
<option name="USE_COMMAND_LINE" value="true" />
<option name="COMMAND_LINE" value="" />
<option name="WIPE_USER_DATA" value="false" />
<option name="DISABLE_BOOT_ANIMATION" value="false" />
<option name="NETWORK_SPEED" value="full" />
<option name="NETWORK_LATENCY" value="none" />
<option name="CLEAR_LOGCAT" value="false" />
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="true" />
<option name="FILTER_LOGCAT_AUTOMATICALLY" value="true" />
<option name="SELECTED_CLOUD_MATRIX_CONFIGURATION_ID" value="0" />
<option name="SELECTED_CLOUD_MATRIX_PROJECT_ID" value="" />
<option name="SELECTED_CLOUD_DEVICE_CONFIGURATION_ID" value="0" />
<option name="SELECTED_CLOUD_DEVICE_PROJECT_ID" value="" />
<option name="IS_VALID_CLOUD_MATRIX_SELECTION" value="false" />
<option name="INVALID_CLOUD_MATRIX_SELECTION_ERROR" value="" />
<option name="IS_VALID_CLOUD_DEVICE_SELECTION" value="false" />
<option name="INVALID_CLOUD_DEVICE_SELECTION_ERROR" value="" />
<option name="CLOUD_DEVICE_SERIAL_NUMBER" value="" />
<method />
</configuration>
<configuration default="true" type="Application" factoryName="Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<option name="MAIN_CLASS_NAME" />
@@ -1357,6 +1458,11 @@
<patterns />
<method />
</configuration>
<configuration default="true" type="JarApplication" factoryName="JAR Application">
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
<envs />
<method />
</configuration>
<configuration default="true" type="Remote" factoryName="Remote">
<option name="USE_SOCKET_TRANSPORT" value="true" />
<option name="SERVER_MODE" value="false" />
@@ -1439,58 +1545,47 @@
</configuration>
</component>
<component name="ShelveChangesManager" show_recycled="false" />
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="e7d7b196-7dbe-4017-ac13-28cca15e160a" name="Default" comment="" />
<created>1450381598364</created>
<changelist id="1a60bf2a-41b9-42f3-a21a-2b8a537063de" name="Default" comment="" />
<created>1452811340653</created>
<option name="number" value="Default" />
<updated>1450381598364</updated>
<updated>1452811340653</updated>
</task>
<servers />
</component>
<component name="ToolWindowManager">
<frame x="1" y="0" width="1678" height="1010" extended-state="1" />
<editor active="false" />
<frame x="1912" y="-8" width="1696" height="1066" extended-state="6" />
<editor active="true" />
<layout>
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32941177" sideWeight="0.49573562" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Palette&#9;" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Build Variants" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.36923078" sideWeight="0.34963325" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Application Servers" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32941177" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32941177" sideWeight="0.4978678" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Captures" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Android" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Gradle Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32941177" sideWeight="0.5042644" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Android" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.36923078" sideWeight="0.6503667" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Designer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="true" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.24969098" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.28667483" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
<window_info id="Gradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
</layout>
</component>
<component name="Vcs.Log.UiProperties">
<option name="RECENTLY_FILTERED_USER_GROUPS">
<collection />
</option>
<option name="RECENTLY_FILTERED_BRANCH_GROUPS">
<collection />
</option>
</component>
<component name="VcsContentAnnotationSettings">
<option name="myLimit" value="2678400000" />
</component>
@@ -1498,4 +1593,14 @@
<breakpoint-manager />
<watches-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/assets/www/js/app.js">
<provider selected="true" editor-type-id="text-editor">
<state vertical-scroll-proportion="0.46703297">
<caret line="50" column="48" selection-start-line="50" selection-start-column="48" selection-end-line="50" selection-end-column="48" />
<folding />
</state>
</provider>
</entry>
</component>
</project>

View File

@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<merger version="3"><dataSet config="debug"><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\CordovaLib\build\intermediates\bundles\debug\assets"/></dataSet><dataSet config="main"><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\CordovaLib\src\androidTest\assets"/></dataSet></merger>
<merger version="3"><dataSet config="debug"><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\CordovaLib\build\intermediates\bundles\debug\assets"/></dataSet><dataSet config="main"><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\CordovaLib\src\androidTest\assets"/></dataSet></merger>

View File

@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<merger version="3"><dataSet config="debug"><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\CordovaLib\build\intermediates\bundles\debug\res"/></dataSet><dataSet config="main"><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\CordovaLib\src\androidTest\res"/><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\CordovaLib\build\generated\res\rs\test\debug"/><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\CordovaLib\build\generated\res\generated\test\debug"/></dataSet><mergedItems/></merger>
<merger version="3"><dataSet config="debug"><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\CordovaLib\build\intermediates\bundles\debug\res"/></dataSet><dataSet config="main"><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\CordovaLib\src\androidTest\res"/><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\CordovaLib\build\generated\res\rs\test\debug"/><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\CordovaLib\build\generated\res\generated\test\debug"/></dataSet><mergedItems/></merger>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.apache.cordova.test">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="14" />
<application>
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="android.test.InstrumentationTestRunner"
android:targetPackage="org.apache.cordova.test"
android:handleProfiling="false"
android:functionalTest="false"
android:label="Tests for org.apache.cordova.test"/>
</manifest>

View File

@@ -83,6 +83,7 @@
</content>
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" exported="" name="sqlite-connector" level="project" />
<orderEntry type="module" module-name="CordovaLib" exported="" />
</component>
</module>

View File

@@ -11,6 +11,10 @@
{
"xml": "<uses-permission android:name=\"com.android.vending.BILLING\" />",
"count": 1
},
{
"xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />",
"count": 1
}
],
"/*": [
@@ -59,6 +63,14 @@
{
"xml": "<feature name=\"FileTransfer\"><param name=\"android-package\" value=\"org.apache.cordova.filetransfer.FileTransfer\" /></feature>",
"count": 1
},
{
"xml": "<feature name=\"SQLitePlugin\"><param name=\"android-package\" value=\"io.liteglue.SQLitePlugin\" /></feature>",
"count": 1
},
{
"xml": "<feature name=\"sqlDB\"><param name=\"android-package\" value=\"me.rahul.plugins.sqlDB.sqlDB\" /></feature>",
"count": 1
}
]
}
@@ -116,6 +128,12 @@
},
"cordova-plugin-file-transfer": {
"PACKAGE_NAME": "com.raataar.wolle_rosen_kaufen"
},
"cordova-sqlite-storage": {
"PACKAGE_NAME": "com.raataar.wolle_rosen_kaufen"
},
"me.rahul.plugins.sqlDB": {
"PACKAGE_NAME": "com.raataar.wolle_rosen_kaufen"
}
},
"dependent_plugins": {},
@@ -358,6 +376,22 @@
"clobbers": [
"window.FileTransfer"
]
},
{
"file": "plugins/cordova-sqlite-storage/www/SQLitePlugin.js",
"id": "cordova-sqlite-storage.SQLitePlugin",
"pluginId": "cordova-sqlite-storage",
"clobbers": [
"SQLitePlugin"
]
},
{
"file": "plugins/me.rahul.plugins.sqlDB/www/sqlDB.js",
"id": "me.rahul.plugins.sqlDB.sqlDB",
"pluginId": "me.rahul.plugins.sqlDB",
"clobbers": [
"window.plugins.sqlDB"
]
}
],
"plugin_metadata": {
@@ -370,6 +404,8 @@
"ionic-plugin-keyboard": "1.0.8",
"cordova-plugin-inappbrowser": "1.1.1",
"cordova-plugin-file": "3.0.0",
"cordova-plugin-file-transfer": "1.4.0"
"cordova-plugin-file-transfer": "1.4.0",
"cordova-sqlite-storage": "0.7.15-pre",
"me.rahul.plugins.sqlDB": "1.0.3"
}
}

View File

@@ -238,6 +238,22 @@ module.exports = [
"clobbers": [
"window.FileTransfer"
]
},
{
"file": "plugins/cordova-sqlite-storage/www/SQLitePlugin.js",
"id": "cordova-sqlite-storage.SQLitePlugin",
"pluginId": "cordova-sqlite-storage",
"clobbers": [
"SQLitePlugin"
]
},
{
"file": "plugins/me.rahul.plugins.sqlDB/www/sqlDB.js",
"id": "me.rahul.plugins.sqlDB.sqlDB",
"pluginId": "me.rahul.plugins.sqlDB",
"clobbers": [
"window.plugins.sqlDB"
]
}
];
module.exports.metadata =
@@ -252,7 +268,9 @@ module.exports.metadata =
"ionic-plugin-keyboard": "1.0.8",
"cordova-plugin-inappbrowser": "1.1.1",
"cordova-plugin-file": "3.0.0",
"cordova-plugin-file-transfer": "1.4.0"
"cordova-plugin-file-transfer": "1.4.0",
"cordova-sqlite-storage": "0.7.15-pre",
"me.rahul.plugins.sqlDB": "1.0.3"
}
// BOTTOM OF METADATA
});

View File

@@ -3,6 +3,7 @@
font-family: 'Lobster', cursive;
}
.lobsterMiddle{
font-family: 'Lobster', cursive;
font-size: 1.2em;
@@ -22,35 +23,45 @@
.item-divider{
background-image: linear-gradient(
hsla(340, 100%, 35%, 1) 20%,
hsl(340,100%,54%) 90%
hsla(0, 94%, 33%, 1) 20%,
hsl(0,94%,54%) 90%
);
color:white;
}
.tabs-addddssertive > .tabs{
background-image: linear-gradient(
hsla(340, 100%, 35%, 1) 20%,
hsl(340,100%,54%) 90%
hsla(0, 94%, 33%, 1) 20%,
hsl(0,94%,54%) 90%
) !important;
}
.tabs-assertive > .tabs{
background-color: #BD0340 !important;
.tabs-assertive > .tabs{
background-color: #A50505 !important;
}
.bar-custom{
background-image: linear-gradient(
hsla(340, 100%, 35%, 1) 20%,
hsl(340,100%,54%) 90%
hsla(0, 94%, 33%, 1) 20%,
hsl(0,94%,54%) 90%
) !important;
font-family: 'Bubblegum Sans', cursive;
}
.button-custom{
background-color: #C60545;
text-decoration: none;
border: 1px solid #C60545;
border-color: #F9135F #F9135F #F9135F #F9135F;
color: #fff
}
font-family: 'Bubblegum Sans', cursive;
background-color: #A50505;
text-decoration: none;
border: 1px solid #A50505;
color: #fff
}
.oleo{
font-family: 'Bubblegum Sans', cursive;
font-size: 1.3em !important;
}

View File

@@ -8,6 +8,7 @@
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Oswald:400,300,700' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Bubblegum+Sans' rel='stylesheet' type='text/css'>
<link href="css/style.css" rel="stylesheet">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
@@ -16,7 +17,7 @@
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="js/ng-cordova.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>

View File

@@ -5,21 +5,55 @@
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
var db;
.run(function($ionicPlatform, $ionicPopup) {
angular.module('starter', ['ionic', 'ngCordova', 'starter.controllers', 'starter.services'])
.run(function($ionicPlatform, $window, $ionicHistory, $database, $ionicPopup, $state, $localstorage, $rootScope) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
$ionicPlatform.registerBackButtonAction(function(event) {
// Handle Android back button to avoid the application exits accidentaly
if ($state.current.name=="tab.dash") {
$ionicPopup.confirm({
title: 'System-Hinweis',
template: 'Möchten Sie die App beenden?'
}).then(function(res) {
if (res) {
ionic.Platform.exitApp();
}
});
} else {
$ionicHistory.clearCache();
$ionicHistory.nextViewOptions({
historyRoot: true
});
$state.go('tab.dash');
}
}, 100);
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
// Mandatory for InAppBrowser plugin
if(window.cordova){
window.open = cordova.InAppBrowser.open;
}
// Copy the populated database to mobile device destination
//if (window.sqlitePlugin && window.cordova) {
if (window.sqlitePlugin && window.cordova) {
window.plugins.sqlDB.copy("raataar_wrk.db", function (e) {
console.log(e);
});
}
function successHandler (result) {
var strResult = "";
@@ -39,7 +73,16 @@ angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
if((window.device && device.platform == "Android") && typeof inappbilling !== "undefined") {
inappbilling.init(successHandler, errorHandler, {showLog:true});
}
// Initialize database through $database service
db = $database.initDB();
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})

View File

@@ -1,6 +1,6 @@
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope,$ionicPopup,$http, $localstorage) {
.controller('DashCtrl', function($scope,$ionicPopup,$http, $database) {
$scope.preis="";
$scope.name="";
@@ -8,7 +8,9 @@ angular.module('starter.controllers', [])
$scope.items=[];
$scope.item=[];
$scope.items=$localstorage.getObject('items');
//db = Database.getDb();
//$scope.items=$localstorage.getObject('items');
$scope.validate = function() {
@@ -22,16 +24,30 @@ angular.module('starter.controllers', [])
};
$scope.loaddata = function() {
$scope.items=$localstorage.getObject('items');
alert(JSON.stringify($scope.items));
$scope.items=[];
$database.getAllBuys().then(function (result) {
if(result.length>0){
alert("daten da");
for(i=0;i<result.length;i++){
$scope.items.push(result[i]);
alert(i);
}
} else {
$scope.items=[];
}
});
};
$scope.savedata = function() {
$scope.item={name: $scope.name, freitext: $scope.freitext, rosen: $scope.preis, bild: "test"};
alert(JSON.stringify($scope.item));
$scope.item={name: $scope.name, bild: "test"};
$scope.items.push($scope.item);
$localstorage.setObject('items',$scope.items);
$database.setBuys($scope.name,"test");
};
function successBuyHandler (result) {
@@ -78,14 +94,22 @@ angular.module('starter.controllers', [])
})
.controller('BuysCtrl', function($scope, $localstorage,$location) {
.controller('BuysCtrl', function($scope, $database,$location) {
$scope.items=[];
$scope.items=$localstorage.getObject('items');
//$scope.items=$localstorage.getObject('items');
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
if ($location.path() == "/tab/buys") {
$scope.items=$localstorage.getObject('items');
}
$database.getAllBuys().then(function (result) {
if(result.length>0){
for(i=0;i<result.length;i++){
$scope.items.push(result[i]);
}
} else {
$scope.items=[];
}
});
}
});

File diff suppressed because one or more lines are too long

View File

@@ -1,19 +1,94 @@
angular.module('starter.services', [])
.factory('$localstorage', ['$window', function($window) {
return {
set: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
setObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key) {
return JSON.parse($window.localStorage[key] || '{}');
return {
set: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
setObject: function(key, value) {
$window.localStorage[key] = angular.toJson(value);
},
getObject: function(key) {
return JSON.parse($window.localStorage[key] || '[]');
},
destroy: function(key) {
$window.localStorage.removeItem(key);
},
log: function(key, defaultValue) {
console.log($window.localStorage[key] || defaultValue);
},
logObject: function(key) {
console.log(JSON.stringify($window.localStorage[key] || '{}'));
}
};
}])
.factory('$database',['$cordovaSQLite', function($cordovaSQLite) {
var self = this;
self.db = null;
var query;
//this updateTable function is for ilustrative use here, it can be changed to manage all queries indeed.
updateTable=function (table, column, value, condition) {
if(!condition){
query = "UPDATE " + table + " SET " + column + " = " + value;
} else{
query = "UPDATE " + table + " SET " + column + " = " + value + " WHERE " + condition;
}
}
}]);
return $cordovaSQLite.execute(self.db,query,[]).
then(function(result) {
console.log(query);
query=null;
return result;
},function(error) {
console.error(error);
query=null;
return error;
});
};
return {
initDB: function() {
if(window.cordova){
//self.db = sqlitePlugin.openDatabase({name: "data.db", location: 2, createFromLocation: 1});
self.db = $cordovaSQLite.openDB("raataar_wrk.db");
} else {
self.db = window.openDatabase('raataar_wrk.db','1','my',800*1024); // only available when WebSQL is available in Browser
}
console.log('Database opened');
return self.db;
},
setBuys: function(itemName,itemBild) {
query="INSERT INTO buys (Name, Bild) VALUES (?,?);";
return $cordovaSQLite.execute(self.db,query,[itemName,itemBild]).
then(function(result) {
console.log("Gespeichert");
query=null;
}, function(error) {
console.error(error);
});
},
getAllBuys: function(){
var ArrayQ=[];
query="SELECT * FROM buys order by id ASC";
return $cordovaSQLite.execute(self.db,query).
then(function(result) {
for(j=0;j<result.rows.length;j++){
var List={};
//console.log(result.rows.item(j));
List.name=result.rows.item(j).Name;
List.bild=result.rows.item(j).Bild;
ArrayQ.push(List);
}
//console.log(ArrayQ);
return ArrayQ;
},function(e){
console.error(error);
return error;
});
}
};
}]);

View File

@@ -1,4 +1,4 @@
@charset "UTF-8";
@charset "UTF-8";
/*!
* Copyright 2014 Drifty Co.
* http://drifty.com/

View File

@@ -0,0 +1,576 @@
cordova.define("cordova-sqlite-storage.SQLitePlugin", function(require, exports, module) { (function() {
var DB_STATE_INIT, DB_STATE_OPEN, READ_ONLY_REGEX, SQLiteFactory, SQLitePlugin, SQLitePluginTransaction, argsArray, dblocations, newSQLError, nextTick, root, txLocks;
root = this;
READ_ONLY_REGEX = /^\s*(?:drop|delete|insert|update|create)\s/i;
DB_STATE_INIT = "INIT";
DB_STATE_OPEN = "OPEN";
txLocks = {};
newSQLError = function(error, code) {
var sqlError;
sqlError = error;
if (!code) {
code = 0;
}
if (!sqlError) {
sqlError = new Error("a plugin had an error but provided no response");
sqlError.code = code;
}
if (typeof sqlError === "string") {
sqlError = new Error(error);
sqlError.code = code;
}
if (!sqlError.code && sqlError.message) {
sqlError.code = code;
}
if (!sqlError.code && !sqlError.message) {
sqlError = new Error("an unknown error was returned: " + JSON.stringify(sqlError));
sqlError.code = code;
}
return sqlError;
};
nextTick = window.setImmediate || function(fun) {
window.setTimeout(fun, 0);
};
/*
Utility that avoids leaking the arguments object. See
https://www.npmjs.org/package/argsarray
*/
argsArray = function(fun) {
return function() {
var args, i, len;
len = arguments.length;
if (len) {
args = [];
i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
} else {
return fun.call(this, []);
}
};
};
SQLitePlugin = function(openargs, openSuccess, openError) {
var dbname;
if (!(openargs && openargs['name'])) {
throw newSQLError("Cannot create a SQLitePlugin db instance without a db name");
}
dbname = openargs.name;
if (typeof dbname !== 'string') {
throw newSQLError('sqlite plugin database name must be a string');
}
this.openargs = openargs;
this.dbname = dbname;
this.openSuccess = openSuccess;
this.openError = openError;
this.openSuccess || (this.openSuccess = function() {
console.log("DB opened: " + dbname);
});
this.openError || (this.openError = function(e) {
console.log(e.message);
});
this.open(this.openSuccess, this.openError);
};
SQLitePlugin.prototype.databaseFeatures = {
isSQLitePluginDatabase: true
};
SQLitePlugin.prototype.openDBs = {};
SQLitePlugin.prototype.addTransaction = function(t) {
if (!txLocks[this.dbname]) {
txLocks[this.dbname] = {
queue: [],
inProgress: false
};
}
txLocks[this.dbname].queue.push(t);
if (this.dbname in this.openDBs && this.openDBs[this.dbname] !== DB_STATE_INIT) {
this.startNextTransaction();
} else {
if (this.dbname in this.openDBs) {
console.log('new transaction is waiting for open operation');
} else {
console.log('database is closed, new transaction is [stuck] waiting until db is opened again!');
}
}
};
SQLitePlugin.prototype.transaction = function(fn, error, success) {
if (!this.openDBs[this.dbname]) {
error(newSQLError('database not open'));
return;
}
this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, true, false));
};
SQLitePlugin.prototype.readTransaction = function(fn, error, success) {
if (!this.openDBs[this.dbname]) {
error(newSQLError('database not open'));
return;
}
this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, false, true));
};
SQLitePlugin.prototype.startNextTransaction = function() {
var self;
self = this;
nextTick((function(_this) {
return function() {
var txLock;
if (!(_this.dbname in _this.openDBs) || _this.openDBs[_this.dbname] !== DB_STATE_OPEN) {
console.log('cannot start next transaction: database not open');
return;
}
txLock = txLocks[self.dbname];
if (!txLock) {
console.log('cannot start next transaction: database connection is lost');
return;
} else if (txLock.queue.length > 0 && !txLock.inProgress) {
txLock.inProgress = true;
txLock.queue.shift().start();
}
};
})(this));
};
SQLitePlugin.prototype.abortAllPendingTransactions = function() {
var j, len1, ref, tx, txLock;
txLock = txLocks[this.dbname];
if (!!txLock && txLock.queue.length > 0) {
ref = txLock.queue;
for (j = 0, len1 = ref.length; j < len1; j++) {
tx = ref[j];
tx.abortFromQ(newSQLError('Invalid database handle'));
}
txLock.queue = [];
txLock.inProgress = false;
}
};
SQLitePlugin.prototype.open = function(success, error) {
var openerrorcb, opensuccesscb;
if (this.dbname in this.openDBs) {
console.log('database already open: ' + this.dbname);
nextTick((function(_this) {
return function() {
success(_this);
};
})(this));
} else {
console.log('OPEN database: ' + this.dbname);
opensuccesscb = (function(_this) {
return function() {
var txLock;
if (!_this.openDBs[_this.dbname]) {
console.log('database was closed during open operation');
}
if (_this.dbname in _this.openDBs) {
_this.openDBs[_this.dbname] = DB_STATE_OPEN;
}
if (!!success) {
success(_this);
}
txLock = txLocks[_this.dbname];
if (!!txLock && txLock.queue.length > 0 && !txLock.inProgress) {
_this.startNextTransaction();
}
};
})(this);
openerrorcb = (function(_this) {
return function() {
console.log('OPEN database: ' + _this.dbname + ' failed, aborting any pending transactions');
if (!!error) {
error(newSQLError('Could not open database'));
}
delete _this.openDBs[_this.dbname];
_this.abortAllPendingTransactions();
};
})(this);
this.openDBs[this.dbname] = DB_STATE_INIT;
cordova.exec(opensuccesscb, openerrorcb, "SQLitePlugin", "open", [this.openargs]);
}
};
SQLitePlugin.prototype.close = function(success, error) {
if (this.dbname in this.openDBs) {
if (txLocks[this.dbname] && txLocks[this.dbname].inProgress) {
console.log('cannot close: transaction is in progress');
error(newSQLError('database cannot be closed while a transaction is in progress'));
return;
}
console.log('CLOSE database: ' + this.dbname);
delete this.openDBs[this.dbname];
if (txLocks[this.dbname]) {
console.log('closing db with transaction queue length: ' + txLocks[this.dbname].queue.length);
} else {
console.log('closing db with no transaction lock state');
}
cordova.exec(success, error, "SQLitePlugin", "close", [
{
path: this.dbname
}
]);
} else {
console.log('cannot close: database is not open');
if (error) {
nextTick(function() {
return error();
});
}
}
};
SQLitePlugin.prototype.executeSql = function(statement, params, success, error) {
var myerror, myfn, mysuccess;
mysuccess = function(t, r) {
if (!!success) {
return success(r);
}
};
myerror = function(t, e) {
if (!!error) {
return error(e);
}
};
myfn = function(tx) {
tx.addStatement(statement, params, mysuccess, myerror);
};
this.addTransaction(new SQLitePluginTransaction(this, myfn, null, null, false, false));
};
SQLitePluginTransaction = function(db, fn, error, success, txlock, readOnly) {
if (typeof fn !== "function") {
/*
This is consistent with the implementation in Chrome -- it
throws if you pass anything other than a function. This also
prevents us from stalling our txQueue if somebody passes a
false value for fn.
*/
throw newSQLError("transaction expected a function");
}
this.db = db;
this.fn = fn;
this.error = error;
this.success = success;
this.txlock = txlock;
this.readOnly = readOnly;
this.executes = [];
if (txlock) {
this.addStatement("BEGIN", [], null, function(tx, err) {
throw newSQLError("unable to begin transaction: " + err.message, err.code);
});
}
};
SQLitePluginTransaction.prototype.start = function() {
var err, error1;
try {
this.fn(this);
this.run();
} catch (error1) {
err = error1;
txLocks[this.db.dbname].inProgress = false;
this.db.startNextTransaction();
if (this.error) {
this.error(newSQLError(err));
}
}
};
SQLitePluginTransaction.prototype.executeSql = function(sql, values, success, error) {
if (this.finalized) {
throw {
message: 'InvalidStateError: DOM Exception 11: This transaction is already finalized. Transactions are committed after its success or failure handlers are called. If you are using a Promise to handle callbacks, be aware that implementations following the A+ standard adhere to run-to-completion semantics and so Promise resolution occurs on a subsequent tick and therefore after the transaction commits.',
code: 11
};
return;
}
if (this.readOnly && READ_ONLY_REGEX.test(sql)) {
this.handleStatementFailure(error, {
message: 'invalid sql for a read-only transaction'
});
return;
}
this.addStatement(sql, values, success, error);
};
SQLitePluginTransaction.prototype.addStatement = function(sql, values, success, error) {
var j, len1, params, t, v;
params = [];
if (!!values && values.constructor === Array) {
for (j = 0, len1 = values.length; j < len1; j++) {
v = values[j];
t = typeof v;
params.push((v === null || v === void 0 || t === 'number' || t === 'string' ? v : v instanceof Blob ? v.valueOf() : v.toString()));
}
}
this.executes.push({
success: success,
error: error,
sql: sql,
params: params
});
};
SQLitePluginTransaction.prototype.handleStatementSuccess = function(handler, response) {
var payload, rows;
if (!handler) {
return;
}
rows = response.rows || [];
payload = {
rows: {
item: function(i) {
return rows[i];
},
length: rows.length
},
rowsAffected: response.rowsAffected || 0,
insertId: response.insertId || void 0
};
handler(this, payload);
};
SQLitePluginTransaction.prototype.handleStatementFailure = function(handler, response) {
if (!handler) {
throw newSQLError("a statement with no error handler failed: " + response.message, response.code);
}
if (handler(this, response) !== false) {
throw newSQLError("a statement error callback did not return false: " + response.message, response.code);
}
};
SQLitePluginTransaction.prototype.run = function() {
var batchExecutes, handlerFor, i, mycb, mycbmap, request, tropts, tx, txFailure, waiting;
txFailure = null;
tropts = [];
batchExecutes = this.executes;
waiting = batchExecutes.length;
this.executes = [];
tx = this;
handlerFor = function(index, didSucceed) {
return function(response) {
var err, error1;
try {
if (didSucceed) {
tx.handleStatementSuccess(batchExecutes[index].success, response);
} else {
tx.handleStatementFailure(batchExecutes[index].error, newSQLError(response));
}
} catch (error1) {
err = error1;
if (!txFailure) {
txFailure = newSQLError(err);
}
}
if (--waiting === 0) {
if (txFailure) {
tx.abort(txFailure);
} else if (tx.executes.length > 0) {
tx.run();
} else {
tx.finish();
}
}
};
};
i = 0;
mycbmap = {};
while (i < batchExecutes.length) {
request = batchExecutes[i];
mycbmap[i] = {
success: handlerFor(i, true),
error: handlerFor(i, false)
};
tropts.push({
qid: 1111,
sql: request.sql,
params: request.params
});
i++;
}
mycb = function(result) {
var j, last, q, r, ref, res, type;
last = result.length - 1;
for (i = j = 0, ref = last; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) {
r = result[i];
type = r.type;
res = r.result;
q = mycbmap[i];
if (q) {
if (q[type]) {
q[type](res);
}
}
}
};
cordova.exec(mycb, null, "SQLitePlugin", "backgroundExecuteSqlBatch", [
{
dbargs: {
dbname: this.db.dbname
},
executes: tropts
}
]);
};
SQLitePluginTransaction.prototype.abort = function(txFailure) {
var failed, succeeded, tx;
if (this.finalized) {
return;
}
tx = this;
succeeded = function(tx) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(txFailure);
}
};
failed = function(tx, err) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(newSQLError("error while trying to roll back: " + err.message, err.code));
}
};
this.finalized = true;
if (this.txlock) {
this.addStatement("ROLLBACK", [], succeeded, failed);
this.run();
} else {
succeeded(tx);
}
};
SQLitePluginTransaction.prototype.finish = function() {
var failed, succeeded, tx;
if (this.finalized) {
return;
}
tx = this;
succeeded = function(tx) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.success) {
tx.success();
}
};
failed = function(tx, err) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(newSQLError("error while trying to commit: " + err.message, err.code));
}
};
this.finalized = true;
if (this.txlock) {
this.addStatement("COMMIT", [], succeeded, failed);
this.run();
} else {
succeeded(tx);
}
};
SQLitePluginTransaction.prototype.abortFromQ = function(sqlerror) {
if (this.error) {
this.error(sqlerror);
}
};
dblocations = ["docs", "libs", "nosync"];
SQLiteFactory = {
/*
NOTE: this function should NOT be translated from Javascript
back to CoffeeScript by js2coffee.
If this function is edited in Javascript then someone will
have to translate it back to CoffeeScript by hand.
*/
opendb: argsArray(function(args) {
var dblocation, errorcb, first, okcb, openargs;
if (args.length < 1) {
return null;
}
first = args[0];
openargs = null;
okcb = null;
errorcb = null;
if (first.constructor === String) {
openargs = {
name: first
};
if (args.length >= 5) {
okcb = args[4];
if (args.length > 5) {
errorcb = args[5];
}
}
} else {
openargs = first;
if (args.length >= 2) {
okcb = args[1];
if (args.length > 2) {
errorcb = args[2];
}
}
}
dblocation = !!openargs.location ? dblocations[openargs.location] : null;
openargs.dblocation = dblocation || dblocations[0];
if (!!openargs.createFromLocation && openargs.createFromLocation === 1) {
openargs.createFromResource = "1";
}
if (!!openargs.androidDatabaseImplementation && openargs.androidDatabaseImplementation === 2) {
openargs.androidOldDatabaseImplementation = 1;
}
if (!!openargs.androidLockWorkaround && openargs.androidLockWorkaround === 1) {
openargs.androidBugWorkaround = 1;
}
return new SQLitePlugin(openargs, okcb, errorcb);
}),
deleteDb: function(first, success, error) {
var args, dblocation;
args = {};
if (first.constructor === String) {
args.path = first;
args.dblocation = dblocations[0];
} else {
if (!(first && first['name'])) {
throw new Error("Please specify db name");
}
args.path = first.name;
dblocation = !!first.location ? dblocations[first.location] : null;
args.dblocation = dblocation || dblocations[0];
}
delete SQLitePlugin.prototype.openDBs[args.path];
return cordova.exec(success, error, "SQLitePlugin", "delete", [args]);
}
};
root.sqlitePlugin = {
sqliteFeatures: {
isSQLitePlugin: true
},
openDatabase: SQLiteFactory.opendb,
deleteDatabase: SQLiteFactory.deleteDb
};
}).call(this);
});

View File

@@ -0,0 +1,11 @@
cordova.define("me.rahul.plugins.sqlDB.sqlDB", function(require, exports, module) { var exec = require('cordova/exec');
exports.copy = function(dbname, location, success, error) {
exec(success, error, "sqlDB", "copy", [dbname, location]);
};
exports.remove = function(dbname, location, success,error) {
exec(success, error, "sqlDB", "remove", [dbname, location]);
};
});

Binary file not shown.

View File

@@ -1,11 +1,11 @@
<ion-view view-title="Gekaufte Rosen">
<ion-content>
<ion-content class="padding">
<div style="padding-bottom:15px;">
<div class="item item-divider oswald">Hier können Sie Ihre gekauften Rosen ansehen oder nochmals versenden!</div>
<ul class="list card">
<div class="item item-divider oleo">Hier können Sie Ihre gekauften Rosen ansehen oder nochmals versenden!</div>
<ul class="list">
<a class="item item-thumbnail-left item-button-right" href="#" ng-repeat="i in items" ng-model="items">
<img src="img/rose1.png">
<h1>{{i.name}}</h1>
@@ -21,10 +21,6 @@
</a>
</ul>
</div>

View File

@@ -1,43 +1,28 @@
<ion-view view-title='Rosen kaufen'>
<ion-content class="padding">
<div class="list card">
<div class="item item-divider oswald">Wolle Rose kaufen?</div>
<div class="item item-body lobster">
<div style="padding-bottom:25px;">
Schenken Sie einem besonderen Menschen eine aussergewöhnliche Aufmerksamkeit.
</div>
<div class="item item-divider oswald">An wen wollen Sie die Rose verschenken</div>
<div class="list list-inset" style="padding-bottom:15px;">
<div class="item item-divider oleo">Schenken Sie einem besonderen Menschen eine außergewöhnliche Aufmerksamkeit!</div>
<label class="item item-input item-stacked-label">
<span class="input-label">Name Ihres Liebsten:</span>
<input type="text" placeholder="" class="lobster" ng-model="$parent.name">
<input type="text" placeholder="" class="oleo" ng-model="$parent.name">
</label>
<label class="item item-input item-stacked-label">
<span class="input-label">Ihre persönliche Nachricht:</span>
<textarea placeholder="" rows="4" cols="10" class="lobster" ng-model="$parent.freitext"></textarea>
<textarea placeholder="" rows="4" cols="10" class="oleo" ng-model="$parent.freitext"></textarea>
</label>
</div>
<div style="padding-bottom:15px;">
<div class="item item-divider oleo">Wählen Sie Ihre Rosen aus</div>
<div class="item item-divider oleo">Wählen Sie Ihre Rosen aus:</div>
<ion-list>
<ion-radio ng-model="$parent.preis" ng-value="'1xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose1.png"><h2 class="lobster">1 Rose </h2><p>Preis: 0,50 € (inkl. Mwst 0,59 €)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'3xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose3.png"><h2 class="lobster">3 Rosen</h2><p>Preis: 1,00 € (inkl. Mwst 1,19 €)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'9xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose10.png"><h2 class="lobster">9 Rosen</h2><p>Preis: 2,00 € (inkl. Mwst 2,38 €)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'1xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose1.png"><h2 class="oleo">1 Rose </h2><p>Preis: 0,50 € (zzgl. gesetzl. MwSt.)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'3xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose3.png"><h2 class="oleo">3 Rosen</h2><p>Preis: 1,00 € (zzgl. gesetzl. MwSt.)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'9xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose10.png"><h2 class="oleo">9 Rosen</h2><p>Preis: 2,00 € (zzgl. gesetzl. MwSt.)</p></ion-radio>
</ion-list>
<label class="item item-input item-select">
<div class="input-label">
Farbe
</div>
<select>
<option selected>Rot</option>
<option>Gelb</option>
<option>Weiß</option>
</select>
</label>
</div>
<div class="item item-divider oswald">Rosen kaufen?</div>
</div>
<div class="list card">
<div class="item item-divider oleo">Rosen jetzt kaufen?</div>
<div class="row">
<div class="col col-50"><button class="button button-full button-small icon-left ion-image button-custom" ng-disabled="!$parent.preis || !$parent.name || !$parent.freitext" ng-click="validate()">Vorschau</button></div>
<div class="col col-50"><button class="button button-full button-small icon-left ion-social-euro button-custom" ng-disabled="!$parent.preis || !$parent.freitext || !$parent.name" ng-click="buyRose()">Jetzt Kaufen</button></div>
@@ -47,7 +32,7 @@
<div class="col col-50"><button class="button button-full button-small icon-left ion-image button-custom" ng-disabled="!$parent.preis || !$parent.name || !$parent.freitext" ng-click="loaddata()">Laden</button></div>
<div class="col col-50"><button class="button button-full button-small icon-left ion-social-euro button-custom" ng-disabled="!$parent.preis || !$parent.freitext || !$parent.name" ng-click="savedata()">Speichern</button></div>
</div>
</div>
</div>
</div>

View File

@@ -238,6 +238,22 @@ module.exports = [
"clobbers": [
"window.FileTransfer"
]
},
{
"file": "plugins/cordova-sqlite-storage/www/SQLitePlugin.js",
"id": "cordova-sqlite-storage.SQLitePlugin",
"pluginId": "cordova-sqlite-storage",
"clobbers": [
"SQLitePlugin"
]
},
{
"file": "plugins/me.rahul.plugins.sqlDB/www/sqlDB.js",
"id": "me.rahul.plugins.sqlDB.sqlDB",
"pluginId": "me.rahul.plugins.sqlDB",
"clobbers": [
"window.plugins.sqlDB"
]
}
];
module.exports.metadata =
@@ -252,7 +268,9 @@ module.exports.metadata =
"ionic-plugin-keyboard": "1.0.8",
"cordova-plugin-inappbrowser": "1.1.1",
"cordova-plugin-file": "3.0.0",
"cordova-plugin-file-transfer": "1.4.0"
"cordova-plugin-file-transfer": "1.4.0",
"cordova-sqlite-storage": "0.7.15-pre",
"me.rahul.plugins.sqlDB": "1.0.3"
}
// BOTTOM OF METADATA
});

View File

@@ -3,6 +3,7 @@
font-family: 'Lobster', cursive;
}
.lobsterMiddle{
font-family: 'Lobster', cursive;
font-size: 1.2em;
@@ -22,35 +23,45 @@
.item-divider{
background-image: linear-gradient(
hsla(340, 100%, 35%, 1) 20%,
hsl(340,100%,54%) 90%
hsla(0, 94%, 33%, 1) 20%,
hsl(0,94%,54%) 90%
);
color:white;
}
.tabs-addddssertive > .tabs{
background-image: linear-gradient(
hsla(340, 100%, 35%, 1) 20%,
hsl(340,100%,54%) 90%
hsla(0, 94%, 33%, 1) 20%,
hsl(0,94%,54%) 90%
) !important;
}
.tabs-assertive > .tabs{
background-color: #BD0340 !important;
.tabs-assertive > .tabs{
background-color: #A50505 !important;
}
.bar-custom{
background-image: linear-gradient(
hsla(340, 100%, 35%, 1) 20%,
hsl(340,100%,54%) 90%
hsla(0, 94%, 33%, 1) 20%,
hsl(0,94%,54%) 90%
) !important;
font-family: 'Bubblegum Sans', cursive;
}
.button-custom{
background-color: #C60545;
text-decoration: none;
border: 1px solid #C60545;
border-color: #F9135F #F9135F #F9135F #F9135F;
color: #fff
}
font-family: 'Bubblegum Sans', cursive;
background-color: #A50505;
text-decoration: none;
border: 1px solid #A50505;
color: #fff
}
.oleo{
font-family: 'Bubblegum Sans', cursive;
font-size: 1.3em !important;
}

View File

@@ -8,6 +8,7 @@
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href='https://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Oswald:400,300,700' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Bubblegum+Sans' rel='stylesheet' type='text/css'>
<link href="css/style.css" rel="stylesheet">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
@@ -16,7 +17,7 @@
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<script src="js/ng-cordova.min.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="cordova.js"></script>

View File

@@ -5,21 +5,55 @@
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
var db;
.run(function($ionicPlatform, $ionicPopup) {
angular.module('starter', ['ionic', 'ngCordova', 'starter.controllers', 'starter.services'])
.run(function($ionicPlatform, $window, $ionicHistory, $database, $ionicPopup, $state, $localstorage, $rootScope) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
$ionicPlatform.registerBackButtonAction(function(event) {
// Handle Android back button to avoid the application exits accidentaly
if ($state.current.name=="tab.dash") {
$ionicPopup.confirm({
title: 'System-Hinweis',
template: 'Möchten Sie die App beenden?'
}).then(function(res) {
if (res) {
ionic.Platform.exitApp();
}
});
} else {
$ionicHistory.clearCache();
$ionicHistory.nextViewOptions({
historyRoot: true
});
$state.go('tab.dash');
}
}, 100);
if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
// Mandatory for InAppBrowser plugin
if(window.cordova){
window.open = cordova.InAppBrowser.open;
}
// Copy the populated database to mobile device destination
//if (window.sqlitePlugin && window.cordova) {
if (window.sqlitePlugin && window.cordova) {
window.plugins.sqlDB.copy("raataar_wrk.db", function (e) {
console.log(e);
});
}
function successHandler (result) {
var strResult = "";
@@ -39,7 +73,16 @@ angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
if((window.device && device.platform == "Android") && typeof inappbilling !== "undefined") {
inappbilling.init(successHandler, errorHandler, {showLog:true});
}
// Initialize database through $database service
db = $database.initDB();
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})

View File

@@ -1,6 +1,6 @@
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope,$ionicPopup,$http, $localstorage) {
.controller('DashCtrl', function($scope,$ionicPopup,$http, $database) {
$scope.preis="";
$scope.name="";
@@ -8,7 +8,9 @@ angular.module('starter.controllers', [])
$scope.items=[];
$scope.item=[];
$scope.items=$localstorage.getObject('items');
//db = Database.getDb();
//$scope.items=$localstorage.getObject('items');
$scope.validate = function() {
@@ -22,16 +24,30 @@ angular.module('starter.controllers', [])
};
$scope.loaddata = function() {
$scope.items=$localstorage.getObject('items');
alert(JSON.stringify($scope.items));
$scope.items=[];
$database.getAllBuys().then(function (result) {
if(result.length>0){
alert("daten da");
for(i=0;i<result.length;i++){
$scope.items.push(result[i]);
alert(i);
}
} else {
$scope.items=[];
}
});
};
$scope.savedata = function() {
$scope.item={name: $scope.name, freitext: $scope.freitext, rosen: $scope.preis, bild: "test"};
alert(JSON.stringify($scope.item));
$scope.item={name: $scope.name, bild: "test"};
$scope.items.push($scope.item);
$localstorage.setObject('items',$scope.items);
$database.setBuys($scope.name,"test");
};
function successBuyHandler (result) {
@@ -78,14 +94,22 @@ angular.module('starter.controllers', [])
})
.controller('BuysCtrl', function($scope, $localstorage,$location) {
.controller('BuysCtrl', function($scope, $database,$location) {
$scope.items=[];
$scope.items=$localstorage.getObject('items');
//$scope.items=$localstorage.getObject('items');
$scope.$on('$stateChangeSuccess', function(event, toState, toParams, fromState, fromParams) {
if ($location.path() == "/tab/buys") {
$scope.items=$localstorage.getObject('items');
}
$database.getAllBuys().then(function (result) {
if(result.length>0){
for(i=0;i<result.length;i++){
$scope.items.push(result[i]);
}
} else {
$scope.items=[];
}
});
}
});

File diff suppressed because one or more lines are too long

View File

@@ -1,19 +1,94 @@
angular.module('starter.services', [])
.factory('$localstorage', ['$window', function($window) {
return {
set: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
setObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key) {
return JSON.parse($window.localStorage[key] || '{}');
return {
set: function(key, value) {
$window.localStorage[key] = value;
},
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
setObject: function(key, value) {
$window.localStorage[key] = angular.toJson(value);
},
getObject: function(key) {
return JSON.parse($window.localStorage[key] || '[]');
},
destroy: function(key) {
$window.localStorage.removeItem(key);
},
log: function(key, defaultValue) {
console.log($window.localStorage[key] || defaultValue);
},
logObject: function(key) {
console.log(JSON.stringify($window.localStorage[key] || '{}'));
}
};
}])
.factory('$database',['$cordovaSQLite', function($cordovaSQLite) {
var self = this;
self.db = null;
var query;
//this updateTable function is for ilustrative use here, it can be changed to manage all queries indeed.
updateTable=function (table, column, value, condition) {
if(!condition){
query = "UPDATE " + table + " SET " + column + " = " + value;
} else{
query = "UPDATE " + table + " SET " + column + " = " + value + " WHERE " + condition;
}
}
}]);
return $cordovaSQLite.execute(self.db,query,[]).
then(function(result) {
console.log(query);
query=null;
return result;
},function(error) {
console.error(error);
query=null;
return error;
});
};
return {
initDB: function() {
if(window.cordova){
//self.db = sqlitePlugin.openDatabase({name: "data.db", location: 2, createFromLocation: 1});
self.db = $cordovaSQLite.openDB("raataar_wrk.db");
} else {
self.db = window.openDatabase('raataar_wrk.db','1','my',800*1024); // only available when WebSQL is available in Browser
}
console.log('Database opened');
return self.db;
},
setBuys: function(itemName,itemBild) {
query="INSERT INTO buys (Name, Bild) VALUES (?,?);";
return $cordovaSQLite.execute(self.db,query,[itemName,itemBild]).
then(function(result) {
console.log("Gespeichert");
query=null;
}, function(error) {
console.error(error);
});
},
getAllBuys: function(){
var ArrayQ=[];
query="SELECT * FROM buys order by id ASC";
return $cordovaSQLite.execute(self.db,query).
then(function(result) {
for(j=0;j<result.rows.length;j++){
var List={};
//console.log(result.rows.item(j));
List.name=result.rows.item(j).Name;
List.bild=result.rows.item(j).Bild;
ArrayQ.push(List);
}
//console.log(ArrayQ);
return ArrayQ;
},function(e){
console.error(error);
return error;
});
}
};
}]);

View File

@@ -1,4 +1,4 @@
@charset "UTF-8";
@charset "UTF-8";
/*!
* Copyright 2014 Drifty Co.
* http://drifty.com/

View File

@@ -0,0 +1,576 @@
cordova.define("cordova-sqlite-storage.SQLitePlugin", function(require, exports, module) { (function() {
var DB_STATE_INIT, DB_STATE_OPEN, READ_ONLY_REGEX, SQLiteFactory, SQLitePlugin, SQLitePluginTransaction, argsArray, dblocations, newSQLError, nextTick, root, txLocks;
root = this;
READ_ONLY_REGEX = /^\s*(?:drop|delete|insert|update|create)\s/i;
DB_STATE_INIT = "INIT";
DB_STATE_OPEN = "OPEN";
txLocks = {};
newSQLError = function(error, code) {
var sqlError;
sqlError = error;
if (!code) {
code = 0;
}
if (!sqlError) {
sqlError = new Error("a plugin had an error but provided no response");
sqlError.code = code;
}
if (typeof sqlError === "string") {
sqlError = new Error(error);
sqlError.code = code;
}
if (!sqlError.code && sqlError.message) {
sqlError.code = code;
}
if (!sqlError.code && !sqlError.message) {
sqlError = new Error("an unknown error was returned: " + JSON.stringify(sqlError));
sqlError.code = code;
}
return sqlError;
};
nextTick = window.setImmediate || function(fun) {
window.setTimeout(fun, 0);
};
/*
Utility that avoids leaking the arguments object. See
https://www.npmjs.org/package/argsarray
*/
argsArray = function(fun) {
return function() {
var args, i, len;
len = arguments.length;
if (len) {
args = [];
i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
} else {
return fun.call(this, []);
}
};
};
SQLitePlugin = function(openargs, openSuccess, openError) {
var dbname;
if (!(openargs && openargs['name'])) {
throw newSQLError("Cannot create a SQLitePlugin db instance without a db name");
}
dbname = openargs.name;
if (typeof dbname !== 'string') {
throw newSQLError('sqlite plugin database name must be a string');
}
this.openargs = openargs;
this.dbname = dbname;
this.openSuccess = openSuccess;
this.openError = openError;
this.openSuccess || (this.openSuccess = function() {
console.log("DB opened: " + dbname);
});
this.openError || (this.openError = function(e) {
console.log(e.message);
});
this.open(this.openSuccess, this.openError);
};
SQLitePlugin.prototype.databaseFeatures = {
isSQLitePluginDatabase: true
};
SQLitePlugin.prototype.openDBs = {};
SQLitePlugin.prototype.addTransaction = function(t) {
if (!txLocks[this.dbname]) {
txLocks[this.dbname] = {
queue: [],
inProgress: false
};
}
txLocks[this.dbname].queue.push(t);
if (this.dbname in this.openDBs && this.openDBs[this.dbname] !== DB_STATE_INIT) {
this.startNextTransaction();
} else {
if (this.dbname in this.openDBs) {
console.log('new transaction is waiting for open operation');
} else {
console.log('database is closed, new transaction is [stuck] waiting until db is opened again!');
}
}
};
SQLitePlugin.prototype.transaction = function(fn, error, success) {
if (!this.openDBs[this.dbname]) {
error(newSQLError('database not open'));
return;
}
this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, true, false));
};
SQLitePlugin.prototype.readTransaction = function(fn, error, success) {
if (!this.openDBs[this.dbname]) {
error(newSQLError('database not open'));
return;
}
this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, false, true));
};
SQLitePlugin.prototype.startNextTransaction = function() {
var self;
self = this;
nextTick((function(_this) {
return function() {
var txLock;
if (!(_this.dbname in _this.openDBs) || _this.openDBs[_this.dbname] !== DB_STATE_OPEN) {
console.log('cannot start next transaction: database not open');
return;
}
txLock = txLocks[self.dbname];
if (!txLock) {
console.log('cannot start next transaction: database connection is lost');
return;
} else if (txLock.queue.length > 0 && !txLock.inProgress) {
txLock.inProgress = true;
txLock.queue.shift().start();
}
};
})(this));
};
SQLitePlugin.prototype.abortAllPendingTransactions = function() {
var j, len1, ref, tx, txLock;
txLock = txLocks[this.dbname];
if (!!txLock && txLock.queue.length > 0) {
ref = txLock.queue;
for (j = 0, len1 = ref.length; j < len1; j++) {
tx = ref[j];
tx.abortFromQ(newSQLError('Invalid database handle'));
}
txLock.queue = [];
txLock.inProgress = false;
}
};
SQLitePlugin.prototype.open = function(success, error) {
var openerrorcb, opensuccesscb;
if (this.dbname in this.openDBs) {
console.log('database already open: ' + this.dbname);
nextTick((function(_this) {
return function() {
success(_this);
};
})(this));
} else {
console.log('OPEN database: ' + this.dbname);
opensuccesscb = (function(_this) {
return function() {
var txLock;
if (!_this.openDBs[_this.dbname]) {
console.log('database was closed during open operation');
}
if (_this.dbname in _this.openDBs) {
_this.openDBs[_this.dbname] = DB_STATE_OPEN;
}
if (!!success) {
success(_this);
}
txLock = txLocks[_this.dbname];
if (!!txLock && txLock.queue.length > 0 && !txLock.inProgress) {
_this.startNextTransaction();
}
};
})(this);
openerrorcb = (function(_this) {
return function() {
console.log('OPEN database: ' + _this.dbname + ' failed, aborting any pending transactions');
if (!!error) {
error(newSQLError('Could not open database'));
}
delete _this.openDBs[_this.dbname];
_this.abortAllPendingTransactions();
};
})(this);
this.openDBs[this.dbname] = DB_STATE_INIT;
cordova.exec(opensuccesscb, openerrorcb, "SQLitePlugin", "open", [this.openargs]);
}
};
SQLitePlugin.prototype.close = function(success, error) {
if (this.dbname in this.openDBs) {
if (txLocks[this.dbname] && txLocks[this.dbname].inProgress) {
console.log('cannot close: transaction is in progress');
error(newSQLError('database cannot be closed while a transaction is in progress'));
return;
}
console.log('CLOSE database: ' + this.dbname);
delete this.openDBs[this.dbname];
if (txLocks[this.dbname]) {
console.log('closing db with transaction queue length: ' + txLocks[this.dbname].queue.length);
} else {
console.log('closing db with no transaction lock state');
}
cordova.exec(success, error, "SQLitePlugin", "close", [
{
path: this.dbname
}
]);
} else {
console.log('cannot close: database is not open');
if (error) {
nextTick(function() {
return error();
});
}
}
};
SQLitePlugin.prototype.executeSql = function(statement, params, success, error) {
var myerror, myfn, mysuccess;
mysuccess = function(t, r) {
if (!!success) {
return success(r);
}
};
myerror = function(t, e) {
if (!!error) {
return error(e);
}
};
myfn = function(tx) {
tx.addStatement(statement, params, mysuccess, myerror);
};
this.addTransaction(new SQLitePluginTransaction(this, myfn, null, null, false, false));
};
SQLitePluginTransaction = function(db, fn, error, success, txlock, readOnly) {
if (typeof fn !== "function") {
/*
This is consistent with the implementation in Chrome -- it
throws if you pass anything other than a function. This also
prevents us from stalling our txQueue if somebody passes a
false value for fn.
*/
throw newSQLError("transaction expected a function");
}
this.db = db;
this.fn = fn;
this.error = error;
this.success = success;
this.txlock = txlock;
this.readOnly = readOnly;
this.executes = [];
if (txlock) {
this.addStatement("BEGIN", [], null, function(tx, err) {
throw newSQLError("unable to begin transaction: " + err.message, err.code);
});
}
};
SQLitePluginTransaction.prototype.start = function() {
var err, error1;
try {
this.fn(this);
this.run();
} catch (error1) {
err = error1;
txLocks[this.db.dbname].inProgress = false;
this.db.startNextTransaction();
if (this.error) {
this.error(newSQLError(err));
}
}
};
SQLitePluginTransaction.prototype.executeSql = function(sql, values, success, error) {
if (this.finalized) {
throw {
message: 'InvalidStateError: DOM Exception 11: This transaction is already finalized. Transactions are committed after its success or failure handlers are called. If you are using a Promise to handle callbacks, be aware that implementations following the A+ standard adhere to run-to-completion semantics and so Promise resolution occurs on a subsequent tick and therefore after the transaction commits.',
code: 11
};
return;
}
if (this.readOnly && READ_ONLY_REGEX.test(sql)) {
this.handleStatementFailure(error, {
message: 'invalid sql for a read-only transaction'
});
return;
}
this.addStatement(sql, values, success, error);
};
SQLitePluginTransaction.prototype.addStatement = function(sql, values, success, error) {
var j, len1, params, t, v;
params = [];
if (!!values && values.constructor === Array) {
for (j = 0, len1 = values.length; j < len1; j++) {
v = values[j];
t = typeof v;
params.push((v === null || v === void 0 || t === 'number' || t === 'string' ? v : v instanceof Blob ? v.valueOf() : v.toString()));
}
}
this.executes.push({
success: success,
error: error,
sql: sql,
params: params
});
};
SQLitePluginTransaction.prototype.handleStatementSuccess = function(handler, response) {
var payload, rows;
if (!handler) {
return;
}
rows = response.rows || [];
payload = {
rows: {
item: function(i) {
return rows[i];
},
length: rows.length
},
rowsAffected: response.rowsAffected || 0,
insertId: response.insertId || void 0
};
handler(this, payload);
};
SQLitePluginTransaction.prototype.handleStatementFailure = function(handler, response) {
if (!handler) {
throw newSQLError("a statement with no error handler failed: " + response.message, response.code);
}
if (handler(this, response) !== false) {
throw newSQLError("a statement error callback did not return false: " + response.message, response.code);
}
};
SQLitePluginTransaction.prototype.run = function() {
var batchExecutes, handlerFor, i, mycb, mycbmap, request, tropts, tx, txFailure, waiting;
txFailure = null;
tropts = [];
batchExecutes = this.executes;
waiting = batchExecutes.length;
this.executes = [];
tx = this;
handlerFor = function(index, didSucceed) {
return function(response) {
var err, error1;
try {
if (didSucceed) {
tx.handleStatementSuccess(batchExecutes[index].success, response);
} else {
tx.handleStatementFailure(batchExecutes[index].error, newSQLError(response));
}
} catch (error1) {
err = error1;
if (!txFailure) {
txFailure = newSQLError(err);
}
}
if (--waiting === 0) {
if (txFailure) {
tx.abort(txFailure);
} else if (tx.executes.length > 0) {
tx.run();
} else {
tx.finish();
}
}
};
};
i = 0;
mycbmap = {};
while (i < batchExecutes.length) {
request = batchExecutes[i];
mycbmap[i] = {
success: handlerFor(i, true),
error: handlerFor(i, false)
};
tropts.push({
qid: 1111,
sql: request.sql,
params: request.params
});
i++;
}
mycb = function(result) {
var j, last, q, r, ref, res, type;
last = result.length - 1;
for (i = j = 0, ref = last; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) {
r = result[i];
type = r.type;
res = r.result;
q = mycbmap[i];
if (q) {
if (q[type]) {
q[type](res);
}
}
}
};
cordova.exec(mycb, null, "SQLitePlugin", "backgroundExecuteSqlBatch", [
{
dbargs: {
dbname: this.db.dbname
},
executes: tropts
}
]);
};
SQLitePluginTransaction.prototype.abort = function(txFailure) {
var failed, succeeded, tx;
if (this.finalized) {
return;
}
tx = this;
succeeded = function(tx) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(txFailure);
}
};
failed = function(tx, err) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(newSQLError("error while trying to roll back: " + err.message, err.code));
}
};
this.finalized = true;
if (this.txlock) {
this.addStatement("ROLLBACK", [], succeeded, failed);
this.run();
} else {
succeeded(tx);
}
};
SQLitePluginTransaction.prototype.finish = function() {
var failed, succeeded, tx;
if (this.finalized) {
return;
}
tx = this;
succeeded = function(tx) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.success) {
tx.success();
}
};
failed = function(tx, err) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(newSQLError("error while trying to commit: " + err.message, err.code));
}
};
this.finalized = true;
if (this.txlock) {
this.addStatement("COMMIT", [], succeeded, failed);
this.run();
} else {
succeeded(tx);
}
};
SQLitePluginTransaction.prototype.abortFromQ = function(sqlerror) {
if (this.error) {
this.error(sqlerror);
}
};
dblocations = ["docs", "libs", "nosync"];
SQLiteFactory = {
/*
NOTE: this function should NOT be translated from Javascript
back to CoffeeScript by js2coffee.
If this function is edited in Javascript then someone will
have to translate it back to CoffeeScript by hand.
*/
opendb: argsArray(function(args) {
var dblocation, errorcb, first, okcb, openargs;
if (args.length < 1) {
return null;
}
first = args[0];
openargs = null;
okcb = null;
errorcb = null;
if (first.constructor === String) {
openargs = {
name: first
};
if (args.length >= 5) {
okcb = args[4];
if (args.length > 5) {
errorcb = args[5];
}
}
} else {
openargs = first;
if (args.length >= 2) {
okcb = args[1];
if (args.length > 2) {
errorcb = args[2];
}
}
}
dblocation = !!openargs.location ? dblocations[openargs.location] : null;
openargs.dblocation = dblocation || dblocations[0];
if (!!openargs.createFromLocation && openargs.createFromLocation === 1) {
openargs.createFromResource = "1";
}
if (!!openargs.androidDatabaseImplementation && openargs.androidDatabaseImplementation === 2) {
openargs.androidOldDatabaseImplementation = 1;
}
if (!!openargs.androidLockWorkaround && openargs.androidLockWorkaround === 1) {
openargs.androidBugWorkaround = 1;
}
return new SQLitePlugin(openargs, okcb, errorcb);
}),
deleteDb: function(first, success, error) {
var args, dblocation;
args = {};
if (first.constructor === String) {
args.path = first;
args.dblocation = dblocations[0];
} else {
if (!(first && first['name'])) {
throw new Error("Please specify db name");
}
args.path = first.name;
dblocation = !!first.location ? dblocations[first.location] : null;
args.dblocation = dblocation || dblocations[0];
}
delete SQLitePlugin.prototype.openDBs[args.path];
return cordova.exec(success, error, "SQLitePlugin", "delete", [args]);
}
};
root.sqlitePlugin = {
sqliteFeatures: {
isSQLitePlugin: true
},
openDatabase: SQLiteFactory.opendb,
deleteDatabase: SQLiteFactory.deleteDb
};
}).call(this);
});

View File

@@ -0,0 +1,11 @@
cordova.define("me.rahul.plugins.sqlDB.sqlDB", function(require, exports, module) { var exec = require('cordova/exec');
exports.copy = function(dbname, location, success, error) {
exec(success, error, "sqlDB", "copy", [dbname, location]);
};
exports.remove = function(dbname, location, success,error) {
exec(success, error, "sqlDB", "remove", [dbname, location]);
};
});

View File

@@ -1,11 +1,11 @@
<ion-view view-title="Gekaufte Rosen">
<ion-content>
<ion-content class="padding">
<div style="padding-bottom:15px;">
<div class="item item-divider oswald">Hier können Sie Ihre gekauften Rosen ansehen oder nochmals versenden!</div>
<ul class="list card">
<div class="item item-divider oleo">Hier können Sie Ihre gekauften Rosen ansehen oder nochmals versenden!</div>
<ul class="list">
<a class="item item-thumbnail-left item-button-right" href="#" ng-repeat="i in items" ng-model="items">
<img src="img/rose1.png">
<h1>{{i.name}}</h1>
@@ -21,10 +21,6 @@
</a>
</ul>
</div>

View File

@@ -1,43 +1,28 @@
<ion-view view-title='Rosen kaufen'>
<ion-content class="padding">
<div class="list card">
<div class="item item-divider oswald">Wolle Rose kaufen?</div>
<div class="item item-body lobster">
<div style="padding-bottom:25px;">
Schenken Sie einem besonderen Menschen eine aussergewöhnliche Aufmerksamkeit.
</div>
<div class="item item-divider oswald">An wen wollen Sie die Rose verschenken</div>
<div class="list list-inset" style="padding-bottom:15px;">
<div class="item item-divider oleo">Schenken Sie einem besonderen Menschen eine außergewöhnliche Aufmerksamkeit!</div>
<label class="item item-input item-stacked-label">
<span class="input-label">Name Ihres Liebsten:</span>
<input type="text" placeholder="" class="lobster" ng-model="$parent.name">
<input type="text" placeholder="" class="oleo" ng-model="$parent.name">
</label>
<label class="item item-input item-stacked-label">
<span class="input-label">Ihre persönliche Nachricht:</span>
<textarea placeholder="" rows="4" cols="10" class="lobster" ng-model="$parent.freitext"></textarea>
<textarea placeholder="" rows="4" cols="10" class="oleo" ng-model="$parent.freitext"></textarea>
</label>
</div>
<div style="padding-bottom:15px;">
<div class="item item-divider oswald">Wählen Sie Ihre Rosen aus</div>
<div class="item item-divider oleo">Wählen Sie Ihre Rosen aus:</div>
<ion-list>
<ion-radio ng-model="$parent.preis" ng-value="'1xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose1.png"><h2 class="lobster">1 Rose </h2><p>Preis: 0,50 € (inkl. Mwst 0,59 €)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'3xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose3.png"><h2 class="lobster">3 Rosen</h2><p>Preis: 1,00 € (inkl. Mwst 1,19 €)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'9xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose10.png"><h2 class="lobster">9 Rosen</h2><p>Preis: 2,00 € (inkl. Mwst 2,38 €)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'1xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose1.png"><h2 class="oleo">1 Rose </h2><p>Preis: 0,50 € (zzgl. gesetzl. MwSt.)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'3xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose3.png"><h2 class="oleo">3 Rosen</h2><p>Preis: 1,00 € (zzgl. gesetzl. MwSt.)</p></ion-radio>
<ion-radio ng-model="$parent.preis" ng-value="'9xrose'" class="item item-thumbnail-left item-text-wrap"><img src="img/rose10.png"><h2 class="oleo">9 Rosen</h2><p>Preis: 2,00 € (zzgl. gesetzl. MwSt.)</p></ion-radio>
</ion-list>
<label class="item item-input item-select">
<div class="input-label">
Farbe
</div>
<select>
<option selected>Rot</option>
<option>Gelb</option>
<option>Weiß</option>
</select>
</label>
</div>
<div class="item item-divider oswald">Rosen kaufen?</div>
</div>
<div class="list card">
<div class="item item-divider oleo">Rosen jetzt kaufen?</div>
<div class="row">
<div class="col col-50"><button class="button button-full button-small icon-left ion-image button-custom" ng-disabled="!$parent.preis || !$parent.name || !$parent.freitext" ng-click="validate()">Vorschau</button></div>
<div class="col col-50"><button class="button button-full button-small icon-left ion-social-euro button-custom" ng-disabled="!$parent.preis || !$parent.freitext || !$parent.name" ng-click="buyRose()">Jetzt Kaufen</button></div>
@@ -47,7 +32,7 @@
<div class="col col-50"><button class="button button-full button-small icon-left ion-image button-custom" ng-disabled="!$parent.preis || !$parent.name || !$parent.freitext" ng-click="loaddata()">Laden</button></div>
<div class="col col-50"><button class="button button-full button-small icon-left ion-social-euro button-custom" ng-disabled="!$parent.preis || !$parent.freitext || !$parent.name" ng-click="savedata()">Speichern</button></div>
</div>
</div>
</div>
</div>

View File

@@ -15,6 +15,13 @@
sha1="565e3f24555b91a41efb1022e4b38d97307ce180">
<dex dex="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\build\intermediates\pre-dexed\debug\classes-a0342bad41111596f8436cda33b5a5ee045fab74.jar" />
</item>
<item
jar="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\libs\sqlite-connector.jar"
jumboMode="false"
revision="22.0.1"
sha1="3193260c427164169c8e7f97cfc2bdd7c8efa18d">
<dex dex="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\build\intermediates\pre-dexed\debug\sqlite-connector-885e15ab34f1a9bfda8db7efc740bde597caea8c.jar" />
</item>
<item
jar="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\build\intermediates\exploded-aar\android\CordovaLib\unspecified\debug\classes.jar"
jumboMode="false"

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<merger version="3"><dataSet config="main"><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\src\androidTest\assets"/></dataSet></merger>
<merger version="3"><dataSet config="main"><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\src\androidTest\assets"/></dataSet></merger>

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<merger version="3"><dataSet config="main"><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\src\androidTest\res"/><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\build\generated\res\rs\test\debug"/><source path="C:\Ionic\Ionic\wollerosenkaufen\platforms\android\build\generated\res\generated\test\debug"/></dataSet><mergedItems/></merger>
<merger version="3"><dataSet config="main"><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\src\androidTest\res"/><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\build\generated\res\rs\test\debug"/><source path="C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\build\generated\res\generated\test\debug"/></dataSet><mergedItems/></merger>

View File

@@ -33,6 +33,12 @@
<feature name="FileTransfer">
<param name="android-package" value="org.apache.cordova.filetransfer.FileTransfer" />
</feature>
<feature name="SQLitePlugin">
<param name="android-package" value="io.liteglue.SQLitePlugin" />
</feature>
<feature name="sqlDB">
<param name="android-package" value="me.rahul.plugins.sqlDB.sqlDB" />
</feature>
<preference name="AndroidPersistentFileLocation" value="Internal" />
<icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
<icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />

View File

@@ -1,2 +1,3 @@
C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\build\intermediates\classes\debug
C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\build\intermediates\pre-dexed\debug\sqlite-connector-885e15ab34f1a9bfda8db7efc740bde597caea8c.jar
C:\Ionic\Ionic\git\wolle-rosen-kaufen\platforms\android\build\intermediates\pre-dexed\debug\classes-ec055bf14dc687da3d1b2ed76b77548ddec8270d.jar

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -7,5 +7,5 @@
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Thu Dec 17 20:46:38 CET 2015
#Fri Jan 15 00:58:01 CET 2016
sdk.dir=C\:\\Program Files (x86)\\Android\\android-sdk

View File

@@ -238,6 +238,22 @@ module.exports = [
"clobbers": [
"window.FileTransfer"
]
},
{
"file": "plugins/cordova-sqlite-storage/www/SQLitePlugin.js",
"id": "cordova-sqlite-storage.SQLitePlugin",
"pluginId": "cordova-sqlite-storage",
"clobbers": [
"SQLitePlugin"
]
},
{
"file": "plugins/me.rahul.plugins.sqlDB/www/sqlDB.js",
"id": "me.rahul.plugins.sqlDB.sqlDB",
"pluginId": "me.rahul.plugins.sqlDB",
"clobbers": [
"window.plugins.sqlDB"
]
}
];
module.exports.metadata =
@@ -252,7 +268,9 @@ module.exports.metadata =
"ionic-plugin-keyboard": "1.0.8",
"cordova-plugin-inappbrowser": "1.1.1",
"cordova-plugin-file": "3.0.0",
"cordova-plugin-file-transfer": "1.4.0"
"cordova-plugin-file-transfer": "1.4.0",
"cordova-sqlite-storage": "0.7.15-pre",
"me.rahul.plugins.sqlDB": "1.0.3"
}
// BOTTOM OF METADATA
});

View File

@@ -0,0 +1,576 @@
cordova.define("cordova-sqlite-storage.SQLitePlugin", function(require, exports, module) { (function() {
var DB_STATE_INIT, DB_STATE_OPEN, READ_ONLY_REGEX, SQLiteFactory, SQLitePlugin, SQLitePluginTransaction, argsArray, dblocations, newSQLError, nextTick, root, txLocks;
root = this;
READ_ONLY_REGEX = /^\s*(?:drop|delete|insert|update|create)\s/i;
DB_STATE_INIT = "INIT";
DB_STATE_OPEN = "OPEN";
txLocks = {};
newSQLError = function(error, code) {
var sqlError;
sqlError = error;
if (!code) {
code = 0;
}
if (!sqlError) {
sqlError = new Error("a plugin had an error but provided no response");
sqlError.code = code;
}
if (typeof sqlError === "string") {
sqlError = new Error(error);
sqlError.code = code;
}
if (!sqlError.code && sqlError.message) {
sqlError.code = code;
}
if (!sqlError.code && !sqlError.message) {
sqlError = new Error("an unknown error was returned: " + JSON.stringify(sqlError));
sqlError.code = code;
}
return sqlError;
};
nextTick = window.setImmediate || function(fun) {
window.setTimeout(fun, 0);
};
/*
Utility that avoids leaking the arguments object. See
https://www.npmjs.org/package/argsarray
*/
argsArray = function(fun) {
return function() {
var args, i, len;
len = arguments.length;
if (len) {
args = [];
i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
} else {
return fun.call(this, []);
}
};
};
SQLitePlugin = function(openargs, openSuccess, openError) {
var dbname;
if (!(openargs && openargs['name'])) {
throw newSQLError("Cannot create a SQLitePlugin db instance without a db name");
}
dbname = openargs.name;
if (typeof dbname !== 'string') {
throw newSQLError('sqlite plugin database name must be a string');
}
this.openargs = openargs;
this.dbname = dbname;
this.openSuccess = openSuccess;
this.openError = openError;
this.openSuccess || (this.openSuccess = function() {
console.log("DB opened: " + dbname);
});
this.openError || (this.openError = function(e) {
console.log(e.message);
});
this.open(this.openSuccess, this.openError);
};
SQLitePlugin.prototype.databaseFeatures = {
isSQLitePluginDatabase: true
};
SQLitePlugin.prototype.openDBs = {};
SQLitePlugin.prototype.addTransaction = function(t) {
if (!txLocks[this.dbname]) {
txLocks[this.dbname] = {
queue: [],
inProgress: false
};
}
txLocks[this.dbname].queue.push(t);
if (this.dbname in this.openDBs && this.openDBs[this.dbname] !== DB_STATE_INIT) {
this.startNextTransaction();
} else {
if (this.dbname in this.openDBs) {
console.log('new transaction is waiting for open operation');
} else {
console.log('database is closed, new transaction is [stuck] waiting until db is opened again!');
}
}
};
SQLitePlugin.prototype.transaction = function(fn, error, success) {
if (!this.openDBs[this.dbname]) {
error(newSQLError('database not open'));
return;
}
this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, true, false));
};
SQLitePlugin.prototype.readTransaction = function(fn, error, success) {
if (!this.openDBs[this.dbname]) {
error(newSQLError('database not open'));
return;
}
this.addTransaction(new SQLitePluginTransaction(this, fn, error, success, false, true));
};
SQLitePlugin.prototype.startNextTransaction = function() {
var self;
self = this;
nextTick((function(_this) {
return function() {
var txLock;
if (!(_this.dbname in _this.openDBs) || _this.openDBs[_this.dbname] !== DB_STATE_OPEN) {
console.log('cannot start next transaction: database not open');
return;
}
txLock = txLocks[self.dbname];
if (!txLock) {
console.log('cannot start next transaction: database connection is lost');
return;
} else if (txLock.queue.length > 0 && !txLock.inProgress) {
txLock.inProgress = true;
txLock.queue.shift().start();
}
};
})(this));
};
SQLitePlugin.prototype.abortAllPendingTransactions = function() {
var j, len1, ref, tx, txLock;
txLock = txLocks[this.dbname];
if (!!txLock && txLock.queue.length > 0) {
ref = txLock.queue;
for (j = 0, len1 = ref.length; j < len1; j++) {
tx = ref[j];
tx.abortFromQ(newSQLError('Invalid database handle'));
}
txLock.queue = [];
txLock.inProgress = false;
}
};
SQLitePlugin.prototype.open = function(success, error) {
var openerrorcb, opensuccesscb;
if (this.dbname in this.openDBs) {
console.log('database already open: ' + this.dbname);
nextTick((function(_this) {
return function() {
success(_this);
};
})(this));
} else {
console.log('OPEN database: ' + this.dbname);
opensuccesscb = (function(_this) {
return function() {
var txLock;
if (!_this.openDBs[_this.dbname]) {
console.log('database was closed during open operation');
}
if (_this.dbname in _this.openDBs) {
_this.openDBs[_this.dbname] = DB_STATE_OPEN;
}
if (!!success) {
success(_this);
}
txLock = txLocks[_this.dbname];
if (!!txLock && txLock.queue.length > 0 && !txLock.inProgress) {
_this.startNextTransaction();
}
};
})(this);
openerrorcb = (function(_this) {
return function() {
console.log('OPEN database: ' + _this.dbname + ' failed, aborting any pending transactions');
if (!!error) {
error(newSQLError('Could not open database'));
}
delete _this.openDBs[_this.dbname];
_this.abortAllPendingTransactions();
};
})(this);
this.openDBs[this.dbname] = DB_STATE_INIT;
cordova.exec(opensuccesscb, openerrorcb, "SQLitePlugin", "open", [this.openargs]);
}
};
SQLitePlugin.prototype.close = function(success, error) {
if (this.dbname in this.openDBs) {
if (txLocks[this.dbname] && txLocks[this.dbname].inProgress) {
console.log('cannot close: transaction is in progress');
error(newSQLError('database cannot be closed while a transaction is in progress'));
return;
}
console.log('CLOSE database: ' + this.dbname);
delete this.openDBs[this.dbname];
if (txLocks[this.dbname]) {
console.log('closing db with transaction queue length: ' + txLocks[this.dbname].queue.length);
} else {
console.log('closing db with no transaction lock state');
}
cordova.exec(success, error, "SQLitePlugin", "close", [
{
path: this.dbname
}
]);
} else {
console.log('cannot close: database is not open');
if (error) {
nextTick(function() {
return error();
});
}
}
};
SQLitePlugin.prototype.executeSql = function(statement, params, success, error) {
var myerror, myfn, mysuccess;
mysuccess = function(t, r) {
if (!!success) {
return success(r);
}
};
myerror = function(t, e) {
if (!!error) {
return error(e);
}
};
myfn = function(tx) {
tx.addStatement(statement, params, mysuccess, myerror);
};
this.addTransaction(new SQLitePluginTransaction(this, myfn, null, null, false, false));
};
SQLitePluginTransaction = function(db, fn, error, success, txlock, readOnly) {
if (typeof fn !== "function") {
/*
This is consistent with the implementation in Chrome -- it
throws if you pass anything other than a function. This also
prevents us from stalling our txQueue if somebody passes a
false value for fn.
*/
throw newSQLError("transaction expected a function");
}
this.db = db;
this.fn = fn;
this.error = error;
this.success = success;
this.txlock = txlock;
this.readOnly = readOnly;
this.executes = [];
if (txlock) {
this.addStatement("BEGIN", [], null, function(tx, err) {
throw newSQLError("unable to begin transaction: " + err.message, err.code);
});
}
};
SQLitePluginTransaction.prototype.start = function() {
var err, error1;
try {
this.fn(this);
this.run();
} catch (error1) {
err = error1;
txLocks[this.db.dbname].inProgress = false;
this.db.startNextTransaction();
if (this.error) {
this.error(newSQLError(err));
}
}
};
SQLitePluginTransaction.prototype.executeSql = function(sql, values, success, error) {
if (this.finalized) {
throw {
message: 'InvalidStateError: DOM Exception 11: This transaction is already finalized. Transactions are committed after its success or failure handlers are called. If you are using a Promise to handle callbacks, be aware that implementations following the A+ standard adhere to run-to-completion semantics and so Promise resolution occurs on a subsequent tick and therefore after the transaction commits.',
code: 11
};
return;
}
if (this.readOnly && READ_ONLY_REGEX.test(sql)) {
this.handleStatementFailure(error, {
message: 'invalid sql for a read-only transaction'
});
return;
}
this.addStatement(sql, values, success, error);
};
SQLitePluginTransaction.prototype.addStatement = function(sql, values, success, error) {
var j, len1, params, t, v;
params = [];
if (!!values && values.constructor === Array) {
for (j = 0, len1 = values.length; j < len1; j++) {
v = values[j];
t = typeof v;
params.push((v === null || v === void 0 || t === 'number' || t === 'string' ? v : v instanceof Blob ? v.valueOf() : v.toString()));
}
}
this.executes.push({
success: success,
error: error,
sql: sql,
params: params
});
};
SQLitePluginTransaction.prototype.handleStatementSuccess = function(handler, response) {
var payload, rows;
if (!handler) {
return;
}
rows = response.rows || [];
payload = {
rows: {
item: function(i) {
return rows[i];
},
length: rows.length
},
rowsAffected: response.rowsAffected || 0,
insertId: response.insertId || void 0
};
handler(this, payload);
};
SQLitePluginTransaction.prototype.handleStatementFailure = function(handler, response) {
if (!handler) {
throw newSQLError("a statement with no error handler failed: " + response.message, response.code);
}
if (handler(this, response) !== false) {
throw newSQLError("a statement error callback did not return false: " + response.message, response.code);
}
};
SQLitePluginTransaction.prototype.run = function() {
var batchExecutes, handlerFor, i, mycb, mycbmap, request, tropts, tx, txFailure, waiting;
txFailure = null;
tropts = [];
batchExecutes = this.executes;
waiting = batchExecutes.length;
this.executes = [];
tx = this;
handlerFor = function(index, didSucceed) {
return function(response) {
var err, error1;
try {
if (didSucceed) {
tx.handleStatementSuccess(batchExecutes[index].success, response);
} else {
tx.handleStatementFailure(batchExecutes[index].error, newSQLError(response));
}
} catch (error1) {
err = error1;
if (!txFailure) {
txFailure = newSQLError(err);
}
}
if (--waiting === 0) {
if (txFailure) {
tx.abort(txFailure);
} else if (tx.executes.length > 0) {
tx.run();
} else {
tx.finish();
}
}
};
};
i = 0;
mycbmap = {};
while (i < batchExecutes.length) {
request = batchExecutes[i];
mycbmap[i] = {
success: handlerFor(i, true),
error: handlerFor(i, false)
};
tropts.push({
qid: 1111,
sql: request.sql,
params: request.params
});
i++;
}
mycb = function(result) {
var j, last, q, r, ref, res, type;
last = result.length - 1;
for (i = j = 0, ref = last; 0 <= ref ? j <= ref : j >= ref; i = 0 <= ref ? ++j : --j) {
r = result[i];
type = r.type;
res = r.result;
q = mycbmap[i];
if (q) {
if (q[type]) {
q[type](res);
}
}
}
};
cordova.exec(mycb, null, "SQLitePlugin", "backgroundExecuteSqlBatch", [
{
dbargs: {
dbname: this.db.dbname
},
executes: tropts
}
]);
};
SQLitePluginTransaction.prototype.abort = function(txFailure) {
var failed, succeeded, tx;
if (this.finalized) {
return;
}
tx = this;
succeeded = function(tx) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(txFailure);
}
};
failed = function(tx, err) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(newSQLError("error while trying to roll back: " + err.message, err.code));
}
};
this.finalized = true;
if (this.txlock) {
this.addStatement("ROLLBACK", [], succeeded, failed);
this.run();
} else {
succeeded(tx);
}
};
SQLitePluginTransaction.prototype.finish = function() {
var failed, succeeded, tx;
if (this.finalized) {
return;
}
tx = this;
succeeded = function(tx) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.success) {
tx.success();
}
};
failed = function(tx, err) {
txLocks[tx.db.dbname].inProgress = false;
tx.db.startNextTransaction();
if (tx.error) {
tx.error(newSQLError("error while trying to commit: " + err.message, err.code));
}
};
this.finalized = true;
if (this.txlock) {
this.addStatement("COMMIT", [], succeeded, failed);
this.run();
} else {
succeeded(tx);
}
};
SQLitePluginTransaction.prototype.abortFromQ = function(sqlerror) {
if (this.error) {
this.error(sqlerror);
}
};
dblocations = ["docs", "libs", "nosync"];
SQLiteFactory = {
/*
NOTE: this function should NOT be translated from Javascript
back to CoffeeScript by js2coffee.
If this function is edited in Javascript then someone will
have to translate it back to CoffeeScript by hand.
*/
opendb: argsArray(function(args) {
var dblocation, errorcb, first, okcb, openargs;
if (args.length < 1) {
return null;
}
first = args[0];
openargs = null;
okcb = null;
errorcb = null;
if (first.constructor === String) {
openargs = {
name: first
};
if (args.length >= 5) {
okcb = args[4];
if (args.length > 5) {
errorcb = args[5];
}
}
} else {
openargs = first;
if (args.length >= 2) {
okcb = args[1];
if (args.length > 2) {
errorcb = args[2];
}
}
}
dblocation = !!openargs.location ? dblocations[openargs.location] : null;
openargs.dblocation = dblocation || dblocations[0];
if (!!openargs.createFromLocation && openargs.createFromLocation === 1) {
openargs.createFromResource = "1";
}
if (!!openargs.androidDatabaseImplementation && openargs.androidDatabaseImplementation === 2) {
openargs.androidOldDatabaseImplementation = 1;
}
if (!!openargs.androidLockWorkaround && openargs.androidLockWorkaround === 1) {
openargs.androidBugWorkaround = 1;
}
return new SQLitePlugin(openargs, okcb, errorcb);
}),
deleteDb: function(first, success, error) {
var args, dblocation;
args = {};
if (first.constructor === String) {
args.path = first;
args.dblocation = dblocations[0];
} else {
if (!(first && first['name'])) {
throw new Error("Please specify db name");
}
args.path = first.name;
dblocation = !!first.location ? dblocations[first.location] : null;
args.dblocation = dblocation || dblocations[0];
}
delete SQLitePlugin.prototype.openDBs[args.path];
return cordova.exec(success, error, "SQLitePlugin", "delete", [args]);
}
};
root.sqlitePlugin = {
sqliteFeatures: {
isSQLitePlugin: true
},
openDatabase: SQLiteFactory.opendb,
deleteDatabase: SQLiteFactory.deleteDb
};
}).call(this);
});

View File

@@ -0,0 +1,11 @@
cordova.define("me.rahul.plugins.sqlDB.sqlDB", function(require, exports, module) { var exec = require('cordova/exec');
exports.copy = function(dbname, location, success, error) {
exec(success, error, "sqlDB", "copy", [dbname, location]);
};
exports.remove = function(dbname, location, success,error) {
exec(success, error, "sqlDB", "remove", [dbname, location]);
};
});

View File

@@ -33,6 +33,12 @@
<feature name="FileTransfer">
<param name="android-package" value="org.apache.cordova.filetransfer.FileTransfer" />
</feature>
<feature name="SQLitePlugin">
<param name="android-package" value="io.liteglue.SQLitePlugin" />
</feature>
<feature name="sqlDB">
<param name="android-package" value="me.rahul.plugins.sqlDB.sqlDB" />
</feature>
<preference name="AndroidPersistentFileLocation" value="Internal" />
<icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
<icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />

View File

@@ -0,0 +1,509 @@
/*
* Copyright (c) 2012-2015: Christopher J. Brody (aka Chris Brody)
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
*/
package io.liteglue;
import android.annotation.SuppressLint;
import android.database.Cursor;
import android.database.CursorWindow;
import android.database.sqlite.SQLiteCursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;
import android.util.Base64;
import android.util.Log;
import java.io.File;
import java.lang.IllegalArgumentException;
import java.lang.Number;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.cordova.CallbackContext;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Android Database helper class
*/
class SQLiteAndroidDatabase
{
private static final Pattern FIRST_WORD = Pattern.compile("^\\s*(\\S+)",
Pattern.CASE_INSENSITIVE);
private static final Pattern WHERE_CLAUSE = Pattern.compile("\\s+WHERE\\s+(.+)$",
Pattern.CASE_INSENSITIVE);
private static final Pattern UPDATE_TABLE_NAME = Pattern.compile("^\\s*UPDATE\\s+(\\S+)",
Pattern.CASE_INSENSITIVE);
private static final Pattern DELETE_TABLE_NAME = Pattern.compile("^\\s*DELETE\\s+FROM\\s+(\\S+)",
Pattern.CASE_INSENSITIVE);
File dbFile;
SQLiteDatabase mydb;
/**
* NOTE: Using default constructor, no explicit constructor.
*/
/**
* Open a database.
*
* @param dbfile The database File specification
*/
void open(File dbfile) throws Exception {
dbFile = dbfile; // for possible bug workaround
mydb = SQLiteDatabase.openOrCreateDatabase(dbfile, null);
}
/**
* Close a database (in the current thread).
*/
void closeDatabaseNow() {
if (mydb != null) {
mydb.close();
mydb = null;
}
}
void bugWorkaround() throws Exception {
this.closeDatabaseNow();
this.open(dbFile);
}
/**
* Executes a batch request and sends the results via cbc.
*
* @param dbname The name of the database.
* @param queryarr Array of query strings
* @param jsonparams Array of JSON query parameters
* @param queryIDs Array of query ids
* @param cbc Callback context from Cordova API
*/
@SuppressLint("NewApi")
void executeSqlBatch(String[] queryarr, JSONArray[] jsonparams,
String[] queryIDs, CallbackContext cbc) {
if (mydb == null) {
// not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database
cbc.error("database has been closed");
return;
}
String query = "";
String query_id = "";
int len = queryarr.length;
JSONArray batchResults = new JSONArray();
for (int i = 0; i < len; i++) {
int rowsAffectedCompat = 0;
boolean needRowsAffectedCompat = false;
query_id = queryIDs[i];
JSONObject queryResult = null;
String errorMessage = "unknown";
try {
boolean needRawQuery = true;
query = queryarr[i];
QueryType queryType = getQueryType(query);
if (queryType == QueryType.update || queryType == queryType.delete) {
if (android.os.Build.VERSION.SDK_INT >= 11) {
SQLiteStatement myStatement = mydb.compileStatement(query);
if (jsonparams != null) {
bindArgsToStatement(myStatement, jsonparams[i]);
}
int rowsAffected = -1; // (assuming invalid)
// Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying:
try {
rowsAffected = myStatement.executeUpdateDelete();
// Indicate valid results:
needRawQuery = false;
} catch (SQLiteException ex) {
// Indicate problem & stop this query:
ex.printStackTrace();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLiteStatement.executeUpdateDelete(): Error=" + errorMessage);
needRawQuery = false;
} catch (Exception ex) {
// Assuming SDK_INT was lying & method not found:
// do nothing here & try again with raw query.
}
if (rowsAffected != -1) {
queryResult = new JSONObject();
queryResult.put("rowsAffected", rowsAffected);
}
} else { // pre-honeycomb
rowsAffectedCompat = countRowsAffectedCompat(queryType, query, jsonparams, mydb, i);
needRowsAffectedCompat = true;
}
}
// INSERT:
if (queryType == QueryType.insert && jsonparams != null) {
needRawQuery = false;
SQLiteStatement myStatement = mydb.compileStatement(query);
bindArgsToStatement(myStatement, jsonparams[i]);
long insertId = -1; // (invalid)
try {
insertId = myStatement.executeInsert();
// statement has finished with no constraint violation:
queryResult = new JSONObject();
if (insertId != -1) {
queryResult.put("insertId", insertId);
queryResult.put("rowsAffected", 1);
} else {
queryResult.put("rowsAffected", 0);
}
} catch (SQLiteException ex) {
// report error result with the error message
// could be constraint violation or some other error
ex.printStackTrace();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLiteDatabase.executeInsert(): Error=" + errorMessage);
}
}
if (queryType == QueryType.begin) {
needRawQuery = false;
try {
mydb.beginTransaction();
queryResult = new JSONObject();
queryResult.put("rowsAffected", 0);
} catch (SQLiteException ex) {
ex.printStackTrace();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLiteDatabase.beginTransaction(): Error=" + errorMessage);
}
}
if (queryType == QueryType.commit) {
needRawQuery = false;
try {
mydb.setTransactionSuccessful();
mydb.endTransaction();
queryResult = new JSONObject();
queryResult.put("rowsAffected", 0);
} catch (SQLiteException ex) {
ex.printStackTrace();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLiteDatabase.setTransactionSuccessful/endTransaction(): Error=" + errorMessage);
}
}
if (queryType == QueryType.rollback) {
needRawQuery = false;
try {
mydb.endTransaction();
queryResult = new JSONObject();
queryResult.put("rowsAffected", 0);
} catch (SQLiteException ex) {
ex.printStackTrace();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLiteDatabase.endTransaction(): Error=" + errorMessage);
}
}
// raw query for other statements:
if (needRawQuery) {
queryResult = this.executeSqlStatementQuery(mydb, query, jsonparams[i], cbc);
if (needRowsAffectedCompat) {
queryResult.put("rowsAffected", rowsAffectedCompat);
}
}
} catch (Exception ex) {
ex.printStackTrace();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + errorMessage);
}
try {
if (queryResult != null) {
JSONObject r = new JSONObject();
r.put("qid", query_id);
r.put("type", "success");
r.put("result", queryResult);
batchResults.put(r);
} else {
JSONObject r = new JSONObject();
r.put("qid", query_id);
r.put("type", "error");
JSONObject er = new JSONObject();
er.put("message", errorMessage);
r.put("result", er);
batchResults.put(r);
}
} catch (JSONException ex) {
ex.printStackTrace();
Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + ex.getMessage());
// TODO what to do?
}
}
cbc.success(batchResults);
}
private int countRowsAffectedCompat(QueryType queryType, String query, JSONArray[] jsonparams,
SQLiteDatabase mydb, int i) throws JSONException {
// quick and dirty way to calculate the rowsAffected in pre-Honeycomb. just do a SELECT
// beforehand using the same WHERE clause. might not be perfect, but it's better than nothing
Matcher whereMatcher = WHERE_CLAUSE.matcher(query);
String where = "";
int pos = 0;
while (whereMatcher.find(pos)) {
where = " WHERE " + whereMatcher.group(1);
pos = whereMatcher.start(1);
}
// WHERE clause may be omitted, and also be sure to find the last one,
// e.g. for cases where there's a subquery
// bindings may be in the update clause, so only take the last n
int numQuestionMarks = 0;
for (int j = 0; j < where.length(); j++) {
if (where.charAt(j) == '?') {
numQuestionMarks++;
}
}
JSONArray subParams = null;
if (jsonparams != null) {
// only take the last n of every array of sqlArgs
JSONArray origArray = jsonparams[i];
subParams = new JSONArray();
int startPos = origArray.length() - numQuestionMarks;
for (int j = startPos; j < origArray.length(); j++) {
subParams.put(j - startPos, origArray.get(j));
}
}
if (queryType == QueryType.update) {
Matcher tableMatcher = UPDATE_TABLE_NAME.matcher(query);
if (tableMatcher.find()) {
String table = tableMatcher.group(1);
try {
SQLiteStatement statement = mydb.compileStatement(
"SELECT count(*) FROM " + table + where);
if (subParams != null) {
bindArgsToStatement(statement, subParams);
}
return (int)statement.simpleQueryForLong();
} catch (Exception e) {
// assume we couldn't count for whatever reason, keep going
Log.e(SQLiteAndroidDatabase.class.getSimpleName(), "uncaught", e);
}
}
} else { // delete
Matcher tableMatcher = DELETE_TABLE_NAME.matcher(query);
if (tableMatcher.find()) {
String table = tableMatcher.group(1);
try {
SQLiteStatement statement = mydb.compileStatement(
"SELECT count(*) FROM " + table + where);
bindArgsToStatement(statement, subParams);
return (int)statement.simpleQueryForLong();
} catch (Exception e) {
// assume we couldn't count for whatever reason, keep going
Log.e(SQLiteAndroidDatabase.class.getSimpleName(), "uncaught", e);
}
}
}
return 0;
}
private void bindArgsToStatement(SQLiteStatement myStatement, JSONArray sqlArgs) throws JSONException {
for (int i = 0; i < sqlArgs.length(); i++) {
if (sqlArgs.get(i) instanceof Float || sqlArgs.get(i) instanceof Double) {
myStatement.bindDouble(i + 1, sqlArgs.getDouble(i));
} else if (sqlArgs.get(i) instanceof Number) {
myStatement.bindLong(i + 1, sqlArgs.getLong(i));
} else if (sqlArgs.isNull(i)) {
myStatement.bindNull(i + 1);
} else {
myStatement.bindString(i + 1, sqlArgs.getString(i));
}
}
}
/**
* Get rows results from query cursor.
*
* @param cur Cursor into query results
* @return results in string form
*/
private JSONObject executeSqlStatementQuery(SQLiteDatabase mydb,
String query, JSONArray paramsAsJson,
CallbackContext cbc) throws Exception {
JSONObject rowsResult = new JSONObject();
Cursor cur = null;
try {
String[] params = null;
params = new String[paramsAsJson.length()];
for (int j = 0; j < paramsAsJson.length(); j++) {
if (paramsAsJson.isNull(j))
params[j] = "";
else
params[j] = paramsAsJson.getString(j);
}
cur = mydb.rawQuery(query, params);
} catch (Exception ex) {
ex.printStackTrace();
String errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLiteAndroidDatabase.executeSql[Batch](): Error=" + errorMessage);
throw ex;
}
// If query result has rows
if (cur != null && cur.moveToFirst()) {
JSONArray rowsArrayResult = new JSONArray();
String key = "";
int colCount = cur.getColumnCount();
// Build up JSON result object for each row
do {
JSONObject row = new JSONObject();
try {
for (int i = 0; i < colCount; ++i) {
key = cur.getColumnName(i);
if (android.os.Build.VERSION.SDK_INT >= 11) {
// Use try & catch just in case android.os.Build.VERSION.SDK_INT >= 11 is lying:
try {
bindPostHoneycomb(row, key, cur, i);
} catch (Exception ex) {
bindPreHoneycomb(row, key, cur, i);
}
} else {
bindPreHoneycomb(row, key, cur, i);
}
}
rowsArrayResult.put(row);
} catch (JSONException e) {
e.printStackTrace();
}
} while (cur.moveToNext());
try {
rowsResult.put("rows", rowsArrayResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
if (cur != null) {
cur.close();
}
return rowsResult;
}
@SuppressLint("NewApi")
private void bindPostHoneycomb(JSONObject row, String key, Cursor cur, int i) throws JSONException {
int curType = cur.getType(i);
switch (curType) {
case Cursor.FIELD_TYPE_NULL:
row.put(key, JSONObject.NULL);
break;
case Cursor.FIELD_TYPE_INTEGER:
row.put(key, cur.getLong(i));
break;
case Cursor.FIELD_TYPE_FLOAT:
row.put(key, cur.getDouble(i));
break;
case Cursor.FIELD_TYPE_BLOB:
row.put(key, new String(Base64.encode(cur.getBlob(i), Base64.DEFAULT)));
break;
case Cursor.FIELD_TYPE_STRING:
default: /* (not expected) */
row.put(key, cur.getString(i));
break;
}
}
private void bindPreHoneycomb(JSONObject row, String key, Cursor cursor, int i) throws JSONException {
// Since cursor.getType() is not available pre-honeycomb, this is
// a workaround so we don't have to bind everything as a string
// Details here: http://stackoverflow.com/q/11658239
SQLiteCursor sqLiteCursor = (SQLiteCursor) cursor;
CursorWindow cursorWindow = sqLiteCursor.getWindow();
int pos = cursor.getPosition();
if (cursorWindow.isNull(pos, i)) {
row.put(key, JSONObject.NULL);
} else if (cursorWindow.isLong(pos, i)) {
row.put(key, cursor.getLong(i));
} else if (cursorWindow.isFloat(pos, i)) {
row.put(key, cursor.getDouble(i));
} else if (cursorWindow.isBlob(pos, i)) {
row.put(key, new String(Base64.encode(cursor.getBlob(i), Base64.DEFAULT)));
} else { // string
row.put(key, cursor.getString(i));
}
}
static QueryType getQueryType(String query) {
Matcher matcher = FIRST_WORD.matcher(query);
if (matcher.find()) {
try {
return QueryType.valueOf(matcher.group(1).toLowerCase());
} catch (IllegalArgumentException ignore) {
// unknown verb
}
}
return QueryType.other;
}
static enum QueryType {
update,
insert,
delete,
select,
begin,
commit,
rollback,
other
}
} /* vim: set expandtab : */

View File

@@ -0,0 +1,660 @@
/*
* Copyright (c) 2012-2015: Christopher J. Brody (aka Chris Brody)
* Copyright (c) 2005-2010, Nitobi Software Inc.
* Copyright (c) 2010, IBM Corporation
*/
package io.liteglue;
import android.annotation.SuppressLint;
import android.util.Base64;
import android.util.Log;
import java.io.File;
import java.lang.IllegalArgumentException;
import java.lang.Number;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
public class SQLitePlugin extends CordovaPlugin {
/**
* Multiple database runner map (static).
* NOTE: no public static accessor to db (runner) map since it would not work with db threading.
* FUTURE put DBRunner into a public class that can provide external accessor.
*/
static ConcurrentHashMap<String, DBRunner> dbrmap = new ConcurrentHashMap<String, DBRunner>();
/**
* SQLiteGlueConnector (instance of SQLiteConnector) for NDK version:
*/
static SQLiteConnector connector = new SQLiteConnector();
/**
* NOTE: Using default constructor, no explicit constructor.
*/
/**
* Executes the request and returns PluginResult.
*
* @param actionAsString The action to execute.
* @param args JSONArry of arguments for the plugin.
* @param cbc Callback context from Cordova API
* @return Whether the action was valid.
*/
@Override
public boolean execute(String actionAsString, JSONArray args, CallbackContext cbc) {
Action action;
try {
action = Action.valueOf(actionAsString);
} catch (IllegalArgumentException e) {
// shouldn't ever happen
Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e);
return false;
}
try {
return executeAndPossiblyThrow(action, args, cbc);
} catch (JSONException e) {
// TODO: signal JSON problem to JS
Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e);
return false;
}
}
private boolean executeAndPossiblyThrow(Action action, JSONArray args, CallbackContext cbc)
throws JSONException {
boolean status = true;
JSONObject o;
String dbname;
switch (action) {
case open:
o = args.getJSONObject(0);
dbname = o.getString("name");
// open database and start reading its queue
this.startDatabase(dbname, o, cbc);
break;
case close:
o = args.getJSONObject(0);
dbname = o.getString("path");
// put request in the q to close the db
this.closeDatabase(dbname, cbc);
break;
case delete:
o = args.getJSONObject(0);
dbname = o.getString("path");
deleteDatabase(dbname, cbc);
break;
case executeSqlBatch:
case backgroundExecuteSqlBatch:
String[] queries = null;
String[] queryIDs = null;
JSONArray jsonArr = null;
int paramLen = 0;
JSONArray[] jsonparams = null;
JSONObject allargs = args.getJSONObject(0);
JSONObject dbargs = allargs.getJSONObject("dbargs");
dbname = dbargs.getString("dbname");
JSONArray txargs = allargs.getJSONArray("executes");
if (txargs.isNull(0)) {
queries = new String[0];
} else {
int len = txargs.length();
queries = new String[len];
queryIDs = new String[len];
jsonparams = new JSONArray[len];
for (int i = 0; i < len; i++) {
JSONObject a = txargs.getJSONObject(i);
queries[i] = a.getString("sql");
queryIDs[i] = a.getString("qid");
jsonArr = a.getJSONArray("params");
paramLen = jsonArr.length();
jsonparams[i] = jsonArr;
}
}
// put db query in the queue to be executed in the db thread:
DBQuery q = new DBQuery(queries, queryIDs, jsonparams, cbc);
DBRunner r = dbrmap.get(dbname);
if (r != null) {
try {
r.q.put(q);
} catch(Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't add to queue", e);
cbc.error("couldn't add to queue");
}
} else {
cbc.error("database not open");
}
break;
}
return status;
}
/**
* Clean up and close all open databases.
*/
@Override
public void onDestroy() {
while (!dbrmap.isEmpty()) {
String dbname = dbrmap.keySet().iterator().next();
this.closeDatabaseNow(dbname);
DBRunner r = dbrmap.get(dbname);
try {
// stop the db runner thread:
r.q.put(new DBQuery());
} catch(Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't stop db thread", e);
}
dbrmap.remove(dbname);
}
}
// --------------------------------------------------------------------------
// LOCAL METHODS
// --------------------------------------------------------------------------
private void startDatabase(String dbname, JSONObject options, CallbackContext cbc) {
// TODO: is it an issue that we can orphan an existing thread? What should we do here?
// If we re-use the existing DBRunner it might be in the process of closing...
DBRunner r = dbrmap.get(dbname);
// Brody TODO: It may be better to terminate the existing db thread here & start a new one, instead.
if (r != null) {
// don't orphan the existing thread; just re-open the existing database.
// In the worst case it might be in the process of closing, but even that's less serious
// than orphaning the old DBRunner.
cbc.success();
} else {
r = new DBRunner(dbname, options, cbc);
dbrmap.put(dbname, r);
this.cordova.getThreadPool().execute(r);
}
}
/**
* Open a database.
*
* @param dbName The name of the database file
*/
private SQLiteAndroidDatabase openDatabase(String dbname, CallbackContext cbc, boolean old_impl) throws Exception {
try {
// ASSUMPTION: no db (connection/handle) is already stored in the map
// [should be true according to the code in DBRunner.run()]
File dbfile = this.cordova.getActivity().getDatabasePath(dbname);
if (!dbfile.exists()) {
dbfile.getParentFile().mkdirs();
}
Log.v("info", "Open sqlite db: " + dbfile.getAbsolutePath());
SQLiteAndroidDatabase mydb = old_impl ? new SQLiteAndroidDatabase() : new SQLiteDatabaseNDK();
mydb.open(dbfile);
if (cbc != null) // XXX Android locking/closing BUG workaround
cbc.success();
return mydb;
} catch (Exception e) {
if (cbc != null) // XXX Android locking/closing BUG workaround
cbc.error("can't open database " + e);
throw e;
}
}
/**
* Close a database (in another thread).
*
* @param dbName The name of the database file
*/
private void closeDatabase(String dbname, CallbackContext cbc) {
DBRunner r = dbrmap.get(dbname);
if (r != null) {
try {
r.q.put(new DBQuery(false, cbc));
} catch(Exception e) {
if (cbc != null) {
cbc.error("couldn't close database" + e);
}
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
}
} else {
if (cbc != null) {
cbc.success();
}
}
}
/**
* Close a database (in the current thread).
*
* @param dbname The name of the database file
*/
private void closeDatabaseNow(String dbname) {
DBRunner r = dbrmap.get(dbname);
if (r != null) {
SQLiteAndroidDatabase mydb = r.mydb;
if (mydb != null)
mydb.closeDatabaseNow();
}
}
private void deleteDatabase(String dbname, CallbackContext cbc) {
DBRunner r = dbrmap.get(dbname);
if (r != null) {
try {
r.q.put(new DBQuery(true, cbc));
} catch(Exception e) {
if (cbc != null) {
cbc.error("couldn't close database" + e);
}
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
}
} else {
boolean deleteResult = this.deleteDatabaseNow(dbname);
if (deleteResult) {
cbc.success();
} else {
cbc.error("couldn't delete database");
}
}
}
/**
* Delete a database.
*
* @param dbName The name of the database file
*
* @return true if successful or false if an exception was encountered
*/
private boolean deleteDatabaseNow(String dbname) {
File dbfile = this.cordova.getActivity().getDatabasePath(dbname);
try {
return cordova.getActivity().deleteDatabase(dbfile.getAbsolutePath());
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e);
return false;
}
}
// NOTE: class hierarchy is ugly, done to reduce number of modules for manual installation.
// FUTURE TBD SQLiteDatabaseNDK class belongs in its own module.
class SQLiteDatabaseNDK extends SQLiteAndroidDatabase {
SQLiteConnection mydb;
/**
* Open a database.
*
* @param dbFile The database File specification
*/
@Override
void open(File dbFile) throws Exception {
mydb = connector.newSQLiteConnection(dbFile.getAbsolutePath(),
SQLiteOpenFlags.READWRITE | SQLiteOpenFlags.CREATE);
}
/**
* Close a database (in the current thread).
*/
@Override
void closeDatabaseNow() {
try {
if (mydb != null)
mydb.dispose();
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database, ignoring", e);
}
}
/**
* Ignore Android bug workaround for NDK version
*/
@Override
void bugWorkaround() { }
/**
* Executes a batch request and sends the results via cbc.
*
* @param dbname The name of the database.
* @param queryarr Array of query strings
* @param jsonparams Array of JSON query parameters
* @param queryIDs Array of query ids
* @param cbc Callback context from Cordova API
*/
@Override
void executeSqlBatch( String[] queryarr, JSONArray[] jsonparams,
String[] queryIDs, CallbackContext cbc) {
if (mydb == null) {
// not allowed - can only happen if someone has closed (and possibly deleted) a database and then re-used the database
cbc.error("database has been closed");
return;
}
int len = queryarr.length;
JSONArray batchResults = new JSONArray();
for (int i = 0; i < len; i++) {
int rowsAffectedCompat = 0;
boolean needRowsAffectedCompat = false;
String query_id = queryIDs[i];
JSONObject queryResult = null;
String errorMessage = "unknown";
try {
String query = queryarr[i];
long lastTotal = mydb.getTotalChanges();
queryResult = this.executeSqlStatementNDK(query, jsonparams[i], cbc);
long newTotal = mydb.getTotalChanges();
long rowsAffected = newTotal - lastTotal;
queryResult.put("rowsAffected", rowsAffected);
if (rowsAffected > 0) {
long insertId = mydb.getLastInsertRowid();
if (insertId > 0) {
queryResult.put("insertId", insertId);
}
}
} catch (Exception ex) {
ex.printStackTrace();
errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage);
}
try {
if (queryResult != null) {
JSONObject r = new JSONObject();
r.put("qid", query_id);
r.put("type", "success");
r.put("result", queryResult);
batchResults.put(r);
} else {
JSONObject r = new JSONObject();
r.put("qid", query_id);
r.put("type", "error");
JSONObject er = new JSONObject();
er.put("message", errorMessage);
r.put("result", er);
batchResults.put(r);
}
} catch (JSONException ex) {
ex.printStackTrace();
Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + ex.getMessage());
// TODO what to do?
}
}
cbc.success(batchResults);
}
/**
* Get rows results from query cursor.
*
* @param cur Cursor into query results
* @return results in string form
*/
private JSONObject executeSqlStatementNDK(String query, JSONArray paramsAsJson,
CallbackContext cbc) throws Exception {
JSONObject rowsResult = new JSONObject();
boolean hasRows = false;
SQLiteStatement myStatement = mydb.prepareStatement(query);
try {
String[] params = null;
params = new String[paramsAsJson.length()];
for (int i = 0; i < paramsAsJson.length(); ++i) {
if (paramsAsJson.isNull(i)) {
myStatement.bindNull(i + 1);
} else {
Object p = paramsAsJson.get(i);
if (p instanceof Float || p instanceof Double)
myStatement.bindDouble(i + 1, paramsAsJson.getDouble(i));
else if (p instanceof Number)
myStatement.bindLong(i + 1, paramsAsJson.getLong(i));
else
myStatement.bindTextNativeString(i + 1, paramsAsJson.getString(i));
}
}
hasRows = myStatement.step();
} catch (Exception ex) {
ex.printStackTrace();
String errorMessage = ex.getMessage();
Log.v("executeSqlBatch", "SQLitePlugin.executeSql[Batch](): Error=" + errorMessage);
// cleanup statement and throw the exception:
myStatement.dispose();
throw ex;
}
// If query result has rows
if (hasRows) {
JSONArray rowsArrayResult = new JSONArray();
String key = "";
int colCount = myStatement.getColumnCount();
// Build up JSON result object for each row
do {
JSONObject row = new JSONObject();
try {
for (int i = 0; i < colCount; ++i) {
key = myStatement.getColumnName(i);
switch (myStatement.getColumnType(i)) {
case SQLColumnType.NULL:
row.put(key, JSONObject.NULL);
break;
case SQLColumnType.REAL:
row.put(key, myStatement.getColumnDouble(i));
break;
case SQLColumnType.INTEGER:
row.put(key, myStatement.getColumnLong(i));
break;
case SQLColumnType.BLOB:
case SQLColumnType.TEXT:
default: // (just in case)
row.put(key, myStatement.getColumnTextNativeString(i));
}
}
rowsArrayResult.put(row);
} catch (JSONException e) {
e.printStackTrace();
}
} while (myStatement.step());
try {
rowsResult.put("rows", rowsArrayResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
myStatement.dispose();
return rowsResult;
}
}
private class DBRunner implements Runnable {
final String dbname;
private boolean oldImpl;
private boolean bugWorkaround;
final BlockingQueue<DBQuery> q;
final CallbackContext openCbc;
SQLiteAndroidDatabase mydb;
DBRunner(final String dbname, JSONObject options, CallbackContext cbc) {
this.dbname = dbname;
this.oldImpl = options.has("androidOldDatabaseImplementation");
Log.v(SQLitePlugin.class.getSimpleName(), "Android db implementation: " + (oldImpl ? "OLD" : "default-NDK"));
this.bugWorkaround = this.oldImpl && options.has("androidBugWorkaround");
if (this.bugWorkaround)
Log.v(SQLitePlugin.class.getSimpleName(), "Android db closing/locking workaround applied");
this.q = new LinkedBlockingQueue<DBQuery>();
this.openCbc = cbc;
}
public void run() {
try {
this.mydb = openDatabase(dbname, this.openCbc, this.oldImpl);
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error, stopping db thread", e);
dbrmap.remove(dbname);
return;
}
DBQuery dbq = null;
try {
dbq = q.take();
while (!dbq.stop) {
mydb.executeSqlBatch(dbq.queries, dbq.jsonparams, dbq.queryIDs, dbq.cbc);
// NOTE: androidLock[Bug]Workaround is not necessary and IGNORED for default-NDK version.
if (this.bugWorkaround && dbq.queries.length == 1 && dbq.queries[0] == "COMMIT")
mydb.bugWorkaround();
dbq = q.take();
}
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "unexpected error", e);
}
if (dbq != null && dbq.close) {
try {
closeDatabaseNow(dbname);
dbrmap.remove(dbname); // (should) remove ourself
if (!dbq.delete) {
dbq.cbc.success();
} else {
try {
boolean deleteResult = deleteDatabaseNow(dbname);
if (deleteResult) {
dbq.cbc.success();
} else {
dbq.cbc.error("couldn't delete database");
}
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't delete database", e);
dbq.cbc.error("couldn't delete database: " + e);
}
}
} catch (Exception e) {
Log.e(SQLitePlugin.class.getSimpleName(), "couldn't close database", e);
if (dbq.cbc != null) {
dbq.cbc.error("couldn't close database: " + e);
}
}
}
}
}
private final class DBQuery {
// XXX TODO replace with DBRunner action enum:
final boolean stop;
final boolean close;
final boolean delete;
final String[] queries;
final String[] queryIDs;
final JSONArray[] jsonparams;
final CallbackContext cbc;
DBQuery(String[] myqueries, String[] qids, JSONArray[] params, CallbackContext c) {
this.stop = false;
this.close = false;
this.delete = false;
this.queries = myqueries;
this.queryIDs = qids;
this.jsonparams = params;
this.cbc = c;
}
DBQuery(boolean delete, CallbackContext cbc) {
this.stop = true;
this.close = true;
this.delete = delete;
this.queries = null;
this.queryIDs = null;
this.jsonparams = null;
this.cbc = cbc;
}
// signal the DBRunner thread to stop:
DBQuery() {
this.stop = true;
this.close = false;
this.delete = false;
this.queries = null;
this.queryIDs = null;
this.jsonparams = null;
this.cbc = null;
}
}
private static enum Action {
open,
close,
delete,
executeSqlBatch,
backgroundExecuteSqlBatch,
}
}
/* vim: set expandtab : */

View File

@@ -0,0 +1,63 @@
package me.rahul.plugins.sqlDB;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DatabaseHelper extends SQLiteOpenHelper {
private Context myContext;
public DatabaseHelper(Context context) {
super(context, sqlDB.dbname, null, 1);
this.myContext = context;
// TODO Auto-generated constructor stub
}
public void createdatabase(File dbPath) throws IOException {
// Log.d("CordovaLog","Inside CreateDatabase = "+dbPath);
this.getReadableDatabase();
try {
copyDatabase(dbPath);
} catch (IOException e) {
throw new Error(
"Create Database Exception ============================ "
+ e);
}
}
private void copyDatabase(File database) throws IOException {
InputStream myInput = myContext.getAssets().open("www/"+sqlDB.dbname);
OutputStream myOutput = new FileOutputStream(database);
byte[] buffer = new byte[1024];
while ((myInput.read(buffer)) > -1) {
myOutput.write(buffer);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
// TODO Auto-generated method stub
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
}
}

View File

@@ -0,0 +1,102 @@
package me.rahul.plugins.sqlDB;
import java.io.File;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
/**
* This class echoes a string called from JavaScript.
*/
public class sqlDB extends CordovaPlugin {
public static String dbname = "dbname";
PluginResult plresult = new PluginResult(PluginResult.Status.NO_RESULT);
@Override
public boolean execute(String action, JSONArray args,
CallbackContext callbackContext) throws JSONException {
if (action.equalsIgnoreCase("copy")) {
this.copyDB(args.getString(0), callbackContext);
return true;
} else if (action.equalsIgnoreCase("remove")) {
String db = args.getString(0);
File path = cordova.getActivity().getDatabasePath(db);
Boolean fileExists = path.exists();
if (fileExists) {
boolean deleted = path.delete();
if (deleted) {
plresult = new PluginResult(PluginResult.Status.OK, deleted);
callbackContext.sendPluginResult(plresult);
} else {
plresult = new PluginResult(PluginResult.Status.ERROR,
deleted);
callbackContext.sendPluginResult(plresult);
}
} else {
plresult = new PluginResult(PluginResult.Status.ERROR,
"File Doesn't Exists");
callbackContext.sendPluginResult(plresult);
}
return true;
} else {
plresult = new PluginResult(PluginResult.Status.INVALID_ACTION);
callbackContext.sendPluginResult(plresult);
return false;
}
}
private void copyDB(String dbName, final CallbackContext callbackContext) {
final File dbpath;
dbname = dbName;
JSONObject error = new JSONObject();
final DatabaseHelper dbhelper = new DatabaseHelper(this.cordova
.getActivity().getApplicationContext());
dbpath = this.cordova.getActivity().getDatabasePath(dbname);
Boolean dbexists = dbpath.exists();
//Log.d("CordovaLog", "DatabasePath = " + dbpath + "&&&& dbname = " + dbname + "&&&&DB Exists =" + dbexists);
if (dbexists) {
try {
error.put("message", "File already exists");
error.put("code", 516);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
plresult = new PluginResult(PluginResult.Status.ERROR, error);
callbackContext.sendPluginResult(plresult);
} else {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
PluginResult plResult = new PluginResult(
PluginResult.Status.NO_RESULT);
// TODO Auto-generated method stub
try {
dbhelper.createdatabase(dbpath);
plResult = new PluginResult(PluginResult.Status.OK);
callbackContext.sendPluginResult(plResult);
} catch (Exception e) {
plResult = new PluginResult(PluginResult.Status.ERROR,
e.getMessage());
callbackContext.sendPluginResult(plResult);
}
}
});
}
}
}