我正在Android中设置推送通知,生成了FCM,但是当通知接收到设备时,应用程序崩溃了,我也想将fcm令牌存储在服务器中
App.js
import React, {useState, useEffect} from 'react';
import {View, TouchableOpacity, TextInput, Text, Image} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import PushNotification from 'react-native-push-notification'
// import FormScreen from './form';
// import RegisterScreen from './register';
import AsyncStorage from '@react-native-community/async-storage';
import NewScreen from './New';
const LoginScreen = ({navigation}) => {
const [intialEmail, setEmail] = useState('');
const [intialName, setName] = useState('');
const userRegister = async () => {
//alert('ok'); // version 0.48
PushNotification.configure({
// (optional) Called when Token is generated (iOS and Android)
onRegister: function(token) {
console.log( 'TOKEN:', token );
},
// (required) Called when a remote or local notification is opened or received
onNotification: function(notification) {
console.log( 'NOTIFICATION:', notification );
},
// ANDROID ONLY: (optional) GCM Sender ID.
// senderID: "YOUR GCM SENDER ID",
// IOS ONLY (optional): default: all - Permissions to register.
// permissions: {
// alert: true,
// badge: true,
// sound: true
// },
// Should the initial notification be popped automatically
// default: true
popInitialNotification: true,
/**
* (optional) default: true
* - Specified if permissions (ios) and token (android and ios) will requested or not,
* - if not, you must call PushNotificationsHandler.requestPermissions() later
*/
// requestPermissions: true,
});
const username = intialEmail;
const password = intialName;
// I want to store the fcm token
const newToken = ???;
try {
//await AsyncStorage.setItem('username', username);
await AsyncStorage.setItem('password', password);
} catch (e) {
// saving error
}
fetch('https://example.com/login.php', {
method: 'post',
header: {
Accept: 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify({
//email: username,
password: password,
}),
})
.then(response => response.json())
.then(responseJson => {
if (responseJson == 'Login Successful') {
//alert("Login Successful");
navigation.navigate('New', {reference: password});
} else {
alert('Incorrect Login Details');
}
})
.catch(error => {
console.error(error);
});
};
const getData = async () => {
try {
// const username = await AsyncStorage.getItem('username');
const password = await AsyncStorage.getItem('password');
// if (username !== null) {
// setEmail(username);
// }
if (password !== null) {
// value previously stored
setName(password);
}
} catch (e) {
// error reading value
}
};
useEffect(() => {
getData();
}, []);
return (
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#fe5900',
}}>
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
{/*<Image style={{resizeMode: 'contain', width:200}} source={require('./assets/logo.png')} />*/}
<Text style={{color: 'white'}}>
Welcome to Smile
</Text>
<Image
style={{width: 200, height: 100, resizeMode: 'contain'}}
source={{
uri: 'https://example.com/img/logo.png',
}}
/>
<TextInput
style={{
backgroundColor: 'white',
paddingLeft: 10,
marginBottom: 10,
width: 300,
height: 50,
color: 'grey',
}}
autoCapitalize="none"
// secureTextEntry={true}
placeholder="Enter your reference no"
value={intialName}
onChangeText={newName => setName(newName)}
/>
<TouchableOpacity
style={{
backgroundColor: '#333',
marginTop: 15,
textAlign: 'center',
width: 150,
paddingTop: 10,
paddingBottom: 10,
paddingLeft: 20,
paddingRight: 20,
}}
onPress={userRegister}>
<Text style={{textAlign: 'center', color: 'white'}}>Login</Text>
</TouchableOpacity>
<TouchableOpacity
style={{
marginTop: 15,
textAlign: 'center',
width: 150,
paddingTop: 10,
paddingBottom: 10,
paddingLeft: 20,
paddingRight: 20,
}}
onPress={() => navigation.navigate('Register')}>
<Text style={{textAlign: 'center', color: 'white'}}>
Forget Password
</Text>
</TouchableOpacity>
</View>
</View>
);
};
const Stack = createStackNavigator();
const App = () => {
return (
<NavigationContainer>
{
<Stack.Navigator initialRoutName="Home">
<Stack.Screen
name="Star"
component={LoginScreen}
options={({navigation, route}) => ({
title: 'Smile Shop',
headerStyle: {
backgroundColor: '#333',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
//headerRight: () => (
// <View style={{flex:1, height:25, flexDirection:'row', paddingRight:10, marginTop:10, marginBottom:10}}>
// <View style={{marginRight:10}}>
// <Button
// onPress={() => navigation.navigate('Login')}
// title="Register"
// color="#020"
// height='30'
// />
// </View>
// <View>
// <Button
// onPress={() => navigation.navigate('Login')}
// title="Login"
// color="#020"
// />
// </View>
// </View>
//),
})}
/>
{/* <Stack.Screen name="Details" component={DetailsScreen} /> */}
{/* <Stack.Screen name="Product" component={ProductScreen} /> */}
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen
name="New"
component={NewScreen}
options={{
title: 'Dashboard',
headerStyle: {
backgroundColor: '#333',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
/>
</Stack.Navigator>
}
</NavigationContainer>
);
};
export default App;
Android> Build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext {
buildToolsVersion = "29.0.2"
minSdkVersion = 16
compileSdkVersion = 29
targetSdkVersion = 29
}
repositories {
google()
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:3.5.3")
classpath('com.google.gms:google-services:4.3.3')
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
mavenLocal()
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
}
maven {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
google()
jcenter()
maven { url 'https://www.jitpack.io' }
}
}
Android>应用> build.gradle
apply plugin: "com.android.application"
apply plugin: 'com.google.gms.google-services'
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. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://reactnative.dev/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // 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 = [
enableHermes: false, // clean and rebuild if changing
]
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
/**
* The preferred build flavor of JavaScriptCore.
*
* For example, to use the international variant, you can use:
* `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
* give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Whether to enable the Hermes VM.
*
* This should be set on project.ext.react and mirrored here. If it is not set
* on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
* and the benefits of using Hermes will therefore be sharply reduced.
*/
def enableHermes = project.ext.react.get("enableHermes", false);
android {
compileSdkVersion rootProject.ext.compileSdkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "com.prosmile"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
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"
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
keyPassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
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:
// https://developer.android.com/studio/build/configure-apk-splits.html
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 fileTree(dir: "libs", include: ["*.jar"])
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation project(':react-native-push-notification')
implementation 'com.google.firebase:firebase-analytics:17.2.2'
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
exclude group:'com.squareup.okhttp3', module:'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
debugImplementation files(hermesPath + "hermes-debug.aar")
releaseImplementation files(hermesPath + "hermes-release.aar")
} else {
implementation jscFlavor
}
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
MainApplicaion.java
package com.prosmile;
import android.app.Application;
import android.content.Context;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
//packages.add(new ReactNativePushNotificationPackage());
return packages;
}
@Override
protected String getJSMainModuleName() {
return "index";
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.prosmile.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
settings.gradle文件
rootProject.name = 'prosmile'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':react-native-push-notification'
project(':react-native-push-notification').projectDir = file('../node_modules/react-native-push-notification/android')
include ':app'
package.json
{
"name": "prosmile",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"@react-native-community/async-storage": "^1.11.0",
"@react-native-community/masked-view": "^0.1.10",
"@react-native-firebase/app": "^8.3.0",
"@react-navigation/native": "^5.7.3",
"@react-navigation/stack": "^5.9.0",
"react": "16.13.1",
"react-native": "0.63.2",
"react-native-gesture-handler": "^1.7.0",
"react-native-push-notification": "^5.0.1",
"react-native-reanimated": "^1.10.2",
"react-native-safe-area-context": "^3.1.4",
"react-native-screens": "^2.10.1"
},
"devDependencies": {
"@babel/core": "7.11.1",
"@babel/runtime": "7.11.2",
"@react-native-community/eslint-config": "1.1.0",
"babel-jest": "25.5.1",
"eslint": "6.8.0",
"jest": "25.5.4",
"metro-react-native-babel-preset": "0.59.0",
"react-test-renderer": "16.13.1"
},
"jest": {
"preset": "react-native"
}
}
生成了FCM令牌,但收到通知后应用崩溃了。
答案 0 :(得分:0)
答案 1 :(得分:0)
很确定在组件内部包含PushNotification.configure()
是破坏它,或者至少破坏了一部分。