ReactNative-Android 从ReactNative项目创建到CodePush 热更新部署

1. 首先声明下环境:因为环境而造成的坑太多了,我都忍不住吐槽N遍了,所以在开始整活之前先搞清楚我们现在用的环境。

2. 首先查看下所使用的 ndoejs 版本 nodejs 16.10.0

E:\ReactLove\rn_hello\rnHello_CodePush_060>node -v
v16.10.0

E:\ReactLove\rn_hello\rnHello_CodePush_060>nvm list

  * 16.10.0 (Currently using 64-bit executable)
    12.18.0
    12.2.0

注意:这里使用的 nvm 是为了方便管理和使用不同的 nodejs,因为不同版本的ReactNative可能会需要不同版本的 nodejs 环境, 否则在构建项目的时候,会发生各种令人吐槽的事情。

3. 查看下 ReactNative 版本

E:\ReactLove\rn_hello\rnHello_CodePush_060>react-native -v
react-native-cli: 2.0.1
react-native: 0.60.0

这里我们可以看到,我们已经安装了 react-native-cli 命令行,然后我们开始准备使用该命令行创建我们新的ReactNative项目,版本是0.60.0。

4. 创建 ReactNative 项目

E:\ReactLove\rn_hello>npx react-native init rnCodePushDemo_060 --version 0.60.0

5. 创建好项目之后,需要修改三个地方,然后才能正常使用,否则直接执行命令 react-native run-android 会报错的,这是经过实战经验所得。

5.1 修改项目根目录下的 babel.config. js 文件

module.exports = {
  presets: [[
    'module:metro-react-native-babel-preset',{
      unstable_disableES6Transforms: true
    }
  ]],
};

5.2 修改项目根目录下的 package.json 文件

{
  "name": "rnCodePushDemo_060",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "react-native start",
    "test": "jest",
    "lint": "eslint ."
  },
  "dependencies": {
    "react": "16.8.6",
    "react-native": "0.60.0"
  },
  "devDependencies": {
    "@babel/core": "7.19.3",
    "@babel/runtime": "7.19.4",
    "@react-native-community/eslint-config": "0.0.3",
    "babel-jest": "24.9.0",
    "eslint": "5.16.0",
    "jest": "24.9.0",
    "metro-react-native-babel-preset": "0.59.0",
    "react-test-renderer": "16.8.6"
  },
  "resolutions": {
    "@babel/traverse": "7.16.7"
  },
  "jest": {
    "preset": "react-native"
  }
}

 "devDependencies": {
    ....
    "metro-react-native-babel-preset": "0.59.0",
  },
  "resolutions": {
    "@babel/traverse": "7.16.7"
  },

如上红色标注的部分,就是在 package.json 文件中修改的内容。

5.3 修改项目 \node_modules\metro-config\src\defaults 目录下的 blacklist.js 文件中的内容

var sharedBlacklist = [

  /node_modules[\/\\]react[\/\\]dist[\/\\].*/,

  /website\/node_modules\/.*/,

  /heapCapture\/bundle\.js/,

  /.*\/__tests__\/.*/

];

黄色部分就是要修改的部分内容,否则在项目直接进行编译和启动的时候,会存现nodejs 服务启动之后就一闪而过,就结束 nodejs 服务了,自然也没法进行项目开发了。

6. 在修改以上三个地方的内容之后,就可以尝试编译和启动React Native项目了

E:\ReactLove\rn_hello\rnCodePushDemo_060>react-native run-android

最终就可以顺利启动项目了, 展示如下:

终端:

nodejs 服务端:

7. 在顺利编译并启动项目之后,我们就开始准备热更新的部分。

热更新其实就是将ReactNative项目中的js打包成一个bundle文件,然后放到服务器上,在应用需要热更新的时候,从服务器上下载这个新的bundle文件,然后将这个bundle文件载入ReactNative框架中,然后进行更新,这样就无须下载新的 Android apk 包,实现业务的更新或者Bug的修改,这也是React Native 被好多大厂所看好的原因,目前除了大厂自研的Android原生热更新框架,下面就是这种类型的热更新是最好的了,其他要不是没有人用,要不就是大厂自己搞着自己玩的,也不开源,没啥意思,能让大家用的也就是React Native。Flutter 除了几家大厂推出来的框架,也不成气候,没啥大意思,估计过几年也就没有前途了,只有用的人多才是有前途的跨平台框架和热更新框架。CodePush 是 微软针对 React Native 推出的热更新插件,可以将新的Bundle文件推送到CodePush 平台上,然后供大家进行下载、加载进行热更新。 

