From 828cb4ef2578631a1a6376fd2b3a3f82a3ca9e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cyanghuaxuan=E2=80=9D?= <“646903573@qq.com”> Date: Thu, 22 Apr 2021 16:28:56 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=A2=9E=E5=8A=A0=E5=8E=9F=E7=94=9FandroidWe?= =?UTF-8?q?bView=202.=E5=85=B3=E4=BA=8E=E6=88=91=E4=BB=AC=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=9A=90=E7=A7=81=E6=94=BF=E7=AD=96=203.=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E6=88=91=E7=9A=84=E9=92=B1=E5=8C=85=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/build.gradle | 7 +- android/src/main/AndroidManifest.xml | 14 +- .../zhiying_base_widget/WebViewActivity.java | 541 ++++++++++++++++++ .../ZhiyingBaseWidgetPlugin.java | 113 ++-- .../ic_baseline_keyboard_arrow_left_24.xml | 5 + .../res/drawable/ic_baseline_refresh_24.xml | 5 + .../src/main/res/layout/activity_web_view.xml | 67 +++ android/src/main/res/values/strings.xml | 1 + example/pubspec.yaml | 2 +- lib/pages/about_us_page/about_us_page.dart | 54 +- .../about_us_page/model/about_us_model.dart | 80 ++- lib/register.dart | 16 +- .../wallet/wallet_detail/wallet_detail.dart | 4 + .../wallet_detail/wallet_detail_bloc.dart | 7 +- lib/zhiying_base_widget.dart | 26 + 15 files changed, 876 insertions(+), 66 deletions(-) create mode 100644 android/src/main/java/cn/zhios/zhiying_base_widget/WebViewActivity.java create mode 100644 android/src/main/res/drawable/ic_baseline_keyboard_arrow_left_24.xml create mode 100644 android/src/main/res/drawable/ic_baseline_refresh_24.xml create mode 100644 android/src/main/res/layout/activity_web_view.xml create mode 100644 android/src/main/res/values/strings.xml diff --git a/android/build.gradle b/android/build.gradle index cc4941b..58f4345 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -25,7 +25,7 @@ android { compileSdkVersion 28 defaultConfig { - minSdkVersion 16 + minSdkVersion 21 testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } lintOptions { @@ -36,3 +36,8 @@ android { } } + +dependencies { + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' +} diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index ac98fab..8db7e8d 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,3 +1,13 @@ + - + package="cn.zhios.zhiying_base_widget"> + + + + + + \ No newline at end of file diff --git a/android/src/main/java/cn/zhios/zhiying_base_widget/WebViewActivity.java b/android/src/main/java/cn/zhios/zhiying_base_widget/WebViewActivity.java new file mode 100644 index 0000000..0f8d1fb --- /dev/null +++ b/android/src/main/java/cn/zhios/zhiying_base_widget/WebViewActivity.java @@ -0,0 +1,541 @@ +package cn.zhios.zhiying_base_widget; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import android.Manifest; +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.graphics.drawable.ColorDrawable; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyEvent; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; +import android.webkit.GeolocationPermissions; +import android.webkit.WebChromeClient; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Logger; + + +public class WebViewActivity extends AppCompatActivity { + + WebView webview; + ImageView back; + ImageView refresh; + + ProgressBar progressBar; + + TextView tvTitle; + + Boolean isRequestPre = false; + String url; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_web_view); + getWindow().setStatusBarColor(Color.TRANSPARENT); + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR); + url = getIntent().getStringExtra("url"); + Log.d("请求连接:", url); + webview = findViewById(R.id.web); + + back = findViewById(R.id.iv_back); + refresh = findViewById(R.id.iv_refresh); + progressBar = findViewById(R.id.pg_bar); + tvTitle = findViewById(R.id.tv_title); + + back.setOnClickListener( + new View.OnClickListener() { + @Override + public void onClick(View v) { + if (webview.canGoBack()) { + webview.goBack(); + } else { + isRequestPre = false; + finish(); + } + } + } + ); + + + refresh.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + webview.reload(); + } + }); + + + WebSettings settings = webview.getSettings(); + + settings.setJavaScriptEnabled(true);//启用js + + settings.setJavaScriptCanOpenWindowsAutomatically(true);//js和android交互 + +// String cacheDirPath = PathCommonDefines.WEBVIEW_CACHE; +// +// settings.setAppCachePath(cacheDirPath); //设置缓存的指定路径 + + settings.setAllowFileAccess(true); // 允许访问文件 + + settings.setAppCacheEnabled(true); //设置H5的缓存打开,默认关闭 + + settings.setUseWideViewPort(true);//设置webview自适应屏幕大小 + + settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);//设置,可能的话使所有列的宽度不超过屏幕宽度 + + settings.setLoadWithOverviewMode(true);//设置webview自适应屏幕大小 + + settings.setDomStorageEnabled(true);//设置可以使用localStorage + + settings.setSupportZoom(false);//关闭zoom按钮 + + settings.setBuiltInZoomControls(false);//关闭zoom + + settings.setGeolocationEnabled(true); + + webview.setVerticalScrollBarEnabled(false); +// +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { +// webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null); +// +// } + + + webview.setWebViewClient(new WebViewClient() { + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + Log.d("WEB重定向", url); + if (WebViewActivity.this.isFinishing()) { + return true; + } + Intent intent2 = new Intent(); + intent2.putExtra("url", url); + WebViewActivity.this.setResult(20210501, intent2); + + if (url.startsWith("http://") || url.startsWith("https://")) { + + } else { + try { + /** + * 统一的scheme协议打开第三方app,若出错说明没有安装该app + * 捕获到错误后不继续加载该url以免加载出错 + */ + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + return true; + } catch (Exception e) { + + } + } + + if (url.startsWith("tel:")) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); + return true; + } + if (url.startsWith("bdnetdisk:")) { + return true; + } + if (url.contains("vipshop://")) {//打开唯品会 + if (isAvilible(WebViewActivity.this, "com.achievo.vipshop")) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(intent); + } else { + Toast.makeText(WebViewActivity.this, "请先安装唯品会app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.contains("androidamap://")) { + if (isAvilible(WebViewActivity.this, "com.autonavi.minimap")) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(intent); + return true; + } else { + Toast.makeText(WebViewActivity.this, "请先安装高德地图app", Toast.LENGTH_SHORT).show(); + } + } + if (url.contains("didapinche://")) { + if (isAvilible(WebViewActivity.this, "com.didapinche.booking")) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(intent); + } else { + Toast.makeText(WebViewActivity.this, "请先安装滴答出行app", Toast.LENGTH_SHORT).show(); + } + return true; + } + + if (url.contains("tmast://")) { + try { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(intent); + } catch (Exception e) { + Toast.makeText(WebViewActivity.this, "请先安装应用宝app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.startsWith("http://ditu.amap.com") || + url.startsWith("https://ditu.amap.com")) { + return true; + } + //品牌店家点击商品,请求接口进行相应的跳转 + if (url.contains("h5.m.taobao.com/awp/core/detail") || url.contains("detail.m.tmall.com/item.htm") + || url.contains("item.m.jd.com/product") || (url.contains("item.m.jd.com/ware/view.action") + || url.contains("wareId=") || url.contains("h5.m.taobao.com/trip/travel-detail/index/index.htm")) + || url.contains("detail.tmall.hk/hk") || url.contains("vip.com/product") + || url.contains("suning.com/product") || url.contains("kaola.com/product") + || url.contains("yangkeduo.com/goods")) { + + + } + if (url.contains("tbopen://") || url.contains("tmall://") || url.contains("taobaotravel://")) { + return true; + } + if (url.contains("openapp.jdmobile:")) { + //打开京东app + if (isAvilible(WebViewActivity.this, "com.jingdong.app.mall")) { + + } + return true; + } + if (url.contains("pinduoduo://com.xunmeng.pinduoduo")) { + if (isAvilible(WebViewActivity.this, "com.xunmeng.pinduoduo")) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(intent); + } else { + Toast.makeText(WebViewActivity.this, "请先安装拼多多app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.contains("imeituan://")) {//打开美团 + if (isAvilible(WebViewActivity.this, "com.sankuai.meituan")) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } else { + Toast.makeText(WebViewActivity.this, "请先安装美团app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.contains("suning://")) { + if (isAvilible(WebViewActivity.this, "com.suning.mobile.ebuy")) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } else { + Toast.makeText(WebViewActivity.this, "请先安装苏宁app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.contains("kaola://")) { + if (isAvilible(WebViewActivity.this, "com.kaola")) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } else { + Toast.makeText(WebViewActivity.this, "请先安装考拉app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.contains("dianping://")) { + return true; + } + if (url.contains("aliim:")) { + return true; + } + if (url.contains("?mod=appapi&act=miandan_course&ctrl=close")) { + finish(); + return true; + } + if (url.contains("vipma.net/quickapp.html?")) { + return true; + } + + if (url.contains("cxcwallet://")) { + if (isAvilible(WebViewActivity.this, "com.cxcblock.wallet")) {//传入指定应用包名 + Intent intent = new Intent(); + intent.setData(Uri.parse(url)); + startActivity(intent); + } else { + Toast.makeText(WebViewActivity.this, "请先安装CXCapp", Toast.LENGTH_SHORT).show(); + } + return true; + } + + + // 如下方案可在非微信内部WebView的H5页面中调出微信支付 + if (url.startsWith("weixin://wap/pay?")) { + try { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + startActivity(intent); + return true; + } catch (Exception e) { + e.printStackTrace(); + Toast.makeText(WebViewActivity.this, "请先安装微信app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.startsWith("weixin://")) { + try { + Intent intent = new Intent(); + intent.setAction(Intent.ACTION_VIEW); + intent.setData(Uri.parse(url)); + startActivity(intent); + return true; + } catch (Exception e) { + e.printStackTrace(); + Toast.makeText(WebViewActivity.this, "请先安装微信app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.endsWith("native://wechat")) { + Intent intent = new Intent(); + ComponentName cmp = new ComponentName("com.tencent.mm", "com.tencent.mm.ui.LauncherUI"); + intent.setAction(Intent.ACTION_MAIN); + intent.addCategory(Intent.CATEGORY_LAUNCHER); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setComponent(cmp); + startActivity(intent); + return true; + } +// if (url.contains("navite://save#")) { +// String[] split = url.split("navite://save#"); +// SDFileHelper sdFileHelper = new SDFileHelper(mActivity); +// sdFileHelper.setOnDownloadFinishListener(new SDFileHelper.OnDownloadFinishListener() { +// @Override +// public void onDownloadFinish(String filePath) { +// ToastUtils.showShort("图片已保存到内存卡根目录" + AppUtil.getAppName() + "文件夹中"); +// } +// }); +// sdFileHelper.savePicture("we_chat_qr_code" + ".jpg", split[1], true); +// return true; +// } + //不拦截的话绑定淘宝关系id的时候会因为下面login.m.taobao.com的拦截而唤醒手淘授权之后导致不能切换帐号 +// if (url.contains("client_id") && url.contains("login.m.taobao.com/logout.htm?")) { +// view.loadUrl(url); +// return true; +// } + if (url.contains("client_id")) { + view.loadUrl(url); + return true; + } +// if (url.contains("login.m.taobao.com")) { +// AliLoginMethodUtil.AliLoginMethod(new AliLoginMethodUtil.AliLoginListener() { +// @Override +// public void loginSuccess(String s, String s1, Session session) { +// +// } +// +// @Override +// public void LoginFail(int i, String s) { +// +// } +// }); +// return true; +// } + + if (url.contains("alipays://platformapi")) { + if (checkAliPayInstalled()) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + startActivity(intent); +// finish(); + } else { + Toast.makeText(WebViewActivity.this, "请先安装支付宝app", Toast.LENGTH_SHORT).show(); + } + return true; + } + if (url.contains("intent://go/ju/webview?")) { + return true; + } + + if (url.contains("deterorder")) { + webview.loadUrl(url); + return true; + } + if (getIntent().getBooleanExtra("isSearchEnter", false) && url.contains("sku=")) { + + } + + return !(url.startsWith("http://") || url.startsWith("https://")); + } + + @Override + public void onLoadResource(WebView view, String url) { + } + + @Override + public void onPageFinished(WebView view, String url) { + } + + }); + + webview.setWebChromeClient(new WebChromeClient() { + @Override + synchronized public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) { + callback.invoke(origin, true, false); +// if (!isRequestPre) { +// isRequestPre = true; +// quanxian(WebViewActivity.this); +// } + + } + + @Override + public void onProgressChanged(WebView view, int newProgress) { + super.onProgressChanged(view, newProgress); + progressBar.setProgress(newProgress); + if (newProgress == 100) { + progressBar.setVisibility(View.GONE); + } else { + progressBar.setVisibility(View.VISIBLE); + } + } + + @Override + public void onReceivedTitle(WebView view, String title) { + super.onReceivedTitle(view, title); + if (title != null && title.length() != 0) { + tvTitle.setText(title); + } else { + tvTitle.setText(url); + } + + } + }); + + webview.loadUrl(url); + + } + + /** + * 检测是否安装支付宝app + * + * @return + */ + public boolean checkAliPayInstalled() { + Uri uri = Uri.parse("alipays://platformapi/startApp"); + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + ComponentName componentName = intent.resolveActivity(getPackageManager()); + return componentName != null; + } + + + /** + * 检查手机上是否安装了指定的软件 + * + * @param context + * @param packageName:应用包名 + * @return + */ + private boolean isAvilible(Context context, String packageName) { + //获取packagemanager + final PackageManager packageManager = context.getPackageManager(); + //获取所有已安装程序的包信息 + List packageInfos = packageManager.getInstalledPackages(0); + //用于存储所有已安装程序的包名 + List packageNames = new ArrayList(); + //从pinfo中将包名字逐一取出,压入pName list中 + if (packageInfos != null) { + for (int i = 0; i < packageInfos.size(); i++) { + String packName = packageInfos.get(i).packageName; + packageNames.add(packName); + } + } + //判断packageNames中是否有目标程序的包名,有TRUE,没有FALSE + return packageNames.contains(packageName); + } + + /** + * 检查是否安装手机淘宝 + * + * @param context + * @return + */ + + public static boolean isInstallTaoBao(Context context) { + PackageInfo packageInfo = null; + try { + packageInfo = context.getPackageManager().getPackageInfo("com.taobao.taobao", 0); + } catch (Exception e) { + packageInfo = null; + e.printStackTrace(); + } + if (packageInfo == null) { + return false; + } else { + return true; + } + } + + + ///检查并请求定位权限 + public void quanxian(final Activity context) { + Log.d("权限请求", "------------"); + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + Log.d("权限请求", "无定位权限------------"); + ActivityCompat.requestPermissions(context, + new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 20210422); + } + } + } catch (SecurityException e) { + e.printStackTrace(); + } + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK) { + if (webview.canGoBack()) { + webview.goBack(); + return true; + } + isRequestPre = true; + } + return super.onKeyDown(keyCode, event); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + if (requestCode == 20210422) { + Log.d("权限请求", "定位权限回调------------"); + webview.clearCache(true); + webview.loadUrl(url); + return; + } + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + webview.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); + webview.destroy(); + } +} \ No newline at end of file diff --git a/android/src/main/java/cn/zhios/zhiying_base_widget/ZhiyingBaseWidgetPlugin.java b/android/src/main/java/cn/zhios/zhiying_base_widget/ZhiyingBaseWidgetPlugin.java index d494562..e4eac3e 100644 --- a/android/src/main/java/cn/zhios/zhiying_base_widget/ZhiyingBaseWidgetPlugin.java +++ b/android/src/main/java/cn/zhios/zhiying_base_widget/ZhiyingBaseWidgetPlugin.java @@ -1,45 +1,90 @@ package cn.zhios.zhiying_base_widget; +import android.app.Activity; +import android.content.Intent; + import androidx.annotation.NonNull; + +import java.util.HashMap; +import java.util.Map; + import io.flutter.embedding.engine.plugins.FlutterPlugin; +import io.flutter.embedding.engine.plugins.activity.ActivityAware; +import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; +import io.flutter.plugin.common.PluginRegistry; import io.flutter.plugin.common.PluginRegistry.Registrar; -/** ZhiyingBaseWidgetPlugin */ -public class ZhiyingBaseWidgetPlugin implements FlutterPlugin, MethodCallHandler { - @Override - public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { - final MethodChannel channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "zhiying_base_widget"); - channel.setMethodCallHandler(new ZhiyingBaseWidgetPlugin()); - } - - // This static function is optional and equivalent to onAttachedToEngine. It supports the old - // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting - // plugin registration via this function while apps migrate to use the new Android APIs - // post-flutter-1.12 via https://flutter.dev/go/android-project-migration. - // - // It is encouraged to share logic between onAttachedToEngine and registerWith to keep - // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called - // depending on the user's project. onAttachedToEngine or registerWith must both be defined - // in the same class. - public static void registerWith(Registrar registrar) { - final MethodChannel channel = new MethodChannel(registrar.messenger(), "zhiying_base_widget"); - channel.setMethodCallHandler(new ZhiyingBaseWidgetPlugin()); - } - - @Override - public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { - if (call.method.equals("getPlatformVersion")) { - result.success("Android " + android.os.Build.VERSION.RELEASE); - } else { - result.notImplemented(); - } - } - - @Override - public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { - } +/** + * ZhiyingBaseWidgetPlugin + */ +public class ZhiyingBaseWidgetPlugin implements FlutterPlugin, MethodCallHandler, ActivityAware, PluginRegistry.ActivityResultListener { + + private Activity activity; + + private ActivityPluginBinding binding; + + private MethodChannel channel; + + @Override + public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { + channel = new MethodChannel(flutterPluginBinding.getBinaryMessenger(), "zhiying_base_widget"); + channel.setMethodCallHandler(this); + } + + + @Override + public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { + if (call.method.equals("getPlatformVersion")) { + result.success("Android " + android.os.Build.VERSION.RELEASE); + } else if (call.method.equals("loadUrl")) { + String url = (String) ((Map) call.arguments).get("url"); + Intent intent = new Intent(activity, WebViewActivity.class); + intent.putExtra("url", url); + activity.startActivityForResult(intent, 20210501); + } else { + result.notImplemented(); + } + } + + @Override + public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { + } + + @Override + public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) { + activity = binding.getActivity(); + binding.addActivityResultListener(this); + } + + @Override + public void onDetachedFromActivityForConfigChanges() { + if (binding != null) { + binding.removeActivityResultListener(this); + } + } + + @Override + public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) { + + } + + @Override + public void onDetachedFromActivity() { + + } + + @Override + public boolean onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == 20210501 && resultCode == 20210501) { + HashMap map = new HashMap<>(); + map.put("url", data.getStringExtra("url")); + channel.invokeMethod("reload", map); + return true; + } + return false; + } } diff --git a/android/src/main/res/drawable/ic_baseline_keyboard_arrow_left_24.xml b/android/src/main/res/drawable/ic_baseline_keyboard_arrow_left_24.xml new file mode 100644 index 0000000..65b78c2 --- /dev/null +++ b/android/src/main/res/drawable/ic_baseline_keyboard_arrow_left_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/src/main/res/drawable/ic_baseline_refresh_24.xml b/android/src/main/res/drawable/ic_baseline_refresh_24.xml new file mode 100644 index 0000000..845c368 --- /dev/null +++ b/android/src/main/res/drawable/ic_baseline_refresh_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/android/src/main/res/layout/activity_web_view.xml b/android/src/main/res/layout/activity_web_view.xml new file mode 100644 index 0000000..d745147 --- /dev/null +++ b/android/src/main/res/layout/activity_web_view.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android/src/main/res/values/strings.xml b/android/src/main/res/values/strings.xml new file mode 100644 index 0000000..73862c4 --- /dev/null +++ b/android/src/main/res/values/strings.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 1b76dd1..f8b772a 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -36,7 +36,7 @@ dev_dependencies: path: ../../zhiying_acquisition zhiying_shopping_mall: git: - ref: 0.0.4 + ref: 0.0.5 url: 'http://192.168.0.138:3000/FnuoOS_ZhiYing/zhiying_shopping_mall.git' zhiying_credit_card: path: ../../zhiying_credit_card diff --git a/lib/pages/about_us_page/about_us_page.dart b/lib/pages/about_us_page/about_us_page.dart index aeb562c..d0ace9f 100644 --- a/lib/pages/about_us_page/about_us_page.dart +++ b/lib/pages/about_us_page/about_us_page.dart @@ -11,6 +11,7 @@ import 'bloc/about_us_event.dart'; import 'bloc/about_us_state.dart'; import 'package:zhiying_comm/util/shared_prefe_util.dart'; import 'package:zhiying_comm/util/global_config.dart'; + /// /// 关于我们 /// @@ -36,7 +37,7 @@ class _AboutUsPageContainer extends StatefulWidget { class __AboutUsPageContainerState extends State<_AboutUsPageContainer> { /// 检查更新 - void _onClickCheckUpdate() async{ + void _onClickCheckUpdate() async { Logger.log('点击了更新'); AppUpdateUtil.updateApp(context, needToast: true, mustShowDialog: true); } @@ -52,17 +53,18 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> { _onClickCheckUpdate(); } else if (model.type == 'comment') { _onClickEvaluation(); - } + } else if (model.type == "") { + } else if (model.type == "") {} } bool _isiOSReview = false; @override void initState() { - _settingIosReview(); super.initState(); } + void _settingIosReview() async { String is_ios_review = await SharedPreferencesUtil.getStringValue(GlobalConfig.IS_IOS_REVIEW, defaultVal: '0'); setState(() { @@ -151,12 +153,12 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> { /// 更新,评价 _isiOSReview ? Container() : _buildListWidget(model), + _buildAgreement(model) ], ), ); } - /// 列表 Widget _buildListWidget(AboutUsModel model) { List widgets = []; @@ -165,7 +167,7 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> { widgets.add(Container()); } else { model.settings.forEach((element) { - if(element.type == 'comment'){ + if (element.type == 'comment') { return; } widgets.add(GestureDetector( @@ -228,4 +230,46 @@ class __AboutUsPageContainerState extends State<_AboutUsPageContainer> { elevation: 0, ); } + + _buildAgreement(AboutUsModel model) { + List widgets = []; + int length = model?.articles?.length ?? 0; + if (length == 0) { + widgets.add(Container()); + } else { + model.articles.forEach((element) { + widgets.add(GestureDetector( + onTap: () => _onClickAgreementItem(element), + behavior: HitTestBehavior.opaque, + child: Container( + margin: const EdgeInsets.symmetric(vertical: 15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + element?.title ?? '', + style: TextStyle(color: HexColor.fromHex('#333333'), fontSize: 13, fontWeight: FontWeight.bold), + ), + Icon( + Icons.arrow_forward_ios, + color: HexColor.fromHex('#999999'), + size: 14, + ) + ], + ), + ), + )); + }); + return Column( + children: widgets, + ); + } + } + + _onClickAgreementItem(Articles element) { + if (element.link != null) { + RouterUtil.openWebview(element.link, context); + } + } + } diff --git a/lib/pages/about_us_page/model/about_us_model.dart b/lib/pages/about_us_page/model/about_us_model.dart index 725e631..5a2ec53 100644 --- a/lib/pages/about_us_page/model/about_us_model.dart +++ b/lib/pages/about_us_page/model/about_us_model.dart @@ -9,25 +9,25 @@ class AboutUsModel { String appVersionColor; List dataKeys; List settings; + List articles; String bottomName; String bottomNameColor; String appVerison; - AboutUsModel({ - this.appBarName, - this.appBarNameColor, - this.appBarBgColor, - this.bgColor, - this.settingsBgColor, - this.appLogo, - this.appVersionText, - this.appVersionColor, - this.dataKeys, - this.settings, - this.bottomName, - this.bottomNameColor, - this.appVerison, - }); + AboutUsModel( + {this.appBarName, + this.appBarNameColor, + this.appBarBgColor, + this.bgColor, + this.settingsBgColor, + this.appLogo, + this.appVersionText, + this.appVersionColor, + this.dataKeys, + this.settings, + this.articles, + this.bottomName, + this.bottomNameColor}); AboutUsModel.fromJson(Map json) { appBarName = json['app_bar_name']; @@ -38,7 +38,6 @@ class AboutUsModel { appLogo = json['app_logo']; appVersionText = json['app_version_text']; appVersionColor = json['app_version_color']; - appVerison = json['appVerison']; dataKeys = json['data_keys'].cast(); if (json['settings'] != null) { settings = new List(); @@ -46,6 +45,12 @@ class AboutUsModel { settings.add(new Settings.fromJson(v)); }); } + if (json['articles'] != null) { + articles = new List(); + json['articles'].forEach((v) { + articles.add(new Articles.fromJson(v)); + }); + } bottomName = json['bottom_name']; bottomNameColor = json['bottom_name_color']; } @@ -64,16 +69,18 @@ class AboutUsModel { if (this.settings != null) { data['settings'] = this.settings.map((v) => v.toJson()).toList(); } + if (this.articles != null) { + data['articles'] = this.articles.map((v) => v.toJson()).toList(); + } data['bottom_name'] = this.bottomName; data['bottom_name_color'] = this.bottomNameColor; - data['appVerison'] = this.appVerison; return data; } } class Settings { - List dataKeys; String type; + List dataKeys; String name; String subName; String nameColor; @@ -82,12 +89,21 @@ class Settings { String descColor; String skipIdentifier; - Settings({this.dataKeys, this.name, this.subName, this.nameColor, this.subNameColor, this.descText, this.descColor, this.skipIdentifier}); + Settings( + {this.type, + this.dataKeys, + this.name, + this.subName, + this.nameColor, + this.subNameColor, + this.descText, + this.descColor, + this.skipIdentifier}); Settings.fromJson(Map json) { + type = json['type']; dataKeys = json['data_keys'].cast(); name = json['name']; - type = json['type']; subName = json['sub_name']; nameColor = json['name_color']; subNameColor = json['sub_name_color']; @@ -98,8 +114,8 @@ class Settings { Map toJson() { final Map data = new Map(); + data['type'] = this.type; data['data_keys'] = this.dataKeys; - data['type'] = this.type; data['name'] = this.name; data['sub_name'] = this.subName; data['name_color'] = this.nameColor; @@ -110,3 +126,25 @@ class Settings { return data; } } + +class Articles { + String type; + String title; + String link; + + Articles({this.type, this.title, this.link}); + + Articles.fromJson(Map json) { + type = json['type']; + title = json['title']; + link = json['link']; + } + + Map toJson() { + final Map data = new Map(); + data['type'] = this.type; + data['title'] = this.title; + data['link'] = this.link; + return data; + } +} diff --git a/lib/register.dart b/lib/register.dart index 96a70dc..9616dd5 100644 --- a/lib/register.dart +++ b/lib/register.dart @@ -1,8 +1,10 @@ import 'dart:async'; import 'dart:io'; +import 'package:flutter/material.dart'; import 'package:flutter_user_agent/flutter_user_agent.dart'; import 'package:jdsdk/jdsdk.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:sharesdk_plugin/sharesdk_interface.dart'; import 'package:sharesdk_plugin/sharesdk_register.dart'; import 'package:zhiying_base_widget/models/app_config_model.dart'; @@ -131,7 +133,8 @@ class BaseWidgetRegister { register.setupWechat(config.keys?.weixin?.appId ?? '', config.keys?.weixin?.secret ?? '', config.keys?.weixin?.universalLink ?? ''); //================ Weibo - register.setupSinaWeibo(config.keys?.weibo?.appkey ?? '', config.keys?.weibo?.secret ?? '', config.keys?.weibo?.redirectUrl ?? '', config.keys?.weibo?.universalLink ?? 'templink'); + register.setupSinaWeibo( + config.keys?.weibo?.appkey ?? '', config.keys?.weibo?.secret ?? '', config.keys?.weibo?.redirectUrl ?? '', config.keys?.weibo?.universalLink ?? 'templink'); // ================ QQ register.setupQQ(config.keys?.qq?.appId ?? '', config.keys?.qq?.appkey ?? ''); @@ -201,6 +204,17 @@ class BaseWidgetRegister { Application.addMethod(() async { // return Future.delayed(Duration(seconds: 1)); }); + + Application.addStringParamsMethod( + type: "openUrl", + method: (data) async { + if (!EmptyUtil.isEmpty(data)) { + if (!await Permission.location.isGranted) { + await showDialog(context: navigatorKey.currentState.overlay.context, child: NotificationSettingDialogNew([NotificationSettingDialogNew.locationPermissModel])); + } + ZhiyingBaseWidget.loadUrl(data['url']); + } + }); } // 注册页面 diff --git a/lib/widgets/wallet/wallet_detail/wallet_detail.dart b/lib/widgets/wallet/wallet_detail/wallet_detail.dart index b8d92a4..c7d628d 100644 --- a/lib/widgets/wallet/wallet_detail/wallet_detail.dart +++ b/lib/widgets/wallet/wallet_detail/wallet_detail.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:tab_indicator_styler/tab_indicator_styler.dart'; +import 'package:zhiying_base_widget/dialog/loading/loading.dart'; import 'package:zhiying_base_widget/dialog/tip_dialog/tip_dialog.dart'; import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/model/wallet_detail_model.dart'; import 'package:zhiying_base_widget/widgets/wallet/wallet_detail/wallet_detail_bloc.dart'; @@ -70,6 +71,7 @@ class _WalletDetailState extends State with TickerProviderStateMix ///骨架图 return WalletDetailSkeleton(); } + Loading.dismiss(); return Container( decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(8)), margin: EdgeInsets.only(left: 12.5, right: 12.5, top: 7.5, bottom: 7.5), @@ -98,6 +100,7 @@ class _WalletDetailState extends State with TickerProviderStateMix indicatorSize: TabBarIndicatorSize.label, onTap: (index) { ///变更平台 + Loading.show(context); changeProvider(_model.providers[index].type); }, tabs: _buildTabs()), @@ -212,6 +215,7 @@ class _WalletDetailState extends State with TickerProviderStateMix ), ), onTap: () { + Loading.show(context); _bloc.selectDay = item.type; _bloc.loadData(_bloc.currentType, _bloc.selectDay); }, diff --git a/lib/widgets/wallet/wallet_detail/wallet_detail_bloc.dart b/lib/widgets/wallet/wallet_detail/wallet_detail_bloc.dart index f23c372..2bfabc5 100644 --- a/lib/widgets/wallet/wallet_detail/wallet_detail_bloc.dart +++ b/lib/widgets/wallet/wallet_detail/wallet_detail_bloc.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:convert'; +import 'package:zhiying_base_widget/dialog/loading/loading.dart'; import 'package:zhiying_comm/util/base_bloc.dart'; import 'package:zhiying_comm/zhiying_comm.dart'; @@ -42,7 +43,11 @@ class WalletDetailBloc extends BlocBase { currentWalletDetailDataModel = listDataModel[0]; refresh(); } - }); + Loading.dismiss(); + }, onError: (e) { + Fluttertoast.showToast(msg: "加载数据出了小差"); + Loading.dismiss(); + }, timeOut: 60000); } ///刷新页面 diff --git a/lib/zhiying_base_widget.dart b/lib/zhiying_base_widget.dart index 32ee91e..ed9c031 100644 --- a/lib/zhiying_base_widget.dart +++ b/lib/zhiying_base_widget.dart @@ -1,5 +1,7 @@ library zhiying_base_widget; +import 'package:flutter/services.dart'; + export 'dialog/loading/loading.dart'; export 'package:flutter_swiper/flutter_swiper.dart'; export 'package:zhiying_base_widget/pages/main_page/model/background_model.dart'; @@ -11,3 +13,27 @@ export 'package:amap_flutter_location/amap_flutter_location.dart'; export 'package:amap_flutter_location/amap_location_option.dart'; export 'package:tab_indicator_styler/tab_indicator_styler.dart'; export 'package:zhiying_base_widget/dialog/global_dialog/notification_setting_dialog/notification_setting_dialog.dart'; + +class ZhiyingBaseWidget { + static const MethodChannel _channel = const MethodChannel('zhiying_base_widget'); + + ///监听重定向的方法 + static addListener(Function(String) reload) { + _channel.setMethodCallHandler((call) { + if (call.method == "reload") { + reload(call.arguments['url']); + } + return null; + }); + } + + ///打开原生webView + static loadUrl(String url) async { + await _channel.invokeMethod("loadUrl", {"url": url}); + } + + static Future get platformVersion async { + final String version = await _channel.invokeMethod('getPlatformVersion'); + return version; + } +}