【问题标题】:Populate Data from SQLLite db for Android using Phonegap使用 Phonegap 从适用于 Android 的 SQLite db 填充数据
【发布时间】:2014-01-10 09:11:04
【问题描述】:

我将 SQLLite 用于我的基于 phonegap 的 Android 应用程序。我面临的问题是,只要应用程序打开,我就能够获取我存储在 local.db 文件中的任何数据。 例如,我有一个设置功能,用户可以保存他/她的设置并将其转到数据库。现在我面临的问题是,一旦应用程序关闭,我就无法获取用户保存的数据,我只要应用程序打开就可以获取数据。 所以问题是数据库不是持久的。即使应用程序关闭,任何人都可以告诉如何将数据存储在内存中吗?

这是我的 mainActivity 文件

public class Demo extends CordovaActivity 
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        super.init();
        super.loadUrl(Config.getStartUrl());            
        try {
            String pName = this.getClass().getPackage().getName();
            this.copy("Databases.db", "/data/data/" + pName + "/app_database/");
            this.copy("0000000000000001.db", "/data/data/" + pName
                    + "/app_database/file__0/");
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    void copy(String file, String folder) throws IOException {

        File CheckDirectory;
        CheckDirectory = new File(folder);
        if (!CheckDirectory.exists()) {
            CheckDirectory.mkdir();
            InputStream in = getApplicationContext().getAssets().open(file);
        OutputStream out = new FileOutputStream(folder + file);

        // Transfer bytes from in to out
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0)
            out.write(buf, 0, len);
        in.close();
        out.close();
        }
    }
} 

这些是我授予的权限:-

        <uses-permission android:name="android.permission.INTERNET" />
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.VIBRATE" />
       <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在将复制代码移动到 NigelK 提到的 if 条件后,成功了。但在卸载构建并创建新构建后,出现以下错误:-

01-10 16:11:34.466: E/SQLiteLog(29253): (1) no such table: CacheGroups
01-10 16:11:34.466: D/WebKit(29253): ERROR: 
01-10 16:11:34.466: D/WebKit(29253): Application Cache Storage: failed to execute statement "DELETE FROM CacheGroups" error "no such table: CacheGroups"
01-10 16:11:34.466: D/WebKit(29253): external/webkit/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp(558) : bool WebCore::ApplicationCacheStorage::executeSQLCommand(const WTF::String&)
01-10 16:11:34.466: E/SQLiteLog(29253): (1) no such table: Caches
01-10 16:11:34.466: D/WebKit(29253): ERROR: 
01-10 16:11:34.466: D/WebKit(29253): Application Cache Storage: failed to execute statement "DELETE FROM Caches" error "no such table: Caches"
01-10 16:11:34.466: D/WebKit(29253): external/webkit/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp(558) : bool WebCore::ApplicationCacheStorage::executeSQLCommand(const WTF::String&)
01-10 16:11:34.466: E/SQLiteLog(29253): (1) no such table: Origins
01-10 16:11:34.466: D/WebKit(29253): ERROR: 
01-10 16:11:34.466: D/WebKit(29253): Application Cache Storage: failed to execute statement "DELETE FROM Origins" error "no such table: Origins"
01-10 16:11:34.466: D/WebKit(29253): external/webkit/Source/WebCore/loader/appcache/ApplicationCacheStorage.cpp(558) : bool WebCore::ApplicationCacheStorage::executeSQLCommand(const WTF::String&)
01-10 16:11:34.476: E/SQLiteLog(29253): (1) no such table: DeletedCacheResources

知道如何解决这个问题吗?

【问题讨论】:

    标签: android sqlite cordova


    【解决方案1】:

    您的数据库是持久的,问题是每次您的应用程序启动时,对 onCreate() 中的 copy() 方法的调用会再次使用 Assets 中保存的副本覆盖数据库。我想你只想复制一次。一种方法是仅在目标目录不存在时才进行复制:

    if (!CheckDirectory.exists()) {
        CheckDirectory.mkdir();
        ...move the copy code inside this if block
    }
    

    或者您可以在 Shared Preferences 中存储一个标志,并在制作副本时设置为 true。在 onCreate 中,仅当该标志为 false 时才进行复制。

    编辑:

    要使用共享首选项标志:

    在 onCreate 中:

    SharedPreferences sp = getSharedPreferences("MYPREFS", Activity.MODE_PRIVATE);
    
    //If no shared prefs exist, e.g. first install, it doesn't matter - the following will return false as a default
    Boolean database_copied = sp.getBoolean("database_copied", false);
    
    if (!database_copied)
    {
        try {
            String pName = this.getClass().getPackage().getName();
            this.copy("Databases.db", "/data/data/" + pName + "/app_database/");
            this.copy("0000000000000001.db", "/data/data/" + pName
                    + "/app_database/file__0/");
            SharedPreferences.Editor editor = sp.edit();
            editor.putBoolean("database_copied", true);
            editor.apply();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    【讨论】:

    • 是的,将复制代码移动到 if 条件就可以了。非常感谢 :)
    • NigelK :卸载以前的构建并创建一个新的构建现在向我显示一个错误。这是我得到的错误:- E/SQLiteLog(26682): (1) no such table: CacheGroups 。知道我做错了什么吗?
    • 我已经用错误日志更新了我的问题,请检查并告诉我我做错了什么。
    • 我希望卸载会删除 /app_database/ 文件夹。但是它似乎没有,所以复制代码不会运行。我使用 SharedPreferences 的其他建议可能更可靠。如果您愿意,请随时不接受我的回答,因为会有更多人再次关注您的问题。
    • 是的,共享首选项在卸载时被清除,这实际上是关键。阅读首选项时,您可以指定不存在的默认值。请查看我的编辑。
    【解决方案2】:

    只需创建一个空白数据库并将其替换为新资产数据库..

    Thread getData = new Thread() {
            public void run() {
    
                Data.qh = new QueryHandler(mContext); // for creating a blank DB
                DB_PATH = getDatabasePath("htest.sqlite").getAbsolutePath(); // get the path of blank DB
                copyDataBase(mContext);
    
            };
        };
    
    
    void copyDataBase(Context mContext) {
    
            try {
    
                String outFileName = DB_PATH;
    
                OutputStream myOutput = new FileOutputStream(outFileName);
    
                byte[] buffer = new byte[1024];
                int length;
    
                InputStream myInput = mContext.getAssets().open("htest.sqlite");
                while ((length = myInput.read(buffer)) > 0) {
                    myOutput.write(buffer, 0, length);
                }
                myInput.close();
    
                myOutput.flush();
                myOutput.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
        }
    

    【讨论】:

      【解决方案3】:

      以下是示例代码,这是在 Javascript 调用中在 html 页面中实现

      function onDeviceReady() 
      {
        var db = window.openDatabase("Database", "1.0", "Cordova Demo", 200000);
        db.transaction(populateDB, errorCB, successCB);
      }
      

      然后我们要在Table中填充数据,调用方法

      function populateDB(tx) 
      {
        var id=$('#id').val();
        var firstname=$('#firstname').val();        
        tx.executeSql('CREATE TABLE IF NOT EXISTS DEMO (id unique, firstname)');
        tx.executeSql('INSERT INTO DEMO (id, firstname) VALUES (?, ?)', [id, firstname]);
      }
      

      要保存数据,请关注任何事件

      <button class="button" id="clickMe" onclick="onDeviceReady();" >Save</button>
      

      【讨论】:

      • 你说的我已经做了,其实问题是数据库在应用关闭的情况下没有获取保存的记录,否则在应用打开的情况下它工作正常。
      猜你喜欢
      • 2016-04-12
      • 1970-01-01
      • 2013-09-11
      • 2012-02-22
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多