8. 在了解了什么是热更新之后,我们正式开始热更新插件的接入:

8.1 首先安装 code-push-cli 命令行工具,如下是全局安装

E:\ReactLove\rn_hello\rnHello_060>npm install -g code-push-cli

8.2 注册 CodePush

E:\ReactLove\rn_hello\rnHello_060>code-push register

这里会弹出一个网站,然后我这里选择使用Github进行登录,然后授权之后,就会弹出包含如下内容的弹框:

Authentication succeeded
Please copy and paste this token to the command window:

558aa5b330e8262fe292a58c4366847a2ff3a3b7

After doing so, please close this browser tab.

将这串字符粘贴到刚才的命令行窗口中,你会得到如下内容:

Enter your token from the browser: 558aa5b330e8262fe292a58c4366847a2ff3a3b7

Successfully logged-in. Your session file was written to C:\Users\PCWin10\AppData\Local\.code-push.config.
You can run the code-push logout command at any time to delete this file and terminate your session.

8.3 注册成功后,应该不会再使用这个 code-push register 命令,除非你想推出重新登录。

8.4 向CodePush服务器注册新的 App

//AppName 就是你要创建的应用名称
//platform 可以使 ios 或者 Android
code-push app add <AppName> <platform> react-native

向CodePush服务器注册一个新的App,名称为 CodePushDemo,命令如下:

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push app add CodePushDemo Android react-native

命令执行完成之后,会看到如下结果:

│ Name       │ Deployment Key                        │
├────────────┼───────────────────────────────────────┤
│ Production │ mcNDEqhhKH2fvm_NNVSzwC1JVPgpaSLFU9WAj │
├────────────┼───────────────────────────────────────┤
│ Staging    │ 4O616rtg7BGZTaH_ynL0QIZynLjIzQvd0WNn_ │ 

上面是一套部署的Key, 分为 Staging 开发版本和 Production 版本,我们这里使用的是开发版本。

注册的App 应用情况可以通过 https://appcenter.ms/apps 来查看,如下:

其中,CodePushDemo 就是我们刚刚创建的项目。

8.5 集成 CodePush SDK ,添加 code-push 包

E:\ReactLove\rn_hello\rnCodePushDemo_060>npm install --save react-native-code-push

8.6 如果8.5 没有提示说输入 Deployment Key,那么我们需要手动配置,如果忘记 Deployment Key,可以通过如下命令来查看:

code-push deployment ls CodePushDemo -k
E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push deployment ls CodePushDemo -k
(node:8212) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
┌────────────┬───────────────────────────────────────┬─────────────────────┬──────────────────────┐
│ Name       │ Deployment Key                        │ Update Metadata     │ Install Metrics      │
├────────────┼───────────────────────────────────────┼─────────────────────┼──────────────────────┤
│ Production │ mcNDEqhhKH2fvm_NNVSzwC1JVPgpaSLFU9WAj │ No updates released │ No installs recorded │
├────────────┼───────────────────────────────────────┼─────────────────────┼──────────────────────┤
│ Staging    │ 4O616rtg7BGZTaH_ynL0QIZynLjIzQvd0WNn_ │ No updates released │ No installs recorded │
└────────────┴───────────────────────────────────────┴─────────────────────┴──────────────────────┘

8.7 手动配置,首先用AndroidStudio 打开 android 项目,然后再 android/settings.gradle 文件中添加如下内容:

include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')

8.8 在 app/build.gradle 文件中添加如下内容:

apply from: '../../node_modules/react-native-code-push/android/codepush.gradle'

//下面这行如果有,则不加
apply from: "../../node_modules/react-native/react.gradle"

