My Database Adapter Class
public class DatabaseAdapter {
// Declare a DatabaseHelper object reference
DatabaseHelper helper;
// Declare a SQLiteDatabase object reference.
SQLiteDatabase db;
// SQLiteDatabase class has methods to create, delete, execute SQL commands and perform other common database
// management tasks.
// Define an ArrayList of Term object.
ArrayList<Term> termsList = new ArrayList<Term>();
// What is Term?
// You'll create a Term class to contain and model the information and make it more easy to implement.
// Define the constructor for DatabaseAdapter
public DatabaseAdapter(Context context){
// Instantiate helper
helper = new DatabaseHelper(context);
// Call getWritableDatabase() method on helper. This is going to give you an object of SQLiteDatabase. Store that in db.
db = helper.getWritableDatabase();
// Now, this SQLiteDatabase object, db, is going to represent the database you have and you are going to use that object
// to perform the different queries that you want to do, for example, insert, update or delete from database.
}
// Define a method to close the database
public void close() {
helper.close();
}
public int deleteData(long id) {
// Define the whereArgs String array
String whereArgs[] = {""+id};
// Call delete() method on db
return db.delete(DatabaseHelper.TABLE_NAME, DatabaseHelper.KEY_ID + "=?", whereArgs);
// delete() returns the number of rows deleted as an integer.
}
public int updateTermFullForm(long id, String meaning) {
// To update the database, you need to create an object of the class called ContentValues that acts like a map, inside which you can
// put your key-value pairs.
// Here, what is expected is the name of the key that you give here is the name of the column in your table
// and the value you want to put inside the column goes in the second parameter.
ContentValues contentValues = new ContentValues();
contentValues.put(DatabaseHelper.KEY_MEANING, meaning);
// You need to create whereArgs[] array. whereArgs[] is just an array that contains the values that are substituted inside the
// question mark (?) of whereClause at run-time, when you are executing the query.
// whereArgs[] is going to contain the values for against you want to compare.
String whereArgs[] = {""+id};
// Call update() method on db
return db.update(DatabaseHelper.TABLE_NAME, contentValues, DatabaseHelper.KEY_ID + "=?", whereArgs);
// update() returns the number of rows affected as an integer.
// The plain sql statement for this can be:
// UPDATE ct SET full_form="New Value" WHERE _id=2
}
public long insertTerm(String words, String meaning) {
// Define a new ContentValues object
ContentValues contentValues = new ContentValues();
// Add term and fullForm into that
contentValues.put(DatabaseHelper.KEY_WORDS, words);
contentValues.put(DatabaseHelper.KEY_MEANING, meaning);
// Call insert() method on db object and return
return db.insert(DatabaseHelper.TABLE_NAME, null, contentValues);
}
// Next, define a method that returns an ArrayList of specific Term objects where the term starts with the String in parameter.
public ArrayList<Term> getSomeTerms(String termStartsWith){
// Call query() method on db and store the returned cursor.
Cursor cursor = db.query(DatabaseHelper.TABLE_NAME, new String[]{DatabaseHelper.KEY_ID, DatabaseHelper.KEY_WORDS,
DatabaseHelper.KEY_MEANING}, DatabaseHelper.KEY_WORDS + " like '"
+ termStartsWith + "%'",null,null,null,null);
// Here, % is a wildcard character which indicates 0 or any number of characters. So, there can be any number of characters
// after “A”, or "B" or "S" etc.
// The plain sql statement for this can be:
// SELECT * FROM ct WHERE terms LIKE 'A%';
// Use a while loop to traverse the database and populate the ArrayList of Term objects
while (cursor.moveToNext()){
// Get the database column index or position by passing the column name
int index1 = cursor.getColumnIndex(DatabaseHelper.KEY_ID);
// Now, get the value of id for that cell
long id = cursor.getInt(index1);
// Do the same thing to get values from other two columns
int index2 = cursor.getColumnIndex(DatabaseHelper.KEY_WORDS);
String words = cursor.getString(index2);
int index3 = cursor.getColumnIndex(DatabaseHelper.KEY_MEANING);
String meaning = cursor.getString(index3);
// Create a Term object from database values
Term term = new Term(id, words, meaning);
// Add the Term object to termsList
termsList.add(term);
}
// return termList
return termsList;
}
// For managing all the operations related to the database, a helper class has been provided by Android
// and it is called SQLiteOpenHelper.
// It takes care of opening the database if it exists, creating it if it does not exists, and upgrading it as necessary.
// So, inside DatabaseAdapter you'll create a static inner class that extends SQLiteOpenHelper.
private static class DatabaseHelper extends SQLiteOpenHelper{
// Define some private static final String variables to store information related to the database
private static final String DATABASE_NAME ="Test.db";
// Database name must be unique within an app, not across all the apps.
private static final String TABLE_NAME = "words";
// When you do change the structure of the database change the version number from 1 to 2
private static final int DATABASE_VERSION = 7;
static final String KEY_ID = "id";
static final String KEY_WORDS = "words";
static final String KEY_MEANING = "meaning";
private Context context;
// Define the constructor
public DatabaseHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
// Store the context received from constructor into this class's context variable
this.context = context;
}
// Since, you're not creating or upgrading the database since you're using a pre-created database file
// copied to the right location, you don't need to write any code inside onCreate() or onUpgrade().
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
}
My PreCreate Database Class
public class PreCreateDB {
static String destPath;
static String destPathwithFilename;
// Lets define copyDB() method
public static void copyDB(Context context){
// Defile two String variables containing path upto "database" folder and "CTDB" file respectively
destPath = "/data/data/" + context.getPackageName() + "/databases";
destPathwithFilename = destPath+"/Test.db";
// Create two File objects from those Strings
File fPath = new File(destPath);
File fPathWithName = new File(destPathwithFilename);
// Now, the question is, why we created two separate File objects?
// It's because in some devices databases folder will be automatically created by Android system.
// In some other devices it won't be there by default.
// So, we need to check if it's not present in the device.
if(!fPath.exists()){
// If true, you'll create the databases folder
fPath.mkdirs();
// And then copy the CTDB Database file from assets folder to databases folder.
// You'll define a method named rawCopy that takes an InputStream and an OutputStream.
// This method will copy the file.
try {
rawCopy(context.getAssets().open("Test.db"), new FileOutputStream(destPath+"/Test.db"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void rawCopy(InputStream inputStream, OutputStream outputStream) throws IOException {
// To copy 1k bytes at a time, create a byte array of size 1024
byte[] buffer = new byte[1024];
// Declare an integer variable to store the total number of bytes read from the buffer.
int length;
// If you call read() method on inputStream object and pass buffer as parameter, it will read 1024 bytes at a time.
// It returns -1 if there is no more data because the end of the stream has been reached.
// Using this information you use a while loop to read from the inputStream and write to the outputStream.
// This copies the database file CTDB from assets folder to data/data/[package-name]/databases folder.
while((length = inputStream.read(buffer)) > 0){
outputStream.write(buffer, 0, length);
}
// Close the input and output streams once you're done
inputStream.close();
outputStream.close();
}
public static void resetDB(Context context) {
// Call rawCopy() inside try block
try {
rawCopy(context.getAssets().open("Test.db"), new FileOutputStream(destPathwithFilename));
} catch (IOException e) {
e.printStackTrace();
}
}
}
MY Show Term Class
public class ShowTerm extends AppCompatActivity {
// Declare a DatabaseAdapter object reference
static DatabaseAdapter databaseAdapter;
// Declare a RecyclerView object reference
static RecyclerView rvTerms;
// Declare an Adapter object reference
TermsAdapter termsAdapter;
// Declare a LayoutManager object reference
RecyclerView.LayoutManager layoutManager;
// Define an ArrayList of type Term
static ArrayList<Term> termsList = new ArrayList<>();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show_term);
// Get the received String from Intent
String termStartsWith = getIntent().getStringExtra("termStartsWith");
// Instantiate DatabaseAdapter class and pass this for the Context
databaseAdapter = new DatabaseAdapter(this);
// Call getSomeTerms() on databaseAdapter object and store the returned ArrayList in
// termsList
termsList = databaseAdapter.getSomeTerms(termStartsWith);
// Obtain a handle for the RecyclerView
rvTerms = findViewById(R.id.rvTerms);
// You may use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
rvTerms.setHasFixedSize(true);
// Instantiate the linear layout manager
layoutManager = new LinearLayoutManager(this);
// Set the layout with RecyclerView
rvTerms.setLayoutManager(layoutManager);
// Create an instance of TermsAdapter. Pass context, termsList and the
// RecyclerView to the constructor
termsAdapter = new TermsAdapter(this, termsList, rvTerms);
// Finally, attach the adapter with the RecyclerView
rvTerms.setAdapter(termsAdapter);
}
}
My Bengali + Hindi Mix Sqlite Database
This Sqlite query giving blank results for Hindi words but English words are showning Properly
My MainActivity Class
public class MainActivity extends AppCompatActivity {
// Store the text to be shared in a String
String shareBody = "Download CTD App now and know about all the important Computer Terms and their Full Forms: \n" +
"https://play.google.com/store/apps/details?id=com.sandipbhattacharya.computertermsdictionary";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create a class containing static methods to copy the database file
// from assets folder into: data/data/package-name/databases folder, from where the app can access it.
// Lets name it PreCreateDB.
// From MainActivity, call the copyDB method of PreCreateDB and pass "this" for Context
PreCreateDB.copyDB(this);
}
public void show(View view) {
// We have set a text with every button. This text simply contains an alphabet.
// Get the clicked Button's text and store in a String variable
String termStartsWith = ((Button) view).getText().toString().trim();
// Create an Intent to go to another Activity where you can show all the Terms that start with a letter termStartsWith contains
Intent intent = new Intent(this, ShowTerm.class);
// Set termStartsWith with the Intent object as Extra
intent.putExtra("termStartsWith", termStartsWith);
// Start the Activity with the Intent
startActivity(intent);
// Create the ShowTerm class.
}
public void reset(View view) {
// You'll use Android AlertDialog to ask the user about his/her choice to continue or discontinue the reset operation.
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("Resetting will delete all your personal data. Proceed?");
builder.setCancelable(true);
builder.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Here, you call a method and pass MainActivity.this as context,
// to replace the database file from assets folder to databases folder.
PreCreateDB.resetDB(MainActivity.this);
}
});
builder.setNegativeButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
AlertDialog alertDialog = builder.create();
alertDialog.show();
}
public void addNew(View view) {
// You'll use an Intent to go to AddNew Activity
Intent intent = new Intent(this, AddNew.class);
startActivity(intent);
}
public void rate(View view) {
// Create an Intent that opens a URL in Google Play
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=" + getPackageName()));
// As you configure this intent, pass "com.android.vending" into Intent.setPackage() so that users see your app's details
// in the Google Play Store app instead of a chooser. Make sure your emulator has pre-installed Play Store app.
intent.setPackage("com.android.vending");
// Start the Activity
try {
startActivity(intent);
}catch (ActivityNotFoundException e) {
Toast.makeText(this, "Couldn't launch Play Store", Toast.LENGTH_LONG).show();
}
}
public void shareApp(View view) {
// Create a send Intent
Intent sendIntent = new Intent(Intent.ACTION_SEND);
// Set the Sharing Type
sendIntent.setType("text/plain");
// Pass your sharing content using the putExtra() method of the Intent
sendIntent.putExtra(Intent.EXTRA_SUBJECT, "Share CTD App");
sendIntent.putExtra(Intent.EXTRA_TEXT, shareBody);
// Next, instruct Android system to let the user choose their sharing medium
startActivity(Intent.createChooser(sendIntent, "Share using"));
// This will pass the sendIntent along with a title to be displayed at the top of the chooser.
// When the user chooses an application from the list, your share content will be passed to that application,
// where he/she will be able to edit the content before sending it if they wish to do so.
}
}
Please Help me because im beginner in android development and it is very important for my dictionary app 🙏
Solved the problem, in Sqlite database your table creation rules are also important when using external database.