Compare commits
74 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7758c61079 | ||
|
|
47b30ca9fb | ||
|
|
7b4d587b13 | ||
|
|
685ee018c6 | ||
|
|
e0915578ba | ||
|
|
c733a6c3b9 | ||
|
|
ec17255a43 | ||
|
|
1fc7baa5a0 | ||
|
|
0df411ee96 | ||
|
|
23178d9694 | ||
|
|
94accc951d | ||
|
|
0207e12aed | ||
|
|
c760465b3e | ||
|
|
f480bd0c7e | ||
|
|
5599560258 | ||
|
|
7b4c119d7d | ||
|
|
6144353079 | ||
|
|
03a5334961 | ||
|
|
04e0a5716e | ||
|
|
91e3f9f785 | ||
|
|
2ebc862e27 | ||
|
|
5d122affce | ||
|
|
9e09b9052a | ||
|
|
2753b8826f | ||
|
|
4e02252b75 | ||
|
|
647ce00e72 | ||
|
|
86a5f2fb50 | ||
|
|
dca5129031 | ||
|
|
e30eb00bf7 | ||
|
|
11e5cb8ec2 | ||
|
|
bdd5c8fbbb | ||
|
|
cd79839748 | ||
|
|
d6b47914c8 | ||
|
|
ce1acb83f0 | ||
|
|
bc360aa06c | ||
|
|
ebe6139a64 | ||
|
|
d354fd1877 | ||
|
|
00b612d6c7 | ||
|
|
a307511193 | ||
|
|
f7f358c5c3 | ||
|
|
f7b50a72a4 | ||
|
|
68ce1fe9fd | ||
|
|
e822ab0b56 | ||
|
|
e33ab682a6 | ||
|
|
0d50ad6d10 | ||
|
|
4143e5c286 | ||
|
|
15425d51aa | ||
|
|
3abcb32a75 | ||
|
|
93124a88a5 | ||
|
|
29b00e3b59 | ||
|
|
04174154d6 | ||
|
|
bf60976d10 | ||
|
|
fb7e3e12f2 | ||
|
|
641d29a6f8 | ||
|
|
0f2ee296b4 | ||
|
|
ecd2ecd517 | ||
|
|
f3e7d8f5c1 | ||
|
|
f4522fb17d | ||
|
|
824a72b156 | ||
|
|
116a44fd1c | ||
|
|
b6190d3250 | ||
|
|
82c40408f7 | ||
|
|
c6c9fb763a | ||
|
|
dda5dcc652 | ||
|
|
d039ad9fa4 | ||
|
|
5c70c98eb9 | ||
|
|
2face21985 | ||
|
|
b38ec7b753 | ||
|
|
32d5aec76b | ||
|
|
bdbcaf4b1e | ||
|
|
f54905f218 | ||
|
|
2d3bd4a375 | ||
|
|
de4ab95437 | ||
|
|
09fba71710 |
34
CHANGELOG.md
@@ -1,3 +1,37 @@
|
||||
## v0.15 (2017-11-25)
|
||||
|
||||
Changes:
|
||||
- Add support for adding shortcuts to home screen when adding or editing a card. (https://github.com/brarcher/loyalty-card-locker/pull/155)
|
||||
- Remove widget, as it was a poor substitute for shortcuts. (https://github.com/brarcher/loyalty-card-locker/pull/155)
|
||||
- Fix exporting backups on Android 7+. (https://github.com/brarcher/loyalty-card-locker/pull/153)
|
||||
- Report more accurate mime type when exporting backup data. (https://github.com/brarcher/loyalty-card-locker/pull/156)
|
||||
- Fix bug where a card could not be edited. (https://github.com/brarcher/loyalty-card-locker/pull/155)
|
||||
|
||||
## v0.14 (2017-10-26)
|
||||
|
||||
Changes:
|
||||
- Add support for app shortcuts (Android 7.1+), where the most recently used cards will appear as shortcuts. (https://github.com/brarcher/loyalty-card-locker/pull/145)
|
||||
- Add a widget which works like a pinned app shortcut, to support devices which run below Android 7.1. (https://github.com/brarcher/loyalty-card-locker/pull/142)
|
||||
|
||||
## v0.13 (2017-07-25)
|
||||
|
||||
Changes:
|
||||
- Add screen rotation lock menu option when displaying a card. If locked, the screen will transition to its "natural" orientation and further screen rotation will be blocked. (https://github.com/brarcher/loyalty-card-locker/pull/128)
|
||||
- If a card is selected from the main screen but cannot be loaded, the application fails gracefully and posts a message. (https://github.com/brarcher/loyalty-card-locker/pull/132)
|
||||
- Fix case where layout IDs for intro wizard could not be found. (https://github.com/brarcher/loyalty-card-locker/pull/128)
|
||||
|
||||
## v0.12 (2017-07-16)
|
||||
|
||||
Changes:
|
||||
|
||||
- A change in v0.11 reduced the memory usage of barcode drawing, but affected the barcode dimensions. This is now changed to maintain the barcode dimensions while reducing memory usage. (https://github.com/brarcher/loyalty-card-locker/pull/126)
|
||||
- Update German and French translations. (https://github.com/brarcher/loyalty-card-locker/pull/122, https://github.com/brarcher/loyalty-card-locker/pull/124, https://github.com/brarcher/loyalty-card-locker/pull/125)
|
||||
|
||||
## v0.11.1 (2017-06-29)
|
||||
|
||||
Changes:
|
||||
- Prevent a crash when rotation the screen in the first run intro wizard.
|
||||
|
||||
## v0.11 (2017-06-26)
|
||||
|
||||
Improvements:
|
||||
|
||||
@@ -48,6 +48,10 @@ Windows:
|
||||
./gradlew.bat build
|
||||
```
|
||||
|
||||
# Translating
|
||||
|
||||
If you are interested in translating this application to another language, create a pull request with changes or find the project listing on [Transifex](https://www.transifex.com/na-243/loyalty-card-locker).
|
||||
|
||||
# Thanks
|
||||
|
||||
This application uses the following image:
|
||||
|
||||
@@ -13,9 +13,9 @@ android {
|
||||
defaultConfig {
|
||||
applicationId "protect.card_locker"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 23
|
||||
versionCode 11
|
||||
versionName "0.11"
|
||||
targetSdkVersion 25
|
||||
versionCode 16
|
||||
versionName "0.15"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
@@ -27,6 +27,7 @@ android {
|
||||
disable "GoogleAppIndexingWarning"
|
||||
disable "ButtonStyle"
|
||||
disable "AlwaysShowAction"
|
||||
disable "MissingTranslation"
|
||||
}
|
||||
|
||||
// This is for Robolectric support for SDK 23
|
||||
|
||||
7
app/proguard-rules.pro
vendored
@@ -15,3 +15,10 @@
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# This keep the class and method names the same, for debugging stack traces
|
||||
-dontobfuscate
|
||||
@@ -8,6 +8,8 @@
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<uses-permission
|
||||
android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
@@ -36,7 +38,8 @@
|
||||
android:name=".LoyaltyCardViewActivity"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:windowSoftInputMode="stateHidden"/>
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:exported="true"/>
|
||||
<activity
|
||||
android:name=".BarcodeSelectorActivity"
|
||||
android:label="@string/selectBarcodeTitle"
|
||||
@@ -49,9 +52,19 @@
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
<activity
|
||||
android:name=".IntroActivity"
|
||||
android:name=".intro.IntroActivity"
|
||||
android:label=""
|
||||
android:configChanges="orientation|screenSize"
|
||||
android:theme="@style/AppTheme.NoActionBar"/>
|
||||
<provider
|
||||
android:name="android.support.v4.content.FileProvider"
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false"
|
||||
android:authorities="${applicationId}">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_provider_paths"/>
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -21,7 +21,7 @@ import java.lang.ref.WeakReference;
|
||||
class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
|
||||
{
|
||||
private static final String TAG = "LoyaltyCardLocker";
|
||||
private static final int MAX_WIDTH = 600;
|
||||
private static final int MAX_WIDTH = 500;
|
||||
|
||||
private final WeakReference<ImageView> imageViewReference;
|
||||
private final String cardId;
|
||||
@@ -29,7 +29,7 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
|
||||
private final int imageHeight;
|
||||
private final int imageWidth;
|
||||
|
||||
public BarcodeImageWriterTask(ImageView imageView, String cardIdString,
|
||||
BarcodeImageWriterTask(ImageView imageView, String cardIdString,
|
||||
BarcodeFormat barcodeFormat)
|
||||
{
|
||||
// Use a WeakReference to ensure the ImageView can be garbage collected
|
||||
@@ -37,11 +37,19 @@ class BarcodeImageWriterTask extends AsyncTask<Void, Void, Bitmap>
|
||||
|
||||
cardId = cardIdString;
|
||||
format = barcodeFormat;
|
||||
imageHeight = imageView.getHeight();
|
||||
|
||||
// No matter how long the window is, there is only so much space
|
||||
// needed for the barcode. Put a limit on it to reduce memory usage
|
||||
imageWidth = Math.min(imageView.getWidth(), MAX_WIDTH);
|
||||
if(imageView.getWidth() < MAX_WIDTH)
|
||||
{
|
||||
imageHeight = imageView.getHeight();
|
||||
imageWidth = imageView.getWidth();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scale down the image to reduce the memory needed to produce it
|
||||
imageWidth = MAX_WIDTH;
|
||||
double ratio = (double)MAX_WIDTH / (double)imageView.getWidth();
|
||||
imageHeight = (int)(imageView.getHeight() * ratio);
|
||||
}
|
||||
}
|
||||
|
||||
public Bitmap doInBackground(Void... params)
|
||||
|
||||
@@ -51,7 +51,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
}
|
||||
}
|
||||
|
||||
public boolean insertLoyaltyCard(final String store, final String note, final String cardId,
|
||||
public long insertLoyaltyCard(final String store, final String note, final String cardId,
|
||||
final String barcodeType)
|
||||
{
|
||||
SQLiteDatabase db = getWritableDatabase();
|
||||
@@ -61,7 +61,7 @@ public class DBHelper extends SQLiteOpenHelper
|
||||
contentValues.put(LoyaltyCardDbIds.CARD_ID, cardId);
|
||||
contentValues.put(LoyaltyCardDbIds.BARCODE_TYPE, barcodeType);
|
||||
final long newId = db.insert(LoyaltyCardDbIds.TABLE, null, contentValues);
|
||||
return (newId != -1);
|
||||
return newId;
|
||||
}
|
||||
|
||||
public boolean insertLoyaltyCard(final SQLiteDatabase db, final int id,
|
||||
|
||||
@@ -7,12 +7,15 @@ import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.provider.OpenableColumns;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.content.FileProvider;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
@@ -24,6 +27,9 @@ import android.widget.Button;
|
||||
import android.widget.Toast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
public class ImportExportActivity extends AppCompatActivity
|
||||
@@ -132,24 +138,34 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void onClick(View v)
|
||||
{
|
||||
startImport(exportFile);
|
||||
Uri uri = Uri.fromFile(exportFile);
|
||||
try
|
||||
{
|
||||
FileInputStream stream = new FileInputStream(exportFile);
|
||||
startImport(stream, uri);
|
||||
}
|
||||
catch(FileNotFoundException e)
|
||||
{
|
||||
Log.e(TAG, "Could not import file " + exportFile.getAbsolutePath(), e);
|
||||
onImportComplete(false, uri);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void startImport(File target)
|
||||
private void startImport(final InputStream target, final Uri targetUri)
|
||||
{
|
||||
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
|
||||
{
|
||||
@Override
|
||||
public void onTaskComplete(boolean success, File file)
|
||||
public void onTaskComplete(boolean success)
|
||||
{
|
||||
onImportComplete(success, file);
|
||||
onImportComplete(success, targetUri);
|
||||
}
|
||||
};
|
||||
|
||||
importExporter = new ImportExportTask(ImportExportActivity.this,
|
||||
true, DataFormat.CSV, target, listener);
|
||||
DataFormat.CSV, target, listener);
|
||||
importExporter.execute();
|
||||
}
|
||||
|
||||
@@ -158,14 +174,14 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
ImportExportTask.TaskCompleteListener listener = new ImportExportTask.TaskCompleteListener()
|
||||
{
|
||||
@Override
|
||||
public void onTaskComplete(boolean success, File file)
|
||||
public void onTaskComplete(boolean success)
|
||||
{
|
||||
onExportComplete(success, file);
|
||||
onExportComplete(success, exportFile);
|
||||
}
|
||||
};
|
||||
|
||||
importExporter = new ImportExportTask(ImportExportActivity.this,
|
||||
false, DataFormat.CSV, exportFile, listener);
|
||||
DataFormat.CSV, exportFile, listener);
|
||||
importExporter.execute();
|
||||
}
|
||||
|
||||
@@ -220,7 +236,34 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void onImportComplete(boolean success, File path)
|
||||
private String fileNameFromUri(Uri uri)
|
||||
{
|
||||
if("file".equals(uri.getScheme()))
|
||||
{
|
||||
return uri.getPath();
|
||||
}
|
||||
|
||||
Cursor returnCursor =
|
||||
getContentResolver().query(uri, null, null, null, null);
|
||||
if(returnCursor == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
|
||||
if(returnCursor.moveToFirst() == false)
|
||||
{
|
||||
returnCursor.close();
|
||||
return null;
|
||||
}
|
||||
|
||||
String name = returnCursor.getString(nameIndex);
|
||||
returnCursor.close();
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
private void onImportComplete(boolean success, Uri path)
|
||||
{
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
|
||||
@@ -236,7 +279,15 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
int messageId = success ? R.string.importedFrom : R.string.importFailed;
|
||||
|
||||
final String template = getResources().getString(messageId);
|
||||
final String message = String.format(template, path.getAbsolutePath());
|
||||
|
||||
// Get the filename of the file being imported
|
||||
String filename = fileNameFromUri(path);
|
||||
if(filename == null)
|
||||
{
|
||||
filename = "(unknown)";
|
||||
}
|
||||
|
||||
final String message = String.format(template, filename);
|
||||
builder.setMessage(message);
|
||||
builder.setNeutralButton(R.string.ok, new DialogInterface.OnClickListener()
|
||||
{
|
||||
@@ -286,10 +337,13 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which)
|
||||
{
|
||||
Uri outputUri = Uri.fromFile(path);
|
||||
Uri outputUri = FileProvider.getUriForFile(ImportExportActivity.this, BuildConfig.APPLICATION_ID, path);
|
||||
Intent sendIntent = new Intent(Intent.ACTION_SEND);
|
||||
sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri);
|
||||
sendIntent.setType("text/plain");
|
||||
sendIntent.setType("text/csv");
|
||||
|
||||
// set flag to give temporary permission to external app to use the FileProvider
|
||||
sendIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
|
||||
ImportExportActivity.this.startActivity(Intent.createChooser(sendIntent,
|
||||
sendLabel));
|
||||
@@ -344,34 +398,28 @@ public class ImportExportActivity extends AppCompatActivity
|
||||
{
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode == RESULT_OK && requestCode == CHOOSE_EXPORT_FILE)
|
||||
{
|
||||
String path = null;
|
||||
|
||||
Uri uri = data.getData();
|
||||
if(uri != null && uri.toString().startsWith("/"))
|
||||
{
|
||||
uri = Uri.parse("file://" + uri.toString());
|
||||
}
|
||||
|
||||
if(uri != null)
|
||||
{
|
||||
path = uri.getPath();
|
||||
}
|
||||
|
||||
if(path != null)
|
||||
{
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
startImport(new File(path));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.e(TAG, "Fail to make sense of URI returned from activity: " + (uri != null ? uri.toString() : "null"));
|
||||
}
|
||||
}
|
||||
else
|
||||
if (resultCode != RESULT_OK || requestCode != CHOOSE_EXPORT_FILE)
|
||||
{
|
||||
Log.w(TAG, "Failed onActivityResult(), result=" + resultCode);
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri = data.getData();
|
||||
if(uri == null)
|
||||
{
|
||||
Log.e(TAG, "Activity returned a NULL URI");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
InputStream reader = getContentResolver().openInputStream(uri);
|
||||
Log.e(TAG, "Starting file import with: " + uri.toString());
|
||||
startImport(reader, uri);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
Log.e(TAG, "Failed to import file: " + uri.toString(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -24,29 +25,46 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
private boolean doImport;
|
||||
private DataFormat format;
|
||||
private File target;
|
||||
private InputStream inputStream;
|
||||
private TaskCompleteListener listener;
|
||||
|
||||
private ProgressDialog progress;
|
||||
|
||||
public ImportExportTask(Activity activity, boolean doImport, DataFormat format, File target,
|
||||
/**
|
||||
* Constructor which will setup a task for exporting to the given file
|
||||
*/
|
||||
ImportExportTask(Activity activity, DataFormat format, File target,
|
||||
TaskCompleteListener listener)
|
||||
{
|
||||
super();
|
||||
this.activity = activity;
|
||||
this.doImport = doImport;
|
||||
this.doImport = false;
|
||||
this.format = format;
|
||||
this.target = target;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private boolean performImport(File importFile, DBHelper db)
|
||||
/**
|
||||
* Constructor which will setup a task for importing from the given InputStream.
|
||||
*/
|
||||
ImportExportTask(Activity activity, DataFormat format, InputStream input,
|
||||
TaskCompleteListener listener)
|
||||
{
|
||||
super();
|
||||
this.activity = activity;
|
||||
this.doImport = true;
|
||||
this.format = format;
|
||||
this.inputStream = input;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
private boolean performImport(InputStream stream, DBHelper db)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
try
|
||||
{
|
||||
FileInputStream fileReader = new FileInputStream(importFile);
|
||||
InputStreamReader reader = new InputStreamReader(fileReader, Charset.forName("UTF-8"));
|
||||
InputStreamReader reader = new InputStreamReader(stream, Charset.forName("UTF-8"));
|
||||
result = MultiFormatImporter.importData(db, reader, format);
|
||||
reader.close();
|
||||
}
|
||||
@@ -55,7 +73,7 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
Log.e(TAG, "Unable to import file", e);
|
||||
}
|
||||
|
||||
Log.i(TAG, "Import of '" + importFile.getAbsolutePath() + "' result: " + result);
|
||||
Log.i(TAG, "Import result: " + result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -105,7 +123,7 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
|
||||
if(doImport)
|
||||
{
|
||||
result = performImport(target, db);
|
||||
result = performImport(inputStream, db);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -117,7 +135,7 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
|
||||
protected void onPostExecute(Boolean result)
|
||||
{
|
||||
listener.onTaskComplete(result, target);
|
||||
listener.onTaskComplete(result);
|
||||
|
||||
progress.dismiss();
|
||||
Log.i(TAG, (doImport ? "Import" : "Export") + " Complete");
|
||||
@@ -130,7 +148,7 @@ class ImportExportTask extends AsyncTask<Void, Void, Boolean>
|
||||
}
|
||||
interface TaskCompleteListener
|
||||
{
|
||||
void onTaskComplete(boolean success, File file);
|
||||
void onTaskComplete(boolean success);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import com.github.paolorotolo.appintro.AppIntro;
|
||||
|
||||
|
||||
public class IntroActivity extends AppIntro
|
||||
{
|
||||
@Override
|
||||
public void init(Bundle savedInstanceState)
|
||||
{
|
||||
addIntroSlide(R.layout.intro1_layout);
|
||||
addIntroSlide(R.layout.intro2_layout);
|
||||
addIntroSlide(R.layout.intro3_layout);
|
||||
addIntroSlide(R.layout.intro4_layout);
|
||||
addIntroSlide(R.layout.intro5_layout);
|
||||
addIntroSlide(R.layout.intro6_layout);
|
||||
}
|
||||
|
||||
private void addIntroSlide(@LayoutRes int layout)
|
||||
{
|
||||
Fragment slide = new IntroSlide();
|
||||
Bundle args = new Bundle();
|
||||
args.putInt("layout", layout);
|
||||
slide.setArguments(args);
|
||||
addSlide(slide);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipPressed(Fragment fragment) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDonePressed(Fragment fragment) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@ package protect.card_locker;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.design.widget.Snackbar;
|
||||
@@ -19,9 +22,11 @@ import android.view.ViewTreeObserver;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
@@ -38,6 +43,9 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
TextView storeFieldView;
|
||||
EditText noteFieldEdit;
|
||||
TextView noteFieldView;
|
||||
CheckBox shortcutCheckbox;
|
||||
View shortcutBorder;
|
||||
View shortcutTablerow;
|
||||
TextView cardIdFieldView;
|
||||
View cardIdDivider;
|
||||
View cardIdTableRow;
|
||||
@@ -53,8 +61,22 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
boolean updateLoyaltyCard;
|
||||
boolean viewLoyaltyCard;
|
||||
|
||||
boolean rotationEnabled;
|
||||
|
||||
DBHelper db;
|
||||
|
||||
private void extractIntentFields(Intent intent)
|
||||
{
|
||||
final Bundle b = intent.getExtras();
|
||||
loyaltyCardId = b != null ? b.getInt("id") : 0;
|
||||
updateLoyaltyCard = b != null && b.getBoolean("update", false);
|
||||
viewLoyaltyCard = b != null && b.getBoolean("view", false);
|
||||
|
||||
Log.d(TAG, "View activity: id=" + loyaltyCardId
|
||||
+ ", updateLoyaltyCard=" + Boolean.toString(updateLoyaltyCard)
|
||||
+ ", viewLoyaltyCard=" + Boolean.toString(viewLoyaltyCard));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState)
|
||||
{
|
||||
@@ -69,12 +91,40 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
final Bundle b = getIntent().getExtras();
|
||||
loyaltyCardId = b != null ? b.getInt("id") : 0;
|
||||
updateLoyaltyCard = b != null && b.getBoolean("update", false);
|
||||
viewLoyaltyCard = b != null && b.getBoolean("view", false);
|
||||
extractIntentFields(getIntent());
|
||||
|
||||
db = new DBHelper(this);
|
||||
|
||||
storeFieldEdit = (EditText) findViewById(R.id.storeNameEdit);
|
||||
storeFieldView = (TextView) findViewById(R.id.storeNameView);
|
||||
noteFieldEdit = (EditText) findViewById(R.id.noteEdit);
|
||||
noteFieldView = (TextView) findViewById(R.id.noteView);
|
||||
shortcutCheckbox = (CheckBox) findViewById(R.id.shortcutCheckbox);
|
||||
shortcutBorder = findViewById(R.id.shortcutBorder);
|
||||
shortcutTablerow = findViewById(R.id.shortcutTablerow);
|
||||
cardIdFieldView = (TextView) findViewById(R.id.cardIdView);
|
||||
cardIdDivider = findViewById(R.id.cardIdDivider);
|
||||
cardIdTableRow = findViewById(R.id.cardIdTableRow);
|
||||
barcodeTypeField = (TextView) findViewById(R.id.barcodeType);
|
||||
barcodeImage = (ImageView) findViewById(R.id.barcode);
|
||||
barcodeImageLayout = findViewById(R.id.barcodeLayout);
|
||||
barcodeCaptureLayout = findViewById(R.id.barcodeCaptureLayout);
|
||||
|
||||
captureButton = (Button) findViewById(R.id.captureButton);
|
||||
enterButton = (Button) findViewById(R.id.enterButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNewIntent(Intent intent)
|
||||
{
|
||||
Log.i(TAG, "Received new intent");
|
||||
extractIntentFields(intent);
|
||||
|
||||
// Reset these fields, so they are re-populated in onResume().
|
||||
storeFieldEdit.setText("");
|
||||
noteFieldEdit.setText("");
|
||||
cardIdFieldView.setText("");
|
||||
barcodeTypeField.setText("");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,24 +148,16 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
storeFieldEdit = (EditText) findViewById(R.id.storeNameEdit);
|
||||
storeFieldView = (TextView) findViewById(R.id.storeNameView);
|
||||
noteFieldEdit = (EditText) findViewById(R.id.noteEdit);
|
||||
noteFieldView = (TextView) findViewById(R.id.noteView);
|
||||
cardIdFieldView = (TextView) findViewById(R.id.cardIdView);
|
||||
cardIdDivider = findViewById(R.id.cardIdDivider);
|
||||
cardIdTableRow = findViewById(R.id.cardIdTableRow);
|
||||
barcodeTypeField = (TextView) findViewById(R.id.barcodeType);
|
||||
barcodeImage = (ImageView) findViewById(R.id.barcode);
|
||||
barcodeImageLayout = findViewById(R.id.barcodeLayout);
|
||||
barcodeCaptureLayout = findViewById(R.id.barcodeCaptureLayout);
|
||||
|
||||
captureButton = (Button) findViewById(R.id.captureButton);
|
||||
enterButton = (Button) findViewById(R.id.enterButton);
|
||||
|
||||
if(updateLoyaltyCard || viewLoyaltyCard)
|
||||
{
|
||||
final LoyaltyCard loyaltyCard = db.getLoyaltyCard(loyaltyCardId);
|
||||
if(loyaltyCard == null)
|
||||
{
|
||||
Log.w(TAG, "Could not lookup loyalty card " + loyaltyCardId);
|
||||
Toast.makeText(this, R.string.noCardExistsError, Toast.LENGTH_LONG).show();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if(storeFieldEdit.getText().length() == 0)
|
||||
{
|
||||
@@ -164,6 +206,9 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
noteFieldView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
shortcutBorder.setVisibility(viewLoyaltyCard ? View.GONE : View.VISIBLE);
|
||||
shortcutTablerow.setVisibility(viewLoyaltyCard ? View.GONE : View.VISIBLE);
|
||||
|
||||
if(cardIdFieldView.getText().length() > 0 && barcodeTypeField.getText().length() > 0)
|
||||
{
|
||||
String formatString = barcodeTypeField.getText().toString();
|
||||
@@ -257,6 +302,7 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
{
|
||||
String store = storeFieldEdit.getText().toString();
|
||||
String note = noteFieldEdit.getText().toString();
|
||||
boolean shouldAddShortcut = shortcutCheckbox.isChecked();
|
||||
String cardId = cardIdFieldView.getText().toString();
|
||||
String barcodeType = barcodeTypeField.getText().toString();
|
||||
|
||||
@@ -279,19 +325,45 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
}
|
||||
else
|
||||
{
|
||||
db.insertLoyaltyCard(store, note, cardId, barcodeType);
|
||||
loyaltyCardId = (int)db.insertLoyaltyCard(store, note, cardId, barcodeType);
|
||||
}
|
||||
|
||||
if(shouldAddShortcut)
|
||||
{
|
||||
addShortcut(loyaltyCardId, store);
|
||||
}
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
private void addShortcut(int id, String name)
|
||||
{
|
||||
Intent shortcutIntent = new Intent(this, LoyaltyCardViewActivity.class);
|
||||
shortcutIntent.setAction(Intent.ACTION_MAIN);
|
||||
// Prevent instances of the view activity from piling up; if one exists let this
|
||||
// one replace it.
|
||||
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putInt("id", id);
|
||||
bundle.putBoolean("view", true);
|
||||
shortcutIntent.putExtras(bundle);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, Intent.ShortcutIconResource
|
||||
.fromContext(this, R.mipmap.ic_launcher));
|
||||
intent.setAction("com.android.launcher.action.INSTALL_SHORTCUT");
|
||||
// Do not duplicate the shortcut if it is already there
|
||||
intent.putExtra("duplicate", false);
|
||||
getApplicationContext().sendBroadcast(intent);
|
||||
|
||||
Toast.makeText(this, R.string.addedShortcut, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu)
|
||||
{
|
||||
final Bundle b = getIntent().getExtras();
|
||||
final boolean updateLoyaltyCard = b != null && b.getBoolean("update", false);
|
||||
final boolean viewLoyaltyCard = b != null && b.getBoolean("view", false);
|
||||
|
||||
if(viewLoyaltyCard)
|
||||
{
|
||||
getMenuInflater().inflate(R.menu.card_view_menu, menu);
|
||||
@@ -305,6 +377,8 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
getMenuInflater().inflate(R.menu.card_add_menu, menu);
|
||||
}
|
||||
|
||||
rotationEnabled = true;
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@@ -313,9 +387,6 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
{
|
||||
int id = item.getItemId();
|
||||
|
||||
final Bundle b = getIntent().getExtras();
|
||||
final int loyaltyCardId = b != null ? b.getInt("id") : 0;
|
||||
|
||||
switch(id)
|
||||
{
|
||||
case android.R.id.home:
|
||||
@@ -335,6 +406,9 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
|
||||
DBHelper db = new DBHelper(LoyaltyCardViewActivity.this);
|
||||
db.deleteLoyaltyCard(loyaltyCardId);
|
||||
|
||||
ShortcutHelper.removeShortcut(LoyaltyCardViewActivity.this, loyaltyCardId);
|
||||
|
||||
finish();
|
||||
dialog.dismiss();
|
||||
}
|
||||
@@ -361,6 +435,22 @@ public class LoyaltyCardViewActivity extends AppCompatActivity
|
||||
finish();
|
||||
return true;
|
||||
|
||||
case R.id.action_lock_unlock:
|
||||
if(rotationEnabled)
|
||||
{
|
||||
item.setIcon(R.drawable.ic_lock_outline_white_24dp);
|
||||
item.setTitle(R.string.unlockScreen);
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
item.setIcon(R.drawable.ic_lock_open_white_24dp);
|
||||
item.setTitle(R.string.lockScreen);
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
|
||||
}
|
||||
rotationEnabled = !rotationEnabled;
|
||||
return true;
|
||||
|
||||
case R.id.action_save:
|
||||
doSave();
|
||||
return true;
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.google.common.collect.ImmutableMap;
|
||||
import java.util.Calendar;
|
||||
import java.util.Map;
|
||||
|
||||
import protect.card_locker.intro.IntroActivity;
|
||||
|
||||
public class MainActivity extends AppCompatActivity
|
||||
{
|
||||
private static final String TAG = "LoyaltyCardLocker";
|
||||
@@ -91,10 +93,14 @@ public class MainActivity extends AppCompatActivity
|
||||
LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(selected);
|
||||
|
||||
Intent i = new Intent(view.getContext(), LoyaltyCardViewActivity.class);
|
||||
i.setAction("");
|
||||
final Bundle b = new Bundle();
|
||||
b.putInt("id", loyaltyCard.id);
|
||||
b.putBoolean("view", true);
|
||||
i.putExtras(b);
|
||||
|
||||
ShortcutHelper.updateShortcuts(MainActivity.this, loyaltyCard, i);
|
||||
|
||||
startActivity(i);
|
||||
}
|
||||
});
|
||||
@@ -185,6 +191,11 @@ public class MainActivity extends AppCompatActivity
|
||||
"AppIntro", "https://github.com/apl-devs/AppIntro"
|
||||
);
|
||||
|
||||
final Map<String, String> USED_ASSETS = ImmutableMap.of
|
||||
(
|
||||
"Save by Bernar Novalyi", "https://thenounproject.com/term/save/716011"
|
||||
);
|
||||
|
||||
StringBuilder libs = new StringBuilder().append("<ul>");
|
||||
for (Map.Entry<String, String> entry : USED_LIBRARIES.entrySet())
|
||||
{
|
||||
@@ -192,6 +203,13 @@ public class MainActivity extends AppCompatActivity
|
||||
}
|
||||
libs.append("</ul>");
|
||||
|
||||
StringBuilder resources = new StringBuilder().append("<ul>");
|
||||
for (Map.Entry<String, String> entry : USED_ASSETS.entrySet())
|
||||
{
|
||||
resources.append("<li><a href=\"").append(entry.getValue()).append("\">").append(entry.getKey()).append("</a></li>");
|
||||
}
|
||||
resources.append("</ul>");
|
||||
|
||||
String appName = getString(R.string.app_name);
|
||||
int year = Calendar.getInstance().get(Calendar.YEAR);
|
||||
|
||||
@@ -229,7 +247,9 @@ public class MainActivity extends AppCompatActivity
|
||||
"</p><hr/><p>" +
|
||||
getString(R.string.app_license) +
|
||||
"</p><hr/><p>" +
|
||||
String.format(getString(R.string.app_libraries), appName, libs.toString());
|
||||
String.format(getString(R.string.app_libraries), appName, libs.toString()) +
|
||||
"</p><hr/><p>" +
|
||||
String.format(getString(R.string.app_resources), appName, resources.toString());
|
||||
|
||||
wv.loadDataWithBaseURL("file:///android_res/drawable/", html, "text/html", "utf-8", null);
|
||||
new AlertDialog.Builder(this)
|
||||
|
||||
153
app/src/main/java/protect/card_locker/ShortcutHelper.java
Normal file
@@ -0,0 +1,153 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ShortcutInfo;
|
||||
import android.content.pm.ShortcutManager;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
class ShortcutHelper
|
||||
{
|
||||
// Android documentation says that no more than 5 shortcuts
|
||||
// are supported. However, that may be too many, as not all
|
||||
// launcher will show all 5. Instead, the number is limited
|
||||
// to 3 here, so that the most recent shortcut has a good
|
||||
// chance of being shown.
|
||||
private static final int MAX_SHORTCUTS = 3;
|
||||
|
||||
/**
|
||||
* Add a card to the app shortcuts, and maintain a list of the most
|
||||
* recently used cards. If there is already a shortcut for the card,
|
||||
* the card is marked as the most recently used card. If adding this
|
||||
* card exceeds the max number of shortcuts, then the least recently
|
||||
* used card shortcut is discarded.
|
||||
*/
|
||||
@TargetApi(25)
|
||||
static void updateShortcuts(Context context, LoyaltyCard card, Intent intent)
|
||||
{
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1)
|
||||
{
|
||||
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
|
||||
LinkedList<ShortcutInfo> list = new LinkedList<>(shortcutManager.getDynamicShortcuts());
|
||||
|
||||
String shortcutId = Integer.toString(card.id);
|
||||
|
||||
// Sort the shortcuts by rank, so working with the relative order will be easier.
|
||||
// This sorts so that the lowest rank is first.
|
||||
Collections.sort(list, new Comparator<ShortcutInfo>()
|
||||
{
|
||||
@Override
|
||||
public int compare(ShortcutInfo o1, ShortcutInfo o2)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1)
|
||||
{
|
||||
return o1.getRank() - o2.getRank();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Integer foundIndex = null;
|
||||
|
||||
for(int index = 0; index < list.size(); index++)
|
||||
{
|
||||
if(list.get(index).getId().equals(shortcutId))
|
||||
{
|
||||
// Found the item already
|
||||
foundIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(foundIndex != null)
|
||||
{
|
||||
// If the item is already found, then the list needs to be
|
||||
// reordered, so that the selected item now has the lowest
|
||||
// rank, thus letting it survive longer.
|
||||
ShortcutInfo found = list.remove(foundIndex.intValue());
|
||||
list.addFirst(found);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The item is new to the list. First, we need to trim the list
|
||||
// until it is able to accept a new item, then the item is
|
||||
// inserted.
|
||||
while(list.size() >= MAX_SHORTCUTS)
|
||||
{
|
||||
list.pollLast();
|
||||
}
|
||||
|
||||
ShortcutInfo shortcut = new ShortcutInfo.Builder(context, Integer.toString(card.id))
|
||||
.setShortLabel(card.store)
|
||||
.setLongLabel(card.store)
|
||||
.setIntent(intent)
|
||||
.build();
|
||||
|
||||
list.addFirst(shortcut);
|
||||
}
|
||||
|
||||
LinkedList<ShortcutInfo> finalList = new LinkedList<>();
|
||||
|
||||
// The ranks are now updated; the order in the list is the rank.
|
||||
for(int index = 0; index < list.size(); index++)
|
||||
{
|
||||
ShortcutInfo prevShortcut = list.get(index);
|
||||
|
||||
Intent shortcutIntent = prevShortcut.getIntent();
|
||||
|
||||
// Prevent instances of the view activity from piling up; if one exists let this
|
||||
// one replace it.
|
||||
shortcutIntent.setFlags(shortcutIntent.getFlags() | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
|
||||
ShortcutInfo updatedShortcut = new ShortcutInfo.Builder(context, prevShortcut.getId())
|
||||
.setShortLabel(prevShortcut.getShortLabel())
|
||||
.setLongLabel(prevShortcut.getLongLabel())
|
||||
.setIntent(shortcutIntent)
|
||||
.setIcon(Icon.createWithResource(context, R.drawable.circle))
|
||||
.setRank(index)
|
||||
.build();
|
||||
|
||||
finalList.addLast(updatedShortcut);
|
||||
}
|
||||
|
||||
shortcutManager.setDynamicShortcuts(finalList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the given card id from the app shortcuts, if such a
|
||||
* shortcut exists.
|
||||
*/
|
||||
@TargetApi(25)
|
||||
static void removeShortcut(Context context, int cardId)
|
||||
{
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1)
|
||||
{
|
||||
ShortcutManager shortcutManager = context.getSystemService(ShortcutManager.class);
|
||||
List<ShortcutInfo> list = shortcutManager.getDynamicShortcuts();
|
||||
|
||||
String shortcutId = Integer.toString(cardId);
|
||||
|
||||
for(int index = 0; index < list.size(); index++)
|
||||
{
|
||||
if(list.get(index).getId().equals(shortcutId))
|
||||
{
|
||||
list.remove(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
shortcutManager.setDynamicShortcuts(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package protect.card_locker.intro;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import com.github.paolorotolo.appintro.AppIntro;
|
||||
|
||||
|
||||
public class IntroActivity extends AppIntro
|
||||
{
|
||||
@Override
|
||||
public void init(Bundle savedInstanceState)
|
||||
{
|
||||
addSlide(new IntroSlide1());
|
||||
addSlide(new IntroSlide2());
|
||||
addSlide(new IntroSlide3());
|
||||
addSlide(new IntroSlide4());
|
||||
addSlide(new IntroSlide5());
|
||||
addSlide(new IntroSlide6());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipPressed(Fragment fragment) {
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDonePressed(Fragment fragment) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
19
app/src/main/java/protect/card_locker/intro/IntroSlide1.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package protect.card_locker.intro;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import protect.card_locker.R;
|
||||
|
||||
public class IntroSlide1 extends Fragment
|
||||
{
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View v = inflater.inflate(R.layout.intro1_layout, container, false);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package protect.card_locker;
|
||||
package protect.card_locker.intro;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
@@ -6,20 +6,15 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
public class IntroSlide extends Fragment
|
||||
{
|
||||
int _layout;
|
||||
import protect.card_locker.R;
|
||||
|
||||
@Override
|
||||
public void setArguments(Bundle bundle)
|
||||
{
|
||||
_layout = bundle.getInt("layout");
|
||||
}
|
||||
public class IntroSlide2 extends Fragment
|
||||
{
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View v = inflater.inflate(_layout, container, false);
|
||||
View v = inflater.inflate(R.layout.intro2_layout, container, false);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
19
app/src/main/java/protect/card_locker/intro/IntroSlide3.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package protect.card_locker.intro;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import protect.card_locker.R;
|
||||
|
||||
public class IntroSlide3 extends Fragment
|
||||
{
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View v = inflater.inflate(R.layout.intro3_layout, container, false);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
19
app/src/main/java/protect/card_locker/intro/IntroSlide4.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package protect.card_locker.intro;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import protect.card_locker.R;
|
||||
|
||||
public class IntroSlide4 extends Fragment
|
||||
{
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View v = inflater.inflate(R.layout.intro4_layout, container, false);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
19
app/src/main/java/protect/card_locker/intro/IntroSlide5.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package protect.card_locker.intro;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import protect.card_locker.R;
|
||||
|
||||
public class IntroSlide5 extends Fragment
|
||||
{
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View v = inflater.inflate(R.layout.intro5_layout, container, false);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
19
app/src/main/java/protect/card_locker/intro/IntroSlide6.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package protect.card_locker.intro;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import protect.card_locker.R;
|
||||
|
||||
public class IntroSlide6 extends Fragment
|
||||
{
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
|
||||
{
|
||||
View v = inflater.inflate(R.layout.intro6_layout, container, false);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
BIN
app/src/main/res/drawable-hdpi/ic_lock_open_white_24dp.png
Normal file
|
After Width: | Height: | Size: 306 B |
BIN
app/src/main/res/drawable-hdpi/ic_lock_outline_white_24dp.png
Normal file
|
After Width: | Height: | Size: 303 B |
BIN
app/src/main/res/drawable-mdpi/ic_lock_open_white_24dp.png
Normal file
|
After Width: | Height: | Size: 200 B |
BIN
app/src/main/res/drawable-mdpi/ic_lock_outline_white_24dp.png
Normal file
|
After Width: | Height: | Size: 198 B |
BIN
app/src/main/res/drawable-nodpi/circle.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
app/src/main/res/drawable-xhdpi/ic_lock_open_white_24dp.png
Normal file
|
After Width: | Height: | Size: 354 B |
BIN
app/src/main/res/drawable-xhdpi/ic_lock_outline_white_24dp.png
Normal file
|
After Width: | Height: | Size: 343 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_lock_open_white_24dp.png
Normal file
|
After Width: | Height: | Size: 512 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_lock_outline_white_24dp.png
Normal file
|
After Width: | Height: | Size: 494 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_lock_open_white_24dp.png
Normal file
|
After Width: | Height: | Size: 665 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_lock_outline_white_24dp.png
Normal file
|
After Width: | Height: | Size: 651 B |
@@ -65,6 +65,7 @@
|
||||
|
||||
<EditText
|
||||
android:id="@+id/storeNameEdit"
|
||||
android:inputType="textCapWords"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="@dimen/inputPadding"
|
||||
@@ -121,6 +122,7 @@
|
||||
|
||||
<EditText
|
||||
android:id="@+id/noteEdit"
|
||||
android:inputType="textCapSentences"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="@dimen/inputPadding"
|
||||
@@ -144,6 +146,55 @@
|
||||
android:background="@color/inputBorder" />
|
||||
</TableRow>
|
||||
|
||||
<!-- Add Shortcut -->
|
||||
<View
|
||||
android:id="@+id/shortcutBorder"
|
||||
android:layout_height="@dimen/inputBorderThickness"
|
||||
android:layout_width="match_parent"
|
||||
android:background="@color/inputBorder" />
|
||||
<TableRow
|
||||
android:id="@+id/shortcutTablerow"
|
||||
android:background="@color/inputBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<View
|
||||
android:gravity="start"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="@dimen/inputBorderThickness"
|
||||
android:background="@color/inputBorder" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_weight="1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingRight="@dimen/inputPadding"
|
||||
android:paddingEnd="@dimen/inputPadding">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/shortcutField"
|
||||
android:text="@string/addShortcut"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:textSize="@dimen/inputSize"
|
||||
android:padding="@dimen/inputPadding"
|
||||
android:layout_alignParentStart="true"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/shortcutCheckbox"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:padding="@dimen/inputPadding"
|
||||
android:textSize="@dimen/inputSize"
|
||||
android:layout_toEndOf="@id/shortcutField"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:gravity="end"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="@dimen/inputBorderThickness"
|
||||
android:background="@color/inputBorder" />
|
||||
</TableRow>
|
||||
|
||||
<!-- Card ID -->
|
||||
<View
|
||||
android:id="@+id/cardIdDivider"
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_lock_unlock"
|
||||
android:icon="@drawable/ic_lock_open_white_24dp"
|
||||
android:title="@string/lockScreen"
|
||||
app:showAsAction="always"/>
|
||||
<item
|
||||
android:id="@+id/action_edit"
|
||||
android:icon="@drawable/ic_mode_edit_white_24dp"
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
<string name="save">Uložit</string>
|
||||
<string name="capture">Naskenovat kartu</string>
|
||||
<string name="enterCard">Vložit vlastnoručně</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="editCard">Edit Card</string>
|
||||
|
||||
<string name="edit">Editovat</string>
|
||||
<string name="delete">Smazat</string>
|
||||
<string name="confirm">Potvrdit</string>
|
||||
|
||||
<string name="deleteTitle">Odstzranit věrnostní kartu</string>
|
||||
<string name="deleteConfirmation">Opravdu chcete smazat tuto věrnostní kartu?</string>
|
||||
<string name="ok">Ano</string>
|
||||
@@ -34,6 +35,7 @@
|
||||
<string name="noStoreError">Nebyl zadán Obchod</string>
|
||||
<string name="noCardIdError">Nebylo zadáno ID karty</string>
|
||||
|
||||
|
||||
<string name="cardIdFormat">%1$s: %2$s</string>
|
||||
|
||||
<string name="importExport">Import/Export</string>
|
||||
@@ -49,7 +51,7 @@
|
||||
<string name="noExternalStoragePermissionError">Nelze importovat nebo exportovat karty bez přístupu k externímu uložišti</string>
|
||||
|
||||
<string name="about">O aplikaci</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%s</xliff:g> Branden Archer</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licensed under the GPLv3.</string>
|
||||
<string name="about_title_fmt">O aplikaci <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Verze: <xliff:g id="version">%s</xliff:g></string>
|
||||
@@ -77,17 +79,4 @@
|
||||
<string name="importOptionFixedButton">Použít složku exportu</string>
|
||||
<string name="sendLabel">Odeslat…</string>
|
||||
|
||||
<!-- NEEDS TRANSLATED --><string name="startIntro">Start Intro</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Title">Welcome to Loyalty Card Keychain\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Description">Manage your barcode-based store/loyalty cards on your phone!\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Description">Add a new card by touching the plus from the card list.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Description">To add the barcode, either capture with the camera or type in manually.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Title">Show Card\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Description">To display a card, click on the store name from the main screen\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Title">Backup\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Description">The cards can be backed-up. To export or import card data touch Import/Export in the menu on the main page.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Title">Feedback\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Description">This app is free, ad-free, and open source. See details by touching About in the menu on the main page.\n\nPlease leave feedback in the app store! (:</string>
|
||||
</resources>
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
<string name="about_title_fmt">Über <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="action_add">Neu</string>
|
||||
<string name="addCardTitle">Neue Kundenkarte</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%s</xliff:g> Branden Archer</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Lizensiert unter der GPLv3.</string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> benutzt die folgenden Fremdbibliotheken: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> verwendet folgenden Dritt-Ressourcen: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="viewCardTitle">Kundenkarte anzeigen</string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="note">Notiz</string>
|
||||
<string name="save">Speichern</string>
|
||||
<string name="scanCardBarcode">Barcode scannen</string>
|
||||
<string name="selectBarcodeTitle">Barcode auswählen</string>
|
||||
<string name="storeName">Firma</string>
|
||||
<string name="noStoreError">Keine Firma angegeben</string>
|
||||
<string name="storeName">Geschäft</string>
|
||||
<string name="noStoreError">Kein Geschäft angegeben</string>
|
||||
<string name="exportName">Exportieren</string>
|
||||
<string name="exportedTo">Exportiert nach: %1$s</string>
|
||||
<string name="fileMissing">Datei fehlt: %1$s</string>
|
||||
@@ -24,27 +25,29 @@
|
||||
<string name="importName">Import</string>
|
||||
<string name="importedFrom">Importiert von: %1$s</string>
|
||||
<string name="noCardIdError">Keine Kartennummer angegeben</string>
|
||||
|
||||
<string name="noExternalStoragePermissionError">Ohne die Berechtigung für den externen Speicher kann kein Import oder Export erfolgen.</string>
|
||||
<string name="noGiftCards">Du hast noch keine Kundenkarte angelegt. Über den "+" Button oben rechts, kannst du welche anlegen.\n\nDiese App ermöglicht es dir, deine Kundenkarten immer mit dir zu führen.</string>
|
||||
<string name="cancel">Abrechen</string>
|
||||
<string name="capture">Karte aufnehmen</string>
|
||||
<string name="noGiftCards">Sie haben noch keine Kundenkarte angelegt. Über den "+" Button oben rechts, können welche angelegt werden.\n\nDiese App ermöglicht es, Kundenkarten immer mit zu führen.</string>
|
||||
<string name="cancel">Abbrechen</string>
|
||||
<string name="capture">Karte erfassen</string>
|
||||
<string name="cardId">Kartennummer</string>
|
||||
<string name="cardIdFormat">%1$s: %2$s</string>
|
||||
<string name="confirm">Bestätigen</string>
|
||||
<string name="copy_to_clipboard">Kopiere die Nummer in die Zwischenablage</string>
|
||||
|
||||
<string name="delete">Löschen</string>
|
||||
<string name="deleteConfirmation">Bitte bestätige, dass du die Karte löschen möchtest.</string>
|
||||
<string name="deleteTitle">Lösche die Kundenkarte</string>
|
||||
<string name="deleteConfirmation">Bitte bestätigen Sie, dass diese Karte gelöscht werden soll.</string>
|
||||
|
||||
<string name="edit">Bearbeiten</string>
|
||||
<string name="editCardTitle">Kundenkarte bearbeiten</string>
|
||||
<string name="enterCard">Karte einfügen</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="editCard">Edit Card</string>
|
||||
<string name="editCard">Karte bearbeiten</string>
|
||||
<string name="exportFailed">Export fehlgeschlagen: %1$s</string>
|
||||
<string name="barcodeType">Barcodeart</string>
|
||||
<string name="barcodeImageDescription">Bild des Barcodes</string>
|
||||
<string name="copy_to_clipboard_toast">Nummer in die Zwischenablage kopiert</string>
|
||||
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="enterBarcodeInstructions">Füge die Kundennummer ein, anschließend wähle die korrekte Barcodeart aus.</string>
|
||||
<string name="enterBarcodeInstructions">Fügen Sie die Kundennummer ein, anschließend wählen Sie die korrekte Barcodeart aus.</string>
|
||||
<string name="app_revision_fmt">Versions Information: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="importing">Importiere…</string>
|
||||
<string name="exporting">Exportiere…</string>
|
||||
@@ -54,29 +57,29 @@
|
||||
<string name="importFailedTitle">Import fehlgeschlagen</string>
|
||||
<string name="exportSuccessfulTitle">Export erfolgreich</string>
|
||||
<string name="exportFailedTitle">Export fehlgeschlagen</string>
|
||||
<string name="exportOptionExplanation">Die Datei wird ins Wurzelverzeichnis des externen Speichers geschrieben.</string>
|
||||
<string name="exportOptionExplanation">Die Datei wird ins Rootverzeichnis des externen Speichers geschrieben.</string>
|
||||
<string name="importOptionFilesystemTitle">Importiere vom Dateisystem</string>
|
||||
<string name="importOptionFilesystemExplanation">Wähle eine Datei im Speicher aus.</string>
|
||||
<string name="importOptionFilesystemButton">Vom Dateisystem</string>
|
||||
<string name="importOptionApplicationTitle">Nutze eine externe App</string>
|
||||
<string name="importOptionApplicationExplanation">Wähle eine Datei aus einer App wie Dropbox, Google Drive, oder deinem bevorzugten Dateisystem aus.</string>
|
||||
<string name="importOptionApplicationExplanation">Wählen Sie eine Datei aus einer App wie Dropbox, Google Drive, oder Ihrem bevorzugten Dateisystem aus.</string>
|
||||
<string name="importOptionApplicationButton">Nutze eine externe App</string>
|
||||
<string name="importOptionFixedTitle">Importiere vom Export Ort</string>
|
||||
<string name="importOptionFixedExplanation">Importiere von derselben Stelle, wo die exportiere Datei liegen würde.</string>
|
||||
<string name="importOptionFixedButton">Verwende die exportierte Stelle</string>
|
||||
<string name="importOptionFixedTitle">Importiere vom Export-Pfad</string>
|
||||
<string name="importOptionFixedExplanation">Importiere vom Export-Pfad.</string>
|
||||
<string name="importOptionFixedButton">Verwende den Export-Pfad.</string>
|
||||
<string name="sendLabel">Senden…</string>
|
||||
|
||||
<!-- NEEDS TRANSLATED --><string name="startIntro">Start Intro</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Title">Welcome to Loyalty Card Keychain\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Description">Manage your barcode-based store/loyalty cards on your phone!\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Description">Add a new card by touching the plus from the card list.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Description">To add the barcode, either capture with the camera or type in manually.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Title">Show Card\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Description">To display a card, click on the store name from the main screen\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Title">Backup\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Description">The cards can be backed-up. To export or import card data touch Import/Export in the menu on the main page.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Title">Feedback\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Description">This app is free, ad-free, and open source. See details by touching About in the menu on the main page.\n\nPlease leave feedback in the app store! (:</string>
|
||||
</resources>
|
||||
<string name="startIntro">Starte Einführung</string>
|
||||
<string name="intro1Title">Willkommen zu Loyalty Card Keychain\n</string>
|
||||
<string name="intro1Description">Verwalten Sie Ihre Barcode-Kundenkarten auf Ihrem Smartphone!\n\n</string>
|
||||
<string name="intro2Title">Karten hinzufügen\n</string>
|
||||
<string name="intro2Description">Fügen Sie neue Karten hinzu indem Sie das "+" Symbol in der Liste berühren.\n\n</string>
|
||||
<string name="intro3Title">Karten hinzufügen\n</string>
|
||||
<string name="intro3Description">Um einen Barcode hinzuzufügen, verwenden Sie die Kamera oder geben Sie den Code manuell ein.\n\n</string>
|
||||
<string name="intro4Title">Karte anzeigen\n</string>
|
||||
<string name="intro4Description">Um eine Karte anzuzeigen, den entsprechenen Namen in der Hauptansicht anwählen.\n\n</string>
|
||||
<string name="intro5Title">Backup\n</string>
|
||||
<string name="intro5Description">Sie können selbstverständlich Backups anlegen. Um Karten zu exportieren oder importieren wählen Sie Import/Export im Menü auf dem Hauptbildschirm.\n\n</string>
|
||||
<string name="intro6Title">Feedback\n</string>
|
||||
<string name="intro6Description">Diese App enthält keine Werbung, und ist freie und quelloffene Software. Für Details berühren Sie Über im Menü auf der Hauptseite.\n\nHinterlassen Sie uns ein Feedback im App-Store (:</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<string name="editCard">Modifier</string>
|
||||
<string name="edit">Modifier</string>
|
||||
<string name="delete">Supprimer</string>
|
||||
|
||||
<string name="confirm">Confirmer</string>
|
||||
<string name="deleteTitle">Supprimer la carte de fidélité</string>
|
||||
<string name="deleteConfirmation">Confirmez que vous souhaitez supprimer cette carte</string>
|
||||
@@ -49,12 +50,13 @@
|
||||
<string name="noExternalStoragePermissionError">Impossible d\'importer ou d\'exporter les données sans l\'autorisation d\'accès au stockage externe</string>
|
||||
|
||||
<string name="about">À propos</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%s</xliff:g> Branden Archer</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licence GPLv3.</string>
|
||||
<string name="about_title_fmt">À propos de <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Version : <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Notes sur les versions : <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> utilise les bibliothèques-tierces suivantes : <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> utilise les ressources-tierces suivantes : <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
|
||||
<string name="selectBarcodeTitle">Choisissez le code-barre</string>
|
||||
<string name="enterBarcodeInstructions">Saisissez les chiffres du code-barres et sélectionnez l\'image qui le représente</string>
|
||||
@@ -78,11 +80,11 @@
|
||||
<string name="importOptionFixedButton">Utiliser l\'emplacement de l\'export</string>
|
||||
<string name="sendLabel">Envoyer…</string>
|
||||
|
||||
<string name="startIntro">Démarrer la présentation</string>
|
||||
<string name="intro1Title">Bienvenue dans Loyalty Card Keychain\n</string>
|
||||
<string name="intro1Description">Gérez vos cartes de fidélité à codes-barres sur votre téléphone !\n\n</string>
|
||||
<string name="startIntro">Présentation</string>
|
||||
<string name="intro1Title">Bienvenue dans\nLoyalty Card Keychain\n</string>
|
||||
<string name="intro1Description">Gérez vos cartes de fidélité\nsur votre téléphone !\n\n</string>
|
||||
<string name="intro2Title">Ajouter une carte\n</string>
|
||||
<string name="intro2Description">Touchez le signe \'+\' en haut de la liste des cartes pour en ajouter une.\n\n</string>
|
||||
<string name="intro2Description">Touchez le signe \'+\' en haut de l\'écran pour ajouter une carte.\n\n</string>
|
||||
<string name="intro3Title">Ajouter une carte\n</string>
|
||||
<string name="intro3Description">Pour enregistrer le code-barres, utilisez l\'appareil-photo ou entrez-le manuellement.\n\n</string>
|
||||
<string name="intro4Title">Afficher une carte\n</string>
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
<string name="noStoreError">Nessun negozio inserito</string>
|
||||
<string name="noCardIdError">Nessun codice carta inserito</string>
|
||||
|
||||
|
||||
<string name="cardIdFormat">%1$s: %2$s</string>
|
||||
<string name="note">Note</string>
|
||||
|
||||
@@ -41,12 +42,13 @@
|
||||
<string name="exporting">Esportazione in corso…</string>
|
||||
<string name="noExternalStoragePermissionError">Impossibile importare o esportare i dati senza il permesso per l\'uso della memoria esterna.</string>
|
||||
<string name="about">Informazioni</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%s</xliff:g> Branden Archer</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Pubblicato sotto licenza GPLv3.</string>
|
||||
<string name="about_title_fmt">Informazioni su <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versione: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Informazione sulla revisione: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> usa le seguenti librerie di terze parti: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> usa le seguenti risorse di terze parti: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
<string name="ok">Ok</string>
|
||||
<string name="enterCard">Inserisci carta</string>
|
||||
<string name="editCard">Modifica carta</string>
|
||||
@@ -55,6 +57,8 @@
|
||||
<string name="copy_to_clipboard">Copia ID negli appunti</string>
|
||||
<string name="copy_to_clipboard_toast">ID della carta copiato negli appunti</string>
|
||||
<string name="confirm">Conferma</string>
|
||||
<string name="lockScreen">Blocca rotazione</string>
|
||||
<string name="unlockScreen">Sblocca rotazione</string>
|
||||
<string name="deleteTitle">Rimuovi carta fedeltà</string>
|
||||
<string name="deleteConfirmation">Conferma che vuoi eliminare questa carta.</string>
|
||||
<string name="importExportHelp">Fare il backup dei dati ti permette di spostare le tue tessere da un dispositivo ad un altro.</string>
|
||||
|
||||
@@ -15,10 +15,11 @@
|
||||
<string name="save">Išsaugoti</string>
|
||||
<string name="capture">Nufotografuoti kortelę</string>
|
||||
<string name="enterCard">Įvesti kortelę</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="editCard">Edit Card</string>
|
||||
|
||||
<string name="edit">Redaguoti</string>
|
||||
<string name="delete">Ištrinti</string>
|
||||
<string name="confirm">Patvirtinti</string>
|
||||
|
||||
<string name="deleteTitle">Panaikinti lojalumo kortelę</string>
|
||||
<string name="deleteConfirmation">Prašome patvirtinti jog Jūs norite panaikinti šią lojalumo kortelę.</string>
|
||||
<string name="ok">Gerai</string>
|
||||
@@ -34,6 +35,7 @@
|
||||
<string name="noStoreError">Parduotuvė neįvesta</string>
|
||||
<string name="noCardIdError">Neįvestas kortelės ID</string>
|
||||
|
||||
|
||||
<string name="cardIdFormat">%1$s: %2$s</string>
|
||||
|
||||
<string name="importExport">Importuoti/Exportuoti</string>
|
||||
@@ -49,7 +51,7 @@
|
||||
<string name="noExternalStoragePermissionError">Negalima importuoti/eksportuoti kortelių be išorinės atminties leidimo</string>
|
||||
|
||||
<string name="about">Apie</string>
|
||||
<string name="app_copyright_fmt">Visos teisės saugomos 2016-<xliff:g>%s</xliff:g> Branden Archer</string>
|
||||
<string name="app_copyright_fmt">Visos teisės saugomos 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licenzijuota pagal GPLv3.</string>
|
||||
<string name="about_title_fmt">Apie <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versija: <xliff:g id="version">%s</xliff:g></string>
|
||||
@@ -61,34 +63,4 @@
|
||||
|
||||
<string name="copy_to_clipboard_toast">Kortelės ID nukopijuota į iškarpinę</string>
|
||||
|
||||
<!-- needs translated --><string name="importExportHelp">Backed up data can allow you to move your cards to another device.</string>
|
||||
<!-- needs translated --><string name="importSuccessfulTitle">Import successful</string>
|
||||
<!-- needs translated --><string name="importFailedTitle">Import failed</string>
|
||||
<!-- needs translated --><string name="exportSuccessfulTitle">Export successful</string>
|
||||
<!-- needs translated --><string name="exportFailedTitle">Export failed</string>
|
||||
<!-- needs translated --><string name="exportOptionExplanation">Data is written to the top directory in external storage.</string>
|
||||
<!-- needs translated --><string name="importOptionFilesystemTitle">Import from filesystem</string>
|
||||
<!-- needs translated --><string name="importOptionFilesystemExplanation">Choose a specific file from the filesystem.</string>
|
||||
<!-- needs translated --><string name="importOptionFilesystemButton">From filesystem</string>
|
||||
<!-- needs translated --><string name="importOptionApplicationTitle">Use external application</string>
|
||||
<!-- needs translated --><string name="importOptionApplicationExplanation">Use an external application like Dropbox, Google Drive, or your favorite file manager to open a file.</string>
|
||||
<!-- needs translated --><string name="importOptionApplicationButton">Use external application</string>
|
||||
<!-- needs translated --><string name="importOptionFixedTitle">Import from export location</string>
|
||||
<!-- needs translated --><string name="importOptionFixedExplanation">Import from the same location on the filesystem that is written to on export.</string>
|
||||
<!-- needs translated --><string name="importOptionFixedButton">Use export location</string>
|
||||
<!-- needs translated --> <string name="sendLabel">Send…</string>
|
||||
|
||||
<!-- NEEDS TRANSLATED --><string name="startIntro">Start Intro</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Title">Welcome to Loyalty Card Keychain\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Description">Manage your barcode-based store/loyalty cards on your phone!\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Description">Add a new card by touching the plus from the card list.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Description">To add the barcode, either capture with the camera or type in manually.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Title">Show Card\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Description">To display a card, click on the store name from the main screen\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Title">Backup\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Description">The cards can be backed-up. To export or import card data touch Import/Export in the menu on the main page.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Title">Feedback\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Description">This app is free, ad-free, and open source. See details by touching About in the menu on the main page.\n\nPlease leave feedback in the app store! (:</string>
|
||||
</resources>
|
||||
|
||||
@@ -41,15 +41,16 @@
|
||||
<string name="exporting">Exporterende…</string>
|
||||
<string name="noExternalStoragePermissionError">Niet mogelijk te importeren of exporteren zonder rechten op externe opslag</string>
|
||||
<string name="about">Over</string>
|
||||
<string name="app_copyright_fmt">Auteursrecht 2016-<xliff:g>%s</xliff:g> Branden Archer</string>
|
||||
<string name="app_copyright_fmt">Auteursrecht 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Gelicenseerd met GPLv3.</string>
|
||||
<string name="about_title_fmt">Over <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Versie: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Revisieïnformatie: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> gebruikt de volgende bibliotheken van derden: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
|
||||
<string name="ok">Oké</string>
|
||||
<string name="enterCard">Voer kaart in</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="editCard">Edit Card</string>
|
||||
|
||||
<string name="selectBarcodeTitle">Selecteer barcode</string>
|
||||
<string name="enterBarcodeInstructions">Voer de waarde van de barcode in en kies daarna de afbeelding die de barcode die je wil gebruiken representeert</string>
|
||||
<string name="copy_to_clipboard">Kopieer het ID naar het klembord</string>
|
||||
@@ -75,17 +76,4 @@
|
||||
<string name="importOptionFixedButton">gebruik exporteerlocaite</string>
|
||||
<string name="sendLabel">Verzend…</string>
|
||||
|
||||
<!-- NEEDS TRANSLATED --><string name="startIntro">Start Intro</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Title">Welcome to Loyalty Card Keychain\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro1Description">Manage your barcode-based store/loyalty cards on your phone!\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro2Description">Add a new card by touching the plus from the card list.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Title">Adding Cards\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro3Description">To add the barcode, either capture with the camera or type in manually.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Title">Show Card\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro4Description">To display a card, click on the store name from the main screen\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Title">Backup\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro5Description">The cards can be backed-up. To export or import card data touch Import/Export in the menu on the main page.\n\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Title">Feedback\n</string>
|
||||
<!-- NEEDS TRANSLATED --><string name="intro6Description">This app is free, ad-free, and open source. See details by touching About in the menu on the main page.\n\nPlease leave feedback in the app store! (:</string>
|
||||
</resources>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
<string name="storeName">Store</string>
|
||||
<string name="note">Note</string>
|
||||
<string name="addShortcut">Add Shortcut</string>
|
||||
<string name="cardId">Card ID</string>
|
||||
<string name="barcodeType">Barcode Type</string>
|
||||
|
||||
@@ -19,11 +20,14 @@
|
||||
<string name="edit">Edit</string>
|
||||
<string name="delete">Delete</string>
|
||||
<string name="confirm">Confirm</string>
|
||||
<string name="lockScreen">Block Rotation</string>
|
||||
<string name="unlockScreen">Unblock Rotation</string>
|
||||
<string name="deleteTitle">Remove Loyalty Card</string>
|
||||
<string name="deleteConfirmation">Please confirm that you want to delete this card.</string>
|
||||
<string name="ok">OK</string>
|
||||
<string name="copy_to_clipboard">Copy ID to clipboard</string>
|
||||
<string name="sendLabel">Send…</string>
|
||||
<string name="addedShortcut">Added shortcut</string>
|
||||
|
||||
<string name="editCardTitle">Edit Loyalty Card</string>
|
||||
<string name="addCardTitle">Add Loyalty Card</string>
|
||||
@@ -34,6 +38,7 @@
|
||||
|
||||
<string name="noStoreError">No Store entered</string>
|
||||
<string name="noCardIdError">No Card ID entered</string>
|
||||
<string name="noCardExistsError">Could not lookup loyalty card</string>
|
||||
|
||||
<string name="cardIdFormat">%1$s: %2$s</string>
|
||||
<string name="storeNameAndNoteFormat" translatable="false">%1$s - %2$s</string>
|
||||
@@ -66,12 +71,13 @@
|
||||
<string name="importOptionFixedButton">Use export location</string>
|
||||
|
||||
<string name="about">About</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%s</xliff:g> Branden Archer</string>
|
||||
<string name="app_copyright_fmt">Copyright 2016-<xliff:g>%d</xliff:g> Branden Archer</string>
|
||||
<string name="app_license">Licensed under the GPLv3.</string>
|
||||
<string name="about_title_fmt">About <xliff:g id="app_name">%s</xliff:g></string>
|
||||
<string name="debug_version_fmt">Version: <xliff:g id="version">%s</xliff:g></string>
|
||||
<string name="app_revision_fmt">Revision Information: <xliff:g id="app_revision_url">%s</xliff:g></string>
|
||||
<string name="app_libraries"><xliff:g id="app_name">%s</xliff:g> uses the following third-party libraries: <xliff:g id="app_libraries_list">%s</xliff:g></string>
|
||||
<string name="app_resources"><xliff:g id="app_name">%s</xliff:g> uses the following third-party resources: <xliff:g id="app_resources_list">%s</xliff:g></string>
|
||||
|
||||
<string name="selectBarcodeTitle">Select Barcode</string>
|
||||
<string name="enterBarcodeInstructions">Enter the barcode value then select the image which represents the barcode you want to use</string>
|
||||
|
||||
3
app/src/main/res/xml/file_provider_paths.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<paths>
|
||||
<external-path name="exportPath" path="/" />
|
||||
</paths>
|
||||
@@ -36,7 +36,8 @@ public class DatabaseTest
|
||||
public void addRemoveOneGiftCard()
|
||||
{
|
||||
assertEquals(0, db.getLoyaltyCardCount());
|
||||
boolean result = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString());
|
||||
long id = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString());
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
@@ -56,7 +57,8 @@ public class DatabaseTest
|
||||
@Test
|
||||
public void updateGiftCard()
|
||||
{
|
||||
boolean result = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString());
|
||||
long id = db.insertLoyaltyCard("store", "note", "cardId", BarcodeFormat.UPC_A.toString());
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
@@ -86,7 +88,8 @@ public class DatabaseTest
|
||||
@Test
|
||||
public void emptyGiftCardValues()
|
||||
{
|
||||
boolean result = db.insertLoyaltyCard("", "", "", "");
|
||||
long id = db.insertLoyaltyCard("", "", "", "");
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
@@ -107,8 +110,9 @@ public class DatabaseTest
|
||||
// that they are sorted
|
||||
for(int index = CARDS_TO_ADD-1; index >= 0; index--)
|
||||
{
|
||||
boolean result = db.insertLoyaltyCard("store" + index, "note" + index, "cardId" + index,
|
||||
long id = db.insertLoyaltyCard("store" + index, "note" + index, "cardId" + index,
|
||||
BarcodeFormat.UPC_A.toString());
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ import org.robolectric.annotation.Config;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
@@ -63,7 +65,8 @@ public class ImportExportTest
|
||||
{
|
||||
String storeName = String.format("store, \"%4d", index);
|
||||
String note = String.format("note, \"%4d", index);
|
||||
boolean result = db.insertLoyaltyCard(storeName, note, BARCODE_DATA, BARCODE_TYPE);
|
||||
long id = db.insertLoyaltyCard(storeName, note, BARCODE_DATA, BARCODE_TYPE);
|
||||
boolean result = (id != -1);
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@@ -211,17 +214,15 @@ public class ImportExportTest
|
||||
class TestTaskCompleteListener implements ImportExportTask.TaskCompleteListener
|
||||
{
|
||||
Boolean success;
|
||||
File file;
|
||||
|
||||
public void onTaskComplete(boolean success, File file)
|
||||
public void onTaskComplete(boolean success)
|
||||
{
|
||||
this.success = success;
|
||||
this.file = file;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void useImportExportTask()
|
||||
public void useImportExportTask() throws FileNotFoundException
|
||||
{
|
||||
final int NUM_CARDS = 10;
|
||||
|
||||
@@ -235,7 +236,7 @@ public class ImportExportTest
|
||||
TestTaskCompleteListener listener = new TestTaskCompleteListener();
|
||||
|
||||
// Export to the file
|
||||
ImportExportTask task = new ImportExportTask(activity, false, format, exportFile, listener);
|
||||
ImportExportTask task = new ImportExportTask(activity, format, exportFile, listener);
|
||||
task.execute();
|
||||
|
||||
// Actually run the task to completion
|
||||
@@ -244,8 +245,6 @@ public class ImportExportTest
|
||||
// Check that the listener was executed
|
||||
assertNotNull(listener.success);
|
||||
assertEquals(true, listener.success);
|
||||
assertNotNull(listener.file);
|
||||
assertEquals(exportFile, listener.file);
|
||||
|
||||
clearDatabase();
|
||||
|
||||
@@ -253,7 +252,9 @@ public class ImportExportTest
|
||||
|
||||
listener = new TestTaskCompleteListener();
|
||||
|
||||
task = new ImportExportTask(activity, true, format, exportFile, listener);
|
||||
FileInputStream fileStream = new FileInputStream(exportFile);
|
||||
|
||||
task = new ImportExportTask(activity, format, fileStream, listener);
|
||||
task.execute();
|
||||
|
||||
// Actually run the task to completion
|
||||
@@ -262,8 +263,6 @@ public class ImportExportTest
|
||||
// Check that the listener was executed
|
||||
assertNotNull(listener.success);
|
||||
assertEquals(true, listener.success);
|
||||
assertNotNull(listener.file);
|
||||
assertEquals(exportFile, listener.file);
|
||||
|
||||
assertEquals(NUM_CARDS, db.getLoyaltyCardCount());
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@ import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
@@ -24,12 +26,14 @@ import org.robolectric.annotation.Config;
|
||||
import org.robolectric.res.builder.RobolectricPackageManager;
|
||||
import org.robolectric.shadows.ShadowActivity;
|
||||
import org.robolectric.shadows.ShadowLog;
|
||||
import org.robolectric.util.ActivityController;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static junit.framework.Assert.assertNull;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@@ -85,6 +89,7 @@ public class LoyaltyCardViewActivityTest
|
||||
*/
|
||||
private void saveLoyaltyCardWithArguments(final Activity activity,
|
||||
final String store, final String note,
|
||||
final boolean addShortcut,
|
||||
final String cardId,
|
||||
final String barcodeType,
|
||||
boolean creatingNewCard)
|
||||
@@ -101,18 +106,25 @@ public class LoyaltyCardViewActivityTest
|
||||
|
||||
final EditText storeField = (EditText) activity.findViewById(R.id.storeNameEdit);
|
||||
final EditText noteField = (EditText) activity.findViewById(R.id.noteEdit);
|
||||
final CheckBox shortcutCheckbox = (CheckBox) activity.findViewById(R.id.shortcutCheckbox);
|
||||
final TextView cardIdField = (TextView) activity.findViewById(R.id.cardIdView);
|
||||
final TextView barcodeTypeField = (TextView) activity.findViewById(R.id.barcodeType);
|
||||
|
||||
storeField.setText(store);
|
||||
noteField.setText(note);
|
||||
shortcutCheckbox.setChecked(addShortcut);
|
||||
cardIdField.setText(cardId);
|
||||
barcodeTypeField.setText(barcodeType);
|
||||
|
||||
ShortcutAddedReceiver shortcutAddedReceiver = new ShortcutAddedReceiver();
|
||||
shortcutAddedReceiver.registerReceiver(activity);
|
||||
|
||||
assertEquals(false, activity.isFinishing());
|
||||
shadowOf(activity).clickMenuItem(R.id.action_save);
|
||||
assertEquals(true, activity.isFinishing());
|
||||
|
||||
shortcutAddedReceiver.unregisterReceiver(activity);
|
||||
|
||||
assertEquals(1, db.getLoyaltyCardCount());
|
||||
|
||||
LoyaltyCard card = db.getLoyaltyCard(1);
|
||||
@@ -120,6 +132,28 @@ public class LoyaltyCardViewActivityTest
|
||||
assertEquals(note, card.note);
|
||||
assertEquals(cardId, card.cardId);
|
||||
assertEquals(barcodeType, card.barcodeType);
|
||||
|
||||
Intent shortcutRequest = shortcutAddedReceiver.lastRequest();
|
||||
|
||||
if(addShortcut)
|
||||
{
|
||||
assertNotNull(shortcutRequest);
|
||||
|
||||
String name = shortcutRequest.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
|
||||
assertEquals(card.store, name);
|
||||
|
||||
Intent startIntent = shortcutRequest.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
|
||||
assertNotNull(startIntent);
|
||||
Bundle startBundle = startIntent.getExtras();
|
||||
assertNotNull(startBundle);
|
||||
|
||||
assertEquals(card.id, startBundle.getInt("id", -1));
|
||||
assertEquals(true, startBundle.getBoolean("view", false));
|
||||
}
|
||||
else
|
||||
{
|
||||
assertNull(shortcutRequest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -182,6 +216,8 @@ public class LoyaltyCardViewActivityTest
|
||||
checkFieldProperties(activity, R.id.storeNameEdit, editVisibility, store);
|
||||
checkFieldProperties(activity, R.id.storeNameView, viewVisibility, store);
|
||||
checkFieldProperties(activity, R.id.noteEdit, editVisibility, note);
|
||||
checkFieldProperties(activity, R.id.shortcutBorder, editVisibility, null);
|
||||
checkFieldProperties(activity, R.id.shortcutTablerow, editVisibility, null);
|
||||
checkFieldProperties(activity, R.id.noteView, viewVisibility, note);
|
||||
checkFieldProperties(activity, R.id.cardIdView, View.VISIBLE, cardId);
|
||||
checkFieldProperties(activity, R.id.cardIdDivider, cardId.isEmpty() ? View.GONE : View.VISIBLE, null);
|
||||
@@ -272,7 +308,30 @@ public class LoyaltyCardViewActivityTest
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", BARCODE_DATA, BARCODE_TYPE);
|
||||
|
||||
// Save and check the gift card
|
||||
saveLoyaltyCardWithArguments(activity, "store", "note", BARCODE_DATA, BARCODE_TYPE, true);
|
||||
saveLoyaltyCardWithArguments(activity, "store", "note", false, BARCODE_DATA, BARCODE_TYPE, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithoutParametersCaptureBarcodeCreateLoyaltyCardSaveShortcut() throws IOException
|
||||
{
|
||||
registerMediaStoreIntentHandler();
|
||||
|
||||
ActivityController activityController = Robolectric.buildActivity(LoyaltyCardViewActivity.class).create();
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
Activity activity = (Activity)activityController.get();
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", "", "");
|
||||
|
||||
// Complete barcode capture successfully
|
||||
captureBarcodeWithResult(activity, R.id.captureButton, true);
|
||||
|
||||
checkAllFields(activity, ViewMode.ADD_CARD, "", "", BARCODE_DATA, BARCODE_TYPE);
|
||||
|
||||
// Save and check the gift card
|
||||
saveLoyaltyCardWithArguments(activity, "store", "note", true, BARCODE_DATA, BARCODE_TYPE, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -414,4 +473,47 @@ public class LoyaltyCardViewActivityTest
|
||||
shadowOf(activity).clickMenuItem(android.R.id.home);
|
||||
assertEquals(true, activity.isFinishing());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkMenu() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(false);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
DBHelper db = new DBHelper(activity);
|
||||
|
||||
db.insertLoyaltyCard("store", "note", BARCODE_DATA, BARCODE_TYPE);
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
final Menu menu = shadowOf(activity).getOptionsMenu();
|
||||
assertTrue(menu != null);
|
||||
|
||||
// The settings and add button should be present
|
||||
assertEquals(menu.size(), 2);
|
||||
|
||||
assertEquals("Block Rotation", menu.findItem(R.id.action_lock_unlock).getTitle().toString());
|
||||
assertEquals("Edit", menu.findItem(R.id.action_edit).getTitle().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startWithMissingLoyaltyCard() throws IOException
|
||||
{
|
||||
ActivityController activityController = createActivityWithLoyaltyCard(true);
|
||||
Activity activity = (Activity)activityController.get();
|
||||
|
||||
activityController.start();
|
||||
activityController.visible();
|
||||
activityController.resume();
|
||||
|
||||
// The activity should find that the card is missing and shut down
|
||||
|
||||
assertTrue(activity.isFinishing());
|
||||
|
||||
// Make sure the activity can close down
|
||||
activityController.pause();
|
||||
activityController.stop();
|
||||
activityController.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import org.robolectric.Robolectric;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ActivityController;
|
||||
import org.robolectric.android.controller.ActivityController;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -131,7 +131,7 @@ public class MainActivityTest
|
||||
|
||||
ComponentName componentName = next.getComponent();
|
||||
String name = componentName.flattenToShortString();
|
||||
assertEquals("protect.card_locker/.IntroActivity", name);
|
||||
assertEquals("protect.card_locker/.intro.IntroActivity", name);
|
||||
|
||||
Bundle extras = next.getExtras();
|
||||
assertNull(extras);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package protect.card_locker;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
|
||||
public class ShortcutAddedReceiver extends BroadcastReceiver
|
||||
{
|
||||
public static final String SHORTCUT_ADD_REQUEST = "com.android.launcher.action.INSTALL_SHORTCUT";
|
||||
|
||||
private Intent _request = null;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent)
|
||||
{
|
||||
_request = intent;
|
||||
}
|
||||
|
||||
public void registerReceiver(Context context)
|
||||
{
|
||||
context.registerReceiver(this, new IntentFilter(SHORTCUT_ADD_REQUEST));
|
||||
}
|
||||
|
||||
public void unregisterReceiver(Context context)
|
||||
{
|
||||
context.unregisterReceiver(this);
|
||||
}
|
||||
|
||||
public Intent lastRequest()
|
||||
{
|
||||
return _request;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
_request = null;
|
||||
}
|
||||
}
|
||||