8.9 在 MainApplication.java 文件中,添加如下内容:

  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());
      return packages;
    }

    @Override
    protected String getJSMainModuleName() {
      return "index";
    }

    @Nullable
    @Override
    protected String getJSBundleFile() {
      return CodePush.getJSBundleFile();
    }
    
  };

    @Nullable
    @Override
    protected String getJSBundleFile() {
      return CodePush.getJSBundleFile();
    }

红色标记部分即为要添加的内容,注意引入 import CodePush 类。

8.10 在 res/values/strings.xml 中添加 CodePushDeploymentKey,这里内容填写的就是前面获取到的 StagingKey。

<resources>
    ... 
    <string name="CodePushDeploymentKey">4O616rtg7BGZTaH_ynL0QIZynLjIzQvd0WNn_</string>
</resources>

8.11 在 app/build.gradle 文件中,添加如下内容:

android {
  ....
 
  buildTypes {
        debug {
            signingConfig signingConfigs.debug
        }
        release {
            // Caution! In production, you need to generate your own keystore file.
            // see https://facebook.github.io/react-native/docs/signed-apk-android.
            //填入 PRODUCTION_KEY
            buildConfigField "String", "CODEPUSH_KEY", '"mcNDEqhhKH2fvm_NNVSzwC1JVPgpaSLFU9WAj"'
            signingConfig signingConfigs.debug
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        }
        releaseStaging {
            minifyEnabled enableProguardInReleaseBuilds
            proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
            //填入 STAGING_KEY
            buildConfigField "String", "CODEPUSH_KEY", '"4O616rtg7BGZTaH_ynL0QIZynLjIzQvd0WNn_"'
        }
    }
  ...

}

8.12  如上,就已经完成了原生部分的代码,下面开始JavaScript 部分的配置:

8.13  在ReactNative项目中的 App.js 文件中进行如下修改:

import React from 'react';
import {
  View,
  Text,
} from 'react-native';

import CodePush from 'react-native-code-push';

const codePushOptions = {
  checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
  updateDialog: true, //发现可更新时是否显示对话框
  installMode: CodePush.InstallMode.IMMEDIATE,
};

class App extends React.Component {

  render() {
    return (
        <View>
          <Text>版本号1.0</Text>
          <Text>我是1.0版本,希望大家能够喜欢</Text>
        </View>
    );
  }

  update = () => {
    CodePush.sync({
      // 安装模式
      // ON_NEXT_RESUME 下次恢复到前台时
      // ON_NEXT_RESTART 下一次重启时
      // IMMEDIATE 马上更新
      installMode: CodePush.InstallMode.IMMEDIATE,
      // 对话框 如果打包和上传没有设置强制更新的话,那么默认就是非强制更新,显示的都是非强制更新配置的内容
      updateDialog: {
        // 是否显示更新描述
        appendReleaseDescription: true,
        // 更新描述的前缀。 默认为"Description"
        descriptionPrefix: '更新内容:',
        // 强制更新按钮文字,默认为continue
        mandatoryContinueButtonLabel: '立即更新',
        // 强制更新时的信息. 默认为"An update is available that must be installed."
        mandatoryUpdateMessage: '必须更新后才能使用',
        // 非强制更新时,按钮文字,默认为"ignore"
        optionalIgnoreButtonLabel: '稍后',
        // 非强制更新时,确认按钮文字. 默认为"Install"
        optionalInstallButtonLabel: '后台更新',
        // 非强制更新时,检查到更新的消息文本
        optionalUpdateMessage: '有新版本了,是否更新?',
        // Alert窗口的标题
        title: '更新提示',
      },
    }).then(r => {

    });
  };

  async componentWillMount() {
    CodePush.disallowRestart(); //禁止重启
    this.update();//开始检查更新
  }

  componentDidMount() {
    CodePush.allowRestart();//加载完了,允许重启
  }
}

App = CodePush(codePushOptions)(App);
export default App;

在 index.js 文件中进行如下修改:

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';

//添加如下关闭黄色警告
console.disableYellowBox = true; //关闭全部黄色警告
console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please use BackHandler instead.'];

AppRegistry.registerComponent(appName, () => App);

