diff --git a/app/build.gradle b/app/build.gradle
index a30cb41..f3e1455 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,39 +1,38 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 29
+ compileSdkVersion 33
defaultConfig {
- applicationId "org.dslul.ticketreader"
- minSdkVersion 15
- targetSdkVersion 29
+ applicationId "it.fossoft.ticketreader"
+ minSdkVersion 16
+ targetSdkVersion 33
versionCode 38
versionName "2.6.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- implementation 'androidx.appcompat:appcompat:1.1.0'
- implementation 'androidx.preference:preference:1.1.0'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.vectordrawable:vectordrawable-animated:1.1.0'
- implementation 'androidx.media:media:1.1.0'
+ implementation 'androidx.media:media:1.6.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
- implementation 'androidx.browser:browser:1.0.0'
- implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation 'com.google.android.material:material:1.0.0'
+ implementation 'androidx.browser:browser:1.5.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation 'com.google.android.material:material:1.9.0'
implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'androidx.test.ext:junit:1.1.1'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
- implementation 'com.google.android.gms:play-services-ads:18.3.0'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'com.yarolegovich:lovely-dialog:1.1.0'
}
diff --git a/app/src/androidTest/java/org/dslul/ticketreader/ExampleInstrumentedTest.java b/app/src/androidTest/java/org/dslul/ticketreader/ExampleInstrumentedTest.java
deleted file mode 100755
index 26b0f37..0000000
--- a/app/src/androidTest/java/org/dslul/ticketreader/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.dslul.ticketreader;
-
-import android.content.Context;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() throws Exception {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
-
- assertEquals("org.dslul.ticketreader", appContext.getPackageName());
- }
-}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e0d7e45..103f632 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,64 +1,66 @@
+ android:name=".MainActivity"
+ android:configChanges="orientation"
+ android:label="@string/app_name"
+ android:screenOrientation="portrait"
+ android:theme="@style/AppTheme.NoActionBar"
+ android:exported="true">
+ android:name=".AliasAutoStartMainActivity"
+ android:label="@string/app_name"
+ android:targetActivity=".MainActivity"
+ android:exported="true">
\ No newline at end of file
diff --git a/app/src/main/java/org/dslul/ticketreader/MainActivity.java b/app/src/main/java/org/dslul/ticketreader/MainActivity.java
index 1a4410d..b580bd0 100755
--- a/app/src/main/java/org/dslul/ticketreader/MainActivity.java
+++ b/app/src/main/java/org/dslul/ticketreader/MainActivity.java
@@ -1,424 +1,406 @@
package org.dslul.ticketreader;
import android.annotation.SuppressLint;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.nfc.tech.IsoDep;
import android.os.Bundle;
import android.os.CountDownTimer;
import androidx.appcompat.app.AppCompatActivity;
import androidx.preference.PreferenceManager;
import androidx.cardview.widget.CardView;
import androidx.appcompat.widget.Toolbar;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TableLayout;
import android.widget.TextView;
import java.util.Calendar;
import java.util.List;
import android.nfc.NfcAdapter;
import android.nfc.tech.NfcA;
import android.widget.Toast;
import android.content.Intent;
import android.content.IntentFilter;
import android.app.PendingIntent;
import android.os.Handler;
import android.os.Message;
import android.app.AlertDialog;
import android.content.DialogInterface;
-import com.google.android.gms.ads.AdRequest;
-import com.google.android.gms.ads.AdView;
-import com.google.android.gms.ads.MobileAds;
-import com.google.android.gms.ads.initialization.InitializationStatus;
-import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
import com.yarolegovich.lovelydialog.LovelyCustomDialog;
import org.dslul.ticketreader.util.HelperFunctions;
import static org.dslul.ticketreader.util.HelperFunctions.millisToString;
public class MainActivity extends AppCompatActivity {
private NfcAdapter mNfcAdapter;
private IntentFilter tech;
private IntentFilter[] intentFiltersArray;
private PendingIntent pendingIntent;
private Intent intent;
private AlertDialog alertDialog;
private Toast currentToast;
- private AdView adview;
private ImageView imageNfc;
private CardView ticketCard;
private CardView statusCard;
private ImageView statusImg;
private TextView statoBiglietto;
private TextView infoLabel;
private TableLayout infoTable;
private TextView tipologia;
private TextView dataLabel;
private TextView dataObliterazione;
private TextView corseRimanenti;
private CountDownTimer timer;
private List dump;
// list of NFC technologies detected:
private final String[][] techListsArray = new String[][] {
new String[] {
//MifareUltralight.class.getName(),
NfcA.class.getName()
},
new String[] {
IsoDep.class.getName()
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//initialize NFC first
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter == null) {
Toast.makeText(this, R.string.nfc_not_supported, Toast.LENGTH_LONG).show();
finish();
return;
}
if (!mNfcAdapter.isEnabled()) {
Toast.makeText(this, R.string.nfc_disabled, Toast.LENGTH_LONG).show();
startActivity(new Intent(android.provider.Settings.ACTION_WIRELESS_SETTINGS));
}
tech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
intentFiltersArray = new IntentFilter[] {tech};
intent = new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
//FLAG_ACTIVITY_REORDER_TO_FRONT FLAG_RECEIVER_REPLACE_PENDING
- pendingIntent = PendingIntent.getActivity(this, 0, intent, 0);
+ pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE);
onNewIntent(getIntent());
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
- adview = (AdView) findViewById(R.id.adView);
imageNfc = (ImageView) findViewById(R.id.imagenfcView);
ticketCard = (CardView) findViewById(R.id.ticketCardView);
statusCard = (CardView) findViewById(R.id.statusCardView);
statusImg = (ImageView) findViewById(R.id.statusImg);
statoBiglietto = (TextView) findViewById(R.id.stato_biglietto);
infoLabel = (TextView) findViewById(R.id.infolabel);
infoTable = (TableLayout) findViewById(R.id.info_table);
tipologia = (TextView) findViewById(R.id.tipologia);
dataLabel = (TextView) findViewById(R.id.validation_or_expire);
dataObliterazione = (TextView) findViewById(R.id.data_obliterazione);
corseRimanenti = (TextView) findViewById(R.id.corse_rimaste);
-
-
- if(!BuildConfig.DEBUG) {
- MobileAds.initialize(this, new OnInitializationCompleteListener() {
- @Override
- public void onInitializationComplete(InitializationStatus initializationStatus) {
- }
- });
- AdRequest adRequest = new AdRequest.Builder().build();
- adview.loadAd(adRequest);
- }
/*
new LovelyInfoDialog(this)
.setTopColorRes(R.color.darkBlueGrey)
.setIcon(R.drawable.ic_info_outline_white_36dp)
//This will add Don't show again checkbox to the dialog. You can pass any ID as argument
.setNotShowAgainOptionEnabled(0)
.setNotShowAgainOptionChecked(false)
.setTitle("BETA")
.setMessage("Questa versione รจ una beta e potrebbe restituire risultati sbagliati. Segnalare per favore ogni incongruenza (insieme ad una copia del contenuto della carta) all'indirizzo email specificato nelle informazioni. Grazie.")
.show();
*/
}
@Override
protected void onResume() {
super.onResume();
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, this.techListsArray);
}
@Override
protected void onPause() {
// disabling foreground dispatch:
//NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
mNfcAdapter.disableForegroundDispatch(this);
super.onPause();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (intent.getAction().equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {
NfcThread nfcThread = new NfcThread(getBaseContext(), intent, mContentHandler, mToastShortHandler, mToastLongHandler, mShowInfoDialogHandler);
nfcThread.start();
}
}
@SuppressLint("HandlerLeak")
private Handler mContentHandler = new Handler() {
public void handleMessage(Message msg) {
List dumplist = (List)msg.obj;
dump = dumplist;
if(timer != null)
timer.cancel();
try {
//smartcard
if(dumplist.size() == 15) {
SmartCard smartcard = new SmartCard(dumplist);
if(smartcard.hasSubscriptions() && !smartcard.hasTickets()) {
dataLabel.setText(R.string.expire_date);
tipologia.setText(smartcard.getSubscriptionName());
dataObliterazione.setText(smartcard.getExpireDate());
if(smartcard.isSubscriptionExpired()) {
corseRimanenti.setText("0");
statoBiglietto.setText(R.string.expired);
statusImg.setImageResource(R.drawable.ic_error_grey_800_36dp);
statusCard.setCardBackgroundColor(getResources().getColor(R.color.colorRed));
} else {
corseRimanenti.setText(R.string.unlimited);
statoBiglietto.setText(R.string.valid);
statusImg.setImageResource(R.drawable.ic_check_circle_grey_800_36dp);
statusCard.setCardBackgroundColor(getResources().getColor(R.color.colorGreen));
}
statusCard.setVisibility(View.VISIBLE);
ticketCard.setVisibility(View.VISIBLE);
infoLabel.setText(R.string.read_another_ticket);
imageNfc.setVisibility(View.GONE);
} else {
createTicketInterface(smartcard.getTicketName(),smartcard.getValidationDate(),
smartcard.getRemainingRides(), smartcard.getRemainingMinutes());
//Toast.makeText(getBaseContext(), R.string.smartcard_tickets_not_supported_yet, Toast.LENGTH_LONG).show();
}
}
//chip on paper
else if(dumplist.size() > 15) {
ChipOnPaper chipOnPaper = new ChipOnPaper(dumplist);
createTicketInterface(chipOnPaper.getTypeName(),chipOnPaper.getDate(),
chipOnPaper.getRemainingRides(), chipOnPaper.getRemainingMinutes());
} else {
statusCard.setVisibility(View.GONE);
ticketCard.setVisibility(View.GONE);
infoLabel.setText(R.string.info_instructions);
imageNfc.setVisibility(View.VISIBLE);
}
} catch (Exception ex) {
Toast.makeText(getBaseContext(), R.string.unknown_error, Toast.LENGTH_LONG).show();
Log.d("card", ex.getMessage());
ex.printStackTrace();
}
}
};
private void createTicketInterface(String name, String date, int remainingRides, long remainingMinutes) {
dataLabel.setText(R.string.data_obliterazione);
tipologia.setText(name);
dataObliterazione.setText(date);
corseRimanenti.setText(Integer.toString(remainingRides));
if(remainingMinutes != 0) {
statoBiglietto.setText(R.string.in_corso);
statusImg.setImageResource(R.drawable.ic_restore_grey_800_36dp);
statusCard.setCardBackgroundColor(getResources().getColor(R.color.colorBlue));
Calendar calendar = Calendar.getInstance();
int sec = calendar.get(Calendar.SECOND);
timer = new CountDownTimer((remainingMinutes*60 - sec)*1000, 1000) {
public void onTick(long millis) {
statoBiglietto.setText(String.format("%s %s",
getResources().getString(R.string.in_corso), millisToString(millis)));
}
public void onFinish() {
statoBiglietto.setText(R.string.corse_esaurite);
statusImg.setImageResource(R.drawable.ic_error_grey_800_36dp);
statusCard.setCardBackgroundColor(getResources().getColor(R.color.colorRed));
if(timer != null)
timer.cancel();
}
}.start();
} else if(remainingRides == 0 && remainingMinutes == 0) {
statoBiglietto.setText(R.string.corse_esaurite);
statusImg.setImageResource(R.drawable.ic_error_grey_800_36dp);
statusCard.setCardBackgroundColor(getResources().getColor(R.color.colorRed));
} else if(remainingRides != 0 && remainingMinutes == 0) {
if(remainingRides == 1)
statoBiglietto.setText(String.format(getResources().getString(R.string.corse_disponibili_singolare), remainingRides));
else
statoBiglietto.setText(String.format(getResources().getString(R.string.corse_disponibili), remainingRides));
statusImg.setImageResource(R.drawable.ic_check_circle_grey_800_36dp);
statusCard.setCardBackgroundColor(getResources().getColor(R.color.colorGreen));
}
statusCard.setVisibility(View.VISIBLE);
ticketCard.setVisibility(View.VISIBLE);
infoLabel.setText(R.string.read_another_ticket);
imageNfc.setVisibility(View.GONE);
}
private Handler mToastShortHandler = new Handler() {
public void handleMessage(Message msg) {
String text = (String)msg.obj;
if(currentToast != null)
currentToast.cancel();
currentToast = Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT);
currentToast.show();
}
};
private Handler mToastLongHandler = new Handler() {
public void handleMessage(Message msg) {
String text = (String)msg.obj;
if(currentToast != null)
currentToast.cancel();
currentToast = Toast.makeText(MainActivity.this, text, Toast.LENGTH_LONG);
currentToast.show();
}
};
private Handler mShowInfoDialogHandler = new Handler() {
public void handleMessage(Message msg) {
String text = (String)msg.obj;
//infoDialog = showInfoDialog(text);
//infoDialog.show();
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_info) {
TextView view = new TextView(getBaseContext());
view.setText(Html.fromHtml(getString(R.string.html_info)));
view.setMovementMethod(LinkMovementMethod.getInstance());
view.setPadding( 40, 40, 40, 40 );
new LovelyCustomDialog(this)
.setTopColorRes(R.color.darkBlueGrey)
.setIcon(R.drawable.ic_info_outline_white_36dp)
.setTitle("Info")
.setView(view)
.show();
return true;
}
if (id == R.id.action_settings) {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}
if (id == R.id.action_copy_content) {
try {
ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
String content = "";
if (dump != null && dump.size() >= 15) {
for (byte[] page : dump) {
content = content.concat(HelperFunctions.byteArrayToHexString(page));
}
ClipData clip = ClipData.newPlainText("content", content);
if (clipboard != null) {
clipboard.setPrimaryClip(clip);
}
Toast.makeText(getBaseContext(), R.string.content_copied, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getBaseContext(), R.string.no_content, Toast.LENGTH_LONG).show();
}
} catch (Exception ex) {
ex.printStackTrace();
}
return true;
}
return super.onOptionsItemSelected(item);
}
private AlertDialog showAlertDialog(String message) {
DialogInterface.OnClickListener dialogInterfaceListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
alertDialog.cancel();
}
};
alertDialog = new AlertDialog.Builder(this)
.setTitle(R.string.information)
.setIcon(android.R.drawable.ic_dialog_info)
.setMessage(message)
.setPositiveButton(R.string.close_dialog, null)
.create();
alertDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
public void onCancel(DialogInterface dialog) {
}
});
return alertDialog;
}
}
diff --git a/app/src/main/res/layout/content_main.xml b/app/src/main/res/layout/content_main.xml
index 998f05d..40af13e 100755
--- a/app/src/main/res/layout/content_main.xml
+++ b/app/src/main/res/layout/content_main.xml
@@ -1,229 +1,217 @@
-
-
-
-
diff --git a/build.gradle b/build.gradle
index f2fa8af..a1d04c8 100755
--- a/build.gradle
+++ b/build.gradle
@@ -1,30 +1,30 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.3'
+ classpath 'com.android.tools.build:gradle:7.2.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven {
url "https://maven.google.com"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index e597517..080aa1e 100755
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
#Mon Aug 26 13:12:33 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip