Export feature
You can now export (it's an early stage) your manual entries to a file to restore it later - Choose where to put your backup - Code for encrypting data (will be enabled soon) - Update version number to 0.0.6
This commit is contained in:
parent
de6fc36e6c
commit
e173e48612
BIN
.idea/caches/build_file_checksums.ser
generated
BIN
.idea/caches/build_file_checksums.ser
generated
Binary file not shown.
@ -6,10 +6,15 @@ android {
|
||||
applicationId "com.herbron.moodl"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 27
|
||||
versionCode 5
|
||||
versionName "0.0.5"
|
||||
versionCode 6
|
||||
versionName "0.0.6"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
dataBinding {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
@ -32,7 +37,7 @@ dependencies {
|
||||
implementation 'com.android.support:cardview-v7:27.1.1'
|
||||
implementation 'com.mcxiaoke.volley:library:1.0.19'
|
||||
implementation 'com.diogobernardino:williamchart:2.5.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
||||
implementation 'com.android.support:support-v4:27.1.1'
|
||||
implementation 'com.android.support:palette-v7:27.1.1'
|
||||
implementation 'com.daimajia.swipelayout:library:1.2.0@aar'
|
||||
@ -47,9 +52,11 @@ dependencies {
|
||||
implementation 'com.mattprecious.swirl:swirl:1.1.0'
|
||||
implementation 'com.wdullaer:materialdatetimepicker:3.5.2'
|
||||
implementation 'com.jmedeisis:draglinearlayout:1.1.0'
|
||||
implementation 'com.applandeo:material-file-picker:1.0.0'
|
||||
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'
|
||||
|
||||
implementation files('../libs/binance-api.jar')
|
||||
implementation files('../libs/commons-codec-1.11.jar');
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import android.app.Dialog;
|
||||
import android.app.KeyguardManager;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
@ -42,7 +43,12 @@ import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.applandeo.FilePicker;
|
||||
import com.applandeo.constants.FileType;
|
||||
import com.applandeo.listeners.OnSelectFileListener;
|
||||
import com.herbron.moodl.BuildConfig;
|
||||
import com.herbron.moodl.DataManagers.DataCrypter;
|
||||
import com.herbron.moodl.DataManagers.DatabaseManager;
|
||||
import com.herbron.moodl.FingerprintToolkit.FingerprintDialogFragment;
|
||||
import com.herbron.moodl.FingerprintToolkit.FingerprintHandler;
|
||||
import com.herbron.moodl.MoodlBox;
|
||||
@ -64,10 +70,10 @@ import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
@ -169,7 +175,7 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
bindPreferenceSummaryToValue(findPreference("default_currency"));
|
||||
bindPreferenceSummaryToValue(findPreference("minimum_value_displayed"));
|
||||
|
||||
findPreference("import").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
findPreference("export").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
|
||||
@ -178,7 +184,33 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
View dialogView = LayoutInflater.from(context).inflate(R.layout.dialog_import_data, null, true);
|
||||
dialogBuilder.setView(dialogView);
|
||||
|
||||
CheckBox enterPasswordCheckbox = dialogView.findViewById(R.id.checkboxEnterPassword);
|
||||
File backupDirectory = new File(Environment.getExternalStorageDirectory(), getString(R.string.app_name));
|
||||
|
||||
if (!backupDirectory.exists()) {
|
||||
if (!backupDirectory.mkdirs()) {
|
||||
Log.d("moodl", "Error while creating directory");
|
||||
}
|
||||
}
|
||||
|
||||
final TextView textViewFilePath = dialogView.findViewById(R.id.textViewFilePath);
|
||||
textViewFilePath.setText(backupDirectory.getAbsolutePath());
|
||||
textViewFilePath.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
new FilePicker.Builder(SettingsActivity.this, new OnSelectFileListener() {
|
||||
@Override
|
||||
public void onSelect(File file) {
|
||||
textViewFilePath.setText(file.getAbsolutePath());
|
||||
}
|
||||
}).fileType("moodl")
|
||||
.hideFiles(true)
|
||||
.directory(backupDirectory.getAbsolutePath())
|
||||
.mainDirectory(Environment.getExternalStorageDirectory().getAbsolutePath())
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
final CheckBox enterPasswordCheckbox = dialogView.findViewById(R.id.checkboxEnterPassword);
|
||||
final TextInputLayout textInputLayoutPassword = dialogView.findViewById(R.id.textInputLayoutPassword);
|
||||
|
||||
enterPasswordCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@ -196,54 +228,34 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
|
||||
}
|
||||
});
|
||||
|
||||
dialogBuilder.setTitle("Restore backup");
|
||||
dialogBuilder.setTitle("Create backup");
|
||||
dialogBuilder.setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
|
||||
checkPermissions();
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.getDefault());
|
||||
Date currentDate = new Date();
|
||||
//String fileName = getString(R.string.app_name) + "_" + formatter.format(currentDate) + ".backup";
|
||||
String fileName = "backup.moodl";
|
||||
String fileName = getString(R.string.app_name) + "_" + formatter.format(currentDate) + ".backup";
|
||||
DatabaseManager databaseManager = new DatabaseManager(SettingsActivity.this);
|
||||
|
||||
File dir = new File(Environment.getExternalStorageDirectory(), getString(R.string.app_name));
|
||||
|
||||
if (!dir.exists()) {
|
||||
if (!dir.mkdirs()) {
|
||||
Log.d("moodl", "Error while creating directory");
|
||||
}
|
||||
}
|
||||
|
||||
File backupFile = new File(dir + "/" + fileName);
|
||||
|
||||
if(backupFile.exists())
|
||||
{
|
||||
try (FileReader fileReader = new FileReader(backupFile)) {
|
||||
BufferedReader bufferedReader = new BufferedReader(fileReader);
|
||||
|
||||
String line;
|
||||
|
||||
while((line = bufferedReader.readLine()) != null)
|
||||
{
|
||||
Log.d("moodl", line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.d("moodl", "Error > " + e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.d("moodl", "Not backup file found");
|
||||
File backupFile = new File(textViewFilePath.getText() + "/" + fileName);
|
||||
|
||||
try (PrintWriter printWriter = new PrintWriter(new FileWriter(backupFile, true))) {
|
||||
|
||||
printWriter.write("Some data");
|
||||
if(enterPasswordCheckbox.isChecked())
|
||||
{
|
||||
DataCrypter.updateKey(textInputLayoutPassword.getEditText().getText().toString());
|
||||
printWriter.write(DataCrypter.encrypt(SettingsActivity.this, databaseManager.getBackupData()));
|
||||
}
|
||||
else
|
||||
{
|
||||
printWriter.write(databaseManager.getBackupData());
|
||||
}
|
||||
|
||||
printWriter.close();
|
||||
} catch (IOException e) {
|
||||
Log.d("moodl", "Error > " + e);
|
||||
}
|
||||
}
|
||||
|
||||
dialog.dismiss();
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
package com.herbron.moodl.DataManagers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.herbron.moodl.R;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class DataCrypter {
|
||||
|
||||
private static Key aesKey;
|
||||
|
||||
public static void updateKey(String key)
|
||||
{
|
||||
for(int i = 0; key.getBytes().length < 32; i++)
|
||||
{
|
||||
key += "0";
|
||||
}
|
||||
|
||||
try {
|
||||
aesKey = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
Log.d("moodl", "Error while creating encryption key " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static String encrypt(Context context, String data)
|
||||
{
|
||||
String encryptedData = null;
|
||||
|
||||
try {
|
||||
|
||||
IvParameterSpec ivParameterSpec = new IvParameterSpec(context.getString(R.string.ivKey).getBytes("UTF-8"));
|
||||
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivParameterSpec);
|
||||
|
||||
byte[] encryptedBytes = cipher.doFinal(data.getBytes());
|
||||
|
||||
encryptedData = Base64.encodeBase64String(encryptedBytes);
|
||||
} catch (NoSuchPaddingException | NoSuchAlgorithmException
|
||||
| InvalidKeyException | BadPaddingException
|
||||
| IllegalBlockSizeException | UnsupportedEncodingException
|
||||
| InvalidAlgorithmParameterException e) {
|
||||
|
||||
Log.d("moodl", "Error while encrypting data " + e.getMessage());
|
||||
|
||||
}
|
||||
|
||||
return encryptedData;
|
||||
}
|
||||
}
|
@ -144,11 +144,33 @@ public class DatabaseManager extends SQLiteOpenHelper{
|
||||
return result.getInt(0);
|
||||
}
|
||||
|
||||
public int deleteCurrencyFromWatchlist(String symbol)
|
||||
public void deleteCurrencyFromWatchlist(String symbol)
|
||||
{
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
|
||||
return db.delete(TABLE_WATCHLIST, KEY_WATCHLIST_SYMBOL + " = '" + symbol + "'", null);
|
||||
db.delete(TABLE_WATCHLIST, KEY_WATCHLIST_SYMBOL + " = '" + symbol + "'", null);
|
||||
db.close();
|
||||
}
|
||||
|
||||
public String getBackupData()
|
||||
{
|
||||
String selectQuerry = "SELECT * FROM " + TABLE_MANUAL_CURRENCIES;
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
Cursor result = db.rawQuery(selectQuerry, null);
|
||||
|
||||
String backupData = "";
|
||||
|
||||
while(result.moveToNext())
|
||||
{
|
||||
for(int i = 0; i < result.getColumnCount(); i++)
|
||||
{
|
||||
backupData += result.getString(i) + ";@";
|
||||
}
|
||||
|
||||
backupData += "\n";
|
||||
}
|
||||
|
||||
return backupData;
|
||||
}
|
||||
|
||||
public List<Currency> getAllCurrenciesFromWatchlist()
|
||||
|
15
app/src/main/res/drawable/background_filepath.xml
Normal file
15
app/src/main/res/drawable/background_filepath.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<shape android:shape="rectangle">
|
||||
<solid android:color="@color/separationColor"/>
|
||||
|
||||
<corners android:radius="5dp"/>
|
||||
<padding
|
||||
android:left="3dp"
|
||||
android:right="3dp"
|
||||
android:top="3dp"
|
||||
android:bottom="3dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
@ -9,6 +9,13 @@
|
||||
android:padding="5dp"
|
||||
android:focusableInTouchMode="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textViewFilePath"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Click to select"
|
||||
android:background="@drawable/background_filepath"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkboxConserveData"
|
||||
android:layout_width="match_parent"
|
||||
@ -31,7 +38,8 @@
|
||||
android:id="@+id/checkboxEnterPassword"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enter_password"/>
|
||||
android:text="@string/enter_password"
|
||||
android:enabled="false"/>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/textInputLayoutPassword"
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
<string name="pref_title_version">Version</string>
|
||||
|
||||
<string name="ivKey">0123456789MoodlH</string> <!--Must be 16 characters-->
|
||||
|
||||
<string name="pref_title_export">Export manual entries</string>
|
||||
<string name="pref_title_import">Import manual entries</string>
|
||||
|
||||
|
@ -28,11 +28,11 @@
|
||||
android:title="@string/pref_title_category_data_backup">
|
||||
|
||||
<PreferenceScreen android:title="@string/pref_title_export"
|
||||
android:key="export"
|
||||
android:enabled="false"/>
|
||||
android:key="export"/>
|
||||
|
||||
<Preference android:title="@string/pref_title_import"
|
||||
android:key="import"/>
|
||||
android:key="import"
|
||||
android:enabled="false"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
|
@ -19,9 +19,8 @@ allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
maven {
|
||||
url "https://jitpack.io"
|
||||
}
|
||||
maven { url "https://jitpack.io" }
|
||||
maven { url "http://dl.bintray.com/lukaville/maven" }
|
||||
}
|
||||
}
|
||||
|
||||
|
BIN
libs/commons-codec-1.11.jar
Normal file
BIN
libs/commons-codec-1.11.jar
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user