Browse Source

UI Changes & Bugfender integration

hbw_build
Wong Joon Hui 2 years ago
parent
commit
01ac0abdae
  1. 17
      .idea/deploymentTargetDropDown.xml
  2. 12
      .idea/misc.xml
  3. 11
      app/build.gradle
  4. 3
      app/src/main/AndroidManifest.xml
  5. 10
      app/src/main/java/com/cst/im30/EchoClient.java
  6. 10
      app/src/main/java/com/cst/im30/EchoClientSetting.java
  7. 2
      app/src/main/java/com/cst/im30/ICEchoClient.java
  8. 38
      app/src/main/java/com/cst/im30/MainApplication.java
  9. 154
      app/src/main/java/com/cst/im30/activity/MainActivity.java
  10. 2
      app/src/main/java/com/cst/im30/activity/SettingActivity.java
  11. 56
      app/src/main/java/com/cst/im30/utility/Logger.java
  12. 5
      app/src/main/res/drawable/echo_ic_offline.xml
  13. 5
      app/src/main/res/drawable/echo_ic_online.xml
  14. 5
      app/src/main/res/drawable/echo_payment_offline.xml
  15. 5
      app/src/main/res/drawable/echo_payment_online.xml
  16. 7
      app/src/main/res/drawable/layout_border.xml
  17. 64
      app/src/main/res/layout/activity_main.xml
  18. 3
      app/src/main/res/values/colors.xml
  19. 2
      app/src/main/res/values/strings.xml
  20. 4
      gradle.properties

17
.idea/deploymentTargetDropDown.xml

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="1640011591" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2022-04-19T01:28:28.927516800Z" />
</component>
</project>

12
.idea/misc.xml

@ -7,10 +7,22 @@
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable-v24/ic_udc_launcher_background.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/btn_general_disable_bg.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/btn_general_enable_bg.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/echo_ic_offline.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/echo_ic_online.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/echo_payment_offline.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/echo_payment_online.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_baseline_account_box_24_green.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_baseline_account_box_24_on.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_baseline_account_box_24_red.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_baseline_keyboard_return_24.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_baseline_payment_24.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_baseline_payment_24_on.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_baseline_settings_24.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_launcher_background.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/ic_status_fail.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/layout_border.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/pop_up_bg.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/drawable/pop_up_round_top_text.xml" value="0.37083333333333335" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/layout/activity_icc.xml" value="0.19739583333333333" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/layout/activity_main.xml" value="0.3546875" />
<entry key="..\:/StudioProjects/kiosk-im30/app/src/main/res/layout/activity_response.xml" value="0.19739583333333333" />

11
app/build.gradle