//添加如下关闭黄色警告
console.disableYellowBox = true; //关闭全部黄色警告
console.ignoredYellowBox = ['Warning: BackAndroid is deprecated. Please use BackHandler instead.'];

8.14 执行 react-native run-android 命令,编译并启动 项目:

E:\ReactLove\rn_hello\rnCodePushDemo_060>react-native run-android

结果如下,即没有进行新的内容修改之前的展示内容:

8.15 对页面的内容进行修改

<View>
     <Text>版本号1.1</Text>
     <Text>我是1.1版本,此版本新增加了许多新的功能,欢迎体验!</Text>
</View>

 8.16 打包并上传 bundle 文件,命令如下,CodePushDemo 就是前面设置的App项目名称, android 为平台类型。

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push release-react CodePushDemo android
E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push release-react CodePushDemo android
(node:7820) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
Detecting android app version:

Using the target binary version value "1.0" from "android\app\build.gradle".

Running "react-native bundle" command:

node node_modules\react-native\local-cli\cli.js bundle --assets-dest C:\Users\PCWin10\AppData\Local\Temp\CodePush\CodePush --bundle-output C:\Users\PCWin10\AppData\Local\Temp\CodePush\CodePush\index.android.bundle --dev false --entry-file index.js --platform android
Loading dependency graph, done.

info Writing bundle output to:, C:\Users\PCWin10\AppData\Local\Temp\CodePush\CodePush\index.android.bundle
info Done writing bundle output
info Copying 2 asset files
info Done copying assets

Releasing update contents to CodePush:

Upload progress:[==================================================] 100% 0.0s
Successfully released an update containing the "C:\Users\PCWin10\AppData\Local\Temp\CodePush\CodePush" directory to the "Staging" deployment of the "CodePushDemo" app.

E:\ReactLove\rn_hello\rnCodePushDemo_060>

8.17 在上传完成之后,可以查看 CodePush 平台上的发布历史记录,刚才发布的也在其中,命令如下:CodePushDemo 是App 项目的名称

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push deployment history CodePushDemo Staging
(node:14968) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
(Use `node --trace-warnings ...` to show where the warning was created)
┌───────┬───────────────┬─────────────┬───────────┬─────────────┬──────────────────────┐
│ Label │ Release Time  │ App Version │ Mandatory │ Description │ Install Metrics      │
├───────┼───────────────┼─────────────┼───────────┼─────────────┼──────────────────────┤
│ v1    │ 8 minutes ago │ 1.0         │ No        │             │ No installs recorded │
└───────┴───────────────┴─────────────┴───────────┴─────────────┴──────────────────────┘

E:\ReactLove\rn_hello\rnCodePushDemo_060>

8.18 在发布到平台完成之后,我们可以开始测试,首先将当前正在运行的该项目App杀掉,然后进行重启,会发现弹出如下弹框:

8.19 我们选择 后台更新,然后过几秒之后,页面就会重新刷新,变成如下内容:

8.20 杀掉App进程,重新启动, 会发现此次进入是没有弹出新的版本提示,说明当前已经是最新的版本。

9. 如何正式部署 Release 版本

因为执行以下命令默认是 Staging 版本的,即推送到 CodePush 平台之后,是在Staging环境中的,而不是 Production 环境的。

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push release-react CodePushDemo android

但是其实跟发布到哪种环境没有关系,其实都是可以的,我们先考虑 Staging 环境。比如我们先前已经打包好一个 Release 包,给用户安装到手机上了,那么请问,此时客户手机上的 deployment key 是什么类型的呢?如果没有改动,依据前面的是配置,我们在打release 包的时候,会发送报错,修改方式如下:

buildTypes {
    debug {
        signingConfig signingConfigs.debug
    }
    release {
        // Caution! In production, you need to generate your own keystore file.
        // see https://facebook.github.io/react-native/docs/signed-apk-android.
        //PRODUCTION_KEY
        buildConfigField "String", "CODEPUSH_KEY", '"mcNDEqhhKH2fvm_NNVSzwC1JVPgpaSLFU9WAj"'
        signingConfig signingConfigs.release
        minifyEnabled enableProguardInReleaseBuilds
        proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
    }
    releaseStaging {
        minifyEnabled enableProguardInReleaseBuilds
        signingConfig signingConfigs.release
        proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
        //STAGING_KEY
        buildConfigField "String", "CODEPUSH_KEY", '"4O616rtg7BGZTaH_ynL0QIZynLjIzQvd0WNn_"'
        matchingFallbacks = ['release', 'debug']
    }
}
signingConfigs {
        debug {
            storeFile file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }
        release {
            storeFile file(STORE_FILE)
            storePassword STORE_FILE_PASSWORD
            keyAlias KEY_ALIAS
            keyPassword KEY_ALIAS_PASSWORD
        }
}
// android/gradle.properties
STORE_FILE=./keystore/CodePushDemo.keystore
KEY_ALIAS=shudan-alias
STORE_FILE_PASSWORD=123456
KEY_ALIAS_PASSWORD=123456

 此时,如果没有修改 res/values/strings.xml 中的内容,那么依旧是 staging key 。

打包 release 包,命令如下:

E:\ReactLove\rn_hello\rnCodePushDemo_060\android>gradlew assembleRelease

然后安装到用户手机上,之后,修改 App.js 内容,再次将 bundle 文件推送到 CodePush 平台,执行的命令如下:

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push release-react CodePushDemo android

因为默认情况下是推送到 Staging 环境中的,因此此时 CodePush 最新的版本是在Staging环境中的,而用户手机上此时App的也是 Staging key,那么CodePush 服务器和 App 上的key 就能对的上,那么就能收到最新版本的提示,就能热更新。

如此说来,前面在 app/build.gradle 文件中定义的  buildConfigField "String", "CODEPUSH_KEY" 好像是没有用到,全靠的是 res/values/strings.xml 中定义的 

<string name="CodePushDeploymentKey">4O616rtg7BGZTaH_ynL0QIZynLjIzQvd0WNn_</string>

这个内容决定了手机App上使用的是那种类型的key, 如果这里采用了Production Key,那么在打包资源和推送到 CodePush 服务器的时候,命令行需要改成如下:

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push release-react CodePushDemo android -d Production

 -d : 表示指定上传的环境,Production 是生产环境,Staging 是开发环境。

结论:关于如何部署最新的版本的问题就看用户手机此时App中的是那种 Key, 此种 key 是配置在

app/res/values/strings.xml 中的  CodePushDeploymentKey 中。

1.  如果是 Staging Key, 那么打包推送的命令是:

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push release-react CodePushDemo android -d Staging

2. 如果是 Production Key, 那么打包推送的命令是:

E:\ReactLove\rn_hello\rnCodePushDemo_060>code-push release-react CodePushDemo android -d Production

10. 自己部署CodePush服务器

如果不想用微软提供的CodePush服务器来做热更新,那么可以考虑自己搭建环境,具体资料将来自己搞的时候再去查吧,暂时到此为止,知道如何将新的 bundle 文件更新到CodePush 服务器上即可。

11. 最后一个问题

既然是更新的javascript 的内容,那么如果新的内容如果是加载本地的图片资源,那么是否会一起打包到 bundle 文件中呢?

答案是可以的,可以将图片资源一块进行打包到bundle文件中,然后进行热更新。测试代码如下:

import React from 'react';
import {
  View,
  Text,
  Image,
  StyleSheet,
    Dimensions
} from 'react-native';

import CodePush from 'react-native-code-push';

const codePushOptions = {
  checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
  updateDialog: true, //发现可更新时是否显示对话框
  installMode: CodePush.InstallMode.IMMEDIATE,
};

class App extends React.Component {

  render() {
    return (
        <View style={styles.container}>
          <Image style={styles.image} resizeMode={"contain"} source={require("./images/laptop_phone_howitworks.png")}/>
          <Image style={{width: 50, height: 100}} resizeMode={"contain"} source={require("./images/laptop_phone_howitworks.png")}/>
          <Image style={styles.image} resizeMode={"contain"} source={{uri:"https://sample-videos.com/img/Sample-jpg-image-50kb.jpg"}}/>
          <Text>版本号1.4</Text>
          <Text>我是1.4版本,测试本地Staging 是否能够匹配服务器上的Production</Text>
        </View>
    );
  }

  update = () => {
    CodePush.sync({
      // 安装模式
      // ON_NEXT_RESUME 下次恢复到前台时
      // ON_NEXT_RESTART 下一次重启时
      // IMMEDIATE 马上更新
      installMode: CodePush.InstallMode.IMMEDIATE,
      // 对话框 如果打包和上传没有设置强制更新的话,那么默认就是非强制更新,显示的都是非强制更新配置的内容
      updateDialog: {
        // 是否显示更新描述
        appendReleaseDescription: true,
        // 更新描述的前缀。 默认为"Description"
        descriptionPrefix: '更新内容:',
        // 强制更新按钮文字,默认为continue
        mandatoryContinueButtonLabel: '立即更新',
        // 强制更新时的信息. 默认为"An update is available that must be installed."
        mandatoryUpdateMessage: '必须更新后才能使用',
        // 非强制更新时,按钮文字,默认为"ignore"
        optionalIgnoreButtonLabel: '稍后',
        // 非强制更新时,确认按钮文字. 默认为"Install"
        optionalInstallButtonLabel: '后台更新',
        // 非强制更新时,检查到更新的消息文本
        optionalUpdateMessage: '有新版本了,是否更新?',
        // Alert窗口的标题
        title: '更新提示',
      },
    }).then(r => {

    });
  };

  async componentWillMount() {
    CodePush.disallowRestart(); //禁止重启
    this.update();//开始检查更新
  }

  componentDidMount() {
    CodePush.allowRestart();//加载完了,允许重启
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: "center",
    backgroundColor: "#F5FCFF",
    paddingTop: 50
  },
  image: {
    margin: 30,
    width: Dimensions.get("window").width - 100,
    //height: 365 * (Dimensions.get("window").width - 100) / 651,
    height:100
  }
});

App = CodePush(codePushOptions)(App);
export default App;

注意,在第一次学习的时候,发现图片竟然加载不进来,就是怎么也不显示,最后发现是自己写法有问题:

<Image style={styles.image} resizeMode={"contain"} soure={require("./images/laptop_phone_howitworks.png")} />
 
<Image soure={{uri: "https://sample-videos.com/img/Sample-jpg-image-50kb.jpg"}} style={styles.image} resizeMode={"contain"}/>

发现没有,是source 写成了 soure,结果自然就不会显示,但是奇葩是尽然不报错,太坑爹,抱着这个问题查了两天。

参考:

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 APP center 中配置 React Native Pushcode,需要按照以下步骤进行操作: 1. 在 APP center 中创建一个新项目,并将其与你的 GitHub 或 Bitbucket 仓库关联。 2. 在你的 React Native 项目中安装 App Center Push SDK。可以使用以下命令: ``` npm install appcenter-push --save ``` 3. 在项目中添加以下代码,以初始化 App Center Push SDK: ```javascript import AppCenterPush from 'appcenter-push'; componentDidMount() { AppCenterPush.setListener({ onPushNotificationReceived: function (pushNotification) { console.log('Push notification received:' + pushNotification.message); } }); AppCenterPush.getInitialNotification().then(notification => { console.log('Initial notification:' + notification); }); } ``` 4. 在 App Center 中创建推送通知。可以通过以下步骤完成: - 在 App Center 中单击“推送”选项卡。 - 点击“新建”按钮。 - 输入通知的标题和正文。 - 选择要接收通知的应用程序。 - 选择要接收通知的设备。 - 点击“发送”按钮。 5. 在应用中测试推送通知。可以使用以下命令向应用发送推送通知: ``` curl -X POST \ -H "Content-Type: application/json" \ -H "X-API-Token: YOUR_API_TOKEN" \ -d '{ "notification_content": { "name": "test notification", "title": "test notification title", "body": "test notification body" }, "notification_target": { "type": "devices_target", "devices": ["YOUR_DEVICE_ID"] } }' \ https://api.appcenter.ms/v0.1/apps/YOUR_ORGANIZATION/YOUR_APP/push/notifications ``` 这将向设备发送一条测试通知。在应用中接收到通知后,可以在控制台中查看通知的日志信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值