diff --git a/ProviGenLib/src/com/tjeannin/provigen/OpenHelper.java b/ProviGenLib/src/com/tjeannin/provigen/OpenHelper.java new file mode 100644 index 0000000..fa08ea1 --- /dev/null +++ b/ProviGenLib/src/com/tjeannin/provigen/OpenHelper.java @@ -0,0 +1,12 @@ +package com.tjeannin.provigen; + +import com.tjeannin.provigen.database.Database; + +/** + * this interface defines the methods used from the SQLite and SqlCipher implementations of SQLiteOpenHelper, + * {@link net.sqlcipher.database.SQLiteOpenHelper} and {@link android.database.sqlite.SQLiteOpenHelper}. + */ +public interface OpenHelper { + Database getWritableDb(); + Database getReadableDb(); +} diff --git a/ProviGenLib/src/com/tjeannin/provigen/ProviGenOpenHelper.java b/ProviGenLib/src/com/tjeannin/provigen/ProviGenOpenHelper.java deleted file mode 100644 index 5214b6f..0000000 --- a/ProviGenLib/src/com/tjeannin/provigen/ProviGenOpenHelper.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.tjeannin.provigen; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteDatabase.CursorFactory; -import android.database.sqlite.SQLiteOpenHelper; -import com.tjeannin.provigen.helper.TableBuilder; -import com.tjeannin.provigen.helper.TableUpdater; - -/** - * A simple implementation of a {@link SQLiteOpenHelper} that: - * - */ -public class ProviGenOpenHelper extends SQLiteOpenHelper { - - private final Class[] contracts; - - /** - * Create a helper object to create, open, and/or manage a database. - * This method always returns very quickly. The database is not actually - * created or opened until one of {@link #getWritableDatabase} or - * {@link #getReadableDatabase} is called. - * - * @param context the context to use to open or create the database. - * @param databaseName the name of the database file, or null for an in-memory database. - * @param factory the factory to use for creating cursor objects, or null for the default. - * @param version the version of the database. Each time the version is increased, missing columns will be added. - */ - public ProviGenOpenHelper(Context context, String databaseName, CursorFactory factory, int version, Class[] contractClasses) { - super(context, databaseName, factory, version); - this.contracts = contractClasses; - } - - @Override - public void onCreate(SQLiteDatabase database) { - for (Class contract : contracts) - new TableBuilder(contract).createTable(database); - } - - @Override - public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { - if (newVersion > oldVersion) { - for (Class contract : contracts) - TableUpdater.addMissingColumns(database, contract); - } - } -} diff --git a/ProviGenLib/src/com/tjeannin/provigen/ProviGenProvider.java b/ProviGenLib/src/com/tjeannin/provigen/ProviGenProvider.java index 975019c..ec9b4ae 100644 --- a/ProviGenLib/src/com/tjeannin/provigen/ProviGenProvider.java +++ b/ProviGenLib/src/com/tjeannin/provigen/ProviGenProvider.java @@ -1,11 +1,14 @@ package com.tjeannin.provigen; -import android.content.*; +import android.content.ContentProvider; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.UriMatcher; import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.text.TextUtils; +import com.tjeannin.provigen.database.Database; import com.tjeannin.provigen.model.Contract; import java.util.ArrayList; @@ -21,7 +24,7 @@ public abstract class ProviGenProvider extends ContentProvider { private UriMatcher uriMatcher; private static final int ITEM = 1; private static final int ITEM_ID = 2; - private SQLiteOpenHelper openHelper; + private OpenHelper openHelper; /** * This method should return an instance of a {@link android.database.sqlite.SQLiteOpenHelper}. @@ -30,7 +33,7 @@ public abstract class ProviGenProvider extends ContentProvider { * @param context A context to pass to the SQLiteOpenHelper instance while creating it. * @return the SQLiteOpenHelper that the ProviGenProvider will use. */ - public abstract SQLiteOpenHelper openHelper(Context context); + public abstract OpenHelper openHelper(Context context); /** * This method should return the list of contract classes that the ProviGenProvider will use. @@ -59,7 +62,7 @@ public boolean onCreate() { @Override public int delete(Uri uri, String selection, String[] selectionArgs) { - SQLiteDatabase database = openHelper.getWritableDatabase(); + Database database = openHelper.getWritableDb(); int numberOfRowsAffected = 0; Contract contract = findMatchingContract(uri); @@ -105,7 +108,7 @@ public String getType(Uri uri) { @Override public Uri insert(Uri uri, ContentValues values) { - SQLiteDatabase database = openHelper.getWritableDatabase(); + Database database = openHelper.getWritableDb(); Contract contract = findMatchingContract(uri); switch (uriMatcher.match(uri)) { @@ -120,7 +123,7 @@ public Uri insert(Uri uri, ContentValues values) { @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - SQLiteDatabase database = openHelper.getReadableDatabase(); + Database database = openHelper.getReadableDb(); Contract contract = findMatchingContract(uri); Cursor cursor = null; @@ -151,7 +154,7 @@ public Cursor query(Uri uri, String[] projection, String selection, String[] sel @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - SQLiteDatabase database = openHelper.getWritableDatabase(); + Database database = openHelper.getWritableDb(); Contract contract = findMatchingContract(uri); int numberOfRowsAffected = 0; diff --git a/ProviGenLib/src/com/tjeannin/provigen/ProviGenSQLCipherOpenHelper.java b/ProviGenLib/src/com/tjeannin/provigen/ProviGenSQLCipherOpenHelper.java new file mode 100644 index 0000000..a64eb45 --- /dev/null +++ b/ProviGenLib/src/com/tjeannin/provigen/ProviGenSQLCipherOpenHelper.java @@ -0,0 +1,83 @@ +package com.tjeannin.provigen; + +import android.content.Context; +import com.tjeannin.provigen.database.Database; +import com.tjeannin.provigen.database.SQLCipherDatabase; +import com.tjeannin.provigen.helper.TableBuilder; +import com.tjeannin.provigen.helper.TableUpdater; + +import net.sqlcipher.database.SQLiteDatabase; +import net.sqlcipher.database.SQLiteDatabase.CursorFactory; +import net.sqlcipher.database.SQLiteOpenHelper; + +/** + * A simple implementation of a {@link SQLiteOpenHelper} that: + * + */ +public class ProviGenSQLCipherOpenHelper extends SQLiteOpenHelper implements OpenHelper { + + private static String sPassword; + private static boolean sIsPasswordInitialized; + + private final Class[] contracts; + + public static void setPassword(String value) { + sPassword = value; + sIsPasswordInitialized = true; + } + + private static String getPassword() { + if ( ! sIsPasswordInitialized) { + throw new IllegalStateException("ProviGenSQLCipherOpenHelper.setPassword must be called before we get here. Consider calling it early in your Application.onCreate method."); + } + + return sPassword; + } + + /** + * Create a helper object to create, open, and/or manage a database. + * This method always returns very quickly. The database is not actually + * created or opened until one of {@link #getWritableDatabase} or + * {@link #getReadableDatabase} is called. + * + * @param context the context to use to open or create the database. + * @param databaseName the name of the database file, or null for an in-memory database. + * @param factory the factory to use for creating cursor objects, or null for the default. + * @param version the version of the database. Each time the version is increased, missing columns will be added. + * @param contractClasses the list of contract classes + */ + public ProviGenSQLCipherOpenHelper(Context context, String databaseName, CursorFactory factory, int version, Class[] contractClasses) { + super(context, databaseName, factory, version); + this.contracts = contractClasses; + } + + @Override + public void onCreate(SQLiteDatabase database) { + Database db = new SQLCipherDatabase(database); + for (Class contract : contracts) + new TableBuilder(contract).createTable(db); + } + + @Override + public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { + if (newVersion > oldVersion) { + Database db = new SQLCipherDatabase(database); + for (Class contract : contracts) + TableUpdater.addMissingColumns(db, contract); + } + } + + @Override + public Database getWritableDb() { + return new SQLCipherDatabase(getWritableDatabase(getPassword())); + } + + @Override + public Database getReadableDb() { + return new SQLCipherDatabase(getReadableDatabase(getPassword())); + } +} diff --git a/ProviGenLib/src/com/tjeannin/provigen/ProviGenSQLiteOpenHelper.java b/ProviGenLib/src/com/tjeannin/provigen/ProviGenSQLiteOpenHelper.java new file mode 100644 index 0000000..c468da0 --- /dev/null +++ b/ProviGenLib/src/com/tjeannin/provigen/ProviGenSQLiteOpenHelper.java @@ -0,0 +1,62 @@ +package com.tjeannin.provigen; + +import android.content.Context; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import com.tjeannin.provigen.database.AndroidSQLiteDatabase; +import com.tjeannin.provigen.database.Database; +import com.tjeannin.provigen.helper.TableBuilder; +import com.tjeannin.provigen.helper.TableUpdater; + +/** + * A simple implementation of a {@link SQLiteOpenHelper} that: + * + */ +public class ProviGenSQLiteOpenHelper extends SQLiteOpenHelper implements OpenHelper { + + private final Class[] contracts; + + /** + * Create a helper object to create, open, and/or manage a database. + * This method always returns very quickly. The database is not actually + * created or opened until one of {@link #getWritableDatabase} or + * {@link #getReadableDatabase} is called. + * + * @param context the context to use to open or create the database. + * @param databaseName the name of the database file, or null for an in-memory database. + * @param factory the factory to use for creating cursor objects, or null for the default. + * @param version the version of the database. Each time the version is increased, missing columns will be added. + * @param contractClasses the list of contract classes + */ + public ProviGenSQLiteOpenHelper(Context context, String databaseName, SQLiteDatabase.CursorFactory factory, int version, Class[] contractClasses) { + super(context, databaseName, factory, version); + this.contracts = contractClasses; + } + + @Override + public void onCreate(SQLiteDatabase database) { + for (Class contract : contracts) + new TableBuilder(contract).createTable(new AndroidSQLiteDatabase(database)); + } + + @Override + public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { + if (newVersion > oldVersion) { + for (Class contract : contracts) + TableUpdater.addMissingColumns(new AndroidSQLiteDatabase(database), contract); + } + } + + @Override + public Database getWritableDb() { + return new AndroidSQLiteDatabase(getWritableDatabase()); + } + + @Override + public Database getReadableDb() { + return new AndroidSQLiteDatabase(getReadableDatabase()); + } +} diff --git a/ProviGenLib/src/com/tjeannin/provigen/database/AndroidSQLiteDatabase.java b/ProviGenLib/src/com/tjeannin/provigen/database/AndroidSQLiteDatabase.java new file mode 100644 index 0000000..8f03840 --- /dev/null +++ b/ProviGenLib/src/com/tjeannin/provigen/database/AndroidSQLiteDatabase.java @@ -0,0 +1,48 @@ +package com.tjeannin.provigen.database; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.SQLException; +import android.database.sqlite.SQLiteDatabase; + +/** + * the {@link SQLiteDatabase} implementation of the {@link Database} interface. it delegates + * to a concrete {@link SQLiteDatabase}. + */ +public class AndroidSQLiteDatabase implements Database { + private final SQLiteDatabase delegate; + + public AndroidSQLiteDatabase(SQLiteDatabase delegate) { + this.delegate = delegate; + } + + @Override + public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) { + return delegate.query(table, columns, selection, selectionArgs, groupBy, having, orderBy); + } + + @Override + public Cursor rawQuery(String sql, String[] selectionArgs) { + return delegate.rawQuery(sql, selectionArgs); + } + + @Override + public long insert(String table, String nullColumnHack, ContentValues values) { + return delegate.insert(table, nullColumnHack, values); + } + + @Override + public int delete(String table, String whereClause, String[] whereArgs) { + return delegate.delete(table, whereClause, whereArgs); + } + + @Override + public int update(String table, ContentValues values, String whereClause, String[] whereArgs) { + return delegate.update(table, values, whereClause, whereArgs); + } + + @Override + public void execSQL(String sql) throws SQLException { + delegate.execSQL(sql); + } +} diff --git a/ProviGenLib/src/com/tjeannin/provigen/database/Database.java b/ProviGenLib/src/com/tjeannin/provigen/database/Database.java new file mode 100644 index 0000000..298d31e --- /dev/null +++ b/ProviGenLib/src/com/tjeannin/provigen/database/Database.java @@ -0,0 +1,23 @@ +package com.tjeannin.provigen.database; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.SQLException; + +/** + * this interface defines the methods used from {@link net.sqlcipher.database.SQLiteDatabase} and + * {@link android.database.sqlite.SQLiteDatabase} + */ +public interface Database { + Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy); + + Cursor rawQuery(String sql, String[] selectionArgs); + + long insert(String table, String nullColumnHack, ContentValues values); + + int delete(String table, String whereClause, String[] whereArgs); + + int update(String table, ContentValues values, String whereClause, String[] whereArgs); + + void execSQL(String sql) throws SQLException; +} diff --git a/ProviGenLib/src/com/tjeannin/provigen/database/SQLCipherDatabase.java b/ProviGenLib/src/com/tjeannin/provigen/database/SQLCipherDatabase.java new file mode 100644 index 0000000..0c1432f --- /dev/null +++ b/ProviGenLib/src/com/tjeannin/provigen/database/SQLCipherDatabase.java @@ -0,0 +1,49 @@ +package com.tjeannin.provigen.database; + +import android.content.ContentValues; +import android.database.Cursor; +import android.database.SQLException; +import net.sqlcipher.database.SQLiteDatabase; + +/** + * the {@link SQLiteDatabase} implementation of the {@link Database} interface. it delegates + * to a concrete {@link SQLiteDatabase}. + */ +public class SQLCipherDatabase implements Database { + private final SQLiteDatabase delegate; + + public SQLCipherDatabase(SQLiteDatabase delegate) { + this.delegate = delegate; + } + + @Override + public Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy) { + return delegate.query(table, columns, selection, selectionArgs, groupBy, having, orderBy); + } + + @Override + public Cursor rawQuery(String sql, String[] selectionArgs) { + return delegate.rawQuery(sql, selectionArgs); + } + + @Override + public long insert(String table, String nullColumnHack, ContentValues values) { + return delegate.insert(table, nullColumnHack, values); + } + + @Override + public int delete(String table, String whereClause, String[] whereArgs) { + return delegate.delete(table, whereClause, whereArgs); + } + + @Override + public int update(String table, ContentValues values, String whereClause, String[] whereArgs) { + return delegate.update(table, values, whereClause, whereArgs); + } + + @Override + public void execSQL(String sql) throws SQLException { + delegate.execSQL(sql); + } +} + diff --git a/ProviGenLib/src/com/tjeannin/provigen/helper/TableBuilder.java b/ProviGenLib/src/com/tjeannin/provigen/helper/TableBuilder.java index 7677c30..5227d42 100644 --- a/ProviGenLib/src/com/tjeannin/provigen/helper/TableBuilder.java +++ b/ProviGenLib/src/com/tjeannin/provigen/helper/TableBuilder.java @@ -1,6 +1,6 @@ package com.tjeannin.provigen.helper; -import android.database.sqlite.SQLiteDatabase; +import com.tjeannin.provigen.database.Database; import com.tjeannin.provigen.model.Constraint; import com.tjeannin.provigen.model.Contract; import com.tjeannin.provigen.model.ContractField; @@ -80,7 +80,7 @@ public String getSQL() { * * @param database The database in which the table need to be created. */ - public void createTable(SQLiteDatabase database) { + public void createTable(Database database) { database.execSQL(getSQL()); } } diff --git a/ProviGenLib/src/com/tjeannin/provigen/helper/TableUpdater.java b/ProviGenLib/src/com/tjeannin/provigen/helper/TableUpdater.java index d4b95ea..5d70fb6 100644 --- a/ProviGenLib/src/com/tjeannin/provigen/helper/TableUpdater.java +++ b/ProviGenLib/src/com/tjeannin/provigen/helper/TableUpdater.java @@ -1,7 +1,7 @@ package com.tjeannin.provigen.helper; import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; +import com.tjeannin.provigen.database.Database; import com.tjeannin.provigen.model.Contract; import com.tjeannin.provigen.model.ContractField; @@ -16,7 +16,7 @@ public class TableUpdater { * @param database The database in which the updated table is. * @param contractClass The contract class to work with. */ - public static void addMissingColumns(SQLiteDatabase database, Class contractClass) { + public static void addMissingColumns(Database database, Class contractClass) { Contract contract = new Contract(contractClass); diff --git a/ProviGenSample/res/values/strings.xml b/ProviGenSample/res/values/strings.xml index 6f3223f..12bef73 100644 --- a/ProviGenSample/res/values/strings.xml +++ b/ProviGenSample/res/values/strings.xml @@ -2,7 +2,7 @@ ProviGenSample Settings - MainActivity + ProviGenSample Add Clear Person Name diff --git a/ProviGenSample/src/com/tjeannin/provigen/sample/MainActivity.java b/ProviGenSample/src/com/tjeannin/provigen/sample/MainActivity.java index b882fef..705cc62 100644 --- a/ProviGenSample/src/com/tjeannin/provigen/sample/MainActivity.java +++ b/ProviGenSample/src/com/tjeannin/provigen/sample/MainActivity.java @@ -13,7 +13,11 @@ import android.view.View.OnClickListener; import android.widget.ListView; +import java.util.Random; + public class MainActivity extends FragmentActivity implements LoaderCallbacks, OnClickListener { + private static Random sRandom = new Random(); + private static int sPersonNumber = 0; private SimpleCursorAdapter adapter; @@ -67,8 +71,8 @@ public void onClick(View view) { switch (view.getId()) { case R.id.add: ContentValues values = new ContentValues(); - values.put(SampleContentProvider.Person.AGE, 20); - values.put(SampleContentProvider.Person.NAME, "Some Name"); + values.put(SampleContentProvider.Person.AGE, sRandom.nextInt(120)); + values.put(SampleContentProvider.Person.NAME, "Some Name " + sPersonNumber++); getContentResolver().insert(SampleContentProvider.Person.CONTENT_URI, values); break; diff --git a/ProviGenSample/src/com/tjeannin/provigen/sample/SampleContentProvider.java b/ProviGenSample/src/com/tjeannin/provigen/sample/SampleContentProvider.java index f141dd6..88487cc 100644 --- a/ProviGenSample/src/com/tjeannin/provigen/sample/SampleContentProvider.java +++ b/ProviGenSample/src/com/tjeannin/provigen/sample/SampleContentProvider.java @@ -1,21 +1,21 @@ package com.tjeannin.provigen.sample; import android.content.Context; -import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import com.tjeannin.provigen.ProviGenBaseContract; -import com.tjeannin.provigen.ProviGenOpenHelper; import com.tjeannin.provigen.ProviGenProvider; +import com.tjeannin.provigen.ProviGenSQLiteOpenHelper; import com.tjeannin.provigen.annotation.Column; import com.tjeannin.provigen.annotation.Column.Type; import com.tjeannin.provigen.annotation.ContentUri; +import com.tjeannin.provigen.OpenHelper; public class SampleContentProvider extends ProviGenProvider { @Override - public SQLiteOpenHelper openHelper(Context context) { - return new ProviGenOpenHelper(getContext(), "ProviGenDatabase", null, 1, new Class[]{Person.class}); + public OpenHelper openHelper(Context context) { + return new ProviGenSQLiteOpenHelper(getContext(), "ProviGenDatabase", null, 1, new Class[]{Person.class}); } @Override diff --git a/ProviGenSqlcipherSample/AndroidManifest.xml b/ProviGenSqlcipherSample/AndroidManifest.xml new file mode 100644 index 0000000..ae24846 --- /dev/null +++ b/ProviGenSqlcipherSample/AndroidManifest.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ProviGenSqlcipherSample/assets/icudt46l.zip b/ProviGenSqlcipherSample/assets/icudt46l.zip new file mode 100644 index 0000000..91dc7f7 Binary files /dev/null and b/ProviGenSqlcipherSample/assets/icudt46l.zip differ diff --git a/ProviGenSqlcipherSample/build.gradle b/ProviGenSqlcipherSample/build.gradle new file mode 100644 index 0000000..904b6b6 --- /dev/null +++ b/ProviGenSqlcipherSample/build.gradle @@ -0,0 +1,18 @@ +android { + buildToolsVersion "19.1.0" + compileSdkVersion 19 + sourceSets { + main { + manifest.srcFile 'AndroidManifest.xml' + java.srcDirs = ['src'] + aidl.srcDirs = ['src'] + renderscript.srcDirs = ['src'] + res.srcDirs = ['res'] + assets.srcDirs = ['assets'] + } + } +} + + + + diff --git a/ProviGenSqlcipherSample/proguard-project.txt b/ProviGenSqlcipherSample/proguard-project.txt new file mode 100644 index 0000000..f2fe155 --- /dev/null +++ b/ProviGenSqlcipherSample/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/ProviGenSqlcipherSample/project.properties b/ProviGenSqlcipherSample/project.properties new file mode 100644 index 0000000..ed6ad53 --- /dev/null +++ b/ProviGenSqlcipherSample/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-19 + diff --git a/ProviGenSqlcipherSample/res/drawable-hdpi/ic_launcher.png b/ProviGenSqlcipherSample/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..96a442e Binary files /dev/null and b/ProviGenSqlcipherSample/res/drawable-hdpi/ic_launcher.png differ diff --git a/ProviGenSqlcipherSample/res/drawable-mdpi/ic_launcher.png b/ProviGenSqlcipherSample/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..359047d Binary files /dev/null and b/ProviGenSqlcipherSample/res/drawable-mdpi/ic_launcher.png differ diff --git a/ProviGenSqlcipherSample/res/drawable-xhdpi/ic_launcher.png b/ProviGenSqlcipherSample/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..71c6d76 Binary files /dev/null and b/ProviGenSqlcipherSample/res/drawable-xhdpi/ic_launcher.png differ diff --git a/ProviGenSqlcipherSample/res/layout/activity_main.xml b/ProviGenSqlcipherSample/res/layout/activity_main.xml new file mode 100644 index 0000000..b75763b --- /dev/null +++ b/ProviGenSqlcipherSample/res/layout/activity_main.xml @@ -0,0 +1,31 @@ + + + + +