Странное поведение для работы regualr sqlite на android


У меня была проблема, которую я уже решил, но я все еще хочу знать, почему решение ее решило. Я написал приложение для android, которое имело базу данных sqlite после того, как пару раз отладил его Метод oncreate в БД не вызывался (хотя раньше все работало нормально) После того, как я изменил номер версии db с 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. Обратите внимание, что мое устройство укоренено и поэтому после вставки данных в db im
изменяет разрешения на файл db для 777, чтобы я мог вытащить его из телефона, чтобы увидеть
что в нем (т. е. прошел запрос или нет)
2. Ошибка что-то есть "для Андроид.база данных.базы данных SQLite.SQLiteException: нет такой
таблицы: пользователь "


шоколадные чипсы печенье будет предоставлено для любого ответа... =)

4 7

4 ответа:

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 (в вашем случае).

  • Если вы изменяете структуру базы данных в 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.только БД.

Если вы удаляете приложение через Диспетчер приложений, все данные удаляются, остается только пакет. При удалении приложения все очищается, включая папку пакета. Даже если вы установили для вашего приложения место установки на внешнюю SD-карту, база данных все равно хранится внутри.

Из документации:

The .файл apk сохраняется на внешнем носителе, но все личные данные пользователя данные, базы данных, оптимизированные .файлы dex и извлеченный машинный код являются сохраняется во внутренней памяти устройства.

Логика SQLiteOpenHelper проста:

  • проверяет, существует ли БД, если не создается новая БД
  • получить версию БД, начальное значение равно 0, поэтому в вашем приложении минимальное значение для версии БД равно 1, чтобы вызвать метод onCreate() хотя бы один раз
  • Если version равно 0, то вызывается onCreate (), или
  • Если версия отличается от версии, предоставленной ваш код onUpgrade() или onDowngrade () называется

Таким образом, всякий раз, когда вы обновляете свою схему, номер версии должен быть увеличен, нет никаких споров об этом, чтобы позволить вашему приложению работать должным образом.

Теперь, в вашем конкретном случае, я могу только догадываться. Я бы сказал, что стирание вашего пакета не было полностью успешным, и биты данных были оставлены, особенно если вы упомянули, что вы сделали некоторые ручные изменения в файле DB. Может быть, это как-то связано с версией Android, работающей на ваше устройство, но вы не упомянули, какое именно.

Вот и все. Надеюсь, мой ответ вас удовлетворит.

Можете ли вы выполнить PRAGMA user_version; в вашем adb, чтобы получить версию БД? Согласно исходному коду SQLiteOpenHelper, SQLite.getVersion () равно SQLiteOpenHelper.mNewVersion, поэтому метод onCreate () не будет вызван. Когда вы chmod 777 на файле db, user_version также будет изменен.

Предполагая, что базы данных не удаляются при удалении приложения, это кажется правдоподобным. Базы данных хранятся здесь DDMS/data/data/PACKAGE_NAME/databases/YOUR_DB_FILE. Вы можете увидеть это, только если ваш телефон укоренен. Пожалуйста, проверьте, верно ли это предположение, и поправьте меня, если я ошибаюсь. Спасибо