我正在开发使用React-viro增强现实的React-native应用程序。我的应用程序在开发模式下运行良好,但是当我尝试通过android studio或“ react-native run-android”在手机上进行构建时,它表示构建成功,但是当应用程序在我的手机上打开时显示错误:“ null不是对象(正在评估I.setJSAnimations”),当我构建APK时,应用立即崩溃。 我不知道该如何区分问题,有什么帮助吗?
我的build.gradle文件:
import com.android.build.OutputFile
/**
* The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
* and bundleReleaseJsAndAssets).
* These basically call `react-native bundle` with the correct arguments during the Android build
* cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
* bundle directly from the development server. Below you can see all the possible configurations
* and their defaults. If you decide to add a configuration block, make sure to add it before the
* `apply from: "../../node_modules/react-native/react.gradle"` line.
*
* project.ext.react = [
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* entryFile: "index.android.js",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
* // whether to bundle JS and assets in release mode
* bundleInRelease: true,
*
* // whether to bundle JS and assets in another build variant (if configured).
* // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
* // The configuration property can be in the following formats
* // 'bundleIn${productFlavor}${buildType}'
* // 'bundleIn${buildType}'
* // bundleInFreeDebug: true,
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // whether to disable dev mode in custom build variants (by default only disabled in release)
* // for example: to disable dev mode in the staging build type (if configured)
* devDisabledInStaging: true,
* // The configuration property can be in the following formats
* // 'devDisabledIn${productFlavor}${buildType}'
* // 'devDisabledIn${buildType}'
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
* // where to put the JS bundle asset in debug mode
* jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
*
* // where to put the JS bundle asset in release mode
* jsBundleDirRelease: "$buildDir/intermediates/assets/release",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in debug mode
* resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
*
* // where to put drawable resources / React Native assets, e.g. the ones you use via
* // require('./image.png')), in release mode
* resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
*
* // by default the gradle tasks are skipped if none of the JS files or assets change; this means
* // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
* // date; if you have any other folders that you want to ignore for performance reasons (gradle
* // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
* // for example, you might want to remove it from here.
* inputExcludes: ["android/**", "ios/**"],
*
* // override which node gets called and with what additional arguments
* nodeExecutableAndArgs: ["node"],
*
* // supply additional arguments to the packager
* extraPackagerArgs: []
* ]
*/
project.ext.react = [
entryFile: "index.js"
]
apply from: "../../node_modules/react-native/react.gradle"
/**
* Set this to true to create two separate APKs instead of one:
* - An APK that only works on ARM devices
* - An APK that only works on x86 devices
* The advantage is the size of the APK is reduced by about 4MB.
* Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device.
*/
def enableSeparateBuildPerCPUArchitecture = false
/**
* Run Proguard to shrink the Java bytecode in release builds.
*/
def enableProguardInReleaseBuilds = false
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
flavorDimensions "platform"
signingConfigs {
release {
if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
storeFile file(MYAPP_UPLOAD_STORE_FILE)
storePassword MYAPP_UPLOAD_STORE_PASSWORD
keyAlias MYAPP_UPLOAD_KEY_ALIAS
keyPassword MYAPP_UPLOAD_KEY_PASSWORD
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
compileSdkVersion 28
minSdkVersion 23
targetSdkVersion 28
multiDexEnabled true
buildToolsVersion '28.0.3'
multiDexEnabled true
applicationId "com.namedSportAR"
versionCode 1
versionName "1.0"
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
productFlavors {
ar {
resValue 'string', 'app_name', 'ViroSample-ar'
buildConfigField 'String', 'VR_PLATFORM', '"GVR"' //default to GVR
}
gvr {
resValue 'string', 'app_name', 'ViroSample-gvr'
buildConfigField 'String', 'VR_PLATFORM', '"GVR"'
}
ovr {
resValue 'string', 'app_name', 'ViroSample-ovr'
applicationIdSuffix '.ovr'
buildConfigField 'String', 'VR_PLATFORM', '"OVR_MOBILE"'
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
def versionCodes = ["armeabi-v7a":1, "x86":2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
dependencies {
implementation project(':@react-native-firebase_app')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.facebook.react:react-native:+'
// implementation project(':arcore_client')
// implementation project(':gvr_common')
// implementation project(path: ':viro_renderer')
// implementation project(path: ':react_viro')
implementation 'com.google.android.exoplayer:exoplayer:2.7.1'
// implementation 'com.google.protobuf.nano:protobuf-javanano:2.7.1'
implementation 'com.amazonaws:aws-android-sdk-core:2.7.7'
implementation 'com.amazonaws:aws-android-sdk-ddb:2.7.7'
implementation 'com.amazonaws:aws-android-sdk-ddb-mapper:2.7.7'
implementation 'com.amazonaws:aws-android-sdk-cognito:2.7.7'
implementation 'com.amazonaws:aws-android-sdk-cognitoidentityprovider:2.7.7'
implementation 'com.android.support:multidex:1.0.0'
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
我的app.js文件:
/*
* Copyright (c) 2017-present, Viro, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
import React, { Component } from 'react';
import {
AppRegistry,
Text,
View,
StyleSheet,
PixelRatio,
TouchableHighlight,
Image,
Icon
} from 'react-native';
import {
ViroVRSceneNavigator,
ViroARSceneNavigator
} from 'react-viro';
var sharedProps = {
apiKey:"2803D6A6-AAFE-4CAB-823F-E7433072671D",
}
// Sets the default scene you want for AR and VR
var InitialARScene = require('./src/PlayScene');
var UNSET = "UNSET";
var VR_NAVIGATOR_TYPE = "VR";
var AR_NAVIGATOR_TYPE = "AR";
// This determines which type of experience to launch in, or UNSET, if the user should
// be presented with a choice of AR or VR. By default, we offer the user a choice.
var defaultNavigatorType = UNSET;
export default class ViroSample extends Component {
constructor() {
super();
this.state = {
navigatorType : defaultNavigatorType,
sharedProps : sharedProps
}
this._getExperienceSelector = this._getExperienceSelector.bind(this);
this._getARNavigator = this._getARNavigator.bind(this);
this._getVRNavigator = this._getVRNavigator.bind(this);
this._getExperienceButtonOnPress = this._getExperienceButtonOnPress.bind(this);
this._exitViro = this._exitViro.bind(this);
}
// Replace this function with the contents of _getVRNavigator() or _getARNavigator()
// if you are building a specific type of experience.
render() {
if (this.state.navigatorType == UNSET) {
return this._getExperienceSelector();
} else if (this.state.navigatorType == VR_NAVIGATOR_TYPE) {
return this._getVRNavigator();
} else if (this.state.navigatorType == AR_NAVIGATOR_TYPE) {
return this._getARNavigator();
}
}
// Presents the user with a choice of an AR or VR experience
_getExperienceSelector() {
return (
<View style={localStyles.outer} >
<View style={localStyles.inner} >
<Image
style={{marginTop: 50, marginBottom: 50, width: 200, height: 50}}
source={require('./assets/logo.png')}
/>
<TouchableHighlight style={localStyles.buttons}
onSubmit={this._getExperienceButtonOnPress(AR_NAVIGATOR_TYPE)}
underlayColor={'#68a0ff'} >
<Text style={localStyles.buttonText}>realtà aumentata</Text>
</TouchableHighlight>
</View>
</View>
);
}
// Returns the ViroARSceneNavigator which will start the AR experience
_getARNavigator() {
return (
<ViroARSceneNavigator {...this.state.sharedProps}
initialScene={{scene: InitialARScene}} />
);
}
// Returns the ViroSceneNavigator which will start the VR experience
_getVRNavigator() {
return (
<ViroVRSceneNavigator {...this.state.sharedProps}
initialScene={{scene: InitialVRScene}} onExitViro={this._exitViro}/>
);
}
// This function returns an anonymous/lambda function to be used
// by the experience selector buttons
_getExperienceButtonOnPress(navigatorType) {
return () => {
this.setState({
navigatorType : navigatorType
})
}
}
// This function "exits" Viro by setting the navigatorType to UNSET.
_exitViro() {
this.setState({
navigatorType : UNSET
})
}
}
var localStyles = StyleSheet.create({
viroContainer :{
flex : 1,
backgroundColor: "#EF7D1A",
},
outer : {
flex : 1,
alignItems:'center',
backgroundColor: "#EF7D1A",
},
inner: {
flex : 1,
alignItems:'center',
backgroundColor: "#EF7D1A",
},
titleText: {
paddingTop: 30,
paddingBottom: 20,
color:'black',
textAlign:'center',
fontSize : 25
},
buttonText: {
color:'black',
textAlign:'center',
fontSize : 20
},
buttons : {
height: 80,
width: 150,
paddingTop:20,
paddingBottom:20,
marginTop:250,
justifyContent: 'center',
alignItems:'center',
backgroundColor:'#EF7D1A',
borderRadius: 10,
borderWidth: 1,
borderColor: '#000000',
},
exitButton : {
height: 50,
width: 100,
paddingTop:10,
paddingBottom:10,
marginTop: 10,
marginBottom: 10,
backgroundColor:'#68a0cf',
borderRadius: 10,
borderWidth: 1,
borderColor: '#fff',
}
});
module.exports = ViroSample
我的PlayScene.js文件:
'use strict';
import React, { Component } from 'react';
import {StyleSheet,Linking} from 'react-native';
import {
ViroBox,
ViroARScene,
ViroText,
ViroConstants,
Viro3DObject,
ViroAmbientLight,
ViroMaterials,
ViroARTrackingTargets,
ViroARImageMarker,
ViroAnimations
} from 'react-viro';
export default class HelloWorldSceneAR extends Component {
constructor() {
super();
// Set initial state here
this.state = {
text : "Initializing AR..."
};
// bind 'this' to functions
this._onInitialized = this._onInitialized.bind(this);
}
render() {
return (
<ViroARScene onTrackingUpdated={this._trackingUpdated}>
<ViroAmbientLight color="#FFFFFF" />
<ViroARImageMarker target={'logo'} onAnchorFound={this._onAnchorFound} onAnchorRemoved={this._onAnchorRemoved} pauseUpdates={this.state.pauseUpdates}>
<Viro3DObject onLoadEnd={this._onModelLoad}
onClick={this.loadInBrowser}
source={require('./assets/ns/AMINONAM-obj.obj')}
resources={[
require('./assets/ns/AMINONAM.mtl'),
require('./assets/ns/TEX_OK.jpg'),
require('./assets/ns/WHITE.jpg'),
require('./assets/ns/arancio.jpg'),
]}
highAccuracyEvents={true}
position={[0, 0.02, 0]} // we place the object in front of us (z = -1)
scale={[0.001, 0.001, 0.001]} // we reduce the size of our Marmelab logo object
animation={
{name:'popup',
run:true},
{name:'ruota',
loop:true,
run:true}
}
rotation={[0, 0, 0]}
type="OBJ"
/>
</ViroARImageMarker>
</ViroARScene>
);
}
loadInBrowser = () => {
Linking.openURL('https://www.namedsport.com/it/').catch(err => console.error("Couldn't load page", err));
};
_onInitialized(state, reason) {
if (state == ViroConstants.TRACKING_NORMAL) {
this.setState({
text : "NamedSport!"
});
} else if (state == ViroConstants.TRACKING_NONE) {
// Handle loss of tracking
}
}
}
ViroAnimations.registerAnimations({
ruota:{properties:{rotateY:360,},
easing:"Linear", duration: 10000},
});
ViroARTrackingTargets.createTargets({
logo: {
type: 'Image',
source: require('./assets/namedsport-box.jpg'), // source of the target image
orientation: 'Up', // desired orientation of the image
physicalWidth: 0.07, // with of the target in meters (10 centimeters in our case)
},
});
var styles = StyleSheet.create({
helloWorldTextStyle: {
fontFamily: 'Arial',
fontSize: 30,
color: '#ffffff',
textAlignVertical: 'center',
textAlign: 'center',
},
});
module.exports = HelloWorldSceneAR;