2016-05-27 2 views
-2

У меня есть простое приложение для словарей, которое использует этот класс обработчика базы данных. (я уже заполнил базу данных с помощью DB Browser и хочу отправить его с приложением)Почему база данных приложения не копируется на устройство Android?

public class DictionaryDatabase extends SQLiteOpenHelper { 
    private static final String DB_NAME = "dict.db"; 
    private static String DB_PATH = "/data/data/com.dictshop.dict/databases/"; 
    private static final String TABLE_DICTIONARY = "dictionary"; 
    private static final String FIELD_WORD = "word"; 
    private static final String FIELD_DEFINITION = "definition"; 
    private static final int DATABASE_VERSION = 1; 
    private Context myContext; 


    DictionaryDatabase(Context context) { 
     super(context, DB_NAME, null, DATABASE_VERSION); 
     this.myContext = context; 
    } 


    public void crateDatabase() throws IOException { 
     boolean vtVarMi = isDatabaseExist(); 

     if (!vtVarMi) { 
      this.getReadableDatabase(); 

      try { 
       copyDataBase(); 
      } catch (IOException e) { 
       throw new Error("Error copying database"); 
      } 
     } 
    } 


    private boolean isDatabaseExist() { 
     SQLiteDatabase kontrol = null; 

     try { 
      String myPath = DB_PATH + DB_NAME; 
      kontrol = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY); 

     } catch (SQLiteException e) { 
      kontrol = null; 
     } 

     if (kontrol != null) { 
      kontrol.close(); 
     } 
     return kontrol != null ? true : false; 
    } 



    private void copyDataBase() throws IOException { 

     // Open your local db as the input stream 
     InputStream myInput = myContext.getAssets().open(DB_NAME); 

     // Path to the just created empty db 
     String outFileName = DB_PATH + DB_NAME; 

     // Open the empty db as the output stream 
     OutputStream myOutput = new FileOutputStream(outFileName); 

     // transfer bytes from the inputfile to the outputfile 
     byte[] buffer = new byte[1024]; 
     int length; 
     while ((length = myInput.read(buffer)) > 0) { 
      myOutput.write(buffer, 0, length); 
     } 

     // Close the streams 
     myOutput.flush(); 
     myOutput.close(); 
     myInput.close(); 
    } 

    @Override 
    public void onCreate(SQLiteDatabase db) { 
     db.execSQL("CREATE TABLE " + TABLE_DICTIONARY + 
       "(_id integer PRIMARY KEY," + 
       FIELD_WORD + " TEXT, " + 
       FIELD_DEFINITION + " TEXT);"); 
    } 

    @Override 
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 
     //Handle database upgrade as needed 
    } 

    public void saveRecord(String word, String definition) { 
     long id = findWordID(word); 
     if (id>0) { 
      updateRecord(id, word,definition); 
     } else { 
      addRecord(word,definition); 
     } 

    } 

    public long addRecord(String word, String definition) { 
     SQLiteDatabase db = getWritableDatabase(); 
     ContentValues values = new ContentValues(); 
     values.put(FIELD_WORD, word); 
     values.put(FIELD_DEFINITION, definition); 
     return db.insert(TABLE_DICTIONARY, null, values); 
    } 
    public int updateRecord(long id, String word, String definition) { 
     SQLiteDatabase db = getWritableDatabase(); 
     ContentValues values = new ContentValues(); 
     values.put("_id", id); 
     values.put(FIELD_WORD, word); 
     values.put(FIELD_DEFINITION, definition); 
     return db.update(TABLE_DICTIONARY, values, "_id = ?", 
       new String[]{String.valueOf(id)}); 
    } 
    public int deleteRecord(long id) { 
     SQLiteDatabase db = getWritableDatabase(); 
     return db.delete(TABLE_DICTIONARY, "_id = ?", new 
       String[]{String.valueOf(id)}); 
    } 

    public long findWordID(String word) { 
     long returnVal = -1; 
     SQLiteDatabase db = getReadableDatabase(); 
     Cursor cursor = db.rawQuery(
       "SELECT _id FROM " + TABLE_DICTIONARY + 
         " WHERE " + FIELD_WORD + " = ?", new String[]{word}); 
     Log.i("findWordID","getCount()="+cursor.getCount()); 
     if (cursor.getCount() == 1) { 
      cursor.moveToFirst(); 
      returnVal = cursor.getInt(0); 
     } 
     return returnVal; 
    } 


    public String getWord(long id) { 
     String returnVal = ""; 
     SQLiteDatabase db = getReadableDatabase(); 
     Cursor cursor = db.rawQuery(
       "SELECT word FROM " + TABLE_DICTIONARY + 
         " WHERE _id = ?", new String[]{String.valueOf(id)}); 
     if (cursor.getCount() == 1) { 
      cursor.moveToFirst(); 
      returnVal = cursor.getString(0); 
     } 
     return returnVal; 
    } 


    public String getDefinition(long id) { 
     String returnVal = ""; 
     SQLiteDatabase db = getReadableDatabase(); 
     Cursor cursor = db.rawQuery(
       "SELECT definition FROM " + TABLE_DICTIONARY + 
         " WHERE _id = ?", new String[]{String.valueOf(id)}); 
     if (cursor.getCount() == 1) { 
      cursor.moveToFirst(); 
      returnVal = cursor.getString(0); 
     } 
     return returnVal; 
    } 


    public Cursor getWordList() { 
     SQLiteDatabase db = getReadableDatabase(); 
     String query = "SELECT _id, " + FIELD_WORD + 
       " FROM " + TABLE_DICTIONARY + " ORDER BY " + FIELD_WORD + 
       " ASC"; 
     return db.rawQuery(query, null); 
    } 
} 

Я толкнул dict.db к проекту:

[email protected]:~$ ~/Android/Sdk/platform-tools/adb -s emulator-5554 push /home/me/Desktop/Dict/dict.db /data/data/com.dictshop.Dict/databases/dict.db 

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

Однако, когда я пытаюсь использовать приложение на устройствах (один корневой, один из них не открыт), данные не отображаются. Что здесь может быть не так?

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

UPDATE: вот MainActivity, который использует использует базу данных:

public class MainActivity extends AppCompatActivity { 
    EditText mEditTextWord; 
    EditText mEditTextDefinition; 
    DictionaryDatabase mDB; 
    ListView mListView; 

     @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 


      Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
      setSupportActionBar(toolbar); 
      // Get a support ActionBar corresponding to this toolbar 
      ActionBar ab = getSupportActionBar(); 
      // Enable the Up button 
      ab.setDisplayHomeAsUpEnabled(true); 

     mDB = new DictionaryDatabase(this); 




     mListView = (ListView)findViewById(R.id.listView); 
     mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> parent, View 
        view, int position, long id) { 
       String nextId = String.valueOf(id+1); 
       Intent intent = new Intent(view.getContext(),DetailActivity.class); 
       intent.putExtra("key" ,mDB.getWord(id)+""); 
       intent.putExtra("value",mDB.getDefinition(id)+""); 
       intent.putExtra("nextId",nextId+""); 
       startActivity(intent); 
      } 
     }); 

     mListView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() { 
      @Override 
      public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { 
       Toast.makeText(MainActivity.this, 
         "Records deleted = " + mDB.deleteRecord(id), 
         Toast.LENGTH_SHORT).show(); 
       updateWordList(); 
       return true; 
      } 
     }); 
     updateWordList(); 

    } 


    private void saveRecord() { 
     mDB.saveRecord(mEditTextWord.getText().toString(), 
       mEditTextDefinition.getText().toString()); 
     mEditTextWord.setText(""); 
     mEditTextDefinition.setText(""); 
     updateWordList(); 
    } 

    private void updateWordList() { 
     SimpleCursorAdapter simpleCursorAdapter = new 
       SimpleCursorAdapter(this, 
       android.R.layout.simple_list_item_1, 
       mDB.getWordList(), 
       new String[]{"word"}, 
       new int[]{android.R.id.text1}, 
       0); 
     mListView.setAdapter(simpleCursorAdapter); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.menu_main, menu); 
     return true; 
    } 

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.share_app: 

       Intent sendIntent = new Intent(); 
       sendIntent.setAction(Intent.ACTION_SEND); 
       sendIntent.putExtra(Intent.EXTRA_TEXT, "this is the app"); 
       sendIntent.setType("text/plain"); 
       startActivity(sendIntent); 

       return true; 


      default: 
       // If we got here, the user's action was not recognized. 
       // Invoke the superclass to handle it. 
       return super.onOptionsItemSelected(item); 
     } 
    } 
} 
+0

