Skip to content

Commit

Permalink
Merge pull request #19 from pushpender-singh-ap/featurs
Browse files Browse the repository at this point in the history
Introduced flashlight control and camera release commands (ANDROID ONLY)
  • Loading branch information
pushpender-singh-ap authored May 17, 2024
2 parents 4448221 + e50057d commit 0384acf
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 2 deletions.
143 changes: 143 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ With this package, users can quickly and easily scan barcodes and QR codes with

If you want to provide your React Native app the ability to read barcodes and QR codes, you should definitely give this package some thought.

The `@pushpendersingh/react-native-scanner` package also includes a flashlight feature that can be turned on and off. This can be useful when scanning QR codes in low light conditions. Please note that this feature is currently only available on Android devices. (v1.2.0-beta.1)

## Getting started

### Requirements
Expand All @@ -20,11 +22,15 @@ Open your project's `Info.plist` and add the following lines inside the outermos
<key>NSCameraUsageDescription</key>
<string>Your message to user when the camera is accessed for the first time</string>
```

Open your project's `Podfile` and add enable the new architecture:

```
:fabric_enabled => true,
```

Run below command to enable the new architecture in IOS folder

```
bundle install && RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
```
Expand All @@ -38,7 +44,9 @@ Open your project's `AndroidManifest.xml` and add the following lines inside the

<uses-feature android:name="android.hardware.camera.any" />
```

Open your project's `gradle.properties` and add enable the new architecture:

```
newArchEnabled=true
```
Expand All @@ -63,6 +71,9 @@ npm install @pushpendersingh/react-native-scanner

To use @pushpendersingh/react-native-scanner, `import` the `@pushpendersingh/react-native-scanner` module and use the `<ReactNativeScannerView />` tag. More usage examples can be seen under the `examples/` folder.

<details>
<summary>Basic usage</summary>

Here is an example of basic usage:

```js
Expand Down Expand Up @@ -129,6 +140,138 @@ export default function App() {
}
}
```
</details>

## Flashlight Feature (Android Only)

<details>
<summary>Flashlight Feature (Android Only)</summary>

To use the flashlight feature, add the following code to your project:

```jsx
import React, {useEffect, useRef, useState} from 'react';
import {
Alert,
Platform,
useWindowDimensions,
Text,
SafeAreaView,
TouchableOpacity,
} from 'react-native';

import {
request,
PERMISSIONS,
openSettings,
RESULTS,
} from 'react-native-permissions';
import {
ReactNativeScannerView,
Commands,
} from '@pushpendersingh/react-native-scanner';

export default function App() {
const {height, width} = useWindowDimensions();
const [isCameraPermissionGranted, setIsCameraPermissionGranted] =
useState(false);
const cameraRef = useRef(null);

useEffect(() => {
checkCameraPermission();

return () => {
Commands.releaseCamera(cameraRef.current);
};
}, []);

const enableFlashlight = () => {
Commands.enableFlashlight(cameraRef.current);
};

const disableFlashlight = () => {
Commands.disableFlashlight(cameraRef.current);
};

const checkCameraPermission = async () => {
request(
Platform.OS === 'ios'
? PERMISSIONS.IOS.CAMERA
: PERMISSIONS.ANDROID.CAMERA,
).then(async (result: any) => {
switch (result) {
case RESULTS.UNAVAILABLE:
break;
case RESULTS.DENIED:
Alert.alert(
'Permission Denied',
'You need to grant camera permission first',
);
openSettings();
break;
case RESULTS.GRANTED:
setIsCameraPermissionGranted(true);
break;
case RESULTS.BLOCKED:
Alert.alert(
'Permission Blocked',
'You need to grant camera permission first',
);
openSettings();
break;
}
});
};

if (isCameraPermissionGranted) {
return (
<SafeAreaView style={{flex: 1}}>
<ReactNativeScannerView
ref={ref => (cameraRef.current = ref)}
style={{height, width}}
onQrScanned={(value: any) => {
console.log(value.nativeEvent);
}}
/>

<TouchableOpacity
style={{
position: 'absolute',
bottom: 20,
left: 20,
padding: 10,
backgroundColor: 'blue',
borderRadius: 10,
}}
onPress={enableFlashlight}>
<Text>Turn ON</Text>
</TouchableOpacity>

<TouchableOpacity
style={{
position: 'absolute',
bottom: 20,
right: 20,
padding: 10,
backgroundColor: 'blue',
borderRadius: 10,
}}
onPress={disableFlashlight}>
<Text>Turn OFF</Text>
</TouchableOpacity>
</SafeAreaView>
);
} else {
return (
<Text style={{fontSize: 30, color: 'red'}}>
You need to grant camera permission first
</Text>
);
}
}
```

