添加调用原生态的相机进行拍照的功能

This commit is contained in:
彭枝刚 2024-12-24 10:15:07 +08:00
parent 7d4acc43d5
commit cf31af7e3f
6 changed files with 114 additions and 2 deletions

57
App.tsx
View File

@ -3,6 +3,7 @@ import {BackHandler, View, Alert} from 'react-native';
import {WebView, WebViewNavigation} from 'react-native-webview';
import {StackNavigationProp} from '@react-navigation/stack';
import {RouteProp} from '@react-navigation/native';
import {launchCamera, launchImageLibrary} from 'react-native-image-picker';
type Props = {
navigation: StackNavigationProp<any>;
@ -11,7 +12,9 @@ type Props = {
const App = ({navigation}: Props) => {
const webViewRef = useRef<WebView | null>(null);
const [canGoBack, setCanGoBack] = useState(false);
const [canGoBack, setCanGoBack,currentDevice, setCurrentDevice] = useState(false);
const cameraRef = useRef(null);
const [hasCameraPermission, setHasCameraPermission] = useState(false);
const injectedJavaScript = `
window.handleBackButton = function() {
@ -23,10 +26,59 @@ const App = ({navigation}: Props) => {
true; // 必须返回一个值,否则注入失败
`;
const onMessage = (event) => {
// Alert.alert('父页面的方法被调用了'+event.nativeEvent.data);
const { callbackId, actionKey } = JSON.parse(event.nativeEvent.data);
if('takePicture' === actionKey){
const options = {
mediaType: 'photo',
maxHeight: 300,
maxWidth: 500,
quality: 1,
includeBase64: true, // 这个选项很重要,它会返回base64图片数据
};
launchCamera(options, response => {
if (response.didCancel) {
console.log('取消选择');
} else if (response.error) {
console.log('出错: ', response.error);
} else {
let imageUri = response.uri || response.assets?.[0]?.uri;
let imageInfo = response.assets?.[0];
if (!imageInfo.base64.startsWith('data:image/jpeg;base64,')) {
imageInfo.base64 = `data:image/jpeg;base64,${imageInfo.base64}`;
}
// return imageInfo.base64;
const imageArray = {
image: imageInfo.base64
}
const script = `
window.callbacks.execute('${callbackId}', 'success', ${JSON.stringify(imageArray)});
`;
webViewRef.current.injectJavaScript(script);
}
});
}
};
const takePhoto = async () => {
if (cameraRef.current) {
const options = { quality: 0.5, base64: true };
const data = await cameraRef.current.takePictureAsync(options);
console.log('Picture taken', data);
return data;
}
};
useEffect(() => {
const backAction = async () => {
if (webViewRef.current) {
console.log('子页面的呼叫');
const hasCustomHandler = await webViewRef.current.injectJavaScript(`window.handleBackButton()`).then(result => result === 'true');
if (hasCustomHandler) {
return true; // 自定义处理已处理返回键事件
@ -67,10 +119,11 @@ const App = ({navigation}: Props) => {
<View style={{flex: 1}}>
<WebView
ref={webViewRef}
source={{uri: 'http://192.168.110.208:11006'}}
source={{uri: 'http://192.168.106.209:8080/'}}
style={{flex: 1}} // 确保WebView占据整个屏幕
onNavigationStateChange={onNavigationStateChange}
injectedJavaScript={injectedJavaScript}
onMessage={onMessage}
/>
</View>
);

View File

@ -1,6 +1,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
android:name=".MainApplication"

View File

@ -5,8 +5,58 @@ import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate
import android.content.pm.PackageManager
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import android.Manifest
import android.os.Bundle
class MainActivity : ReactActivity() {
companion object {
const val PERMISSION_REQUEST_CODE = 1
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_main)
if (checkPermission()) {
// 权限已获取,可以打开相机
// openCamera()
} else {
// 请求权限
requestPermission()
}
}
private fun checkPermission(): Boolean {
return ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
}
private fun requestPermission() {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), PERMISSION_REQUEST_CODE)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
PERMISSION_REQUEST_CODE -> {
if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
// 权限被用户同意,可以打开相机
openCamera()
} else {
// 权限被用户拒绝,引导用户到设置页面手动开启
// ...
}
return
}
}
}
private fun openCamera() {
// 打开相机逻辑
}
/**
* Returns the name of the main component registered from JavaScript. This is used to schedule
* rendering of the component.

View File

@ -11,6 +11,7 @@ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader
// import org.reactnative.camera.RNCameraPackage;
class MainApplication : Application(), ReactApplication {
@ -20,6 +21,7 @@ class MainApplication : Application(), ReactApplication {
PackageList(this).packages.apply {
// Packages that cannot be autolinked yet can be added manually here, for example:
// add(MyReactNativePackage())
// add(RNCameraPackage())
}
override fun getJSMainModuleName(): String = "index"

View File

@ -8,6 +8,8 @@ buildscript {
kotlinVersion = "1.9.24"
}
repositories {
maven { url 'https://maven.aliyun.com/repository/google' }
maven { url 'https://maven.aliyun.com/repository/public' }
google()
mavenCentral()
}

View File

@ -15,6 +15,7 @@
"punycode": "^2.3.1",
"react": "18.3.1",
"react-native": "0.76.1",
"react-native-image-picker": "^7.2.3",
"react-native-webview": "^13.12.3"
},
"devDependencies": {