Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
R
ReactNative Ubal Simulator
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OPEN-SHARING
ReactNative Ubal Simulator
Commits
fca91b54
Commit
fca91b54
authored
Mar 27, 2025
by
Gandha Ryanto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update library
parent
dc92304d
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
249 additions
and
55 deletions
+249
-55
App.tsx
App.tsx
+112
-18
build.gradle
android/app/build.gradle
+1
-1
MyModuleMdd.kt
...oid/app/src/main/java/com/rn_mdd_simulator/MyModuleMdd.kt
+136
-36
No files found.
App.tsx
View file @
fca91b54
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
import
{
View
,
View
,
Button
,
Text
,
Text
,
NativeModules
,
NativeModules
,
Platform
,
Platform
,
NativeEventEmitter
,
NativeEventEmitter
,
StyleSheet
,
TouchableOpacity
,
ActivityIndicator
,
}
from
'react-native'
;
}
from
'react-native'
;
const
MyModuleMdd
=
NativeModules
.
MyModuleMdd
;
const
MyModuleMdd
=
NativeModules
.
MyModuleMdd
;
...
@@ -13,7 +15,7 @@ const MyCustomEventEmitter = new NativeEventEmitter(MyModuleMdd);
...
@@ -13,7 +15,7 @@ const MyCustomEventEmitter = new NativeEventEmitter(MyModuleMdd);
const
App
=
()
=>
{
const
App
=
()
=>
{
const
[
balance
,
setBalance
]
=
useState
(
0
);
const
[
balance
,
setBalance
]
=
useState
(
0
);
const
[
nfcInitialized
]
=
useState
(
false
);
const
[
nfcInitialized
,
setNfcInitialized
]
=
useState
(
false
);
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
Platform
.
OS
===
'android'
)
{
if
(
Platform
.
OS
===
'android'
)
{
...
@@ -21,40 +23,132 @@ const App = () => {
...
@@ -21,40 +23,132 @@ const App = () => {
if
(
MyModuleMdd
)
{
if
(
MyModuleMdd
)
{
// Initialize MyNFCModuleMdd
// Initialize MyNFCModuleMdd
MyModuleMdd
.
initNfc
();
MyModuleMdd
.
initNfc
();
setNfcInitialized
(
true
);
}
else
{
}
else
{
console
.
error
(
'MyNFCModuleMdd is not available.'
);
console
.
error
(
'MyNFCModuleMdd is not available.'
);
}
}
}
}
},
[]);
},
[]);
MyCustomEventEmitter
.
addListener
(
'MyEvent'
,
event
=>
{
useEffect
(()
=>
{
console
.
log
(
event
.
message
);
const
eventListener
=
MyCustomEventEmitter
.
addListener
(
'MyEvent'
,
event
=>
{
});
console
.
log
(
'Received event:'
,
event
.
message
);
try
{
// Try to parse the message as JSON
const
data
=
JSON
.
parse
(
event
.
message
);
// Check if this is a card info response
if
(
data
.
balance
!==
undefined
)
{
setBalance
(
data
.
balance
);
console
.
log
(
'Balance updated:'
,
data
.
balance
);
}
}
catch
(
error
)
{
// If it's not JSON, it's probably just a status message
console
.
log
(
'Status message:'
,
event
.
message
);
}
});
// Cleanup listener on component unmount
return
()
=>
{
eventListener
.
remove
();
};
},
[]);
const
handleUpdateBalance
=
()
=>
{
const
handleUpdateBalance
=
()
=>
{
const
newBalance
=
100
;
// Example new balance
const
newBalance
=
5000
;
// Setting to 5000 to clearly see the change
console
.
warn
(
nfcInitialized
);
console
.
log
(
'Attempting to update balance to:'
,
newBalance
);
// Always reinitialize NFC before update to ensure fresh state
MyModuleMdd
.
initNfc
();
MyModuleMdd
.
initNfc
();
setNfcInitialized
(
true
);
MyModuleMdd
.
updateBalance
(
newBalance
);
// Short delay to ensure NFC is ready
// You can also call a method to retrieve the updated balance here if needed
setTimeout
(()
=>
{
MyModuleMdd
.
updateBalance
(
newBalance
);
},
500
);
};
};
const
handleGetBalance
=
()
=>
{
const
handleGetBalance
=
()
=>
{
MyModuleMdd
.
initNfc
();
if
(
!
nfcInitialized
)
{
MyModuleMdd
.
initNfc
();
setNfcInitialized
(
true
);
}
MyModuleMdd
.
getBalance
();
MyModuleMdd
.
getBalance
();
};
};
return
(
const
[
loading
,
_setLoading
]
=
useState
(
false
);
<
View
style=
{
{
flex
:
1
,
justifyContent
:
'center'
,
alignItems
:
'center'
}
}
>
<
Text
>
Current Balance:
{
balance
}
</
Text
>
interface
CustomButtonProps
{
{
Platform
.
OS
===
'android'
&&
(
title
:
string
;
<
Button
title=
"Update Balance"
onPress=
{
handleUpdateBalance
}
/>
onPress
:
()
=>
void
;
disabled
?:
boolean
;
}
const
CustomButton
=
({
title
,
onPress
,
disabled
=
false
,
}:
CustomButtonProps
)
=>
(
<
TouchableOpacity
style=
{
[
styles
.
button
,
disabled
&&
styles
.
disabledButton
]
}
onPress=
{
onPress
}
disabled=
{
disabled
}
>
{
loading
?
(
<
ActivityIndicator
color=
"#fff"
/>
)
:
(
<
Text
style=
{
styles
.
buttonText
}
>
{
title
}
</
Text
>
)
}
)
}
<
Button
title=
"Get Balance"
onPress=
{
handleGetBalance
}
/>
</
TouchableOpacity
>
);
return
(
<
View
style=
{
styles
.
container
}
>
<
Text
style=
{
styles
.
balanceText
}
>
Current Balance:
{
balance
}
</
Text
>
<
View
style=
{
styles
.
buttonContainer
}
>
{
Platform
.
OS
===
'android'
&&
(
<
CustomButton
title=
"Update Balance"
onPress=
{
handleUpdateBalance
}
disabled=
{
loading
}
/>
)
}
<
CustomButton
title=
"Get Balance"
onPress=
{
handleGetBalance
}
disabled=
{
loading
}
/>
</
View
>
</
View
>
</
View
>
);
);
};
};
const
styles
=
StyleSheet
.
create
({
container
:
{
flex
:
1
,
justifyContent
:
'center'
,
alignItems
:
'center'
,
padding
:
20
,
},
balanceText
:
{
fontSize
:
18
,
marginBottom
:
20
,
},
buttonContainer
:
{
width
:
'100%'
,
maxWidth
:
300
,
},
button
:
{
backgroundColor
:
'#007bff'
,
padding
:
15
,
borderRadius
:
5
,
alignItems
:
'center'
,
marginVertical
:
10
,
},
disabledButton
:
{
backgroundColor
:
'#6c757d'
,
},
buttonText
:
{
color
:
'#fff'
,
fontSize
:
16
,
fontWeight
:
'bold'
,
},
});
export
default
App
;
export
default
App
;
android/app/build.gradle
View file @
fca91b54
...
@@ -116,7 +116,7 @@ repositories {
...
@@ -116,7 +116,7 @@ repositories {
dependencies
{
dependencies
{
// The version of react-native is set by the React Native Gradle Plugin
// The version of react-native is set by the React Native Gradle Plugin
implementation
(
group:
'com.mdd.topup'
,
name:
'mdd_nfc_manager_android-release'
,
version:
'1.0.
4
'
,
ext:
'aar'
)
implementation
(
group:
'com.mdd.topup'
,
name:
'mdd_nfc_manager_android-release'
,
version:
'1.0.
12
'
,
ext:
'aar'
)
//retrofit
//retrofit
implementation
(
"io.reactivex.rxjava2:rxjava:2.2.19"
)
implementation
(
"io.reactivex.rxjava2:rxjava:2.2.19"
)
...
...
android/app/src/main/java/com/rn_mdd_simulator/MyModuleMdd.kt
View file @
fca91b54
...
@@ -18,6 +18,7 @@ import id.mdd.mdd_nfc_manager_android.models.CardInfoObject
...
@@ -18,6 +18,7 @@ import id.mdd.mdd_nfc_manager_android.models.CardInfoObject
class
MyModuleMdd
(
private
val
reactContext
:
ReactApplicationContext
)
:
class
MyModuleMdd
(
private
val
reactContext
:
ReactApplicationContext
)
:
ReactContextBaseJavaModule
(
reactContext
),
ActivityEventListener
,
LifecycleEventListener
{
ReactContextBaseJavaModule
(
reactContext
),
ActivityEventListener
,
LifecycleEventListener
{
private
var
currentState
=
MddNfcManager
.
NfcState
.
CARD_INFO
private
var
currentState
=
MddNfcManager
.
NfcState
.
CARD_INFO
private
var
pendingBalance
:
Double
?
=
null
private
val
TAG
:
String
=
"MyModuleMdd"
private
val
TAG
:
String
=
"MyModuleMdd"
private
var
nfcManager
:
MddNfcManager
?
=
null
private
var
nfcManager
:
MddNfcManager
?
=
null
private
var
eventEmitter
:
DeviceEventManagerModule
.
RCTDeviceEventEmitter
?
=
null
private
var
eventEmitter
:
DeviceEventManagerModule
.
RCTDeviceEventEmitter
?
=
null
...
@@ -29,20 +30,25 @@ class MyModuleMdd(private val reactContext: ReactApplicationContext) :
...
@@ -29,20 +30,25 @@ class MyModuleMdd(private val reactContext: ReactApplicationContext) :
override
fun
initialize
()
{
override
fun
initialize
()
{
super
.
initialize
()
super
.
initialize
()
reactContext
.
addActivityEventListener
(
this
)
;
reactContext
.
addActivityEventListener
(
this
)
reactContext
.
addLifecycleEventListener
(
this
)
;
reactContext
.
addLifecycleEventListener
(
this
)
eventEmitter
=
reactApplicationContext
eventEmitter
=
reactApplicationContext
.
getJSModule
(
DeviceEventManagerModule
.
RCTDeviceEventEmitter
::
class
.
java
)
.
getJSModule
(
DeviceEventManagerModule
.
RCTDeviceEventEmitter
::
class
.
java
)
nfcManager
=
MddNfcManager
(
try
{
reactApplicationContext
,
nfcManager
=
MddNfcManager
(
currentActivity
,
reactApplicationContext
,
"1234567abc"
,
currentActivity
,
"165eea86947a4e9483d1902f93495fc6"
,
"1234567abc"
,
"355933093746314"
,
"165eea86947a4e9483d1902f93495fc6"
,
0
"355933093746314"
,
)
1
)
println
(
"NFC Manager initialized successfully"
)
}
catch
(
e
:
Exception
)
{
println
(
"Error initializing NFC Manager: ${e.message}"
)
}
}
}
override
fun
onCatalystInstanceDestroy
()
{
override
fun
onCatalystInstanceDestroy
()
{
...
@@ -53,31 +59,55 @@ class MyModuleMdd(private val reactContext: ReactApplicationContext) :
...
@@ -53,31 +59,55 @@ class MyModuleMdd(private val reactContext: ReactApplicationContext) :
@ReactMethod
@ReactMethod
fun
initNfc
()
{
fun
initNfc
()
{
println
(
"initNfc called"
)
println
(
"initNfc called"
)
nfcManager
?.
startNfc
()
try
{
if
(
nfcManager
==
null
)
{
val
params
=
WritableNativeMap
()
println
(
"Reinitializing NFC Manager"
)
params
.
putString
(
"message"
,
"initNfc triggered from Kotlin!"
)
nfcManager
=
MddNfcManager
(
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
reactApplicationContext
,
currentActivity
,
"1234567abc"
,
"165eea86947a4e9483d1902f93495fc6"
,
"355933093746314"
,
1
)
}
nfcManager
?.
startNfc
()
println
(
"NFC started successfully"
)
val
params
=
WritableNativeMap
()
params
.
putString
(
"message"
,
"NFC initialized and started"
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
}
catch
(
e
:
Exception
)
{
println
(
"Error in initNfc: ${e.message}"
)
val
params
=
WritableNativeMap
()
params
.
putString
(
"message"
,
"Error initializing NFC: ${e.message}"
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
}
}
}
@ReactMethod
@ReactMethod
fun
updateBalance
(
newBalance
:
Double
)
{
fun
updateBalance
(
newBalance
:
Double
)
{
// Update balance code
println
(
"update balance called with: $newBalance"
)
p
rintln
(
"update balance called"
)
p
endingBalance
=
newBalance
currentState
=
MddNfcManager
.
NfcState
.
UPDATE
currentState
=
MddNfcManager
.
NfcState
.
UPDATE
val
params
=
WritableNativeMap
()
val
params
=
WritableNativeMap
()
params
.
putString
(
"message"
,
"
update balance triggered from Kotlin!
"
)
params
.
putString
(
"message"
,
"
Please tap your card to update balance
"
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
// Ensure NFC is started
nfcManager
?.
startNfc
()
}
}
@ReactMethod
@ReactMethod
fun
getBalance
()
{
fun
getBalance
()
{
// Get balance code
println
(
"get balance called"
)
println
(
"get balance called"
)
currentState
=
MddNfcManager
.
NfcState
.
CARD_INFO
currentState
=
MddNfcManager
.
NfcState
.
CARD_INFO
val
params
=
WritableNativeMap
()
val
params
=
WritableNativeMap
()
params
.
putString
(
"message"
,
"
get balance triggered from Kotlin!
"
)
params
.
putString
(
"message"
,
"
Please tap your card to read balance
"
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
// Ensure NFC is started
nfcManager
?.
startNfc
()
}
}
override
fun
onActivityResult
(
p0
:
Activity
?,
p1
:
Int
,
p2
:
Int
,
p3
:
Intent
?)
{
override
fun
onActivityResult
(
p0
:
Activity
?,
p1
:
Int
,
p2
:
Int
,
p3
:
Intent
?)
{
...
@@ -85,36 +115,106 @@ class MyModuleMdd(private val reactContext: ReactApplicationContext) :
...
@@ -85,36 +115,106 @@ class MyModuleMdd(private val reactContext: ReactApplicationContext) :
}
}
override
fun
onNewIntent
(
intent
:
Intent
)
{
override
fun
onNewIntent
(
intent
:
Intent
)
{
Log
.
d
(
TAG
,
"onNewIntent"
)
Log
.
d
(
TAG
,
"onNewIntent received"
)
println
(
"Current NFC State: $currentState"
)
if
(
currentState
==
MddNfcManager
.
NfcState
.
CARD_INFO
)
{
if
(
currentState
==
MddNfcManager
.
NfcState
.
CARD_INFO
)
{
nfcManager
?.
getCardInfo
(
intent
,
object
:
MddNfcManager
.
LibraryCallback
{
try
{
override
fun
onResult
(
result
:
CardInfoObject
)
{
println
(
"Starting to read card info..."
)
val
params
=
WritableNativeMap
()
println
(
"NFC Manager instance: $nfcManager"
)
params
.
putString
(
"message"
,
Gson
().
toJson
(
result
))
nfcManager
?.
getCardInfo
(
intent
,
object
:
MddNfcManager
.
LibraryCallback
{
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
override
fun
onResult
(
result
:
CardInfoObject
)
{
}
println
(
"Card info received: ${Gson().toJson(result)}"
)
})
val
params
=
WritableNativeMap
()
}
else
if
(
currentState
==
MddNfcManager
.
NfcState
.
UPDATE
)
{
params
.
putString
(
"message"
,
Gson
().
toJson
(
result
))
nfcManager
?.
update
(
intent
,
"081518012374"
,
"developer@gmail.com"
,
object
:
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
MddNfcManager
.
LibraryCallback
{
}
override
fun
onResult
(
result
:
CardInfoObject
)
{
})
val
params
=
WritableNativeMap
()
}
catch
(
e
:
Exception
)
{
params
.
putString
(
"message"
,
Gson
().
toJson
(
result
))
println
(
"Error reading card: ${e.message}"
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
val
params
=
WritableNativeMap
()
params
.
putString
(
"message"
,
"Error reading card: ${e.message}"
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
}
}
else
if
(
currentState
==
MddNfcManager
.
NfcState
.
UPDATE
&&
pendingBalance
!=
null
)
{
try
{
println
(
"Starting balance update with value: $pendingBalance"
)
println
(
"NFC Manager instance: $nfcManager"
)
println
(
"Current state before update: $currentState"
)
if
(
nfcManager
==
null
)
{
throw
Exception
(
"NFC Manager is null"
)
}
}
})
val
balanceToUpdate
=
pendingBalance
// Store for verification
nfcManager
?.
update
(
intent
,
balanceToUpdate
.
toString
(),
"081518012374"
,
object
:
MddNfcManager
.
LibraryCallback
{
override
fun
onResult
(
result
:
CardInfoObject
)
{
println
(
"Update callback received with result: ${Gson().toJson(result)}"
)
// Verify the update
println
(
"Expected balance: $balanceToUpdate"
)
println
(
"Actual balance in result: ${result.balance}"
)
val
params
=
WritableNativeMap
()
params
.
putString
(
"message"
,
Gson
().
toJson
(
result
))
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
// Reset state after successful update
currentState
=
MddNfcManager
.
NfcState
.
CARD_INFO
pendingBalance
=
null
}
}
)
println
(
"Update method called successfully"
)
}
catch
(
e
:
Exception
)
{
println
(
"Error in update method: ${e.message}"
)
println
(
"Stack trace: ${e.stackTrace.joinToString("
\
n
")}"
)
val
params
=
WritableNativeMap
()
params
.
putString
(
"message"
,
"Error updating balance: ${e.message}"
)
eventEmitter
?.
emit
(
"MyEvent"
,
params
)
// Reset state on error
currentState
=
MddNfcManager
.
NfcState
.
CARD_INFO
pendingBalance
=
null
}
}
}
}
}
override
fun
onHostResume
()
{
override
fun
onHostResume
()
{
Log
.
d
(
TAG
,
"onHostResume"
)
Log
.
d
(
TAG
,
"onHostResume"
)
try
{
// Reinitialize NFC when app resumes if needed
if
(
nfcManager
==
null
)
{
println
(
"Reinitializing NFC Manager on resume"
)
nfcManager
=
MddNfcManager
(
reactApplicationContext
,
currentActivity
,
"1234567abc"
,
"165eea86947a4e9483d1902f93495fc6"
,
"355933093746314"
,
1
)
}
nfcManager
?.
startNfc
()
println
(
"NFC restarted on resume"
)
}
catch
(
e
:
Exception
)
{
println
(
"Error restarting NFC on resume: ${e.message}"
)
}
}
}
override
fun
onHostPause
()
{
override
fun
onHostPause
()
{
Log
.
d
(
TAG
,
"onHostPause"
)
Log
.
d
(
TAG
,
"onHostPause"
)
// Keep track of current state
println
(
"App paused with NFC state: $currentState"
)
}
}
override
fun
onHostDestroy
()
{
override
fun
onHostDestroy
()
{
Log
.
d
(
TAG
,
"onHostDestroy"
)
Log
.
d
(
TAG
,
"onHostDestroy"
)
// Clean up resources
nfcManager
=
null
eventEmitter
=
null
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment