Added basic SQLite functionality NOT FUNCTIONAL YET

Unfortunately the Databse connection is not functional yet
as we seem to have some general problems with the db handling.
This commit is contained in:
Alexander Doerflinger
2017-08-08 12:56:44 +02:00
parent 5a1ba02c20
commit 349c67f093
8 changed files with 394 additions and 11 deletions

2
.idea/misc.xml generated
View File

@@ -56,7 +56,7 @@
<ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" /> <ConfirmationsSetting value="0" id="Remove" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -7,8 +7,8 @@ android {
applicationId "com.de.aldo_apps.aldo.mariokartcircuitselector" applicationId "com.de.aldo_apps.aldo.mariokartcircuitselector"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 25 targetSdkVersion 25
versionCode 3 versionCode 4
versionName "0.3" versionName "0.4"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
} }
buildTypes { buildTypes {

Binary file not shown.

View File

@@ -6,6 +6,11 @@ package com.de.aldo_apps.aldo.mariokartcircuitselector;
public class Constants { public class Constants {
/**
* The Version Code of the Database.
*/
public static final Integer DATABASE_VERSION = 1;
/** /**
* As SQLite does not have a native boolean value, we use integers to represent true and false. * As SQLite does not have a native boolean value, we use integers to represent true and false.
* This is the value for a true statement. * This is the value for a true statement.
@@ -18,10 +23,16 @@ public class Constants {
*/ */
public final static Integer FALSE = 0; public final static Integer FALSE = 0;
/**
* The Path to the Database
*/
public static final String DATABASE_PATH
= "/data/data/com.de.aldo_apps.aldo.mariokartcircuitselector/databases/";
/** /**
* The Name of the complete database. * The Name of the complete database.
*/ */
public static final String DATABASE_NAME = "mario_kart_circuit_selector.db"; public static final String DATABASE_NAME = "mario_kart_circuit_selector";
/** /**
* The name of the table containing all information according accessories. * The name of the table containing all information according accessories.

View File

@@ -0,0 +1,329 @@
package com.de.aldo_apps.aldo.mariokartcircuitselector;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.de.aldo_apps.aldo.mariokartcircuitselector.database_models.Accessory;
import com.de.aldo_apps.aldo.mariokartcircuitselector.database_models.Character;
import com.de.aldo_apps.aldo.mariokartcircuitselector.database_models.Kart;
import com.de.aldo_apps.aldo.mariokartcircuitselector.database_models.Track;
import com.de.aldo_apps.aldo.mariokartcircuitselector.database_models.Wheels;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import static com.de.aldo_apps.aldo.mariokartcircuitselector.Constants.KEY_AVAILABLE;
import static com.de.aldo_apps.aldo.mariokartcircuitselector.Constants.KEY_GAME;
import static com.de.aldo_apps.aldo.mariokartcircuitselector.Constants.KEY_ID;
import static com.de.aldo_apps.aldo.mariokartcircuitselector.Constants.KEY_NAME;
import static com.de.aldo_apps.aldo.mariokartcircuitselector.Constants.TABLE_TRACK;
import static com.de.aldo_apps.aldo.mariokartcircuitselector.Constants.TABLE_WHEELS;
/**
* The Database Handler class which opens/closes connection and handles all CRUD Operations
* on the Database.
*
* @author aldo7224
* @version 0.1
* @since 08.08.2017
*/
public class DatabaseHandler extends SQLiteOpenHelper {
/**
* Tag for debugging output.
*/
private static final String TAG = "DatabaseHandler";
private final Context mContext;
private SQLiteDatabase mDatabase;
public DatabaseHandler(final Context context) {
super(context, Constants.DATABASE_NAME, null, Constants.DATABASE_VERSION);
mContext = context;
}
@Override
public void onCreate(final SQLiteDatabase sqLiteDatabase) {
mDatabase = sqLiteDatabase;
Log.d(TAG, "onCreate: Is new database opened? [" + mDatabase.isOpen() + "]");
if (!checkDataBase()) {
// Maybe the DB already exists but we need to upgrade.
Log.d(TAG, "onCreate: Dropping all Tables (in case they already exist).");
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Constants.TABLE_GAME);
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Constants.TABLE_ACCESSORY);
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Constants.TABLE_CHARACTER);
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Constants.TABLE_KART);
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Constants.TABLE_RULESET);
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + Constants.TABLE_TRACK);
sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + TABLE_WHEELS);
try {
Log.d(TAG, "onCreate: Copying the Database from Assets Folder to database path.");
copyDataBase();
} catch (IOException exception) {
Log.d(TAG, "onCreate: Could not Copy Database. Exception ["
+ exception.getMessage() + "]");
}
}
}
@Override
public void onUpgrade(final SQLiteDatabase sqLiteDatabase,
final int oldVersion,
final int newVersion) {
// Dropping Tables and Creating them again. All handled by onCreate.
Log.d(TAG, "onUpgrade: Databse was upgraded. Performing upgrade.");
onCreate(sqLiteDatabase);
}
/**
* Check if the database already exist to avoid re-copying the file each time you open the
* application. Also check if the Version Code of the Database changed, so maybe the data need
* to be copied again.
* @return true if it exists, false if it doesn't
*/
private boolean checkDataBase(){
Log.d(TAG, "checkDataBase: Checking Database availability.");
SQLiteDatabase checkDB = null;
if (mDatabase != null && mDatabase.isOpen()) {
Log.d(TAG, "checkDataBase: Closing real database to prevent exception when " +
"opening test DB.");
checkDB = mDatabase;
} else {
try {
final String myPath = Constants.DATABASE_PATH + Constants.DATABASE_NAME;
Log.d(TAG, "checkDataBase: Opening Test-Database.");
checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
} catch (final SQLiteException exception) {
//database does't exist yet.
Log.d(TAG, "checkDataBase: Opening of database throws Exception ["
+ exception.getMessage() + "]. Database seems to not exist yet.");
}
}
// If Database exists we need to close the Database.
if (checkDB != null) {
Log.d(TAG, "checkDataBase: Database seems to exist already.");
// If the Version Code is Lower than the predefined value, we need to upgrade the DB.
if (checkDB.getVersion() < Constants.DATABASE_VERSION) {
Log.d(TAG, "checkDataBase: Database Version code from new and old one differ.");
checkDB.close();
return false;
}
Log.d(TAG, "checkDataBase: Closing Database.");
checkDB.close();
}
return checkDB != null;
}
/**
* Copies your database from your local assets-folder to the just created empty database in the
* system folder, from where it can be accessed and handled.
* This is done by transfering bytestream.
* */
private void copyDataBase() throws IOException {
//Open your local db as the input stream
Log.d(TAG, "copyDataBase: Opening InputStream for DB in assets folder.");
final InputStream inputStream = mContext.getAssets().open(Constants.DATABASE_NAME);
// Path to the just created empty db
final String outFileName = Constants.DATABASE_PATH + Constants.DATABASE_NAME;
//Open the empty db as the output stream
Log.d(TAG, "copyDataBase: Opening Outputstream for DB on hard disk [" + outFileName + "]");
final OutputStream outputStream = new FileOutputStream(outFileName);
//transfer bytes from the inputfile to the outputfile
final byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) > 0) {
Log.d(TAG, "copyDataBase: Writing single Chunk of DB from assets to hard disk.");
outputStream.write(buffer, 0, length);
}
//Close the streams
Log.d(TAG, "copyDataBase: Flushing Stream.");
outputStream.flush();
Log.d(TAG, "copyDataBase: Closing Output Stream.");
outputStream.close();
Log.d(TAG, "copyDataBase: Closing Input Stream.");
inputStream.close();
}
/**
* Helper method to update the availability status of a single track.
*
* @param track The track which should be marked as available/unavailable.
* @param isAvailable The status of availability to be set.
*
* @return The result code of the update function.
*/
public int changeTrackAvailability(final Track track, final boolean isAvailable) {
final SQLiteDatabase db = this.getWritableDatabase();
final ContentValues values = new ContentValues();
values.put(Constants.KEY_GAME, track.getGame());
values.put(KEY_NAME, track.getName());
values.put(Constants.KEY_PACKAGE, track.getPackage());
values.put(Constants.KEY_NUMBER, track.getmNumber());
if (isAvailable) {
values.put(KEY_AVAILABLE, Constants.TRUE);
} else {
values.put(KEY_AVAILABLE, Constants.FALSE);
}
return db.update(Constants.TABLE_TRACK, values, KEY_ID + " = ?",
new String[] {String.valueOf(track.getId()) });
}
/**
* Helper method to update the availability status of a single character.
*
* @param character The character which should be marked as available/unavailable.
* @param isAvailable The status of availability to be set.
*
* @return The result code of the update function.
*/
public int changeCharacterAvailability(final Character character, final boolean isAvailable) {
final SQLiteDatabase db = this.getWritableDatabase();
final ContentValues values = new ContentValues();
values.put(Constants.KEY_GAME, character.getGame());
values.put(KEY_NAME, character.getName());
values.put(Constants.KEY_WEIGHT, character.getWeight());
if (isAvailable) {
values.put(KEY_AVAILABLE, Constants.TRUE);
} else {
values.put(KEY_AVAILABLE, Constants.FALSE);
}
return db.update(Constants.TABLE_CHARACTER, values, KEY_ID + " = ?",
new String[] {String.valueOf(character.getId()) });
}
/**
* Helper method to update the availability status of a single kart.
*
* @param kart The kart which should be marked as available/unavailable.
* @param isAvailable The status of availability to be set.
*
* @return The result code of the update function.
*/
public int changeKartAvailability(final Kart kart, final boolean isAvailable) {
final SQLiteDatabase db = this.getWritableDatabase();
final ContentValues values = new ContentValues();
values.put(Constants.KEY_GAME, kart.getGame());
values.put(KEY_NAME, kart.getName());
values.put(Constants.KEY_WEIGHT, kart.getWeight());
values.put(Constants.KEY_WHEELS, kart.getWheels());
values.put(Constants.KEY_ACCESSORY, kart.getAccessory());
values.put(Constants.KEY_DEDICATED_DRIVER, kart.getDedicatedDriver());
values.put(Constants.KEY_FREE_FOR_ALL, kart.getFreeForAll());
if (isAvailable) {
values.put(KEY_AVAILABLE, Constants.TRUE);
} else {
values.put(KEY_AVAILABLE, Constants.FALSE);
}
return db.update(Constants.TABLE_KART, values, KEY_ID + " = ?",
new String[] {String.valueOf(kart.getId()) });
}
/**
* Helper method to update the availability status of a single accessory.
*
* @param accessory The accessory which should be marked as available/unavailable.
* @param isAvailable The status of availability to be set.
*
* @return The result code of the update function.
*/
public int changeAccessoryAvailability(final Accessory accessory, final boolean isAvailable) {
final SQLiteDatabase db = this.getWritableDatabase();
final ContentValues values = new ContentValues();
values.put(Constants.KEY_GAME, accessory.getGame());
values.put(KEY_NAME, accessory.getName());
if (isAvailable) {
values.put(KEY_AVAILABLE, Constants.TRUE);
} else {
values.put(KEY_AVAILABLE, Constants.FALSE);
}
return db.update(Constants.TABLE_ACCESSORY, values, KEY_ID + " = ?",
new String[] {String.valueOf(accessory.getId()) });
}
/**
* Helper method to update the availability status of a single wheels.
*
* @param wheels The wheels which should be marked as available/unavailable.
* @param isAvailable The status of availability to be set.
*
* @return The result code of the update function.
*/
public int changeWheelsAvailability(final Wheels wheels, final boolean isAvailable) {
final SQLiteDatabase db = this.getWritableDatabase();
final ContentValues values = new ContentValues();
values.put(Constants.KEY_GAME, wheels.getGame());
values.put(KEY_NAME, wheels.getGame());
if (isAvailable) {
values.put(KEY_AVAILABLE, Constants.TRUE);
} else {
values.put(KEY_AVAILABLE, Constants.FALSE);
}
return db.update(TABLE_WHEELS, values, KEY_ID + " = ?",
new String[] {String.valueOf(wheels.getId()) });
}
public Track testDBConnection(final int id) {
Log.d(TAG, "testDBConnection: Opening Readable Database.");
final SQLiteDatabase dbToUse;
if (mDatabase != null && mDatabase.isOpen()) {
dbToUse = mDatabase;
} else {
dbToUse = this.getReadableDatabase();
}
Log.d(TAG, "testDBConnection: Query a single track for id = [" + id + "]");
Cursor cursor = dbToUse.query(TABLE_TRACK, new String[] { KEY_ID,
KEY_NAME, KEY_AVAILABLE }, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null) {
Log.d(TAG, "testDBConnection: Moving cursor to first.");
cursor.moveToFirst();
} else {
Log.d(TAG, "testDBConnection: cursor is null");
return null;
}
Track track = new Track();
track.setName(cursor.getString(cursor.getColumnIndex(KEY_NAME)));
track.setGame(cursor.getString(cursor.getColumnIndex(KEY_GAME)));
track.setId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_ID))));
track.setAvailable(Integer.parseInt(cursor.getString(cursor.getColumnIndex(KEY_AVAILABLE))));
dbToUse.close();
// return contact
return track;
}
}

View File

@@ -2,6 +2,12 @@ package com.de.aldo_apps.aldo.mariokartcircuitselector;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.de.aldo_apps.aldo.mariokartcircuitselector.database_models.Track;
public class GameSelection extends AppCompatActivity { public class GameSelection extends AppCompatActivity {
@@ -9,5 +15,24 @@ public class GameSelection extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game_selection); setContentView(R.layout.activity_game_selection);
final DatabaseHandler handler = new DatabaseHandler(this);
final EditText editText = (EditText) findViewById(R.id.id_input);
final Button button = (Button) findViewById(R.id.ok_button);
final TextView result = (TextView) findViewById(R.id.result_field);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final int id = Integer.parseInt(editText.getText().toString());
final Track track = handler.testDBConnection(id);
final String resultStr = track.getGame() + " - " + track.getName() + " - " + track.getAvailable() + " - ";
result.setText(resultStr);
}
});
} }
} }

View File

@@ -1,18 +1,30 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.de.aldo_apps.aldo.mariokartcircuitselector.GameSelection"> tools:context="com.de.aldo_apps.aldo.mariokartcircuitselector.GameSelection">
<EditText
android:id="@+id/id_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number" />
<Button
android:id="@+id/ok_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Get Track"
/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Hello World!" android:id="@+id/result_field"
app:layout_constraintBottom_toBottomOf="parent" android:text="TestContent Goes here" />
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout> </LinearLayout>