本机反应:安装下载的apk

时间:2017-01-03 07:09:31

标签: android react-native

我正在做反应原生的自动更新模块。对于Android版本,应该下载新版本的apk并安装它。可以使用react-native-fs下载apk,但我如何安装apk? 或者更一般,我如何在react本机应用程序中运行外部文件?

3 个答案:

答案 0 :(得分:2)

不。您不能在通用情况下(在root设备上可能是这种情况)。

这是谷歌市场(或供应商市场)的任务。当您将新版本的应用程序推向市场时,它应该可以开箱即用,当然用户可以选择自动更新。

但是,您可以启动安装对话框,请参阅:Install Application programmatically on Android

要下载文件,应用程序可以使用react-native-fs模块。

要使用显式数据类型application/vnd.android.package-archive打开Intent,可以使用react-native-mime-intent

答案 1 :(得分:1)

我知道已经过去了一段时间,但是@vovkasm答案已经很长时间了。您可以使用rn-fetch-blob实现自己想要的 那就是我在应用程序中所做的-从URL下载.apk,然后完成下载后自动运行安装,这会将应用程序更新为新版本。 它同时提供:下载和打开文件。 请记住,对于android 8+,这要求对清单中的REQUEST_INSTALL_PACKAGES具有附加的签名许可权,但前提是所有文件都可以正常运行。

下载带有操作视图意图的.apk的简单示例:

RNFetchBlob.android.actionViewIntent(
      resource.path(), //path where the file is downloaded
      "application/vnd.android.package-archive",
    )

正如@vovkasm所写,仍然可以使用react-native-fs下载文件,不确定是否要读取.apk tho。

我注意到react-native-fs没有处理连接错误和下载进度,这在rn-fetch-blob上不起作用,但是另一方面,rn-fetch-blob支持下载管理器,而{{ 1}}不会...您总是可以根据需要混合使用两者:)

答案 2 :(得分:-1)

是的,你可以做到。 https://github.com/mikehardy/react-native-update-apk

1-创建 Updater.js 根目录并将 fileProviderAuthority 编辑为 throw new AuthenticationError('You do not have permission for this request');

your package name + .provider

2- 添加库和添加文件

        import {Alert} from 'react-native';
        import * as UpdateAPK from 'rn-update-apk';
        
        export default (onStart, onComp) => {
          const update = new UpdateAPK.UpdateAPK({
            iosAppId: '1104809018',
            apkVersionUrl: 'https://example.com/apk/test-version.json',
//Must have test version json file and apk file to the remote server. You can find the contents of the Json file in the repo on the link and examine it.
            fileProviderAuthority: 'com.lorien.provider',
        
            needUpdateApp: (needUpdate) => {
              needUpdate(true);
        
            },
        
            forceUpdateApp: () => {
              console.log('forceUpdateApp callback called');
            },
        
            notNeedUpdateApp: () => {
              console.log('notNeedUpdateApp callback called');
            },
        
            downloadApkStart: () => {
              console.log('downloadApkStart callback called');
            },
        
            downloadApkProgress: (progress) => {
              console.log(`downloadApkProgress callback called - ${progress}%...`);
              onStart(progress);
            },
        
            downloadApkEnd: () => {
              console.log('downloadApkEnd callback called');
              onComp();
            },
            onError: (err) => {
              console.log('onError callback called', err);
              Alert.alert('There was an error', err.message);
            },
          });
        
              update.checkUpdate();
            };
    

3- 像这样编辑 Android 清单:(关注 xmlns 行、权限和提供者标签)

    npm install rn-update-apk 
(You may need to replace it if you get an error. Find the library in react_modules and change this line as import change tandroidx.core.content.FileProvider)
    npm install react-native-fs
    npm install react-native-exit-app
    npm install react-native-simple-dialogs
    
    Add files
    
    go android>app>src>main>res
    create a folder named xml
    
    and create a js file named filepaths.xml in xml folder like this:
    
        <?xml version="1.0" encoding="utf-8"?>
        <paths xmlns:android="http://schemas.android.com/apk/res/android">
          <cache-path name="cache" path="/" /> 
        </paths>
    

4- 在主js中使用和调用UPDATER:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.lorien"
      xmlns:tools="http://schemas.android.com/tools">
    
        <uses-permission android:name="android.permission.INTERNET" />
        <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
    
        <application
          android:name=".MainApplication"
          android:label="@string/app_name"
          android:icon="@mipmap/ic_launcher"
          android:roundIcon="@mipmap/ic_launcher_round"
          android:allowBackup="false"
          android:usesCleartextTraffic="true"
          android:theme="@style/AppTheme">
          <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
          </activity>
          <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
          <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <!-- you might need the tools:replace thing to workaround rn-fetch-blob or other definitions of provider -->
            <!-- just make sure if you "replace" here that you include all the paths you are replacing *plus* the cache path we use -->
            <meta-data tools:replace="android:resource"
              android:name="android.support.FILE_PROVIDER_PATHS"
              android:resource="@xml/filepaths" />
          </provider>
        </application>
    
    </manifest>