diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..25c1f0e --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,13 @@ +# These are supported funding model platforms + +github: [amitshekhariitbhu] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/CHANGELOG.md b/CHANGELOG.md index dcdfbf1..27b7bb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,22 @@ Change Log ========== +Version 1.0.6 *(2019-03-07)* +---------------------------- + +* Fix: Fix query error +* Fix: Fix DebugDb class not found error + + +Version 1.0.5 *(2019-02-18)* +---------------------------- + +* Reduce size by taking out encrypted database library as a separate module +* New: Add support for database delete +* Changed compile to implementation +* Fix: Minor bug fixes + + Version 1.0.4 *(2018-06-23)* ---------------------------- @@ -48,7 +64,7 @@ Version 0.5.0 *(2017-01-21)* * New: Export DB * New: Method to get DB version -* Fix: Fix prouard issue and other minor issues +* Fix: Fix proguard issue and other minor issues Version 0.4.0 *(2016-11-29)* diff --git a/README.md b/README.md index 82c307d..5df3361 100644 --- a/README.md +++ b/README.md @@ -31,16 +31,31 @@ ### All these features work without rooting your device -> No need of rooted device -### Check out another awesome library for fast and simple networking in Android +### Check out our other Open Source Projects * [Fast Android Networking Library](https://github.com/amitshekhariitbhu/Fast-Android-Networking) +* [Learn to build a ride-sharing Android app like Uber, Lyft](https://github.com/MindorksOpenSource/ridesharing-uber-lyft-app) +* [Kotlin-Coroutines-Android-Examples](https://github.com/MindorksOpenSource/Kotlin-Coroutines-Android-Examples) ### Using Android Debug Database Library in your application Add this to your app's build.gradle ```groovy -debugImplementation 'com.amitshekhar.android:debug-db:1.0.5' +debugImplementation 'com.amitshekhar.android:debug-db:1.0.6' +``` + +Using the Android Debug Database with encrypted database + +```groovy +debugImplementation 'com.amitshekhar.android:debug-db-encrypt:1.0.6' +``` +And to provide the password for the DB, you should add this in the Gradle: +DB_PASSWORD_{VARIABLE}, if for example, PERSON is the database name: DB_PASSWORD_PERSON +```groovy +debug { + resValue("string", "DB_PASSWORD_PERSON", "password") +} ``` Use `debugImplementation` so that it will only compile in your debug build and not in your release build. diff --git a/build.gradle b/build.gradle index 7153aea..d2353ea 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.0' + classpath 'com.android.tools.build:gradle:3.3.1' classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4' classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' } diff --git a/debug-db-base/debug-db-base-upload.gradle b/debug-db-base/debug-db-base-upload.gradle index 797abd0..62d53ba 100755 --- a/debug-db-base/debug-db-base-upload.gradle +++ b/debug-db-base/debug-db-base-upload.gradle @@ -24,7 +24,7 @@ def siteUrl = 'https://github.com/amitshekhariitbhu/Android-Debug-Database' def gitUrl = 'https://github.com/amitshekhariitbhu/Android-Debug-Database.git' group = "com.amitshekhar.android" -version = '1.0.5' +version = '1.0.6' install { repositories.mavenInstaller { @@ -67,6 +67,7 @@ task sourcesJar(type: Jar) { task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs + failOnError false classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) classpath += configurations.compile } diff --git a/debug-db-base/src/main/java/com/amitshekhar/utils/DatabaseHelper.java b/debug-db-base/src/main/java/com/amitshekhar/utils/DatabaseHelper.java index 4acaf9a..adf36e6 100644 --- a/debug-db-base/src/main/java/com/amitshekhar/utils/DatabaseHelper.java +++ b/debug-db-base/src/main/java/com/amitshekhar/utils/DatabaseHelper.java @@ -124,6 +124,25 @@ public static TableDataResponse getTableData(SQLiteDB db, String selectQuery, St tableData.isSuccessful = true; tableData.rows = new ArrayList<>(); + + String[] columnNames = cursor.getColumnNames(); + + List tableInfoListModified = new ArrayList<>(); + + for (String columnName : columnNames) { + for (TableDataResponse.TableInfo tableInfo : tableData.tableInfos) { + if (columnName.equals(tableInfo.title)) { + tableInfoListModified.add(tableInfo); + break; + } + } + } + + if (tableData.tableInfos.size() != tableInfoListModified.size()) { + tableData.tableInfos = tableInfoListModified; + tableData.isEditable = false; + } + if (cursor.getCount() > 0) { do { diff --git a/debug-db-encrypt/build.gradle b/debug-db-encrypt/build.gradle index e883bc9..ab7d87a 100644 --- a/debug-db-encrypt/build.gradle +++ b/debug-db-encrypt/build.gradle @@ -18,7 +18,7 @@ android { } dependencies { - implementation project(':debug-db-base') + api project(':debug-db-base') implementation 'net.zetetic:android-database-sqlcipher:3.5.9' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' diff --git a/debug-db-encrypt/debug-db-encrypt-upload.gradle b/debug-db-encrypt/debug-db-encrypt-upload.gradle index 2132ec6..6f60e6a 100755 --- a/debug-db-encrypt/debug-db-encrypt-upload.gradle +++ b/debug-db-encrypt/debug-db-encrypt-upload.gradle @@ -24,7 +24,7 @@ def siteUrl = 'https://github.com/amitshekhariitbhu/Android-Debug-Database' def gitUrl = 'https://github.com/amitshekhariitbhu/Android-Debug-Database.git' group = "com.amitshekhar.android" -version = '1.0.5' +version = '1.0.6' install { repositories.mavenInstaller { @@ -67,6 +67,7 @@ task sourcesJar(type: Jar) { task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs + failOnError false classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) classpath += configurations.compile } diff --git a/debug-db/build.gradle b/debug-db/build.gradle index 41f9805..c6f76ed 100644 --- a/debug-db/build.gradle +++ b/debug-db/build.gradle @@ -18,7 +18,7 @@ android { } dependencies { - implementation project(':debug-db-base') + api project(':debug-db-base') testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' diff --git a/debug-db/debug-db-upload.gradle b/debug-db/debug-db-upload.gradle index 744a524..b4dfd79 100755 --- a/debug-db/debug-db-upload.gradle +++ b/debug-db/debug-db-upload.gradle @@ -24,7 +24,7 @@ def siteUrl = 'https://github.com/amitshekhariitbhu/Android-Debug-Database' def gitUrl = 'https://github.com/amitshekhariitbhu/Android-Debug-Database.git' group = "com.amitshekhar.android" -version = '1.0.5' +version = '1.0.6' install { repositories.mavenInstaller { @@ -67,6 +67,7 @@ task sourcesJar(type: Jar) { task javadoc(type: Javadoc) { source = android.sourceSets.main.java.srcDirs + failOnError false classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) classpath += configurations.compile } diff --git a/sample-app-encrypt/build.gradle b/sample-app-encrypt/build.gradle index e7cb4f6..ae27b46 100644 --- a/sample-app-encrypt/build.gradle +++ b/sample-app-encrypt/build.gradle @@ -2,34 +2,33 @@ apply plugin: 'com.android.application' android { compileSdkVersion 28 - - - defaultConfig { applicationId "com.sample.encrypt" minSdkVersion 15 targetSdkVersion 28 versionCode 1 versionName "1.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } - buildTypes { + debug { + resValue("string", "PORT_NUMBER", "8080") + resValue("string", "DB_PASSWORD_PERSON", "a_password") + } release { minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } - } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - + debugImplementation project(':debug-db-encrypt') implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'net.zetetic:android-database-sqlcipher:3.5.9' + implementation 'android.arch.persistence.room:runtime:1.1.1' + annotationProcessor 'android.arch.persistence.room:compiler:1.1.1' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/MainActivity.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/MainActivity.java index 93d016c..e035da3 100644 --- a/sample-app-encrypt/src/main/java/com/sample/encrypt/MainActivity.java +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/MainActivity.java @@ -1,13 +1,147 @@ +/* + * + * * Copyright (C) 2019 Amit Shekhar + * * Copyright (C) 2011 Android Open Source Project + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + package com.sample.encrypt; -import android.support.v7.app.AppCompatActivity; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.SharedPreferences; import android.os.Bundle; +import android.preference.PreferenceManager; +import android.support.v7.app.AppCompatActivity; +import android.view.View; + +import com.sample.encrypt.database.CarDBHelper; +import com.sample.encrypt.database.ContactDBHelper; +import com.sample.encrypt.database.ExtTestDBHelper; +import com.sample.encrypt.database.PersonDBHelper; +import com.sample.encrypt.database.room.User; +import com.sample.encrypt.database.room.UserDBHelper; +import com.sample.encrypt.utils.Utils; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class MainActivity extends AppCompatActivity { + @SuppressLint("CommitPrefEdits") @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Set stringSet = new HashSet<>(); + stringSet.add("SetOne"); + stringSet.add("SetTwo"); + stringSet.add("SetThree"); + + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + + SharedPreferences prefsOne = getSharedPreferences("countPrefOne", Context.MODE_PRIVATE); + SharedPreferences prefsTwo = getSharedPreferences("countPrefTwo", Context.MODE_PRIVATE); + + sharedPreferences.edit().putString("testOne", "one").commit(); + sharedPreferences.edit().putInt("testTwo", 2).commit(); + sharedPreferences.edit().putLong("testThree", 100000L).commit(); + sharedPreferences.edit().putFloat("testFour", 3.01F).commit(); + sharedPreferences.edit().putBoolean("testFive", true).commit(); + sharedPreferences.edit().putStringSet("testSix", stringSet).commit(); + + prefsOne.edit().putString("testOneNew", "one").commit(); + + prefsTwo.edit().putString("testTwoNew", "two").commit(); + + ContactDBHelper contactDBHelper = new ContactDBHelper(getApplicationContext()); + if (contactDBHelper.count() == 0) { + for (int i = 0; i < 100; i++) { + String name = "name_" + i; + String phone = "phone_" + i; + String email = "email_" + i; + String street = "street_" + i; + String place = "place_" + i; + contactDBHelper.insertContact(name, phone, email, street, place); + } + } + + CarDBHelper carDBHelper = new CarDBHelper(getApplicationContext()); + if (carDBHelper.count() == 0) { + for (int i = 0; i < 50; i++) { + String name = "name_" + i; + String color = "RED"; + float mileage = i + 10.45f; + carDBHelper.insertCar(name, color, mileage); + } + } + + ExtTestDBHelper extTestDBHelper = new ExtTestDBHelper(getApplicationContext()); + if (extTestDBHelper.count() == 0) { + for (int i = 0; i < 20; i++) { + String value = "value_" + i; + extTestDBHelper.insertTest(value); + } + } + + // Create Person encrypted database + PersonDBHelper personDBHelper = new PersonDBHelper(getApplicationContext()); + if (personDBHelper.count() == 0) { + for (int i = 0; i < 100; i++) { + String firstName = PersonDBHelper.PERSON_COLUMN_FIRST_NAME + "_" + i; + String lastName = PersonDBHelper.PERSON_COLUMN_LAST_NAME + "_" + i; + String address = PersonDBHelper.PERSON_COLUMN_ADDRESS + "_" + i; + personDBHelper.insertPerson(firstName, lastName, address); + } + } + + // Room database + UserDBHelper userDBHelper = new UserDBHelper(getApplicationContext()); + if (userDBHelper.count() == 0) { + List userList = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + User user = new User(); + user.id = (long) (i + 1); + user.name = "user_" + i; + userList.add(user); + } + userDBHelper.insertUser(userList); + } + + // Room inMemory database + if (userDBHelper.countInMemory() == 0) { + List userList = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + User user = new User(); + user.id = (long) (i + 1); + user.name = "in_memory_user_" + i; + userList.add(user); + } + userDBHelper.insertUserInMemory(userList); + } + + Utils.setCustomDatabaseFiles(getApplicationContext()); + Utils.setInMemoryRoomDatabases(userDBHelper.getInMemoryDatabase()); + } + + public void showDebugDbAddress(View view) { + Utils.showDebugDBAddressLogToast(getApplicationContext()); } } diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/CarDBHelper.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/CarDBHelper.java new file mode 100644 index 0000000..c620a4d --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/CarDBHelper.java @@ -0,0 +1,134 @@ +/* + * + * * Copyright (C) 2019 Amit Shekhar + * * Copyright (C) 2011 Android Open Source Project + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package com.sample.encrypt.database; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import java.util.ArrayList; + +/** + * Created by amitshekhar on 06/02/17. + */ + +public class CarDBHelper extends SQLiteOpenHelper { + + public static final String DATABASE_NAME = "Car.db"; + public static final String CARS_TABLE_NAME = "cars"; + public static final String CARS_COLUMN_ID = "id"; + public static final String CARS_COLUMN_NAME = "name"; + public static final String CARS_COLUMN_COLOR = "color"; + public static final String CCARS_COLUMN_MILEAGE = "mileage"; + + public CarDBHelper(Context context) { + super(context, DATABASE_NAME, null, 1); + } + + @Override + public void onCreate(SQLiteDatabase db) { + // TODO Auto-generated method stub + db.execSQL( + "create table cars " + + "(id integer primary key, name text, color text, mileage real)" + ); + + db.execSQL("create table [transaction] (id integer primary key, name text)"); + + for (int i = 0; i < 10; i++) { + db.execSQL("insert into [transaction] (name) values ('hello');"); + } + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + // TODO Auto-generated method stub + db.execSQL("DROP TABLE IF EXISTS cars"); + onCreate(db); + } + + public boolean insertCar(String name, String color, float mileage) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues contentValues = new ContentValues(); + contentValues.put("name", name); + contentValues.put("color", color); + contentValues.put("mileage", mileage); + db.insert("cars", null, contentValues); + return true; + } + + public Cursor getData(int id) { + SQLiteDatabase db = this.getReadableDatabase(); + Cursor res = db.rawQuery("select * from cars where id=" + id + "", null); + return res; + } + + public int numberOfRows() { + SQLiteDatabase db = this.getReadableDatabase(); + int numRows = (int) DatabaseUtils.queryNumEntries(db, CARS_TABLE_NAME); + return numRows; + } + + public boolean updateCar(Integer id, String name, String color, float mileage) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues contentValues = new ContentValues(); + contentValues.put("name", name); + contentValues.put("color", color); + contentValues.put("mileage", mileage); + db.update("cars", contentValues, "id = ? ", new String[]{Integer.toString(id)}); + return true; + } + + public Integer deleteCar(Integer id) { + SQLiteDatabase db = this.getWritableDatabase(); + return db.delete("cars", + "id = ? ", + new String[]{Integer.toString(id)}); + } + + public ArrayList getAllCars() { + ArrayList arrayList = new ArrayList<>(); + + //hp = new HashMap(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor res = db.rawQuery("select * from cars", null); + res.moveToFirst(); + + while (!res.isAfterLast()) { + arrayList.add(res.getString(res.getColumnIndex(CARS_COLUMN_NAME))); + res.moveToNext(); + } + return arrayList; + } + + public int count() { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.rawQuery("select * from cars", null); + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + return cursor.getInt(0); + } else { + return 0; + } + } +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/ContactDBHelper.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/ContactDBHelper.java new file mode 100644 index 0000000..b0f4ef3 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/ContactDBHelper.java @@ -0,0 +1,136 @@ +/* + * + * * Copyright (C) 2019 Amit Shekhar + * * Copyright (C) 2011 Android Open Source Project + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package com.sample.encrypt.database; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import java.util.ArrayList; +import java.util.Calendar; + +/** + * Created by amitshekhar on 16/11/16. + */ +public class ContactDBHelper extends SQLiteOpenHelper { + + public static final String DATABASE_NAME = "Contact.db"; + public static final String CONTACTS_TABLE_NAME = "contacts"; + public static final String CONTACTS_COLUMN_ID = "id"; + public static final String CONTACTS_COLUMN_NAME = "name"; + public static final String CONTACTS_COLUMN_EMAIL = "email"; + public static final String CONTACTS_COLUMN_STREET = "street"; + public static final String CONTACTS_COLUMN_CITY = "place"; + public static final String CONTACTS_COLUMN_PHONE = "phone"; + public static final String CONTACTS_CREATED_AT = "createdAt"; + + public ContactDBHelper(Context context) { + super(context, DATABASE_NAME, null, 1); + } + + @Override + public void onCreate(SQLiteDatabase db) { + // TODO Auto-generated method stub + db.execSQL( + "create table contacts " + + "(id integer primary key, name text, phone text, email text, street text, place text, createdAt integer)" + ); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + // TODO Auto-generated method stub + db.execSQL("DROP TABLE IF EXISTS contacts"); + onCreate(db); + } + + public boolean insertContact(String name, String phone, String email, String street, String place) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues contentValues = new ContentValues(); + contentValues.put("name", name); + contentValues.put("phone", phone); + contentValues.put("email", email); + contentValues.put("street", street); + contentValues.put("place", place); + contentValues.put(CONTACTS_CREATED_AT, Calendar.getInstance().getTimeInMillis()); + db.insert("contacts", null, contentValues); + return true; + } + + public Cursor getData(int id) { + SQLiteDatabase db = this.getReadableDatabase(); + Cursor res = db.rawQuery("select * from contacts where id=" + id + "", null); + return res; + } + + public int numberOfRows() { + SQLiteDatabase db = this.getReadableDatabase(); + int numRows = (int) DatabaseUtils.queryNumEntries(db, CONTACTS_TABLE_NAME); + return numRows; + } + + public boolean updateContact(Integer id, String name, String phone, String email, String street, String place) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues contentValues = new ContentValues(); + contentValues.put("name", name); + contentValues.put("phone", phone); + contentValues.put("email", email); + contentValues.put("street", street); + contentValues.put("place", place); + db.update("contacts", contentValues, "id = ? ", new String[]{Integer.toString(id)}); + return true; + } + + public Integer deleteContact(Integer id) { + SQLiteDatabase db = this.getWritableDatabase(); + return db.delete("contacts", + "id = ? ", + new String[]{Integer.toString(id)}); + } + + public ArrayList getAllCotacts() { + ArrayList arrayList = new ArrayList<>(); + + //hp = new HashMap(); + SQLiteDatabase db = this.getReadableDatabase(); + Cursor res = db.rawQuery("select * from contacts", null); + res.moveToFirst(); + + while (!res.isAfterLast()) { + arrayList.add(res.getString(res.getColumnIndex(CONTACTS_COLUMN_NAME))); + res.moveToNext(); + } + return arrayList; + } + + public int count() { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.rawQuery("select * from contacts", null); + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + return cursor.getInt(0); + } else { + return 0; + } + } +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/ExtTestDBHelper.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/ExtTestDBHelper.java new file mode 100644 index 0000000..582a9f3 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/ExtTestDBHelper.java @@ -0,0 +1,92 @@ +package com.sample.encrypt.database; + +import android.content.ContentValues; +import android.content.Context; +import android.content.ContextWrapper; +import android.database.Cursor; +import android.database.DatabaseErrorHandler; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; + +import java.io.File; +import java.util.Calendar; + +public class ExtTestDBHelper extends SQLiteOpenHelper { + + public static final String DIR_NAME = "custom_dir"; + public static final String DATABASE_NAME = "ExtTest.db"; + public static final String TEST_TABLE_NAME = "test"; + public static final String TEST_ID = "id"; + public static final String TEST_COLUMN_VALUE = "value"; + public static final String TEST_CREATED_AT = "createdAt"; + + public ExtTestDBHelper(Context context) { + super(new CustomDatabasePathContext(context), DATABASE_NAME, null, 1); + } + + @Override + public void onCreate(SQLiteDatabase db) { + // TODO Auto-generated method stub + db.execSQL( + String.format( + "create table %s (%s integer primary key, %s text, %s integer)", + TEST_TABLE_NAME, + TEST_ID, + TEST_COLUMN_VALUE, + TEST_CREATED_AT + ) + ); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + // TODO Auto-generated method stub + db.execSQL("DROP TABLE IF EXISTS " + TEST_TABLE_NAME); + onCreate(db); + } + + public boolean insertTest(String value) { + SQLiteDatabase db = this.getWritableDatabase(); + ContentValues contentValues = new ContentValues(); + contentValues.put("value", value); + contentValues.put(TEST_CREATED_AT, Calendar.getInstance().getTimeInMillis()); + db.insert(TEST_TABLE_NAME, null, contentValues); + return true; + } + + public int count() { + SQLiteDatabase db = getReadableDatabase(); + Cursor cursor = db.rawQuery("select COUNT(*) from " + TEST_TABLE_NAME, null); + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + return cursor.getInt(0); + } else { + return 0; + } + } + + private static class CustomDatabasePathContext extends ContextWrapper { + + public CustomDatabasePathContext(Context base) { + super(base); + } + + @Override + public File getDatabasePath(String name) { + File databaseDir = new File(String.format("%s/%s", getFilesDir(), ExtTestDBHelper.DIR_NAME)); + databaseDir.mkdirs(); + File databaseFile = new File(String.format("%s/%s/%s", getFilesDir(), ExtTestDBHelper.DIR_NAME, name)); + return databaseFile; + } + + @Override + public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) { + return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null); + } + + @Override + public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) { + return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null); + } + } +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/PersonDBHelper.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/PersonDBHelper.java new file mode 100644 index 0000000..bb95c46 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/PersonDBHelper.java @@ -0,0 +1,136 @@ +/* + * + * * Copyright (C) 2019 Amit Shekhar + * * Copyright (C) 2011 Android Open Source Project + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package com.sample.encrypt.database; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; + +import net.sqlcipher.DatabaseUtils; +import net.sqlcipher.database.SQLiteDatabase; +import net.sqlcipher.database.SQLiteOpenHelper; + +import java.util.ArrayList; + +public class PersonDBHelper extends SQLiteOpenHelper { + + public static final String DATABASE_NAME = "Person.db"; + public static final String PERSON_TABLE_NAME = "person"; + public static final String PERSON_COLUMN_ID = "id"; + public static final String PERSON_COLUMN_FIRST_NAME = "first_name"; + public static final String PERSON_COLUMN_LAST_NAME = "last_name"; + public static final String PERSON_COLUMN_ADDRESS = "address"; + private static final String DB_PASSWORD = "a_password"; + + public PersonDBHelper(Context context) { + + super(context, DATABASE_NAME, null, 1); + SQLiteDatabase.loadLibs(context); + } + + @Override + public void onCreate(SQLiteDatabase db) { + db.execSQL( + "create table person " + + "(id integer primary key, first_name text, last_name text, address text)" + ); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS person"); + onCreate(db); + } + + public boolean insertPerson(String firstName, String lastName, String address) { + SQLiteDatabase db = this.getWritableDatabase(DB_PASSWORD); + ContentValues contentValues = new ContentValues(); + contentValues.put("first_name", firstName); + contentValues.put("last_name", lastName); + contentValues.put("address", address); + db.insert("person", null, contentValues); + db.close(); + return true; + } + + public Cursor getData(int id) { + SQLiteDatabase db = this.getReadableDatabase(DB_PASSWORD); + Cursor res = db.rawQuery("select * from person where id=" + id + "", null); + return res; + } + + public int numberOfRows() { + SQLiteDatabase db = this.getReadableDatabase(DB_PASSWORD); + int numRows = (int) DatabaseUtils.queryNumEntries(db, PERSON_TABLE_NAME); + return numRows; + } + + public boolean updatePerson(Integer id, String firstName, String lastName, String address, float mileage) { + SQLiteDatabase db = this.getWritableDatabase(DB_PASSWORD); + ContentValues contentValues = new ContentValues(); + contentValues.put("first_name", firstName); + contentValues.put("last_name", lastName); + contentValues.put("address", address); + db.update("person", contentValues, "id = ? ", new String[]{Integer.toString(id)}); + db.close(); + return true; + } + + public Integer deletePerson(Integer id) { + SQLiteDatabase db = this.getWritableDatabase(DB_PASSWORD); + return db.delete("person", + "id = ? ", + new String[]{Integer.toString(id)}); + } + + public ArrayList getAllPerson() { + ArrayList arrayList = new ArrayList<>(); + + SQLiteDatabase db = this.getReadableDatabase(DB_PASSWORD); + Cursor res = db.rawQuery("select * from person", null); + res.moveToFirst(); + + while (!res.isAfterLast()) { + arrayList.add( + res.getString(res.getColumnIndex(PERSON_COLUMN_FIRST_NAME)) + " " + + res.getString(res.getColumnIndex(PERSON_COLUMN_LAST_NAME))); + res.moveToNext(); + } + res.close(); + db.close(); + return arrayList; + } + + public int count() { + SQLiteDatabase db = getReadableDatabase(DB_PASSWORD); + Cursor cursor = db.rawQuery("select * from person", null); + try { + if (cursor != null && cursor.getCount() > 0) { + cursor.moveToFirst(); + return cursor.getInt(0); + } else { + return 0; + } + } finally { + cursor.close(); + db.close(); + } + } +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/AppDatabase.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/AppDatabase.java new file mode 100644 index 0000000..63aa947 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/AppDatabase.java @@ -0,0 +1,14 @@ +package com.sample.encrypt.database.room; + +import android.arch.persistence.room.Database; +import android.arch.persistence.room.RoomDatabase; + +/** + * Created by anandgaurav on 12/02/18. + */ +@Database(entities = {User.class}, version = 1, exportSchema = false) +public abstract class AppDatabase extends RoomDatabase { + + public abstract UserDao userDao(); + +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/User.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/User.java new file mode 100644 index 0000000..f5fdf32 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/User.java @@ -0,0 +1,17 @@ +package com.sample.encrypt.database.room; + +import android.arch.persistence.room.Entity; +import android.arch.persistence.room.PrimaryKey; + +/** + * Created by anandgaurav on 12/02/18. + */ +@Entity(tableName = "users") +public class User { + + @PrimaryKey + public Long id; + + public String name; + +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/UserDBHelper.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/UserDBHelper.java new file mode 100644 index 0000000..7304480 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/UserDBHelper.java @@ -0,0 +1,46 @@ +package com.sample.encrypt.database.room; + +import android.arch.persistence.db.SupportSQLiteDatabase; +import android.arch.persistence.room.Room; +import android.content.Context; + +import java.util.List; + +/** + * Created by anandgaurav on 12/02/18. + */ + +public class UserDBHelper { + + private final AppDatabase appDatabase; + private final AppDatabase inMemoryAppDatabase; + + public UserDBHelper(Context context) { + appDatabase = Room.databaseBuilder(context, AppDatabase.class, "User.db") + .allowMainThreadQueries() + .build(); + inMemoryAppDatabase = Room.inMemoryDatabaseBuilder(context, AppDatabase.class) + .allowMainThreadQueries() + .build(); + } + + public void insertUser(List userList) { + appDatabase.userDao().insertAll(userList); + } + + public void insertUserInMemory(List userList) { + inMemoryAppDatabase.userDao().insertAll(userList); + } + + public int count() { + return appDatabase.userDao().loadAll().size(); + } + + public int countInMemory() { + return inMemoryAppDatabase.userDao().loadAll().size(); + } + + public SupportSQLiteDatabase getInMemoryDatabase() { + return inMemoryAppDatabase.getOpenHelper().getWritableDatabase(); + } +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/UserDao.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/UserDao.java new file mode 100644 index 0000000..e93f507 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/database/room/UserDao.java @@ -0,0 +1,33 @@ +package com.sample.encrypt.database.room; + +import android.arch.persistence.room.Dao; +import android.arch.persistence.room.Delete; +import android.arch.persistence.room.Insert; +import android.arch.persistence.room.OnConflictStrategy; +import android.arch.persistence.room.Query; + +import java.util.List; + +/** + * Created by anandgaurav on 12/02/18. + */ + +@Dao +public interface UserDao { + + @Query("SELECT * FROM users") + List loadAll(); + + @Query("SELECT * FROM users WHERE id IN (:userIds)") + List loadAllByIds(List userIds); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insert(User user); + + @Insert(onConflict = OnConflictStrategy.REPLACE) + void insertAll(List users); + + @Delete + void delete(User user); + +} diff --git a/sample-app-encrypt/src/main/java/com/sample/encrypt/utils/Utils.java b/sample-app-encrypt/src/main/java/com/sample/encrypt/utils/Utils.java new file mode 100644 index 0000000..f6aa926 --- /dev/null +++ b/sample-app-encrypt/src/main/java/com/sample/encrypt/utils/Utils.java @@ -0,0 +1,91 @@ +/* + * + * * Copyright (C) 2019 Amit Shekhar + * * Copyright (C) 2011 Android Open Source Project + * * + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * + */ + +package com.sample.encrypt.utils; + +import android.arch.persistence.db.SupportSQLiteDatabase; +import android.content.Context; +import android.util.Pair; +import android.widget.Toast; + +import com.sample.encrypt.BuildConfig; +import com.sample.encrypt.database.ExtTestDBHelper; + +import java.io.File; +import java.lang.reflect.Method; +import java.util.HashMap; + +/** + * Created by amitshekhar on 07/02/17. + */ + +public class Utils { + + private Utils() { + // This class is not publicly instantiable + } + + public static void showDebugDBAddressLogToast(Context context) { + if (BuildConfig.DEBUG) { + try { + Class debugDB = Class.forName("com.amitshekhar.DebugDB"); + Method getAddressLog = debugDB.getMethod("getAddressLog"); + Object value = getAddressLog.invoke(null); + Toast.makeText(context, (String) value, Toast.LENGTH_LONG).show(); + } catch (Exception ignore) { + + } + } + } + + public static void setCustomDatabaseFiles(Context context) { + if (BuildConfig.DEBUG) { + try { + Class debugDB = Class.forName("com.amitshekhar.DebugDB"); + Class[] argTypes = new Class[]{HashMap.class}; + Method setCustomDatabaseFiles = debugDB.getMethod("setCustomDatabaseFiles", argTypes); + HashMap> customDatabaseFiles = new HashMap<>(); + // set your custom database files + customDatabaseFiles.put(ExtTestDBHelper.DATABASE_NAME, + new Pair<>(new File(context.getFilesDir() + "/" + ExtTestDBHelper.DIR_NAME + + "/" + ExtTestDBHelper.DATABASE_NAME), "")); + setCustomDatabaseFiles.invoke(null, customDatabaseFiles); + } catch (Exception ignore) { + + } + } + } + + public static void setInMemoryRoomDatabases(SupportSQLiteDatabase... database) { + if (BuildConfig.DEBUG) { + try { + Class debugDB = Class.forName("com.amitshekhar.DebugDB"); + Class[] argTypes = new Class[]{HashMap.class}; + HashMap inMemoryDatabases = new HashMap<>(); + // set your inMemory databases + inMemoryDatabases.put("InMemoryOne.db", database[0]); + Method setRoomInMemoryDatabase = debugDB.getMethod("setInMemoryRoomDatabases", argTypes); + setRoomInMemoryDatabase.invoke(null, inMemoryDatabases); + } catch (Exception ignore) { + + } + } + } + +} diff --git a/sample-app-encrypt/src/main/res/layout/activity_main.xml b/sample-app-encrypt/src/main/res/layout/activity_main.xml index 84f1951..b5d361c 100644 --- a/sample-app-encrypt/src/main/res/layout/activity_main.xml +++ b/sample-app-encrypt/src/main/res/layout/activity_main.xml @@ -1,18 +1,39 @@ - - + + + android:paddingBottom="@dimen/activity_vertical_margin" + android:paddingLeft="@dimen/activity_horizontal_margin" + android:paddingRight="@dimen/activity_horizontal_margin" + android:paddingTop="@dimen/activity_vertical_margin" + tools:context="com.sample.encrypt.MainActivity"> - + android:textColor="@android:color/black" + android:onClick="showDebugDbAddress" + android:layout_gravity="center" + android:text="@string/show_debug_db_address" /> - \ No newline at end of file + diff --git a/sample-app-encrypt/src/main/res/values/strings.xml b/sample-app-encrypt/src/main/res/values/strings.xml index 4e9db46..5de66ea 100644 --- a/sample-app-encrypt/src/main/res/values/strings.xml +++ b/sample-app-encrypt/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ Sample App Encrypt + Show Debug Db Address diff --git a/sample-app/build.gradle b/sample-app/build.gradle index fbc380c..b81a721 100644 --- a/sample-app/build.gradle +++ b/sample-app/build.gradle @@ -32,7 +32,6 @@ android { buildTypes { debug { resValue("string", "PORT_NUMBER", "8080") - resValue("string", "DB_PASSWORD_PERSON", "a_password") } release { minifyEnabled false @@ -42,9 +41,8 @@ android { } dependencies { - debugImplementation project(':debug-db-encrypt') + debugImplementation project(':debug-db') implementation 'com.android.support:appcompat-v7:28.0.0' - implementation 'net.zetetic:android-database-sqlcipher:3.5.9' implementation 'android.arch.persistence.room:runtime:1.1.1' annotationProcessor 'android.arch.persistence.room:compiler:1.1.1' testImplementation 'junit:junit:4.12' diff --git a/sample-app/src/main/java/com/sample/MainActivity.java b/sample-app/src/main/java/com/sample/MainActivity.java index 3634b36..79d86ac 100644 --- a/sample-app/src/main/java/com/sample/MainActivity.java +++ b/sample-app/src/main/java/com/sample/MainActivity.java @@ -30,7 +30,6 @@ import com.sample.database.CarDBHelper; import com.sample.database.ContactDBHelper; import com.sample.database.ExtTestDBHelper; -import com.sample.database.PersonDBHelper; import com.sample.database.room.User; import com.sample.database.room.UserDBHelper; import com.sample.utils.Utils; @@ -101,17 +100,6 @@ protected void onCreate(Bundle savedInstanceState) { } } - // Create Person encrypted database - PersonDBHelper personDBHelper = new PersonDBHelper(getApplicationContext()); - if (personDBHelper.count() == 0) { - for (int i = 0; i < 100; i++) { - String firstName = PersonDBHelper.PERSON_COLUMN_FIRST_NAME + "_" + i; - String lastName = PersonDBHelper.PERSON_COLUMN_LAST_NAME + "_" + i; - String address = PersonDBHelper.PERSON_COLUMN_ADDRESS + "_" + i; - personDBHelper.insertPerson(firstName, lastName, address); - } - } - // Room database UserDBHelper userDBHelper = new UserDBHelper(getApplicationContext()); if (userDBHelper.count() == 0) { diff --git a/settings.gradle b/settings.gradle index 1cdd68f..b36a834 100644 --- a/settings.gradle +++ b/settings.gradle @@ -17,4 +17,4 @@ * */ -include ':app', ':debug-db-base', ':debug-db', ':debug-db-encrypt' +include ':sample-app', ':debug-db-base', ':debug-db', ':debug-db-encrypt', ':sample-app-encrypt'