@ -31,6 +31,8 @@ android {
buildConfigField("String", "IC_CHANNEL_ID", IC_CHANNEL_ID)
buildConfigField("String", "IC_EVENT_TYPE", IC_EVENT_TYPE)
buildConfigField("String", "BUGFENDER_TOKEN", BUGFENDER_TOKEN)
}
buildTypes {
@ -94,6 +96,15 @@ dependencies {
//noinspection GradleDynamicVersion
implementation 'me.grantland:autofittextview:0.2.+'
implementation 'com.jakewharton:process-phoenix:2.1.2'
// AWS
implementation "com.amazonaws:aws-android-sdk-logs:2.44.0"
// Bugfender
//noinspection GradleDynamicVersion
implementation 'com.bugfender.sdk:android:3.+'
debugImplementation 'com.github.amitshekhariitbhu.Android-Debug-Database:debug-db:v1.0.6'
}

3
app/src/main/AndroidManifest.xml

@ -4,7 +4,10 @@
package="com.cst.im30">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:name=".MainApplication"

10
app/src/main/java/com/cst/im30/EchoClient.java

@ -10,15 +10,9 @@ import net.mrbin99.laravelechoandroid.channel.SocketIOChannel;
public class EchoClient {
private Echo echo;
private EchoOptions options;
private final EchoOptions options;
private String host;
private MainActivity context;
public EchoClient(MainActivity context, String host) {
this.context = context;
this.host = host;
public EchoClient(String host) {
this.options = new EchoOptions();
this.options.host = host;

10
app/src/main/java/com/cst/im30/EchoClientSetting.java

@ -10,15 +10,9 @@ import net.mrbin99.laravelechoandroid.channel.SocketIOChannel;
public class EchoClientSetting {
private Echo echo;
private EchoOptions options;
private final EchoOptions options;
private String host;
private SettingActivity context;
public EchoClientSetting(SettingActivity context, String host) {
this.context = context;
this.host = host;
public EchoClientSetting(String host) {
this.options = new EchoOptions();
this.options.host = host;

2
app/src/main/java/com/cst/im30/ICEchoClient.java

@ -5,7 +5,7 @@ import com.cst.im30.activity.MainActivity;
public class ICEchoClient extends EchoClient {
public ICEchoClient(MainActivity context, String host) {
super(context, host);
super(host);
}

38
app/src/main/java/com/cst/im30/MainApplication.java

@ -6,12 +6,14 @@ import android.app.Application;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import com.bugfender.sdk.Bugfender;
import com.cst.im30.activity.MainActivity;
import com.cst.im30.model.CancelRequest;
import com.cst.im30.model.CancelResponse;
@ -37,6 +39,10 @@ public class MainApplication extends Application {
public static boolean paymentIsConnected = false;
public static boolean icIsConnected = false;
public static final int MAX_RETRY = 5;
public static int failCountIC = 0;
public static int failCountPayment = 0;
public static boolean working = false;
public static String incomingCode = null;
@ -94,23 +100,50 @@ public class MainApplication extends Application {
currentSaleCompletionRequest = null;
currentSaleCompletionResponse = null;
Logger.logI("RESET");
Logger.logD("RESET");
}
@Override
public void onCreate() {
super.onCreate();
//Logger.logV("Application Start");
initializeBugfender();
initializeCrashHandler();
}
@SuppressLint("MissingPermission")
private void initializeBugfender() {
//Logger.logD("Attaching Bugfender");
Bugfender.init(this, BuildConfig.BUGFENDER_TOKEN, BuildConfig.DEBUG);
String serialNumber;
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
serialNumber = android.os.Build.getSerial();
} else {
serialNumber = android.os.Build.SERIAL;
}
Bugfender.setDeviceString("S/N", serialNumber);
Bugfender.setDeviceString("Kiosk Code", BuildConfig.KIOSK_CODE);
Bugfender.setDeviceString("Echo Server", BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
Bugfender.enableCrashReporting();
//Bugfender.enableLogcatLogging();
}
private void initializeCrashHandler() {
Thread.setDefaultUncaughtExceptionHandler(this::handleUncaughtException);
//Logger.logV("Crash Handler Attached");
}
public void handleUncaughtException(Thread thread, Throwable e) {
if (e instanceof Exception) {
Log.e("CST", "Exception: " + Log.getStackTraceString(e));
Log.e(Logger.TAG, "Exception: " + Log.getStackTraceString(e));
}
if (isUIThread()) { // exception occurred from UI thread
restartApp();
@ -132,4 +165,5 @@ public class MainApplication extends Application {
mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
System.exit(2);
}
}

154
app/src/main/java/com/cst/im30/activity/MainActivity.java

@ -1,24 +1,33 @@
package com.cst.im30.activity;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.READ_PHONE_STATE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import com.cst.im30.BuildConfig;
import com.cst.im30.EchoClient;
@ -39,22 +48,28 @@ import com.cst.im30.utility.PaymentUtils;
import com.daimajia.slider.library.SliderLayout;
import com.daimajia.slider.library.SliderTypes.BaseSliderView;
import com.daimajia.slider.library.SliderTypes.TextSliderView;
import com.jakewharton.processphoenix.ProcessPhoenix;
import net.mrbin99.laravelechoandroid.EchoCallback;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
public class MainActivity extends AppCompatActivity implements CallableInterface {
public static final String TAG = "MainActivity.";
ImageView load;
AnimationDrawable animationDrawable;
private ImageView load;
private AnimationDrawable animationDrawable;
private String status;
// Echo Server Connection
private LinearLayout echoStatusLayout;
private ImageView paymentEchoStatusImageView, icEchoStatusImageView;
private TextView paymentEchoStatusTextView, icEchoStatusTextView;
private TextView testTitle; //todo until new screen
@ -74,9 +89,11 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
if (verifyIC(name, cardNo)) {
showStatusDialog(true, "NRIC Match");
service.verifySuccess(MainApplication.currentCode);
Logger.recordICScan("[MATCH] " + name + ":" + cardNo);
} else {
showStatusDialog(false, "NRIC Not Match");
service.verifyFail(MainApplication.currentCode);
Logger.recordICScan("[NOT MATCH] " + name + ":" + cardNo);
}
}
} else if (result.getResultCode() == Activity.RESULT_CANCELED) {
@ -89,14 +106,23 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
}
});
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPermissions();
sliderLayout = findViewById(R.id.slider_layout_ma);
sliderLayout.setVisibility(View.INVISIBLE); //todo until get good image
echoStatusLayout = findViewById(R.id.echoStatusLayout);
paymentEchoStatusImageView = findViewById(R.id.paymentEchoStatusImageView);
icEchoStatusImageView = findViewById(R.id.icEchoStatusImageView);
paymentEchoStatusTextView = findViewById(R.id.paymentEchoStatusTextView);
icEchoStatusTextView = findViewById(R.id.icEchoStatusTextView);
testTitle = findViewById(R.id.testText);
load = findViewById(R.id.loading_image_mt);
@ -212,9 +238,13 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
runOnUiThread(() -> {
sliderLayout.setVisibility(View.INVISIBLE);
testTitle.setVisibility(View.INVISIBLE);
animationDrawable = (AnimationDrawable) load.getDrawable();
animationDrawable.start();
load.setVisibility(View.VISIBLE);
echoStatusLayout.setVisibility(View.INVISIBLE);
});
}
@ -224,7 +254,10 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
runOnUiThread(() -> {
//sliderLayout.setVisibility(View.VISIBLE);
testTitle.setVisibility(View.VISIBLE);
animationDrawable.stop();
load.setVisibility(View.GONE);
echoStatusLayout.setVisibility(View.VISIBLE);
});
}
@ -581,18 +614,19 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
@Override
public void onDestroy() {
super.onDestroy();
disconnectEchoClientIC();
disconnectEchoClientPayment();
}
private void initEchoClientIC() {
Logger.logD("echoClient IC: " + BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
MainApplication.icClient = new EchoClient(this, BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
//Logger.logD("echoClient IC: " + BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
MainApplication.icClient = new EchoClient(BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
}
private void initEchoClientPayment() {
Logger.logD("echoClient Payment: " + BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
MainApplication.paymentClient = new EchoClient(this, BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
//Logger.logD("echoClient Payment: " + BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
MainApplication.paymentClient = new EchoClient(BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT);
}
private void connectEchoClientIC() {
@ -616,13 +650,17 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
}
private void onConnectSuccessPayment(Object[] args) {
MainApplication.paymentIsConnected = true;
try {
String channelID = BuildConfig.SOCKET_PREFIX + BuildConfig.PAYMENT_CHANNEL_ID + BuildConfig.KIOSK_CODE;
String eventType = BuildConfig.PAYMENT_EVENT_TYPE;
EchoCallback echoCallback = this::receiveMessagePayment;
MainApplication.paymentClient.channel(channelID).listen(eventType, echoCallback);
Logger.logD("Listening to: " + eventType + " on " + channelID);
MainApplication.paymentIsConnected = true;
MainApplication.failCountPayment = 0;
updatePaymentOnline();
} catch (Exception ex) {
Logger.logE("Error on contact: " + ex.getMessage());
}
@ -630,17 +668,31 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
private void onConnectFailurePayment(Object[] args) {
MainApplication.paymentIsConnected = false;
Logger.logW("Failed To Connect Payment");
if (MainApplication.failCountIC == 0) {
Logger.logW("Failed To Connect to Payment Socket. Retrying up to " + MainApplication.MAX_RETRY + " times");
}
MainApplication.failCountPayment++;
if (MainApplication.failCountPayment >= MainApplication.MAX_RETRY) {
Logger.logE("Payment Echo Connection Failed More than " + MainApplication.MAX_RETRY + " times! Restarting app...");
ProcessPhoenix.triggerRebirth(MainActivity.this);
}
updatePaymentOffline();
}
private void onConnectSuccessIC(Object[] args) {
MainApplication.icIsConnected = true;
try {
String channelID = BuildConfig.SOCKET_PREFIX + BuildConfig.IC_CHANNEL_ID + BuildConfig.KIOSK_CODE;
String eventType = BuildConfig.IC_EVENT_TYPE;
EchoCallback echoCallback = this::receiveMessageIC;
MainApplication.icClient.channel(channelID).listen(eventType, echoCallback);
Logger.logD("Listening to: " + eventType + " on " + channelID);
MainApplication.icIsConnected = true;
MainApplication.failCountIC = 0;
updateICOnline();
} catch (Exception ex) {
Logger.logE("Error on contact: " + ex.getMessage());
}
@ -648,10 +700,53 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
private void onConnectFailureIC(Object[] args) {
MainApplication.icIsConnected = false;
Logger.logW("Failed To Connect IC");
if (MainApplication.failCountIC == 0) {
Logger.logW("Failed To Connect toIC Socket. Retrying up to " + MainApplication.MAX_RETRY + " times");
}
MainApplication.failCountIC++;
if (MainApplication.failCountIC >= MainApplication.MAX_RETRY) {
Logger.logE("IC Echo Connection Failed More than " + MainApplication.MAX_RETRY + " times! Restarting app...");
ProcessPhoenix.triggerRebirth(MainActivity.this);
}
updateICOffline();
}
private void updatePaymentOnline() {
runOnUiThread(() -> {
paymentEchoStatusImageView.setImageResource(R.drawable.echo_payment_online);
paymentEchoStatusTextView.setText(R.string.online_caps);
paymentEchoStatusTextView.setTextColor(getResources().getColor(R.color.online));
});
}
private void updatePaymentOffline() {
runOnUiThread(() -> {
paymentEchoStatusImageView.setImageResource(R.drawable.echo_payment_offline);
paymentEchoStatusTextView.setText(R.string.offline_caps);
paymentEchoStatusTextView.setTextColor(getResources().getColor(R.color.offline));
});
}
private void updateICOnline() {
runOnUiThread(() -> {
icEchoStatusImageView.setImageResource(R.drawable.echo_ic_online);
icEchoStatusTextView.setText(R.string.online_caps);
icEchoStatusTextView.setTextColor(getResources().getColor(R.color.online));
});
}
private void updateICOffline() {
runOnUiThread(() -> {
icEchoStatusImageView.setImageResource(R.drawable.echo_ic_offline);
icEchoStatusTextView.setText(R.string.offline_caps);
icEchoStatusTextView.setTextColor(getResources().getColor(R.color.offline));
});
}
public void startWork() {
Logger.logD("START WORK");
MainApplication.working = true;
}
@ -659,4 +754,41 @@ public class MainActivity extends AppCompatActivity implements CallableInterface
public void onBackPressed() {
Logger.logI("Back Button Disabled!");
}
@RequiresApi(api = Build.VERSION_CODES.M)
private void checkPermissions() {
List<String> permsArray = new ArrayList<>();
if (ContextCompat.checkSelfPermission(this, WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
Logger.logD("Requesting Write External Storage Permission");
permsArray.add(WRITE_EXTERNAL_STORAGE);
}
if (ContextCompat.checkSelfPermission(this, READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
Logger.logD("Requesting Read External Storage Permission");
permsArray.add(READ_EXTERNAL_STORAGE);
}
if (ContextCompat.checkSelfPermission(this, READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
Logger.logD("Requesting Read Phone State Permission");
permsArray.add(READ_PHONE_STATE);
}
if (permsArray.size() > 0) {
String[] perms = permsArray.toArray(new String[0]);
requestPermissions(perms, 200);
}
}
/*private void setupCloudWatch() {
String accessKey = "";
String secretKey = "";
BasicAWSCredentials basicAWSCredentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonCloudWatchLogsClient client = new AmazonCloudWatchLogsClient(basicAWSCredentials);
Regions regions = Regions.AP_SOUTHEAST_1; // Singapore
client.setRegion(Region.getRegion(regions));
String logGroupName = "TEST123";
CreateLogGroupRequest createLogGroupRequest = new CreateLogGroupRequest(logGroupName);
client.createLogGroup(new CreateLogGroupRequest(""));
}*/
}

2
app/src/main/java/com/cst/im30/activity/SettingActivity.java

@ -17,7 +17,6 @@ import androidx.core.content.ContextCompat;
import com.cst.im30.BuildConfig;
import com.cst.im30.EchoClientSetting;
import com.cst.im30.R;
import com.cst.im30.common.Constants;
import org.json.JSONException;
import org.json.JSONObject;
@ -87,7 +86,6 @@ public class SettingActivity extends AppCompatActivity {
// Create the client
echoClient = new EchoClientSetting(
this,
BuildConfig.ECHO_SERVER_URL + ":" + BuildConfig.ECHO_SERVER_PORT
);
}

56
app/src/main/java/com/cst/im30/utility/Logger.java

@ -1,7 +1,17 @@
package com.cst.im30.utility;
import android.os.Environment;
import android.util.Log;
import com.bugfender.sdk.Bugfender;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.regex.Pattern;
public class Logger {
@ -11,40 +21,86 @@ public class Logger {
StackTraceElement l = new Exception().getStackTrace()[1];
String title = getClassSimpleName(l.getClassName()) + "/" + l.getMethodName() + "():"+l.getLineNumber();
Log.d(TAG, title + " - " + message);
Bugfender.d("DEBUG", title + " - " + message);
}
public static void logI(String message) {
StackTraceElement l = new Exception().getStackTrace()[1];
String title = getClassSimpleName(l.getClassName()) + "/" + l.getMethodName() + "():"+l.getLineNumber();
Log.i(TAG, title + " - " + message);
Bugfender.i("INFO", title + " - " + message);
}
public static void logV(String message) {
StackTraceElement l = new Exception().getStackTrace()[1];
String title = getClassSimpleName(l.getClassName()) + "/" + l.getMethodName() + "():"+l.getLineNumber();
Log.v(TAG, title + " - " + message);
Bugfender.t("VERBOSE", title + " - " + message);
}
public static void logE(String message) {
StackTraceElement l = new Exception().getStackTrace()[1];
String title = getClassSimpleName(l.getClassName()) + "/" + l.getMethodName() + "():"+l.getLineNumber();
Log.e(TAG, title + " - " + message);
Bugfender.e("ERROR", title + " - " + message);
}
public static void logW(String message) {
StackTraceElement l = new Exception().getStackTrace()[1];
String title = getClassSimpleName(l.getClassName()) + "/" + l.getMethodName() + "():"+l.getLineNumber();
Log.w(TAG, title + " - " + message);
Bugfender.w("DEBUG", title + " - " + message);
}
public static void logWTF(String message) {
StackTraceElement l = new Exception().getStackTrace()[1];
String title = getClassSimpleName(l.getClassName()) + "/" + l.getMethodName() + "():"+l.getLineNumber();
Log.wtf(TAG, title + " - " + message);
Bugfender.f("WTF", title + " - " + message);
}
private static String getClassSimpleName(String className) {
String[] strs = className.split(Pattern.quote("."));
return strs[strs.length - 1];
}
public static String getTimeStamp() {
return new SimpleDateFormat("yyyyMMdd HH:mm:ss", Locale.ENGLISH).format(new Date());
}
// ---------------------------------------------------------------------------------------------
public static void recordICScan(String data) {
try {
String filename = new SimpleDateFormat("yyyyMMdd", Locale.ENGLISH).format(new Date());
File appDirectory = new File(Environment.getExternalStorageDirectory() + "/CST");
File logDirectory = new File(appDirectory + "/icLogs");
File logFile = new File(logDirectory, filename + ".txt");
// create app folder
if (!appDirectory.exists()) {
appDirectory.mkdir();
}
// create log folder
if (!logDirectory.exists()) {
logDirectory.mkdir();
}
String dataToWrite = "[" + getTimeStamp() + "] - " + data + "\n";
FileOutputStream out = new FileOutputStream(logFile, true);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(out);
outputStreamWriter.write(dataToWrite);
outputStreamWriter.close();
Logger.logD("Recorded to " + logFile.getName());
Bugfender.i("IC SCAN", dataToWrite);
}
catch (IOException e) {
Log.e("Exception", "File write failed: " + e.toString());
}
}
}

5
app/src/main/res/drawable/echo_ic_offline.xml

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#C60E0E"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M3,5v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2L5,3c-1.11,0 -2,0.9 -2,2zM15,9c0,1.66 -1.34,3 -3,3s-3,-1.34 -3,-3 1.34,-3 3,-3 3,1.34 3,3zM6,17c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1v1L6,18v-1z"/>
</vector>

5
app/src/main/res/drawable/echo_ic_online.xml

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#4DAE37"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M3,5v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2L5,3c-1.11,0 -2,0.9 -2,2zM15,9c0,1.66 -1.34,3 -3,3s-3,-1.34 -3,-3 1.34,-3 3,-3 3,1.34 3,3zM6,17c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1v1L6,18v-1z"/>
</vector>

5
app/src/main/res/drawable/echo_payment_offline.xml

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#C60E0E"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,4L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,6c0,-1.11 -0.89,-2 -2,-2zM20,18L4,18v-6h16v6zM20,8L4,8L4,6h16v2z"/>
</vector>

5
app/src/main/res/drawable/echo_payment_online.xml

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#4DAE37"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20,4L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,6c0,-1.11 -0.89,-2 -2,-2zM20,18L4,18v-6h16v6zM20,8L4,8L4,6h16v2z"/>
</vector>

7
app/src/main/res/drawable/layout_border.xml

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dip" android:color="#B1BCBE" />
<corners android:radius="10dip"/>
<padding android:left="0dip" android:top="0dip" android:right="0dip" android:bottom="0dip" />
</shape>

64
app/src/main/res/layout/activity_main.xml

@ -4,6 +4,70 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.MainActivity">
<LinearLayout
android:id="@+id/echoStatusLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:orientation="horizontal"
android:weightSum="2">
<FrameLayout
android:layout_margin="16dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/layout_border"
android:layout_weight="1">
<ImageView
android:id="@+id/paymentEchoStatusImageView"
android:layout_margin="32dp"
android:layout_width="match_parent"
android:adjustViewBounds="true"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:src="@drawable/echo_payment_offline"
android:contentDescription="Payment Connection Status"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/paymentEchoStatusTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/offline_caps"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/offline"
android:layout_marginBottom="8dp"
android:gravity="bottom|center_horizontal"/>
</FrameLayout>
<FrameLayout
android:layout_margin="16dp"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@drawable/layout_border"
android:layout_weight="1">
<ImageView
android:id="@+id/icEchoStatusImageView"
android:layout_margin="32dp"
android:layout_width="match_parent"
android:scaleType="fitXY"
android:adjustViewBounds="true"
android:layout_height="wrap_content"
android:src="@drawable/echo_ic_offline"
android:contentDescription="NRIC Connection Status"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/icEchoStatusTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/offline_caps"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/offline"
android:layout_marginBottom="8dp"
android:gravity="bottom|center_horizontal"/>
</FrameLayout>
</LinearLayout>
<com.daimajia.slider.library.SliderLayout
android:id="@+id/slider_layout_ma"

3
app/src/main/res/values/colors.xml

@ -20,4 +20,7 @@
<color name="green_2dcc70">#2DCC70</color>
<color name="grey_8e98a6">#8e98a6</color>
<color name="offline">#C60E0E</color>
<color name="online">#4DAE37</color>
</resources>

2
app/src/main/res/values/strings.xml

@ -75,5 +75,7 @@
<string name="btn_no_pay_again_status">Cancel</string>
<string name="success">Success</string>
<string name="fail">Fail</string>
<string name="offline_caps">OFFLINE</string>
<string name="online_caps">ONLINE</string>
</resources>

4
gradle.properties

@ -35,4 +35,6 @@ PAYMENT_CHANNEL_ID="payment#"
PAYMENT_EVENT_TYPE=".makepayment"
IC_CHANNEL_ID="verification#"
IC_EVENT_TYPE=".guestverification"
IC_EVENT_TYPE=".guestverification"
BUGFENDER_TOKEN="rocgWcZ0aLZH7s1XqK6PpV3WeyBVb0w0"
Loading…
Cancel
Save