</details>

## Props

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import androidx.camera.core.CameraControl

class ReactNativeScannerView(context: Context) : LinearLayout(context) {

Expand All @@ -36,6 +37,7 @@ class ReactNativeScannerView(context: Context) : LinearLayout(context) {
private lateinit var scanner: BarcodeScanner
private var analysisUseCase: ImageAnalysis = ImageAnalysis.Builder()
.build()
private lateinit var cameraControl: CameraControl

companion object {
private const val REQUEST_CODE_PERMISSIONS = 10
Expand Down Expand Up @@ -196,10 +198,31 @@ class ReactNativeScannerView(context: Context) : LinearLayout(context) {
analysisUseCase
)

val camera = cameraProvider.bindToLifecycle(
(reactApplicationContext.currentActivity as AppCompatActivity),
cameraSelector,
surfacePreview,
analysisUseCase
)
cameraControl = camera.cameraControl

} catch (exc: Exception) {

}

}, ContextCompat.getMainExecutor(context))
}

fun enableFlashlight() {
cameraControl.enableTorch(true)
}

fun disableFlashlight() {
cameraControl.enableTorch(false)
}

fun releaseCamera() {
cameraExecutor.shutdown()
mCameraProvider?.unbindAll()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,18 @@ class ReactNativeScannerViewManager(private val mCallerContext: ReactApplication
return NAME
}

override fun enableFlashlight(view: ReactNativeScannerView?) {
view?.enableFlashlight()
}

override fun disableFlashlight(view: ReactNativeScannerView?) {
view?.disableFlashlight()
}

override fun releaseCamera(view: ReactNativeScannerView?) {
view?.releaseCamera()
}

override fun createViewInstance(reactContext: ThemedReactContext): ReactNativeScannerView {
val reactnativeScannerView = ReactNativeScannerView(mCallerContext)
reactnativeScannerView.setUpCamera(mCallerContext)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pushpendersingh/react-native-scanner",
"version": "1.1.0",
"version": "1.2.0-beta.1",
"description": "A QR code & Barcode Scanner for React Native Projects.",
"main": "lib/commonjs/index",
"module": "lib/module/index",
Expand Down
19 changes: 18 additions & 1 deletion src/ReactNativeScannerViewNativeComponent.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
import type { ViewProps } from 'react-native';
import type { ViewProps, HostComponent } from 'react-native';
import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';

type Event = Readonly<{
value: string;
}>;

interface NativeCommands {
enableFlashlight: (
viewRef: React.ElementRef<HostComponent<NativeProps>>
) => Promise<void>;
disableFlashlight: (
viewRef: React.ElementRef<HostComponent<NativeProps>>
) => Promise<void>;
releaseCamera: (
viewRef: React.ElementRef<HostComponent<NativeProps>>
) => Promise<void>;
}

interface NativeProps extends ViewProps {
onQrScanned?: DirectEventHandler<Event>; // Event name should start with "on"
}

export const Commands = codegenNativeCommands<NativeCommands>({
supportedCommands: ['enableFlashlight', 'disableFlashlight', 'releaseCamera'],
});

export default codegenNativeComponent<NativeProps>('ReactNativeScannerView');

0 comments on commit 0384acf

Please sign in to comment.