Commit f76d4160 authored by Gandha Ryanto's avatar Gandha Ryanto

Initial commit

parents
*.iml
.gradle
/local.properties
/.idea/caches/build_file_checksums.ser
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
.DS_Store
/build
/captures
.externalNativeBuild
unik-update-balance-lib/.idea/
unik-update-balance-lib/build/
brizzi-debug/build/
PayLib-release-1.4.17/build/
mybanklibrary/.cxx/
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="RIGHT_MARGIN" value="215" />
<codeStyleSettings language="XML">
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>
\ No newline at end of file
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
</annotationProcessing>
<bytecodeTargetLevel target="11" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="PLATFORM" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/PayLib-release-1.4.43" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="http://mobile-repo.mdd.co.id:8081/artifactory/libs-release-local/" />
</remote-repository>
<remote-repository>
<option name="id" value="C:\Users\ITDEV\AppData\Local\Android\Sdk\extras\m2repository" />
<option name="name" value="C:\Users\ITDEV\AppData\Local\Android\Sdk\extras\m2repository" />
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/m2repository" />
</remote-repository>
<remote-repository>
<option name="id" value="C:\Users\ITDEV\AppData\Local\Android\Sdk\extras\android\m2repository" />
<option name="name" value="C:\Users\ITDEV\AppData\Local\Android\Sdk\extras\android\m2repository" />
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/android/m2repository" />
</remote-repository>
<remote-repository>
<option name="id" value="C:\Users\ITDEV\AppData\Local\Android\Sdk\extras\google\m2repository" />
<option name="name" value="C:\Users\ITDEV\AppData\Local\Android\Sdk\extras\google\m2repository" />
<option name="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/extras/google/m2repository" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="http://mobile-repo.mdd.co.id:8081/artifactory/android-libs/" />
</remote-repository>
<remote-repository>
<option name="id" value="$USER_HOME$/Android/Sdk/extras/google/m2repository" />
<option name="name" value="$USER_HOME$/Android/Sdk/extras/google/m2repository" />
<option name="url" value="file:$USER_HOME$/Android/Sdk/extras/google/m2repository" />
</remote-repository>
<remote-repository>
<option name="id" value="$USER_HOME$/Android/Sdk/extras/android/m2repository" />
<option name="name" value="$USER_HOME$/Android/Sdk/extras/android/m2repository" />
<option name="url" value="file:$USER_HOME$/Android/Sdk/extras/android/m2repository" />
</remote-repository>
<remote-repository>
<option name="id" value="$USER_HOME$/Android/Sdk/extras/m2repository" />
<option name="name" value="$USER_HOME$/Android/Sdk/extras/m2repository" />
<option name="url" value="file:$USER_HOME$/Android/Sdk/extras/m2repository" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
<option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="15">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
<item index="6" class="java.lang.String" itemvalue="android.annotation.Nullable" />
<item index="7" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
<item index="11" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
<item index="12" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
<item index="13" class="java.lang.String" itemvalue="io.reactivex.annotations.Nullable" />
<item index="14" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="14">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
<item index="5" class="java.lang.String" itemvalue="android.annotation.NonNull" />
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
<item index="11" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
<item index="12" class="java.lang.String" itemvalue="io.reactivex.annotations.NonNull" />
<item index="13" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
configurations.maybeCreate("default")
artifacts.add("default", file('PayLib-release-1.4.43.aar'))
\ No newline at end of file
apply plugin: 'com.android.library'
apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 15
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'io.reactivex.rxjava2:rxjava:2.2.19'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation 'androidx.appcompat:appcompat:1.2.0'
// implementation project(path: ':unik-update-balance-lib')
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
compileOnly 'org.projectlombok:lombok:1.18.12'
annotationProcessor 'org.projectlombok:lombok:1.18.12'
}
//region publish to repo
def libraryGroupId = 'com.mdd.payment'
def libraryArtifactId = 'aar-deviceid-release'
def libraryVersion = '2.0.7'
publishing {
publications {
aar(MavenPublication) {
groupId libraryGroupId
version libraryVersion
artifactId libraryArtifactId
artifact("$buildDir/outputs/aar/${artifactId}.aar")
pom.withXml {
def dependenciesNode = asNode().appendNode('dependencies')
//Iterate over the compile dependencies (we don't want the test ones), adding a <dependency> node for each
configurations.implementation.allDependencies.each {
def dependencyNode = dependenciesNode.appendNode('dependency')
dependencyNode.appendNode('groupId', it.group)
dependencyNode.appendNode('artifactId', it.name)
dependencyNode.appendNode('version', it.version)
}
}
}
}
}
//task copyLibs(type: Copy) {
// from configurations.customConfig
// into 'libs'
//}
artifactory {
contextUrl = artifactory_url
publish {
repository {
repoKey = "android-libs"
username = "admin"
password = "Mddcoid*123#"
}
defaults {
publications('aar')
publishArtifacts = true
properties = ['qa.level': 'basic', 'q.os': 'android', 'dev.team': 'core']
publishPom = true
}
}
}
//enderegion
\ No newline at end of file
aux
Aux
aUx
AUx
auX
AuX
aUX
AUX
AUX
con
Con
cOn
COn
coN
CoN
cON
CON
CON
nul
Nul
nUl
NUl
nuL
NuL
nUL
NUL
NUL
prn
Prn
pRn
PRn
prN
PrN
pRN
PRN
PRN
com1
Com1
cOm1
COm1
coM1
CoM1
cOM1
COM1
COM1
com2
Com2
cOm2
COm2
coM2
CoM2
cOM2
COM2
COM2
com3
Com3
cOm3
COm3
coM3
CoM3
cOM3
COM3
COM3
com4
Com4
cOm4
COm4
coM4
CoM4
cOM4
COM4
COM4
com5
Com5
cOm5
COm5
coM5
CoM5
cOM5
COM5
COM5
com6
Com6
cOm6
COm6
coM6
CoM6
cOM6
COM6
COM6
com7
Com7
cOm7
COm7
coM7
CoM7
cOM7
COM7
COM7
com8
Com8
cOm8
COm8
coM8
CoM8
cOM8
COM8
COM8
com9
Com9
cOm9
COm9
coM9
CoM9
cOM9
COM9
COM9
lpt1
Lpt1
lPt1
LPt1
lpT1
LpT1
lPT1
LPT1
LPT1
lpt2
Lpt2
lPt2
LPt2
lpT2
LpT2
lPT2
LPT2
LPT2
lpt3
Lpt3
lPt3
LPt3
lpT3
LpT3
lPT3
LPT3
LPT3
lpt4
Lpt4
lPt4
LPt4
lpT4
LpT4
lPT4
LPT4
LPT4
lpt5
Lpt5
lPt5
LPt5
lpT5
LpT5
lPT5
LPT5
LPT5
lpt6
Lpt6
lPt6
LPt6
lpT6
LpT6
lPT6
LPT6
LPT6
lpt7
Lpt7
lPt7
LPt7
lpT7
LpT7
lPT7
LPT7
LPT7
lpt8
Lpt8
lPt8
LPt8
lpT8
LpT8
lPT8
LPT8
LPT8
lpt9
Lpt9
lPt9
LPt9
lpT9
LpT9
lPT9
LPT9
LPT9
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-obfuscationdictionary dictionary.txt
-classobfuscationdictionary dictionary.txt
-packageobfuscationdictionary dictionary.txt
-optimizationpasses 5
-keepattributes InnerClasses
# Retrofit 2.X
## https://square.github.io/retrofit/ ##
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepclasseswithmembers class * {
@retrofit2.http.* <methods>;
}
# RxJava 0.21
-keep class rx.schedulers.Schedulers {
public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
public <methods>;
}
-keep class rx.schedulers.TestScheduler {
public <methods>;
}
-keep class rx.schedulers.Schedulers {
public static ** test();
}
-keep class com.mdd.aar.deviceid.RegisterCallback
-keepclassmembers class com.mdd.aar.deviceid.RegisterCallback {
public <methods>;
}
-keep class com.mdd.aar.deviceid.UnlockAarCallback
-keepclassmembers class com.mdd.aar.deviceid.UnlockAarCallback {
public <methods>;
}
-keep enum com.mdd.aar.deviceid.DeviceEnvironment
-keepclassmembers enum com.mdd.aar.deviceid.DeviceEnvironment{
public <fields>;
}
-keep class com.mdd.aar.deviceid.AarDeviceId
-keepclassmembers class com.mdd.aar.deviceid.AarDeviceId {
public <methods>;
}
-keep class retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
-keepclassmembers class com.mdd.aar.deviceid.AarDeviceId {
public <methods>;
}
##---------------Begin: proguard configuration for Gson ----------
# Gson uses generic type information stored in a class file when working with fields. Proguard
# removes such information by default, so configure it to keep all of it.
-keepattributes Signature
# For using GSON @Expose annotation
-keepattributes *Annotation*
# Gson specific classes
-dontwarn sun.misc.**
#-keep class com.google.gson.stream.** { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.examples.android.model.** { <fields>; }
# Prevent proguard from stripping interface information from TypeAdapter, TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * extends com.google.gson.TypeAdapter
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
# Prevent R8 from leaving Data object members always null
-keepclassmembers,allowobfuscation class * {
@com.google.gson.annotations.SerializedName <fields>;
}
##---------------End: proguard configuration for Gson ----------
\ No newline at end of file
package com.mdd.aar.deviceid;
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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.mdd.aar.deviceid.test", appContext.getPackageName());
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mdd.aar.deviceid" />
package com.mdd.aar.deviceid;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
import android.preference.PreferenceManager;
import android.util.Log;
import com.mdd.aar.deviceid.exceptions.DeviceNotRegisteredException;
import com.mdd.aar.deviceid.http.Api;
import com.mdd.aar.deviceid.http.responses.RegisterDeviceResponse;
import com.mdd.aar.deviceid.http.responses.UnlockAarResponse;
import java.io.File;
import java.io.IOException;
/**
* Created by Husnan on 17/05/2020
*/
public class
AarDeviceId {
private final Context context;
private String TAG = "AarDeviceId";
public AarDeviceId(Context context) {
this.context = context;
}
public String getDeviceId() throws DeviceNotRegisteredException {
String deviceId = getSharedPreferences().getString("com.mdd.aar.deviceId", null);
if (deviceId == null)
throw new DeviceNotRegisteredException();
return deviceId;
}
public String unlockAar(String accessToken, DeviceEnvironment deviceEnvironment, String deviceId, String debugToken, String bypassMode) {
Api api = new Api(accessToken, deviceEnvironment);
UnlockAarResponse unlockAarResponse = api.unlockAar(deviceId, debugToken, bypassMode);
if (unlockAarResponse.isOk()) {
return unlockAarResponse.getData().getDebugResponse();
} else {
return null;
}
}
public String unlockAarV3(String accessToken, DeviceEnvironment deviceEnvironment, String deviceId, String debugToken, String bypassMode) {
Api api = new Api(accessToken, deviceEnvironment);
UnlockAarResponse unlockAarResponse = api.unlockAarV3(accessToken, deviceId, debugToken, bypassMode);
if (unlockAarResponse.isOk()) {
return unlockAarResponse.getData().getDebugResponse();
} else {
return null;
}
}
public UnlockAarResponse unlockLibrary(String accessToken, DeviceEnvironment deviceEnvironment, String deviceId, String debugToken, String bypassMode) {
Api api = new Api(accessToken, deviceEnvironment);
UnlockAarResponse unlockAarResponse = api.unlockAarV3(accessToken, deviceId, debugToken, bypassMode);
if (unlockAarResponse.isOk()) {
return unlockAarResponse;
} else {
return null;
}
}
private SharedPreferences getSharedPreferences() {
return PreferenceManager.getDefaultSharedPreferences(context);
}
public void init(String accessToken, DeviceEnvironment deviceEnvironment) {
String deviceId = getDeviceIdToSharedPreferences();
if (deviceId != null) {
storeDeviceIdToSharedPreferences(deviceId);
} else {
Api api = new Api(accessToken, deviceEnvironment);
RegisterDeviceResponse registerDeviceResponse = api.registerDevice();
if (registerDeviceResponse.isOk()) {
deviceId = registerDeviceResponse.getData().getDeviceId();
Log.d(TAG, "onSuccess: " + deviceId);
// createHiddenFile(deviceId);
storeDeviceIdToSharedPreferences(deviceId);
} else {
Log.d(TAG, "onFailed: " + registerDeviceResponse.getResponse().getMessage());
}
}
}
private void createHiddenFile(String generatedDeviceId) {
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard, "/com.mdd.aar/");
File file1 = new File(file, "." + generatedDeviceId);
try {
file1.createNewFile();
} catch (IOException e) {
Log.e(TAG, "createHiddenFile: " + e.getMessage());
}
}
private String getDeviceIdFromHiddenFile() {
String deviceId = null;
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard, "/com.mdd.aar/");
if (file.isDirectory()) {
String[] list = file.list();
for (String l : list) {
if (l.charAt(0) == '.' && !l.equalsIgnoreCase(".nomedia")) {
deviceId = l.substring(1);
break;
}
}
} else {
boolean mkdirs = file.mkdirs();
if (!mkdirs) {
Log.e(TAG, "getDeviceIdFromHiddenFile: failed to create " + file.getAbsolutePath());
} else {
Log.e(TAG, "getDeviceIdFromHiddenFile: success to create " + file.getAbsolutePath());
}
createNoMediaFile(file);
}
return deviceId;
}
private void createNoMediaFile(File file) {
File file1 = new File(file, ".nomedia");
try {
boolean newFile = file1.createNewFile();
if (!newFile) {
Log.e(TAG, "createNoMediaFile: failed to create " + file.getAbsolutePath());
} else {
Log.e(TAG, "createNoMediaFile: success to create " + file.getAbsolutePath());
}
} catch (IOException e) {
Log.e(TAG, "createNoMediaFile: " + e.getMessage());
}
}
private void storeDeviceIdToSharedPreferences(String generatedDeviceId) {
SharedPreferences.Editor prefEditor = getSharedPreferences().edit();
prefEditor.putString("com.mdd.aar.deviceId", generatedDeviceId);
prefEditor.apply();
}
private String getDeviceIdToSharedPreferences() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String data = prefs.getString("com.mdd.aar.deviceId", (String) null);
return data;
}
}
package com.mdd.aar.deviceid;
/**
* Created by Husnan on 17/05/2020
*/
public enum DeviceEnvironment {
DEVELOPMENT,
STAGING,
PROD,
UNLOCK
}
package com.mdd.aar.deviceid.exceptions;
/**
* Created by Husnan on 17/05/2020
*/
public class DeviceNotRegisteredException extends Exception {
public DeviceNotRegisteredException() {
super("This device not registered yet, please init your device..");
}
}
package com.mdd.aar.deviceid.http;
import android.os.Build;
import com.mdd.aar.deviceid.DeviceEnvironment;
import com.mdd.aar.deviceid.http.requests.AuthLoginRequest;
import com.mdd.aar.deviceid.http.requests.RefreshTokenRequest;
import com.mdd.aar.deviceid.http.requests.RegisterDeviceRequest;
import com.mdd.aar.deviceid.http.requests.UnlockAarRequest;
import com.mdd.aar.deviceid.http.responses.AuthLoginResponse;
import com.mdd.aar.deviceid.http.responses.RegisterDeviceResponse;
import com.mdd.aar.deviceid.http.responses.UnlockAarResponse;
import com.mdd.aar.deviceid.services.DeviceService;
import java.util.concurrent.TimeUnit;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
/**
* Created by Husnan on 17/05/2020
*/
public class Api {
private final DeviceEnvironment deviceEnvironment;
private final String token;
public Api(String accessToken, DeviceEnvironment deviceEnvironment) {
this.deviceEnvironment = deviceEnvironment;
token = accessToken;
}
public RegisterDeviceResponse registerDevice() {
DeviceService deviceService = getClient().create(DeviceService.class);
RegisterDeviceRequest request = new RegisterDeviceRequest();
request.setManufacturer(Build.MANUFACTURER);
request.setBrand(Build.BRAND);
request.setDataSource("AAR");
request.setModel(Build.MODEL);
request.setPhoneType(Build.DEVICE);
return deviceService.register("Bearer: " + token, request)
.observeOn(Schedulers.io())
.subscribeOn(Schedulers.io())
.blockingGet();
}
public Single<AuthLoginResponse> loginMerchant(AuthLoginRequest authLoginRequest) {
// MdsEndpoint mdsEndpoint = getApiInterfaces();
// return mdsEndpoint.authLogin(authLoginRequest);
DeviceService deviceService = getClient().create(DeviceService.class);
return deviceService.authLogin(authLoginRequest);
}
public Single<AuthLoginResponse> refreshToken(String token, RefreshTokenRequest refreshTokenRequest) {
// MdsEndpoint mdsEndpoint = getApiInterfaces();
// return mdsEndpoint.refreshToken(makeToken(token), refreshTokenRequest);
DeviceService deviceService = getClient().create(DeviceService.class);
return deviceService.refreshToken(token, refreshTokenRequest);
}
public UnlockAarResponse unlockAar(String deviceId, String debugToken, String bypassMode) {
DeviceService deviceService = getClient().create(DeviceService.class);
UnlockAarRequest request = new UnlockAarRequest();
request.setDeviceId(deviceId);
request.setDebugToken(debugToken);
request.setBypassMode(bypassMode);
return deviceService.unlockAar("Bearer: " + token, request)
.observeOn(Schedulers.io())
.subscribeOn(Schedulers.io())
.blockingGet();
}
public UnlockAarResponse unlockAarV3(String accessToken, String deviceId, String debugToken, String bypassMode) {
DeviceService deviceService = getClient().create(DeviceService.class);
UnlockAarRequest request = new UnlockAarRequest();
request.setDeviceId(deviceId);
request.setDebugToken(debugToken);
request.setBypassMode(bypassMode);
return deviceService.unlockAarV3(accessToken, request)
.observeOn(Schedulers.io())
.subscribeOn(Schedulers.io())
.blockingGet();
}
private Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(100, TimeUnit.SECONDS)
.writeTimeout(100, TimeUnit.SECONDS)
.readTimeout(110, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(getBaseUrl())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(client)
.build();
return retrofit;
}
private String getBaseUrl() {
switch (deviceEnvironment) {
case PROD:
return "https://api-prod.multidaya.id";
case DEVELOPMENT:
return "https://api-dev.mdd.co.id";
case STAGING:
return "https://api-staging.multidaya.id";
case UNLOCK:
return "https://apiv2.mdd.co.id:30309";
}
return "";
}
}
package com.mdd.aar.deviceid.http.requests;
import com.google.gson.Gson;
import lombok.Getter;
import lombok.Setter;
@Getter
public class AuthLoginRequest {
private String username, password;
public AuthLoginRequest(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}
package com.mdd.aar.deviceid.http.requests;
import com.google.gson.Gson;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class RefreshTokenRequest {
String refresh_token;
public RefreshTokenRequest(String refresh_token) {
this.refresh_token = refresh_token;
}
public RefreshTokenRequest() {
}
@Override
public String toString() {
return new Gson().toJson(this);
}
}
package com.mdd.aar.deviceid.http.requests;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 17/05/2020
*/
@Getter
@Setter
public class RegisterDeviceRequest {
@SerializedName("model")
String model;
@SerializedName("manufacturer")
String manufacturer;
@SerializedName("brand")
String brand;
@SerializedName("phone_type")
String phoneType;
@SerializedName("data_source")
String dataSource;
}
package com.mdd.aar.deviceid.http.requests;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 17/05/2020
*/
@Getter
@Setter
public class UnlockAarRequest {
@SerializedName("device_id")
String deviceId;
@SerializedName("debug_token")
String debugToken;
@SerializedName("bypass_mode")
String bypassMode;
}
package com.mdd.aar.deviceid.http.responses;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 17/05/2020
*/
@Getter
@Setter
public class ApiResponse {
@SerializedName("code")
int code;
@SerializedName("message")
String message;
@SerializedName("latency")
double latency;
@SerializedName("host")
String host;
}
package com.mdd.aar.deviceid.http.responses;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 24/04/2020
*/
@Getter
@Setter
public class AuthData {
@SerializedName("name")
String name;
@SerializedName("username")
String username;
@SerializedName("authLevel")
String authLevel;
@SerializedName("expired_at")
String expiredAt;
@SerializedName("access_token")
String accessToken;
@SerializedName("refresh_token")
String refreshToken;
}
package com.mdd.aar.deviceid.http.responses;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class AuthLoginResponse {
@SerializedName("response")
ApiResponse response;
@SerializedName("data")
AuthData data;
}
package com.mdd.aar.deviceid.http.responses;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 17/05/2020
*/
@Getter
@Setter
public class RegisterDeviceData {
@SerializedName("device_id")
String deviceId;
}
package com.mdd.aar.deviceid.http.responses;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 17/05/2020
*/
@Getter
@Setter
public class RegisterDeviceResponse {
@SerializedName("response")
ApiResponse response;
@SerializedName("data")
RegisterDeviceData data;
public boolean isOk() {
return getResponse().getCode() == 200;
}
}
package com.mdd.aar.deviceid.http.responses;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 17/05/2020
*/
@Getter
@Setter
public class UnlockAarData {
@SerializedName("debug_response")
String debugResponse;
@SerializedName("created_at")
String createdAt;
@SerializedName("expired_at")
String expiredAt;
@SerializedName("state")
String state;
}
package com.mdd.aar.deviceid.http.responses;
import com.google.gson.annotations.SerializedName;
import lombok.Getter;
import lombok.Setter;
/**
* Created by Husnan on 17/05/2020
*/
@Setter
@Getter
public class UnlockAarResponse {
@SerializedName("response")
ApiResponse response;
@SerializedName("data")
UnlockAarData data;
public boolean isOk() {
return getResponse().getCode() == 200;
}
}
package com.mdd.aar.deviceid.services;
import com.mdd.aar.deviceid.http.requests.AuthLoginRequest;
import com.mdd.aar.deviceid.http.requests.RefreshTokenRequest;
import com.mdd.aar.deviceid.http.requests.RegisterDeviceRequest;
import com.mdd.aar.deviceid.http.requests.UnlockAarRequest;
import com.mdd.aar.deviceid.http.responses.AuthLoginResponse;
import com.mdd.aar.deviceid.http.responses.RegisterDeviceResponse;
import com.mdd.aar.deviceid.http.responses.UnlockAarData;
import com.mdd.aar.deviceid.http.responses.UnlockAarResponse;
import io.reactivex.Single;
import retrofit2.http.Body;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Path;
/**
* Created by Husnan on 17/05/2020
*/
public interface DeviceService {
@Headers({
"Accept: application/json",
"Content-Type: application/json"
})
@POST("/auth-service/v1/login")
Single<AuthLoginResponse> authLogin(@Body AuthLoginRequest authLoginRequest);
@Headers({
"Accept: application/json",
"Content-Type: application/json"
})
@POST("/auth-service/v1/refresh-token")
Single<AuthLoginResponse> refreshToken(@Header("Authorization") String token, @Body RefreshTokenRequest refreshTokenRequest);
@Headers({
"Accept: application/json",
"Content-Type: application/json"
})
@POST("/device-service/register")
Single<RegisterDeviceResponse> register(@Header("Authorization") String accessToken, @Body RegisterDeviceRequest request);
@Headers({
"Accept: application/json",
"Content-Type: application/json"
})
@POST("/aar-service/aar/unlock")
Single<UnlockAarResponse> unlockAar(@Header("Authorization") String accessToken, @Body UnlockAarRequest request);
@Headers({
"Accept: application/json",
"Content-Type: application/json"
})
@POST("/aar-service/aar/unlock/{token}")
Single<UnlockAarResponse> unlockAarV3(@Path("token") String token, @Body UnlockAarRequest request);
}
<resources>
<string name="app_name">Aar DeviceId</string>
</resources>
package com.mdd.aar.deviceid;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
\ No newline at end of file
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
defaultConfig {
applicationId "com.medicom.dudikov.mypaxsimulator"
minSdkVersion 22
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
}
}
}
compileOptions {
encoding "UTF-8"
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
}
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
ndkVersion = '21.3.6528147'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.1'
// Dependencies for working with Architecture components
// You'll probably have to update the version numbers in guild.gradle (Project)
implementation "android.arch.persistence.room:runtime:$rootProject.roomVersion"
annotationProcessor "android.arch.persistence.room:compiler:$rootProject.roomVersion"
androidTestImplementation "android.arch.persistence.room:testing:$rootProject.roomVersion"
implementation "android.arch.lifecycle:extensions:$rootProject.archLifecycleVersion"
//annotationProcessor "android.arch.lifecycle:compiler:$rootProject.archLifecycleVersion"
androidTestImplementation "android.arch.core:core-testing:$rootProject.archLifecycleVersion"
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.1', {
exclude group: 'com.android.support', module: 'support-annotations'
})
implementation 'com.sunmi:printerlibrary:1.0.9'
implementation 'com.google.zxing:core:3.3.2'
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
//http
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation "androidx.preference:preference:1.1.1"
implementation(group: 'com.mdd.payment', name: 'mybanklibrary-release', version: '3.7.0', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'organicdrv-release', version: '2.1.2', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'paylib-release', version: '1.0.1', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'aar-deviceid-release', version: '2.0.5', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'nativecripto-release', version: '2.0.1', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'sunmilibrary-release', version: '2.2.1', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'isodeplibrary-release', version: '2.1.2', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'z91library-release', version: '2.1.2', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'verifonelibrary-release', version: '2.1.2', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'paxlibrary-release', version: '2.1.3', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'ingenicolibrary-release', version: '1.0.3', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'wepoylibrary-release', version: '2.2.6', ext: 'aar')
implementation(group: 'com.mdd.payment', name: 'd130library-release', version: '1.0.0', ext: 'aar')
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "3b109e1a65b0e38d75f0564ab164d6bf",
"entities": [
{
"tableName": "parameters_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`c_parameters_desc` TEXT NOT NULL, `c_parameters_value` TEXT NOT NULL, PRIMARY KEY(`c_parameters_desc`))",
"fields": [
{
"fieldPath": "mDescription",
"columnName": "c_parameters_desc",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "mValue",
"columnName": "c_parameters_value",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"c_parameters_desc"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"3b109e1a65b0e38d75f0564ab164d6bf\")"
]
}
}
\ No newline at end of file
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "3b109e1a65b0e38d75f0564ab164d6bf",
"entities": [
{
"tableName": "parameters_table",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`c_parameters_desc` TEXT NOT NULL, `c_parameters_value` TEXT NOT NULL, PRIMARY KEY(`c_parameters_desc`))",
"fields": [
{
"fieldPath": "mDescription",
"columnName": "c_parameters_desc",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "mValue",
"columnName": "c_parameters_value",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"c_parameters_desc"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
}
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"3b109e1a65b0e38d75f0564ab164d6bf\")"
]
}
}
\ No newline at end of file
package com.medicom.dudikov.mypaxsimulator;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.medicom.dudikov.mypaxsimulator", appContext.getPackageName());
}
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.medicom.dudikov.mypaxsimulator">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".MyApp"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme.NoActionBar"
android:usesCleartextTraffic="true">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SettingsActivity"
android:theme="@style/MyMaterialTheme" />
</application>
</manifest>
\ No newline at end of file
package com.medicom.dudikov.mypaxsimulator.Api;
public class ApiH2HConfig {
String mid;
String tid;
String token;
public ApiH2HConfig(String mid, String tid, String token) {
this.mid = mid;
this.tid = tid;
this.token = token;
}
public String getMid() {
return mid;
}
public String getTid() {
return tid;
}
public String getToken() {
return token;
}
}
\ No newline at end of file
package com.medicom.dudikov.mypaxsimulator.Api;
import android.util.Log;
import com.medicom.dudikov.mypaxsimulator.http.BaseApiServices;
import com.medicom.dudikov.mypaxsimulator.http.RetrofitClient;
import com.medicom.dudikov.mypaxsimulator.http.request.RequestAccessToken;
import com.medicom.dudikov.mypaxsimulator.http.request.TopupMandiriConfirmJson;
import com.medicom.dudikov.mypaxsimulator.http.request.TopupMandiriPendingJson;
import com.medicom.dudikov.mypaxsimulator.http.request.TopupMandiriReversalJson;
import com.medicom.dudikov.mypaxsimulator.http.request.TopupMandiriUpdateJson;
import com.medicom.dudikov.mypaxsimulator.http.response.ResponseToken;
import java.io.IOException;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ApiUtils {
// public static final String BASE_URL_API = "http://192.168.2.194/";
public static final String BASE_URL_API_DEV = "http://apidev.mdd.co.id:28194/";
private static final String BASE_URL_API = "https://apiv2.mdd.co.id:30307/";
private static final String BASE_URL_API_STAG = "https://apiv2.mdd.co.id:30307/";
private static final String BASE_URL_API_TOKEN = "http://apidev.mdd.co.id:28194/internal/topup-bri/";
private static final String TAG = "ApiUtils";
private static BaseApiServices getAPIService() {
return RetrofitClient.getClient(BASE_URL_API_STAG).create(BaseApiServices.class);
}
private static BaseApiServices getAPIService(String baseUrl) {
return RetrofitClient.getClient(baseUrl).create(BaseApiServices.class);
}
private static BaseApiServices getAPIDevService() {
return RetrofitClient.getClient(BASE_URL_API_DEV).create(BaseApiServices.class);
}
public static String topupMandiriPending(TopupMandiriPendingJson topupMandiriPendingJson) throws IOException {
BaseApiServices mApiService = getAPIService();
Response response = mApiService.topupMandiriPending(topupMandiriPendingJson).execute();
Boolean isSuccess = response.isSuccessful();
String resp = "";
if (isSuccess) {
assert response.body() != null;
resp = response.body().toString();
} else {
ResponseBody errorBody = response.errorBody();
if (errorBody != null) {
resp = errorBody.string();
}
}
return resp;
}
public static String topupMandiriUpdateSynchronous(TopupMandiriUpdateJson topupMandiriUpdateJson) throws IOException {
BaseApiServices mApiService = getAPIService();
Response response = mApiService.topupMandiriUpdate(topupMandiriUpdateJson).execute();
Boolean isSuccess = response.isSuccessful();
String resp = "";
if (isSuccess) {
assert response.body() != null;
resp = response.body().toString();
} else {
ResponseBody errorBody = response.errorBody();
if (errorBody != null) {
resp = errorBody.string();
}
}
return resp;
}
public static String getTopupMandiriUpdateConfirmResponseBody(TopupMandiriConfirmJson topupMandiriConfirmJson) {
BaseApiServices mApiService = getAPIService();
try {
return mApiService.topupMandiriupdateConfirm(topupMandiriConfirmJson).execute().body();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public static String getTopupMandiriReversalResponseBody(TopupMandiriReversalJson topupMandiriReversalJson) {
BaseApiServices mApiService = getAPIService();
try {
return mApiService.topupMandiriReversal(topupMandiriReversalJson).execute().body();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public static void hitApiTokenMDD(BaseApiServices.CallbackToken callback){
BaseApiServices mApiService = getAPIService(BASE_URL_API_TOKEN);
RequestAccessToken request = new RequestAccessToken();
request.setToken("165eea86947a4e9483d1902f93495fc6");
request.setMid("1234567abc");
try {
mApiService.getAccesToken(request).enqueue(new Callback<ResponseToken>() {
@Override
public void onResponse(Call<ResponseToken> call, Response<ResponseToken> response) {
callback.onSuccess(response.body());
}
@Override
public void onFailure(Call<ResponseToken> call, Throwable t) {
Log.e("responseFailure", t.getMessage());
}
});
}catch(Exception e){
e.printStackTrace();
}
}
}
package com.medicom.dudikov.mypaxsimulator.Api;
public interface InitConfig {
ApiH2HConfig getH2HConfig();
}
package com.medicom.dudikov.mypaxsimulator.Database;
import androidx.room.TypeConverter;
import java.sql.Date;
public class Converters {
@TypeConverter
public static Date fromTimestamp(Long value) {
return value == null ? null : new Date(value);
}
@TypeConverter
public static Long dateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
\ No newline at end of file
package com.medicom.dudikov.mypaxsimulator.Database;
import android.content.Context;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.room.Database;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;
import androidx.sqlite.db.SupportSQLiteDatabase;
@Database(entities = {ParametersTable.class}, version = 1)
@TypeConverters({Converters.class})
public abstract class LocalDatabase extends RoomDatabase {
public abstract ParametersTableDAO ParametersDao();
// marking the instance as volatile to ensure atomic access to the variable
private static volatile LocalDatabase INSTANCE;
static LocalDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (LocalDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
LocalDatabase.class, "edc_database")
// Wipes and rebuilds instead of migrating if no Migration object.
// Migration is not part of this codelab.
.fallbackToDestructiveMigration()
.addCallback(sRoomDatabaseCallback)
.build();
}
}
}
return INSTANCE;
}
/**
* Override the onOpen method to populate the database.
* For this sample, we clear the database every time it is created or opened.
* <p>
* If you want to populate the database only when the database is created for the 1st time,
* override RoomDatabase.Callback()#onCreate
*/
private static final RoomDatabase.Callback sRoomDatabaseCallback = new RoomDatabase.Callback() {
@Override
public void onOpen(@NonNull SupportSQLiteDatabase db) {
super.onOpen(db);
}
@Override
public void onCreate(@NonNull SupportSQLiteDatabase db) {
// new PopulateDbAsync(INSTANCE).execute();
}
};
/**
* Populate the database in the background.
* If you want to start with more words, just add them.
*/
private static class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
private final ParametersTableDAO mParameterDao;
PopulateDbAsync(LocalDatabase db) {
mParameterDao = db.ParametersDao();
}
@Override
protected Void doInBackground(final Void... params) {
// Start the app with a clean database every time.
// Not needed if you only populate on creation.
//mDao.deleteAll();
//ParametersTable parameters = new ParametersTable("trans_number", "1");
//mDao.insert(parameters);
//parameters = new ParametersTable("World");
//mDao.insert(parameters);
return null;
}
}
}
package com.medicom.dudikov.mypaxsimulator.Database;
import android.content.Context;
import android.os.AsyncTask;
import androidx.lifecycle.LiveData;
import java.util.List;
public class ParametersRepository {
private final ParametersTableDAO mParametersDao;
private final LiveData<List<ParametersTable>> mAllParameters;
public ParametersRepository(Context context) {
LocalDatabase db = LocalDatabase.getDatabase(context);
mParametersDao = db.ParametersDao();
mAllParameters = mParametersDao.getAlphabetizedParameters();
}
// Room executes all queries on a separate thread.
// Observed LiveData will notify the observer when the data has changed.
public LiveData<List<ParametersTable>> getAllParameters() {
return mAllParameters;
}
public String findValue(String Desc, String defaultValue) {
String res = mParametersDao.findValue(Desc);
if (res == null) {
ParametersTable parValue = new ParametersTable(Desc, defaultValue);
mParametersDao.insert(parValue);
res = defaultValue;
}
return res;
}
// You must call this on a non-UI thread or your app will crash.
// Like this, Room ensures that you're not doing any long running operations on the main
// thread, blocking the UI.
public void insert(ParametersTable parameters) {
new insertAsyncTask(mParametersDao).execute(parameters);
}
private static class insertAsyncTask extends AsyncTask<ParametersTable, Void, Void> {
private final ParametersTableDAO mAsyncTaskDao;
insertAsyncTask(ParametersTableDAO dao) {
mAsyncTaskDao = dao;
}
@Override
protected Void doInBackground(final ParametersTable... params) {
mAsyncTaskDao.insert(params[0]);
return null;
}
}
}
package com.medicom.dudikov.mypaxsimulator.Database;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
@Entity(tableName = "parameters_table")
public class ParametersTable {
@NonNull
@PrimaryKey
@ColumnInfo(name = "c_parameters_desc")
private final String mDescription;
@NonNull
@ColumnInfo(name = "c_parameters_value")
private final String mValue;
public ParametersTable(@NonNull String mDescription, @NonNull String mValue) {
this.mDescription = mDescription;
this.mValue = mValue;
}
@NonNull
public String getDescription() {
return this.mDescription;
}
@NonNull
public String getValue() {
return this.mValue;
}
}
package com.medicom.dudikov.mypaxsimulator.Database;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import java.util.List;
@Dao
public interface ParametersTableDAO {
@Query("SELECT * from PARAMETERS_TABLE ORDER BY c_parameters_desc ASC")
LiveData<List<ParametersTable>> getAlphabetizedParameters();
@Insert(onConflict = OnConflictStrategy.REPLACE)
void insert(ParametersTable Parameters);
@Update
void update(ParametersTable Parameters);
@Query("SELECT c_parameters_value from PARAMETERS_TABLE where c_parameters_desc=:mDescription")
String findValue(String mDescription);
@Query("DELETE FROM PARAMETERS_TABLE")
void deleteAll();
}
package com.medicom.dudikov.mypaxsimulator;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersRepository;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersTable;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link FragmentBankBCA.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link FragmentBankBCA#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentBankBCA extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
private EditText mMid;
private EditText mTid;
private EditText mMinBalance;
public FragmentBankBCA() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FragmentBankBCA.
*/
// TODO: Rename and change types and number of parameters
public static FragmentBankBCA newInstance(String param1, String param2) {
FragmentBankBCA fragment = new FragmentBankBCA();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMid = view.findViewById(R.id.edMID);
mTid = view.findViewById(R.id.edTID);
mMinBalance = view.findViewById(R.id.edMinBalance);
mMid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bca_mid", mMid.getText().toString()));
}
}
});
mTid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bca_tid", mTid.getText().toString()));
}
}
});
mMinBalance.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bca_min_balance", mMinBalance.getText().toString()));
}
}
});
AsyncTask.execute(new Runnable() {
@Override
public void run() {
ParametersRepository Parameters = new ParametersRepository(getActivity());
final String mid = Parameters.findValue("bca_mid", "000885000015999");
final String tid = Parameters.findValue("bca_tid", "ABC12345");
final String minBalance = Parameters.findValue("bca_min_balance", "0");
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mMid.setText(mid);
mTid.setText(tid);
mMinBalance.setText(minBalance);
}
});
}
});
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bank_bca, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
package com.medicom.dudikov.mypaxsimulator;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersRepository;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersTable;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link FragmentBankBRI.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link FragmentBankBRI#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentBankBRI extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public FragmentBankBRI() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FragmentBankBRI.
*/
// TODO: Rename and change types and number of parameters
public static FragmentBankBRI newInstance(String param1, String param2) {
FragmentBankBRI fragment = new FragmentBankBRI();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bank_bri, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final EditText mMid = view.findViewById(R.id.edMid);
final EditText mTid = view.findViewById(R.id.edTid);
final EditText mProcode = view.findViewById(R.id.edProcode);
final EditText mBatch = view.findViewById(R.id.edBatch);
final EditText mReference = view.findViewById(R.id.edReference);
mMid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bri_mid", mMid.getText().toString()));
}
}
});
mTid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bri_tid", mTid.getText().toString()));
}
}
});
mProcode.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bri_procode", mProcode.getText().toString()));
}
}
});
mBatch.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bri_batch", mBatch.getText().toString()));
}
}
});
mReference.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("bri_reference", mReference.getText().toString()));
}
}
});
AsyncTask.execute(new Runnable() {
@Override
public void run() {
ParametersRepository Parameters = new ParametersRepository(getActivity());
final String mid = Parameters.findValue("bri_mid", "01234567");
final String tid = Parameters.findValue("bri_tid", "0123456789ABCDEF");
final String procode = Parameters.findValue("bri_procode", "012345");
final String batch = Parameters.findValue("bri_batch", "03");
final String reference = Parameters.findValue("bri_reference", "01");
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mMid.setText(mid);
mTid.setText(tid);
mProcode.setText(procode);
mBatch.setText(batch);
mReference.setText(reference);
}
});
}
});
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
package com.medicom.dudikov.mypaxsimulator;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersRepository;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersTable;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link FragmentBankDKI.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link FragmentBankDKI#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentBankDKI extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
private EditText mMid;
private EditText mTid;
private EditText mStanStart;
public FragmentBankDKI() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FragmentBankDKI.
*/
// TODO: Rename and change types and number of parameters
public static FragmentBankDKI newInstance(String param1, String param2) {
FragmentBankDKI fragment = new FragmentBankDKI();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bank_dki, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMid = view.findViewById(R.id.edMID);
mTid = view.findViewById(R.id.edTID);
mStanStart = view.findViewById(R.id.edStanStart);
mMid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("dki_mid", mMid.getText().toString()));
}
}
});
mTid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("dki_tid", mTid.getText().toString()));
}
}
});
mStanStart.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("dki_stan_start", mStanStart.getText().toString()));
}
}
});
AsyncTask.execute(new Runnable() {
@Override
public void run() {
ParametersRepository Parameters = new ParametersRepository(getActivity());
final String mid = Parameters.findValue("dki_mid", "000885000015999");
final String tid = Parameters.findValue("dki_tid", "ABC12345");
final String minBalance = Parameters.findValue("dki_stan_start", "0");
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mMid.setText(mid);
mTid.setText(tid);
mStanStart.setText(minBalance);
}
});
}
});
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
package com.medicom.dudikov.mypaxsimulator;
import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.medicom.dudikov.mybanklibrary.mandiriLib;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersRepository;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersTable;
import com.medicom.organicdrv.OrganicDriver;
import com.medicom.organicdrv.utilsLib;
import java.util.Objects;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link FragmentBankMandiri.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link FragmentBankMandiri#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentBankMandiri extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
private EditText mSamPin;
private EditText mMid;
private EditText mTid;
private EditText mKaPin;
private EditText mMactros;
private EditText mPuk;
public FragmentBankMandiri() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FragmentBankMandiri.
*/
// TODO: Rename and change types and number of parameters
public static FragmentBankMandiri newInstance(String param1, String param2) {
FragmentBankMandiri fragment = new FragmentBankMandiri();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_bank_mandiri, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mSamPin = view.findViewById(R.id.edSamPin);
mMid = view.findViewById(R.id.edMID);
mTid = view.findViewById(R.id.edTID);
mKaPin = view.findViewById(R.id.edKAPin);
mMactros = view.findViewById(R.id.edMactros);
mPuk = view.findViewById(R.id.edPuk);
Button mUnblockPIN = view.findViewById(R.id.btnUnblockPin);
mUnblockPIN.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
mandiriLib mandiriLibrary = new mandiriLib();
int[] errorRst = new int[1];
mandiriLibrary.mandiriSetSamSlot(OrganicDriver.ORGANIC_SAM1);
byte[] bPin = utilsLib.HexStringToByteArray(mSamPin.getText().toString());
byte[] bPuk = utilsLib.HexStringToByteArray(mPuk.getText().toString());
mandiriLibrary.mandiriSamResetPin(false, bPuk, bPin, errorRst);
} catch (Exception e) {
e.printStackTrace();
}
}
});
mSamPin.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("mandiri_sam_pin", mSamPin.getText().toString()));
}
}
});
mMid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("mandiri_mid", mMid.getText().toString()));
}
}
});
mTid.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("mandiri_tid", mTid.getText().toString()));
}
}
});
mKaPin.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("mandiri_ka_pin", mKaPin.getText().toString()));
}
}
});
mMactros.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("mandiri_mactros", mMactros.getText().toString()));
}
}
});
mPuk.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
ParametersRepository Parameters = new ParametersRepository(getActivity());
Parameters.insert(new ParametersTable("mandiri_puk", mPuk.getText().toString()));
}
}
});
AsyncTask.execute(new Runnable() {
@Override
public void run() {
ParametersRepository Parameters = new ParametersRepository(getActivity());
final String samPin = Parameters.findValue("mandiri_sam_pin", "0123456789ABCDEF");
final String mid = Parameters.findValue("mandiri_mid", "0001");
final String tid = Parameters.findValue("mandiri_tid", "01234567");
final String kaPin = Parameters.findValue("mandiri_ka_pin", "0123456789ABCDEF");
final String mactros = Parameters.findValue("mandiri_mactros", "5566778800012222");
final String puk = Parameters.findValue("mandiri_puk", "0123456789ABCDEF");
Objects.requireNonNull(getActivity()).runOnUiThread(new Runnable() {
@Override
public void run() {
mSamPin.setText(samPin);
mMid.setText(mid);
mTid.setText(tid);
mKaPin.setText(kaPin);
mMactros.setText(mactros);
mPuk.setText(puk);
}
});
}
});
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
package com.medicom.dudikov.mypaxsimulator;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link FragmentRoot.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {@link FragmentRoot#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentRoot extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
public FragmentRoot() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment FragmentRoot.
*/
// TODO: Rename and change types and number of parameters
public static FragmentRoot newInstance(String param1, String param2) {
FragmentRoot fragment = new FragmentRoot();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_root, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
package com.medicom.dudikov.mypaxsimulator;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.StrictMode;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.FragmentTransaction;
import com.google.android.material.navigation.NavigationView;
import com.medicom.dudikov.mypaxsimulator.Database.ParametersRepository;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, FragmentRoot.OnFragmentInteractionListener, FragmentBasic.OnFragmentInteractionListener{
private DrawerLayout drawer;
private Fragment fragment = null;
private int idxDriver;
private static Intent newIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
AsyncTask.execute(new Runnable() {
@Override
public void run() {
ParametersRepository Parameters = new ParametersRepository(getApplication());
idxDriver = Integer.parseInt(Parameters.findValue("idx_driver", "0"));
}
});
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
//drawer.setDrawerListener(toggle);//deprecated
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
//navigationView.inflateHeaderView(R.layout.navigation_header_main);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.READ_PHONE_STATE)
!= PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Please grant permission", Toast.LENGTH_SHORT).show();
// Permission is not granted
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.READ_PHONE_STATE)) {
// Show an explanation to the user *asynchronously* -- don't block
// this thread waiting for the user's response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed; request the permission
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_PHONE_STATE, Manifest.permission.INTERNET, Manifest.permission.WRITE_EXTERNAL_STORAGE},
1);
}
} else {
// Permission has already been granted
if (savedInstanceState == null) {
fragment = new FragmentBasic();
callFragment(fragment);
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
fragment = new FragmentRoot();
callFragment(fragment);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.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.menuSettings) {
onSettingClick();
return true;
}
return super.onOptionsItemSelected(item);
}
protected void onSettingClick() {
Intent i;
i = new Intent(getApplicationContext(), SettingsActivity.class);
startActivity(i);
}
// untuk mengganti isi kontainer menu yang dipiih
private void callFragment(Fragment fragment) {
String fragmentTag = fragment.getClass().getName();
Fragment oldFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
//if oldFragment already exits in fragmentManager use it
if (oldFragment != null) {
fragment = oldFragment;
}
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_container, fragment, fragmentTag)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
.commit();
getSupportFragmentManager().executePendingTransactions();
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Bundle gateInArg = new Bundle();
gateInArg.putInt("ENGGINE_USE", idxDriver);
if (id == R.id.menuHome) {
fragment = new FragmentRoot();
fragment.setArguments(gateInArg);
callFragment(fragment);
} else if (id == R.id.menuBasic) {
fragment = new FragmentBasic();
fragment.setArguments(gateInArg);
callFragment(fragment);
}
drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
protected void onResume() {
super.onResume();
}
@Override
public void onFragmentInteraction(Uri uri) {
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
newIntent = intent;
Log.e("NewIntent", "true");
}
public static Intent getNewIntent(){
return newIntent;
}
}
package com.medicom.dudikov.mypaxsimulator;
import android.app.Application;
import android.content.Context;
import com.sunmi.peripheral.printer.InnerPrinterCallback;
import com.sunmi.peripheral.printer.InnerPrinterException;
import com.sunmi.peripheral.printer.InnerPrinterManager;
import com.sunmi.peripheral.printer.SunmiPrinterService;
public class MyApp extends Application {
public static Context context;
public static SunmiPrinterService sunmiPrinterService;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
bindPrintService();
}
private void bindPrintService() {
try {
InnerPrinterManager.getInstance().bindService(this, new InnerPrinterCallback() {
@Override
protected void onConnected(SunmiPrinterService service) {
MyApp.sunmiPrinterService = service;
}
@Override
protected void onDisconnected() {
MyApp.sunmiPrinterService = null;
}
});
} catch (InnerPrinterException e) {
e.printStackTrace();
}
}
}
package com.medicom.dudikov.mypaxsimulator.http;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.connectTimeout(10000, TimeUnit.SECONDS)
.writeTimeout(10000, TimeUnit.SECONDS)
.readTimeout(10000, TimeUnit.SECONDS)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment