Skip to content

Commit

Permalink
Merge pull request #1003 from kaloudis/android-nfc-linking
Browse files Browse the repository at this point in the history
Android: set up NFC app linking
  • Loading branch information
kaloudis committed May 27, 2022
2 parents 4ecc56a + 94acb99 commit 16f64f2
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 20 deletions.
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ dependencies {
// gif
implementation 'com.facebook.fresco:fresco:2.6.0'
implementation 'com.facebook.fresco:animated-gif:2.6.0'
implementation "com.hypertrack:hyperlog:0.0.10"

if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
Expand Down
2 changes: 0 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:screenOrientation="portrait">
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
Expand Down
1 change: 1 addition & 0 deletions android/app/src/main/java/com/zeus/MainApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(new MobileToolsPackage());
return packages;
}
@Override
Expand Down
90 changes: 90 additions & 0 deletions android/app/src/main/java/com/zeus/MobileTools.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// based on Blixt LNDMobileTools
// https://github.com/hsjoberg/blixt-wallet/blob/master/android/app/src/main/java/com/blixtwallet/MainApplication.java
package app.zeusln.zeus;

import android.nfc.Tag;
import android.nfc.NfcAdapter;
import android.nfc.NdefMessage;
import android.nfc.tech.Ndef;
import android.nfc.NdefRecord;

import java.util.Arrays;
import java.io.UnsupportedEncodingException;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;

import com.hypertrack.hyperlog.HyperLog;

class MobileTools extends ReactContextBaseJavaModule {
final String TAG = "MobileTools";

public MobileTools(ReactApplicationContext reactContext) {
super(reactContext);
}

@Override
public String getName() {
return "MobileTools";
}

@ReactMethod
public void getIntentNfcData(Promise promise) {
// https://code.tutsplus.com/tutorials/reading-nfc-tags-with-android--mobile-17278
Tag tag = getReactApplicationContext()
.getCurrentActivity().getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag == null) {
promise.resolve(null);
return;
}

Ndef ndef = Ndef.get(tag);
if (ndef == null) {
HyperLog.d(TAG, "NFC tag is not NDEF");
promise.resolve(null);
}

NdefMessage ndefMessage = ndef.getCachedNdefMessage();

NdefRecord[] records = ndefMessage.getRecords();
if (records.length > 0) {
// Get first record and ignore the rest
NdefRecord record = records[0];
if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();

// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";

// Get the Language Code
int languageCodeLength = payload[0] & 0063;

// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"

try {
String s = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
promise.resolve(s);
return;
} catch (UnsupportedEncodingException e) {
HyperLog.e(TAG, "Error returning ndef data", e);
}
}
else {
HyperLog.d(TAG, "Cannot read NFC Tag Record");
}
}
promise.resolve(null);
}
}
22 changes: 22 additions & 0 deletions android/app/src/main/java/com/zeus/MobileToolsPackage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package app.zeusln.zeus;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class MobileToolsPackage implements ReactPackage {
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}

@Override
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
return Arrays.asList(new MobileTools(reactContext));
}
}
8 changes: 0 additions & 8 deletions android/app/src/main/res/xml/nfc_tech_filter.xml

This file was deleted.

12 changes: 9 additions & 3 deletions stores/InvoicesStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,20 @@ export default class InvoicesStore {
@action
public clearAddress = () => (this.onChainAddress = null);

@action
public clearPayReq = () => {
this.pay_req = null;
this.getPayReqError = null;
};

@action
public getPayReq = (
paymentRequest: string,
descriptionPreimage?: string
) => {
this.loading = true;
this.pay_req = null;
this.paymentRequest = paymentRequest;
this.loading = true;
this.feeEstimate = null;

return RESTUtils.decodePaymentRequest([paymentRequest])
Expand All @@ -249,14 +255,14 @@ export default class InvoicesStore {
);
}

this.loading = false;
this.getPayReqError = null;
this.loading = false;
})
.catch((error: any) => {
// handle error
this.loading = false;
this.pay_req = null;
this.getPayReqError = error.toString();
this.loading = false;
});
};

Expand Down
16 changes: 12 additions & 4 deletions utils/LinkingUtils.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { Linking } from 'react-native';
import { Linking, NativeModules } from 'react-native';
import { localeString } from './LocaleUtils';
import handleAnything from './handleAnything';

class LinkingUtils {
handleInitialUrl = (navigation: any) =>
Linking.getInitialURL().then(
(url) => url && this.handleDeepLink(url, navigation)
);
Linking.getInitialURL().then(async (url) => {
if (url) {
this.handleDeepLink(url, navigation);
return;
}
if (Platform.OS === 'android') {
const nfcData =
await NativeModules.MobileTools.getIntentNfcData();
if (nfcData) this.handleDeepLink(nfcData, navigation);
}
});

handleDeepLink = (url: string, navigation: any) =>
handleAnything(url)
Expand Down
10 changes: 7 additions & 3 deletions views/PaymentRequest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ export default class PaymentRequest extends React.Component<
loading,
loadingFeeEstimate,
successProbability,
feeEstimate
feeEstimate,
clearPayReq
} = InvoicesStore;

const requestAmount = pay_req && pay_req.getRequestAmount;
Expand Down Expand Up @@ -133,7 +134,10 @@ export default class PaymentRequest extends React.Component<
const BackButton = () => (
<Icon
name="arrow-back"
onPress={() => navigation.navigate('Wallet', { refresh: true })}
onPress={() => {
clearPayReq();
navigation.navigate('Wallet', { refresh: true });
}}
color={themeColor('text')}
underlayColor="transparent"
/>
Expand Down Expand Up @@ -178,7 +182,7 @@ export default class PaymentRequest extends React.Component<
</View>
)}

{!!pay_req && (
{!loading && !!pay_req && (
<View style={styles.content}>
<View style={styles.center}>
{isNoAmountInvoice ? (
Expand Down

0 comments on commit 16f64f2

Please sign in to comment.