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];
}
·······
网友评论