美文网首页
flutter app升级

flutter app升级

作者: 林祖朋 | 来源:发表于2019-12-11 10:04 被阅读0次

App的升级,主要是Android和IOS的升级。

问题起因:
小编尝试了现有的flutter第三方升级,效果不是很理想,带来很多的问题,比如编译不通过,跳转失败,无法安装等问题。于是决定用flutter与原生交互一下,看能否解决这个问题。

思路:
Android升级,主要有两种方式,跳转应用商店和应用内下载升级。这里主要探讨应用内下载方式。IOS升级则是直接跳转AppStore。经过综合考虑,针对于Android升级,先用flutter程序去下载最新的Apk到指定的位置。然后调用原生方法去升级。对于IOS升级,直接调用原生方法,去AppStore升级。

详细流程代码:

 //与原生通信的通道。
  var methodChannel = MethodChannel('com.lin.app/main');

  void _up() async {
   
    if (Platform.isAndroid) {
      //安卓下载并升级
      //这里将apk下载到应用下的cache文件夹。避免了请求内存权限。
      Directory tempDir = await getTemporaryDirectory();
      //apk的文件地址
      _savePath = tempDir.path + "/app.apk";

      HttpTool.download(widget._downLoadApkUrl, _savePath, _cancelToken,
          (int count, int total) {
        print("下载进度$count");
        print("下载总量$total");

        if (count == total) {
          //安装apk
          // MyToast.show("go安装apk");
          onClickInstallApk();
        } else {
          _yesUping = true;

          _progress = count ~/ (1024 * 1024);
          _total = total ~/ (1024 * 1024);

          setState(() {});
        }
      });
    } else if (Platform.isIOS) {
      //ios 直接跳应用商店
      onClickGotoAppStore();
    }
  }

 void onClickInstallApk() async {
    await methodChannel.invokeListMethod("installApk");
  }

  void onClickGotoAppStore() async {
    await methodChannel.invokeListMethod("goUp");
  }

Android端准备如下:

1.在AndroidManifest.xml中需添加一下:

    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

2.在application中:

<!-- 适配Android 7.0 拍照 和安装app -->
        <provider

            tools:replace="android:authorities"
            android:name="androidx.core.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                tools:replace="android:resource"
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths" />
        </provider>

3.在app/res/xml中新建provider_paths文件,详细内容如下:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">

   <cache-path
       name="cache_files"
       path="."/>

</paths>

MainActivity处理方式:

package com.yuhang.mall;

import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;


import androidx.core.content.FileProvider;

import java.io.File;

import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {

    /*
       1、通道名字,为任意但唯一的字符串,一般以包名开头区分
       2、必须和Dart代码中的通道名字一致
    */
    private static final String CHANNEL = "com.lin.app/main";
    //方法名字,必须和Dart端保持一致
    private static final String InstallApk = "installApk";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    GeneratedPluginRegistrant.registerWith(this);

    new MethodChannel(getFlutterView(),CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
        @Override
        public void onMethodCall(MethodCall call, MethodChannel.Result result) {
            switch (call.method){
                case InstallApk:
                    goInstall();
                    break;
                 default:
                     break;
            }
        }
    });

  }

    private void goInstall() {
     //apk路径一定得和flutter下载apk的位置一致。
      String apkName=getCacheDir().getPath()+"/app.apk";
        try {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (Build.VERSION.SDK_INT >= 24) {
               //7.0以下处理
                Uri apkUri = FileProvider.getUriForFile(MainActivity.this,
                         "com.lin.app.provider", new File(apkName));
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
            } else {
                intent.setDataAndType(Uri.parse("file://" + apkName), "application/vnd.android.package-archive");
            }
            startActivity(intent);
        } catch (Exception e) {

        }
    }

}

IOS端:
在Runner下新建FlutterNativePlugin.h,详细代码如下:

#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>

NS_ASSUME_NONNULL_BEGIN

@interface FlutterNativePlugin : NSObject <FlutterPlugin>

@end

NS_ASSUME_NONNULL_END

在Runner下新建FlutterNativePlugin.m,详细代码如下:

#import <Foundation/Foundation.h>

#import "FlutterNativePlugin.h"

@implementation FlutterNativePlugin

+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar> *)registrar {
    FlutterMethodChannel *channel = [FlutterMethodChannel methodChannelWithName:@"com.lin.app/main" binaryMessenger:[registrar messenger]];
    FlutterNativePlugin *instance = [[FlutterNativePlugin alloc]init];
    [registrar addMethodCallDelegate:instance channel:channel];
}

- (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result {
    if ([call.method isEqualToString:@"goUp"]) {
        NSLog(@"success to goUp");
        //跳转去appstore 100000000是appId
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1000000000"]];
        
    }else {
        result(FlutterMethodNotImplemented);
    }
}

@end

在AppDelegate中。

········
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  [GeneratedPluginRegistrant registerWithRegistry:self];
    
  [FlutterNativePlugin registerWithRegistrar:[self registrarForPlugin:@"FlutterNativePlugin"]];

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
·······

相关文章

网友评论

      本文标题:flutter app升级

      本文链接:https://www.haomeiwen.com/subject/cfxogctx.html