android上regualr sqlite操作的一个奇怪行为

我有一个问题,我已经解决了,但我仍然想知道为什么解决方案解决了它。 我写了一个android应用程序,有一个sqlite数据库后,我调试了几次数据库中的oncreate方法没有被调用(即使一切工作正常之前)后,我更改了数据库版本号从1到2一切工作再次罚款即使我通过应用程序管理器卸载了应用程序,并且还删除了缓存和本地数据库信息。 我的问题如下 - 本地数据库数据是否保存在其他地方? 如果没有 - 为什么只有在我升级了版本号之后,即使删除了所有与应用相关的数据,它也能正常工作?

/**
 * A class to handle sqlite reads/writes of user related data to be collected
 */
public class UserDataManager extends SQLiteOpenHelper {

    // Class Variables
    private final String TAG = UserDataManager.class.getSimpleName();

    // Database Version
    private static final int DATABASE_VERSION = 1;

    // Database Name
    public static final String DATABASE_NAME = "tmc";

    // Tables
    private static final String TABLE_USER = "user";

    // Tables and table columns names
    private String CREATE_USER_TABLE;
    private static final String COLUMN_USER_ID = "user_id";
    private static final String COLUMN_USER_MAIL = "email";
    private static final String COLUMN_USER_ACTIVE = "user_active";
    private static final String COLUMN_USER_NAME = "name";
    private static final String COLUMN_USER_PASSWORD = "password";
    private static final String COLUMN_USER_PHONE_NUMBER = "phone_number";

