Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

android permissions util #218

Merged
merged 2 commits into from
Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ useEffect(() => {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Permission Permission',
message: 'App needs access to your Location ',
title: 'Location Permission',
message: 'Stripe Terminal needs access to your location',
buttonPositive: 'Accept',
}
);
Expand All @@ -150,6 +150,32 @@ useEffect(() => {
}, []);
```

For convenience, Stripe Terminal SDK also provides an util that handles all needed Android permissions.
In order to use it follow below instrustions:

```tsx
import { requestNeededAndroidPermissions } from 'stripe-terminal-react-native';

try {
const granted = await requestNeededAndroidPermissions({
accessFineLocation: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, we only need additional text for location, BT just shows a standard prompt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that's correct

title: 'Location Permission',
message: 'Stripe Terminal needs access to your location',
buttonPositive: 'Accept',
},
});
if (granted) {
// init SDK
} else {
console.error(
'Location and BT services are required in order to connect to a reader.'
);
}
} catch (e) {
console.error(e);
}
```

#### Manifest

To enable compatibility the library with the latest Android 12 please make sure that you add following requirements:
Expand Down
4 changes: 2 additions & 2 deletions docs/integration-builder/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export default function App() {
const granted = await PermissionsAndroid.request(
'android.permission.ACCESS_FINE_LOCATION',
{
title: 'Location Permission Permission',
message: 'App needs access to your Location ',
title: 'Location Permission',
message: 'Stripe Terminal needs access to your location',
buttonPositive: 'Accept',
}
);
Expand Down
30 changes: 28 additions & 2 deletions docs/set-up-your-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ useEffect(() => {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Permission Permission',
message: 'App needs access to your Location ',
title: 'Location Permission',
message: 'Stripe Terminal needs access to your location',
buttonPositive: 'Accept',
}
);
Expand All @@ -102,6 +102,32 @@ useEffect(() => {
}, []);
```

For convenience, Stripe Terminal SDK also provides an util that handles all needed Android permissions.
In order to use it follow below instrustions:

```tsx
import { requestNeededAndroidPermissions } from 'stripe-terminal-react-native';

try {
const granted = await requestNeededAndroidPermissions({
accessFineLocation: {
title: 'Location Permission',
message: 'Stripe Terminal needs access to your location',
buttonPositive: 'Accept',
},
});
if (granted) {
// init SDK
} else {
console.error(
'Location and BT services are required in order to connect to a reader.'
);
}
} catch (e) {
console.error(e);
}
```

#### Manifest

To enable compatibility the library with the latest Android 12 please make sure that you ad following requirements:
Expand Down
95 changes: 26 additions & 69 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ import {
TransitionPresets,
} from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import {
Alert,
PermissionsAndroid,
Platform,
StatusBar,
StyleSheet,
} from 'react-native';
import { Alert, Platform, StatusBar, StyleSheet } from 'react-native';
import { colors } from './colors';
import { LogContext, Log, Event } from './components/LogContext';
import DiscoverReadersScreen from './screens/DiscoverReadersScreen';
Expand All @@ -27,11 +21,11 @@ import ReadReusableCardScreen from './screens/ReadReusableCardScreen';
import LogListScreen from './screens/LogListScreen';
import LogScreen from './screens/LogScreen';
import RegisterInternetReaderScreen from './screens/RegisterInternetReaderScreen';
import { isAndroid12orHigher } from './utils';
import {
Reader,
Location,
useStripeTerminal,
requestNeededAndroidPermissions,
} from 'stripe-terminal-react-native';
import { LogBox } from 'react-native';

Expand Down Expand Up @@ -104,81 +98,44 @@ export default function App() {
const clearLogs = useCallback(() => setlogs([]), []);
const { initialize: initStripe } = useStripeTerminal();

useEffect(() => {
const handlePermissionsSuccess = async () => {
const { error } = await initStripe({
logLevel: 'verbose',
});
if (error) {
Alert.alert('StripeTerminal init failed', error.message);
} else {
console.log('StripeTerminal has been initialized properly');
}
};
const handlePermissionsSuccess = useCallback(async () => {
const { error } = await initStripe({
logLevel: 'verbose',
});
if (error) {
Alert.alert('StripeTerminal init failed', error.message);
} else {
console.log('StripeTerminal has been initialized properly');
}
}, [initStripe]);

useEffect(() => {
async function handlePermissions() {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
const granted = await requestNeededAndroidPermissions({
accessFineLocation: {
title: 'Location Permission',
message: 'App needs access to your Location ',
message: 'Stripe Terminal needs access to your location',
buttonPositive: 'Accept',
}
);

if (hasGrantedPermission(granted)) {
if (isAndroid12orHigher()) {
const grantedBT = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
{
title: 'BT Permission',
message: 'App needs access to Bluetooth ',
buttonPositive: 'Accept',
}
);

const grantedBTScan = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
{
title: 'BT Permission',
message: 'App needs access to Bluetooth ',
buttonPositive: 'Accept',
}
);
if (
hasGrantedPermission(grantedBT) &&
hasGrantedPermission(grantedBTScan)
) {
handlePermissionsSuccess();
return;
} else {
handlePermissionsError();
return;
}
}
},
});
if (granted) {
handlePermissionsSuccess();
} else {
handlePermissionsError();
console.error(
'Location and BT services are required in order to connect to a reader.'
);
}
} catch {}
} catch (e) {
console.error(e);
}
}
if (Platform.OS === 'android') {
handlePermissions();
} else {
handlePermissionsSuccess();
}
}, [initStripe]);

const handlePermissionsError = () => {
console.error(
'Location and BT services are required in order to connect to a reader.'
);
};

const hasGrantedPermission = (status: string) => {
return status === PermissionsAndroid.RESULTS.GRANTED;
};
}, [handlePermissionsSuccess]);

const addLogs = useCallback((newLog: Log) => {
const updateLog = (log: Log) =>
Expand Down
3 changes: 3 additions & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ export {
withStripeTerminal,
WithStripeTerminalProps,
} from './components/withStripeTerminal';

// utils
export { requestNeededAndroidPermissions } from './utils/androidPermissionsUtils';
59 changes: 59 additions & 0 deletions src/utils/androidPermissionsUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { PermissionsAndroid, Platform } from 'react-native';

const defaultFineLocationParams = {
title: 'Location Permission',
message: 'Stripe Terminal needs access to your location',
buttonPositive: 'Accept',
};

type PermissionsProps = {
accessFineLocation?: {
title: string;
message: string;
buttonPositive: string;
};
};

const isAndroid12orHigher = () =>
Platform.OS === 'android' && Platform.Version >= 31;

export async function requestNeededAndroidPermissions({
accessFineLocation = defaultFineLocationParams,
}: PermissionsProps | undefined = {}): Promise<boolean> {
let hasGrantedLocationPermissions = false;
let hasGrantedBluetoothPermissions = false;

const grantedFineLocation = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
accessFineLocation || defaultFineLocationParams
);

if (hasGrantedPermission(grantedFineLocation)) {
hasGrantedLocationPermissions = true;

if (isAndroid12orHigher()) {
const grantedBT = await PermissionsAndroid.request(
// BLUETOOTH_CONNECT doesn't support customization
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT
);

const grantedBTScan = await PermissionsAndroid.request(
// BLUETOOTH_SCAN doesn't support customization
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN
);
if (
hasGrantedPermission(grantedBT) &&
hasGrantedPermission(grantedBTScan)
) {
hasGrantedBluetoothPermissions = true;
}
} else {
hasGrantedBluetoothPermissions = true;
}
}
return hasGrantedBluetoothPermissions && hasGrantedLocationPermissions;
}

const hasGrantedPermission = (status: string) => {
return status === PermissionsAndroid.RESULTS.GRANTED;
};