Любое сообщение об ошибке? LogCat? – Nabin

+0

Не похоже, что вы нажали dict.db на устройства. Так почему вы ожидаете увидеть его там? –

+0

@NabinKhadka Я не вижу ошибки в консоли. Не уверен, что такое logcat. – narad

ответ

0

SQLiteAssetHelper является то, что вы хотите. Выполните следующие действия:

Добавить зависимость в файл build.gradle своего приложения модуля:

dependencies { 
    compile 'com.readystatesoftware.sqliteasset:sqliteassethelper:+' 
} 

Скопируйте базу данных в каталог активов, в подкаталоге assets/databases. Итак:

assets/databases/dict.db 

Создать класс:

public class MyDatabase extends SQLiteAssetHelper { 

    private static final String DATABASE_NAME = "dict.db"; 
    private static final int DATABASE_VERSION = 1; 

    public MyDatabase(Context context) { 
     super(context, DATABASE_NAME, null, DATABASE_VERSION); 
    } 
} 

Для справки: https://github.com/jgilfelt/android-sqlite-asset-helper

+0

Я кратко попробовал 'sqliteassethelper'. Это сломало мое приложение, поэтому я решил остаться в стороне от него.ИМХО, это лишняя хлопот, а не решение. Однако, если вы можете обернуть его вокруг моего существующего класса, я с удовольствием попробую его. – narad

+0

Я вижу, еще одно предлагаемое решение состоит в том, что вы размещаете свою предварительно заполненную БД в папке с ресурсами и затем копируете ее в обычный каталог базы данных. См. [This] (http://blog.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/). На самом деле, ваш код кажется очень похожим на их, однако вы никогда не называли 'createDatabase()' в 'onCreate()'. Попробуй это. –

+0

Правильно, но я не знаю, как вызвать 'crateDatabase() внутри моей MainActivity. Я пробовал разные вещи, но всегда получаю ошибку. Вы можете помочь в этом, пожалуйста? – narad

0

Это пример SQLite местный

public class SqliteHelper extends SQLiteOpenHelper { 

public static String DB_PATH = "/data/data/com.dictshop.dict/databases/"; 
private static String DB_NAME = "dict.db"; 
private final Context context; 

public SqliteHelper(Context context) { 
    super(context, DB_NAME, null, 1); 
    this.context = context; 
} 

/** 
* copy database from assets to the device if not existed 
**/ 
public boolean isCreatedDatabase() throws IOException { 
    // Default is database have data 
    boolean result = true; 
    // check data 
    if (!checkExistDataBase()) { 
     this.getReadableDatabase(); 
     try { 
      copyDataBase(); 
      result = false; 
     } catch (Exception e) { 
      throw new Error("Error copying database"); 
     } 

    } 
    return result; 
} 


/** 
* check database exist on the device? 
*/ 
private boolean checkExistDataBase() { 

    try { 
     String myPath = DB_PATH + DB_NAME; 
     File fileDB = new File(myPath); 
     if (fileDB.exists()) { 
      return true; 
     } else 
      return false; 
    } catch (Exception e) { 
     return false; 
    } 
} 

/** 
* copy database from assets folder to the device 
* 
* @throws IOException 
*/ 
private void copyDataBase() throws IOException { 
    InputStream myInput = context.getAssets().open(DB_NAME); 
    OutputStream myOutput = new FileOutputStream(DB_PATH + DB_NAME); 
    byte[] buffer = new byte[1024]; 
    int length; 
    while ((length = myInput.read(buffer)) > 0) { 
     myOutput.write(buffer, 0, length); 
    } 
    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 

} 
} 

в MainActivity.class

public class MainActivity extends Activity { 


@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_test); 
    // create DB 
    isCreateDB(); 
} 

/* 
* Copy db from asset to database 
*/ 
private boolean isCreateDB() { 
    SqliteHelper data = new SqliteHelper(this); 
    try { 

     return data.isCreatedDatabase(); 

    } catch (IOException e) { 
     Toast.makeText(this, "Error Copy data", Toast.LENGTH_LONG).show(); 
     e.printStackTrace(); 
     return false; 
    } 
} 

Надежды. Это поможет вам !!!

Смежные вопросы