    /**
     * Class constructor
     * 
     * @param context
     *            The context to run in
     */
    public UserDataManager(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) {

        CREATE_USER_TABLE = "CREATE TABLE IF NOT EXISTS " + TABLE_USER + " ("
                + COLUMN_USER_ID + " INTEGER PRIMARY KEY NOT NULL, "
                + COLUMN_USER_MAIL + " VARCHAR(64) NOT NULL, "
                + COLUMN_USER_NAME + " VARCHAR(64) NOT NULL, "
                + COLUMN_USER_PASSWORD + " VARCHAR(64) NOT NULL, "
                + COLUMN_USER_PHONE_NUMBER + " VARCHAR(64) NOT NULL, "
                + COLUMN_USER_ACTIVE + " INT NOT NULL);";

        // create the tables
        db.execSQL(CREATE_USER_TABLE);
    }

    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        // Drop older table if existed
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_USER);

        // Create tables again
        onCreate(db);
    }

    /**
     * Adding a user to the database
     * 
     * @param userId
     *            The created user id
     * @param userName
     *            The user name
     * @param userEmail
     *            The user email
     * @param userPassword
     *            The user password
     * @param userPhoneNumber
     *            The user phone number
     * @param isActive
     *            Set to 1 if the user is active 0 otherwise
     * @return True if the user added successfully false otherwise
     */
    public boolean AddUser(int userId, String userName, String userEmail,
            String userPassword, String userPhoneNumber, boolean isActive) {

        // method variables
        long rowId;
        boolean pass = false;
        int active = isActive ? 1 : 0;
        SQLiteDatabase db = null;
        ContentValues row = null;

        // try to add the user to the db
        try {
            row = new ContentValues();
            db = this.getWritableDatabase();
            db.delete(TABLE_USER, null, null);
            row.put(COLUMN_USER_ID, userId);
            row.put(COLUMN_USER_NAME, userName);
            row.put(COLUMN_USER_MAIL, userEmail);
            row.put(COLUMN_USER_PASSWORD, userPassword);
            row.put(COLUMN_USER_CAR_NUMBER, userPhoneNumber);
            row.put(COLUMN_USER_ACTIVE, active);
            rowId = db.insert(TABLE_USER, null, row);
            if (rowId > -1) {
                pass = true;
            }
        } catch (SQLException exception) {
            Log.e(TAG, exception.getMessage());
        } finally {
            if (db != null) {
                // close database connection
                db.close();
            }
        }
        return pass;
    }

    /**
     * Get the current registered user
     * 
     * @return The id of the column of the registered user
     */
    public int GetRegisteredUserId() {

        // method variables
        int columnIndex = -1;
        int userId = -1;
        SQLiteDatabase db = null;
        Cursor cursor = null;

        // try to get the user from the database
        try {
            db = this.getReadableDatabase();
            cursor = db.query(TABLE_USER, new String[] { COLUMN_USER_ID },
                    null, null, null, null, null);
            if (cursor != null) {
                boolean moved = cursor.moveToFirst();
                if (moved) {
                    columnIndex = cursor.getColumnIndex(COLUMN_USER_ID);
                    if (columnIndex > -1) {
                        userId = cursor.getInt(columnIndex);
                    }
                }
            }
        } catch (SQLException exception) {
            Log.e(TAG, exception.getMessage());
        } finally {
            if (cursor != null)
                // release cursor
                cursor.close();
            if (db != null)
                // close database connection
                db.close();
        }
        return userId;
    }

    /**
     * Get the current user email
     * 
     * @return The id of the column of the registered user
     */
    public String GetRegisteredUserEmail() {

        // method variables
        int columnIndex = -1;
        String userEmail = null;
        SQLiteDatabase db = null;
        Cursor cursor = null;

        // try to get the user from the database
        try {
            db = this.getReadableDatabase();
            cursor = db.query(TABLE_USER, new String[] { COLUMN_USER_MAIL },
                    null, null, null, null, null);
            if (cursor != null) {
                boolean moved = cursor.moveToFirst();
                if (moved) {
                    columnIndex = cursor.getColumnIndex(COLUMN_USER_MAIL);
                    if (columnIndex > -1) {
                        userEmail = cursor.getString(columnIndex);
                    }
                }
            }
        } catch (SQLException exception) {
            Log.e(TAG, exception.getMessage());
        } finally {
            if (cursor != null)
                // release cursor
                cursor.close();
            if (db != null)
                // close database connection
                db.close();
        }
        return userEmail;
    }

    /**
     * Get the current user password
     * 
     * @return The password of the current logged user
     */
    public String GetRegisteredUserPassword() {

        // method variables
        int columnIndex = -1;
        String userPassword = null;
        SQLiteDatabase db = null;
        Cursor cursor = null;

        // try to get the user from the database
        try {
            db = this.getReadableDatabase();
            cursor = db.query(TABLE_USER,
                    new String[] { COLUMN_USER_PASSWORD }, null, null, null,
                    null, null);
            if (cursor != null) {
                boolean moved = cursor.moveToFirst();
                if (moved) {
                    columnIndex = cursor.getColumnIndex(COLUMN_USER_PASSWORD);
                    if (columnIndex > -1) {
                        userPassword = cursor.getString(columnIndex);
                    }
                }
            }
        } catch (SQLException exception) {
            Log.e(TAG, exception.getMessage());
        } finally {
            if (cursor != null)
                // release cursor
                cursor.close();
            if (db != null)
                // close database connection
                db.close();
        }
        return userPassword;
    }

    /**
     * Get number of rows in the user table
     * 
     * @return the number of the rows in the user table (How many users are
     *         saved in the DB)
     */
    public int GetRowCount() {

        // method variables
        int rowsCount = 0;
        SQLiteDatabase db = null;
        Cursor cursor = null;

        // try to get the user from the database
        try {
            db = this.getReadableDatabase();
            cursor = db.query(TABLE_USER, null, null, null, null, null, null);
            if (cursor != null) {
                boolean moved = cursor.moveToFirst();
                if (moved) {
                    do {
                        rowsCount++;
                    } while (cursor.moveToNext());
                }
            }
        } catch (SQLException exception) {
            Log.e(TAG, exception.getMessage());
        } finally {
            if (cursor != null)
                // release cursor
                cursor.close();
            if (db != null)
                // close database connection
                db.close();
        }
        return rowsCount;
    }

    /**
     * Remove a user from the database
     * 
     * @param userId
     *            The user id
     */
    public void LogoutUser() {

        // method variables
        SQLiteDatabase db = null;

        // try to remove a user from the database
        try {
            db = this.getWritableDatabase();
            onUpgrade(db, DATABASE_VERSION, DATABASE_VERSION);
        } catch (SQLException exception) {
            Log.e(TAG, exception.getMessage());
        } finally {
            if (db != null) {
                // close database connection
                db.close();
            }
        }
    }

    /**
     * Set a user to be active or not
     * 
     * @param isActive
     *            1 if the cigarette is active 0 otherwise
     * @return True if the cigarette active field has changed false otherwise
     */
    public boolean SetUserActive(boolean isActive) {
        // method variables
        int rowsAffected;
        int active = isActive ? 1 : 0;
        long userId;
        String userIdString;
        boolean pass = true;
        SQLiteDatabase db = null;
        ContentValues values = null;

        // try to remove a device from the database
        try {
            userId = GetRegisteredUserId();
            if (userId > -1) {
                userIdString = String.valueOf(userId);
                db = this.getWritableDatabase();
                values = new ContentValues();
                values.put(COLUMN_USER_ACTIVE, active);
                rowsAffected = db.update(TABLE_USER, values, COLUMN_USER_ID
                        + " = ?", new String[] { userIdString });
                if (rowsAffected != 1) {
                    pass = false;
                }
            }
        } catch (SQLException exception) {
            Log.e(TAG, exception.getMessage());
        } finally {
            if (db != null) {
                // close database connection
                db.close();
            }
        }
        return pass;
    }
}



笔记 -
1.请注意,我的设备是根源,所以在将数据插入到数据库后
改变数据库文件的权限为777,所以我可以从手机上看到它
它有什么(即查询是否通过)
2.正在抛出的错误是“android.database.sqlite.SQLiteException:没有这样的
表:用户“


巧克力饼干将被授予任何答案... =)


Why did it worked only after I upgraded the version number not even when I erased all the app related data?

  • 只要您开始使用getReadableDatabase()getWriteableDatabase()或任何其他SQLiteHelper类代码。 第一个方法调用是onCreate(SQLiteDatabase db) ,它在你的应用程序数据库路径/data/data/PACKAGE_NAME/databases/tmc (在你的情况)下创建Database。

  • 如果在SQliteHelper修改数据库结构,第一个调用的方法是onUpgrage() ,它检查Database_Version是否被修改。 如果是这样的话,它执行onUpgrade()和一系列DROP TABLE IF EXIST然后是onCreate() ,通过替换以前的数据库文件再次在您的应用程序路径下创建具有新结构的数据库。

  • 使用应用程序管理器清除缓存数据确实清除了该应用程序的数据库和缓存数据。 但SQLiteHelper确实使用新旧版本来检查Database_Version 。 如果新的比旧的更大。 它会调用onUpgrage()然后再调用onCreate()

  • 当您打算将数据库与Android应用程序一起使用时,它将获得具有应用程序进程安全性的/data/data/PACKAGE_NAME/databases/tmc下的存储。 无法访问数据库文件,除非您拥有您已拥有的扎根Android设备。


  • 你可以创建Developer Options或任何你喜欢的东西,只需将数据库从你的应用程序过程中提取到SD卡,以获得无根的设备。

    Copy database file from application process path to SD Card for unrooted devices.

    try {
           File sd = Environment.getExternalStorageDirectory();
           File data = Environment.getDataDirectory();
            if (sd.canWrite()) {
            String currentDBPath = "/data/data/" + getPackageName() + "/databases/ZnameDB"; //Your DATABASE_NAME
            String backupDBPath = "ZnameDB_Dev.db"; //DATABASE_COPY_NAME UNDER SDCARD
            File currentDB = new File(currentDBPath);
            File backupDB = new File(sd, backupDBPath);
            if (currentDB.exists()) {
            FileChannel src = new FileInputStream(currentDB).getChannel();
            FileChannel dst = new FileOutputStream(backupDB).getChannel();
            dst.transferFrom(src, 0, src.size());
            src.close();
            dst.close();
            Toast.makeText(SettingsActivity.this, "Database Transfered!", Toast.LENGTH_SHORT).show();
              }
             }
         } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
    

    回答您的第一个问题,所有数据仅存储在YOUR_PACKAGE / databases / DATABASE.db下。

    如果您通过应用程序管理器擦除应用程序,则所有数据都将被删除,只剩包。 如果你卸载你的应用程序,一切都将被清除,包括包文件夹 即使您将您的应用程序安装位置设置为外部SD卡,数据库仍然会在内部存储。

    从文档:

    .apk文件保存在外部存储器中,但所有私有用户数据,数据库,优化.dex文件和提取的本机代码都保存在内部设备内存中。

    SQLiteOpenHelper逻辑很简单:

  • 检查数据库是否存在,如果没有创建新数据库
  • 检索数据库版本,初始值为0,这就是为什么在您的应用程序DB版本的最小值是1,至少调用onCreate()方法一次
  • 如果版本等于0,则调用onCreate()或
  • 如果版本不同于您的代码onUpgrade()或onDowngrade()所提供的版本
  • 所以,每当你升级你的方案时,版本号必须增加,这是没有争议的,为了让你的应用程序正常工作。

    现在,在你的具体情况下,我只能猜测。 我会说擦除你的软件包并不是完全成功的,而且还有一些数据被遗留,特别是如果你提到你对数据库文件做了一些手动修改。 也许它与你的设备上运行的Android版本有关,但你没有提到它是哪一个。

    就这样。 我希望我的回答令人满意。


    你可以执行PRAGMA user_version; 在你的adb中获取数据库版本? 根据SQLiteOpenHelper的源代码,SQLite.getVersion()等于SQLiteOpenHelper.mNewVersion,因此不会调用onCreate()方法。 当你在db文件上chmod 777时,user_version也会被修改。

    链接地址: http://www.djcxy.com/p/20459.html

    上一篇: A strange behavior for regualr sqlite operation on android

    下一篇: Input accept attribute in Firefox