秦港相关方
|
|
@ -0,0 +1,44 @@
|
|||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.build/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
**/doc/api/
|
||||
**/ios/Flutter/.last_build_id
|
||||
.dart_tool/
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.pub-cache/
|
||||
.pub/
|
||||
/build/
|
||||
|
||||
# Symbolication related
|
||||
app.*.symbols
|
||||
|
||||
# Obfuscation related
|
||||
app.*.map.json
|
||||
/lib/git-cheatsheet.md
|
||||
# Android Studio will place build artifacts here
|
||||
/android/app/debug
|
||||
/android/app/release
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "d7b523b356d15fb81e7d340bbe52b47f93937323"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
||||
# Tracks metadata for the flutter migrate command
|
||||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
base_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
- platform: web
|
||||
create_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
base_revision: d7b523b356d15fb81e7d340bbe52b47f93937323
|
||||
|
||||
# User provided section
|
||||
|
||||
# List of Local paths (relative to this file) that should be
|
||||
# ignored by the migrate tool.
|
||||
#
|
||||
# Files that are not part of the templates will be ignored by default.
|
||||
unmanaged_files:
|
||||
- 'lib/main.dart'
|
||||
- 'ios/Runner.xcodeproj/project.pbxproj'
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# flutter_integrated_whb
|
||||
|
||||
危化项目.
|
||||
|
||||
## Getting Started
|
||||
|
||||
This project is a starting point for a Flutter application.
|
||||
|
||||
A few resources to get you started if this is your first Flutter project:
|
||||
|
||||
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||
|
||||
For help getting started with Flutter development, view the
|
||||
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||
samples, guidance on mobile development, and a full API reference.
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# This file configures the analyzer, which statically analyzes Dart code to
|
||||
# check for errors, warnings, and lints.
|
||||
#
|
||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||
# invoked from the command line by running `flutter analyze`.
|
||||
|
||||
# The following line activates a set of recommended lints for Flutter apps,
|
||||
# packages, and plugins designed to encourage good coding practices.
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
linter:
|
||||
|
||||
# The lint rules applied to this project can be customized in the
|
||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||
# included above or to enable additional rules. A list of all available lints
|
||||
# and their documentation is published at https://dart.dev/lints.
|
||||
#
|
||||
# Instead of disabling a lint rule for the entire project in the
|
||||
# section below, it can also be suppressed for a single line of code
|
||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||
# producing the lint.
|
||||
rules:
|
||||
camel_case_types: false
|
||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
gradle-wrapper.jar
|
||||
/.gradle
|
||||
/captures/
|
||||
/gradlew
|
||||
/gradlew.bat
|
||||
/local.properties
|
||||
GeneratedPluginRegistrant.java
|
||||
.cxx/
|
||||
|
||||
# Remember to never publicly share your keystore.
|
||||
# See https://flutter.dev/to/reference-keystore
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
import java.util.Properties
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
id("dev.flutter.flutter-gradle-plugin")
|
||||
}
|
||||
// 🔐 加载 key.properties
|
||||
val keystoreProperties = Properties()
|
||||
val keystorePropertiesFile = rootProject.file("key.properties")
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(keystorePropertiesFile.inputStream())
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.company.myapp2"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = "28.1.13356709"
|
||||
|
||||
// 使用 JDK 17 / JavaVersion.VERSION_17(推荐与 AGP 8.9.x 兼容)
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
// jvmTarget 要与 Java 版本一致
|
||||
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.company.myapp2"
|
||||
minSdk = 24
|
||||
targetSdk = flutter.targetSdkVersion
|
||||
versionCode = flutter.versionCode
|
||||
versionName = flutter.versionName
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
storeFile = file(keystoreProperties["storeFile"] as String)
|
||||
storePassword = keystoreProperties["storePassword"] as String
|
||||
keyAlias = keystoreProperties["keyAlias"] as String
|
||||
keyPassword = keystoreProperties["keyPassword"] as String
|
||||
}
|
||||
// debug signingConfig 通常存在(Android Gradle 会有默认 debug 签名)
|
||||
// 如果你自定义 debug 签名,则可以在这里创建
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
isMinifyEnabled = false
|
||||
isShrinkResources = false
|
||||
}
|
||||
debug {
|
||||
// 使用默认 debug 签名(或你自定义的 debug)
|
||||
// signingConfig = signingConfigs.getByName("debug")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- 定位权限 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
|
||||
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
|
||||
|
||||
<!-- Android 13+ -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
|
||||
|
||||
<!-- Android 12 及以下 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<!-- 相机 -->
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<!-- 麦克风 -->
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
|
||||
<!-- 通讯录 -->
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
|
||||
<!-- 蓝牙 -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 12+ -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <!-- Android 12+ -->
|
||||
|
||||
<!-- 网络 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<!-- 存储(兼容旧版,Android 11+ 基本无效) -->
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29"
|
||||
tools:replace="android:maxSdkVersion" />
|
||||
|
||||
<!-- NFC -->
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
||||
|
||||
<!-- 安装 APK -->
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
|
||||
<!-- 角标适配不同厂商 -->
|
||||
<!-- Samsung -->
|
||||
<uses-permission android:name="com.sec.android.provider.badge.permission.READ"/>
|
||||
<uses-permission android:name="com.sec.android.provider.badge.permission.WRITE"/>
|
||||
<!-- Huawei -->
|
||||
<uses-permission android:name="com.huawei.android.launcher.permission.CHANGE_BADGE" />
|
||||
<uses-permission android:name="com.huawei.android.launcher.permission.READ_SETTINGS" />
|
||||
<uses-permission android:name="com.huawei.android.launcher.permission.WRITE_SETTINGS" />
|
||||
<!-- HTC -->
|
||||
<uses-permission android:name="com.htc.launcher.permission.READ_SETTINGS"/>
|
||||
<uses-permission android:name="com.htc.launcher.permission.UPDATE_SHORTCUT"/>
|
||||
<!-- Apex -->
|
||||
<uses-permission android:name="com.anddoes.launcher.permission.UPDATE_COUNT"/>
|
||||
<!-- Sony -->
|
||||
<uses-permission android:name="com.sonyericsson.home.permission.BROADCAST_BADGE"/>
|
||||
<uses-permission android:name="com.sonymobile.home.permission.PROVIDER_INSERT_BADGE"/>
|
||||
<!-- Solid -->
|
||||
<uses-permission android:name="com.majeur.launcher.permission.UPDATE_BADGE"/>
|
||||
|
||||
<application
|
||||
android:label="@string/appName"
|
||||
android:name=".MyApplication"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:enableOnBackInvokedCallback="true">
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop"
|
||||
android:taskAffinity=""
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme" />
|
||||
<meta-data
|
||||
android:name="com.baidu.lbsapi.API_KEY"
|
||||
android:value="43G1sKuHV6oRTrdR9VTIGPF9soej7V5a" />
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<!-- FileProvider 配置 -->
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="com.company.myapp2.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths" />
|
||||
</provider>
|
||||
<!-- Flutter 插件需要 -->
|
||||
<meta-data
|
||||
android:name="flutterEmbedding"
|
||||
android:value="2" />
|
||||
</application>
|
||||
|
||||
<!-- Android 11+ package visibility -->
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
||||
<data android:mimeType="text/plain"/>
|
||||
</intent>
|
||||
|
||||
<!-- 允许安装器查询 -->
|
||||
<package android:name="com.android.packageinstaller" />
|
||||
</queries>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
package com.company.myapp2
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import androidx.core.content.FileProvider
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
import io.flutter.embedding.engine.FlutterEngine
|
||||
import io.flutter.plugin.common.MethodChannel
|
||||
import java.io.File
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
private val CHANNEL = "app.install"
|
||||
private val REQ_INSTALL_UNKNOWN = 9999
|
||||
|
||||
// 暂存安装请求(仅在跳转设置并等待返回时使用)
|
||||
private var pendingApkPath: String? = null
|
||||
private var pendingResult: MethodChannel.Result? = null
|
||||
|
||||
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||
super.configureFlutterEngine(flutterEngine)
|
||||
MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
|
||||
when (call.method) {
|
||||
"installApk" -> {
|
||||
val path = call.argument<String>("path")
|
||||
if (path == null) {
|
||||
result.error("NO_PATH", "no path provided", null)
|
||||
return@setMethodCallHandler
|
||||
}
|
||||
handleInstallRequest(path, result)
|
||||
}
|
||||
else -> result.notImplemented()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleInstallRequest(path: String, result: MethodChannel.Result) {
|
||||
val file = File(path)
|
||||
if (!file.exists()) {
|
||||
result.error("NO_FILE", "file not exist", null)
|
||||
return
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
// 8.0+ 需要 app 级别未知来源授权
|
||||
if (!packageManager.canRequestPackageInstalls()) {
|
||||
// 存储请求信息以便用户返回后继续
|
||||
pendingApkPath = path
|
||||
pendingResult = result
|
||||
|
||||
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES,
|
||||
Uri.parse("package:$packageName"))
|
||||
// 使用 startActivityForResult 以便用户返回后可以继续安装
|
||||
startActivityForResult(intent, REQ_INSTALL_UNKNOWN)
|
||||
return
|
||||
}
|
||||
}
|
||||
// 已有授权 或 非 8.0+:直接安装
|
||||
installApkInternal(path, result)
|
||||
}
|
||||
|
||||
// 真正执行安装的函数(假定有权限)
|
||||
private fun installApkInternal(path: String, result: MethodChannel.Result) {
|
||||
val file = File(path)
|
||||
if (!file.exists()) {
|
||||
result.error("NO_FILE", "file not exist", null)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
val apkUri: Uri = FileProvider.getUriForFile(this, "$packageName.fileprovider", file)
|
||||
val intent = Intent(Intent.ACTION_VIEW)
|
||||
intent.setDataAndType(apkUri, "application/vnd.android.package-archive")
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
startActivity(intent)
|
||||
result.success(true)
|
||||
} catch (e: Exception) {
|
||||
result.error("INSTALL_FAILED", e.message, null)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == REQ_INSTALL_UNKNOWN) {
|
||||
// 用户从系统设置页返回后,检查是否已授权
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (packageManager.canRequestPackageInstalls()) {
|
||||
// 授权已开:继续安装
|
||||
val path = pendingApkPath
|
||||
val res = pendingResult
|
||||
// 清理 pending 状态
|
||||
pendingApkPath = null
|
||||
pendingResult = null
|
||||
if (path != null && res != null) {
|
||||
installApkInternal(path, res)
|
||||
} else {
|
||||
// 安全兜底:若没有 pending 数据,通知 caller 重新触发
|
||||
res?.error("NO_PENDING", "no pending install info", null)
|
||||
}
|
||||
} else {
|
||||
// 用户仍未授权
|
||||
pendingApkPath = null
|
||||
pendingResult?.error("NEED_INSTALL_PERMISSION", "user did not allow install unknown apps", null)
|
||||
pendingResult = null
|
||||
}
|
||||
} else {
|
||||
// API < 26:尝试直接安装一次作为尝试(某些 ROM 无法精准判断)
|
||||
val path = pendingApkPath
|
||||
val res = pendingResult
|
||||
pendingApkPath = null
|
||||
pendingResult = null
|
||||
if (path != null && res != null) {
|
||||
installApkInternal(path, res)
|
||||
} else {
|
||||
res?.error("NO_PENDING", "no pending install info", null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package com.company.myapp2
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
|
||||
class MyApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
// 通过反射调用 SDKInitializer,避免在编译期要求依赖存在
|
||||
try {
|
||||
val sdkClass = Class.forName("com.baidu.mapapi.SDKInitializer")
|
||||
// setAgreePrivacy(boolean) - 有些 SDK 要求先同意隐私
|
||||
try {
|
||||
val setAgree = sdkClass.getMethod("setAgreePrivacy", java.lang.Boolean::class.javaPrimitiveType)
|
||||
setAgree.invoke(null, true)
|
||||
Log.i("MyApplication", "SDKInitializer.setAgreePrivacy invoked via reflection")
|
||||
} catch (t: Throwable) {
|
||||
Log.w("MyApplication", "setAgreePrivacy not available or failed: ${t.message}")
|
||||
}
|
||||
|
||||
// initialize(Context)
|
||||
try {
|
||||
val initMethod = sdkClass.getMethod("initialize", Context::class.java)
|
||||
initMethod.invoke(null, this)
|
||||
Log.i("MyApplication", "SDKInitializer.initialize invoked via reflection")
|
||||
} catch (t: Throwable) {
|
||||
Log.w("MyApplication", "initialize(Context) not available or failed: ${t.message}")
|
||||
}
|
||||
} catch (e: ClassNotFoundException) {
|
||||
// 运行时没有找到该类(可能 plugin 未包含 SDK),记录日志但不崩溃
|
||||
Log.w("MyApplication", "Baidu SDKInitializer class not found at runtime: ${e.message}")
|
||||
} catch (e: Throwable) {
|
||||
Log.e("MyApplication", "Unexpected error while initializing Baidu SDK via reflection", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 345 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
After Width: | Height: | Size: 345 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="appName">秦港相关方</string>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
|
||||
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
<item name="android:forceDarkAllowed">false</item>
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
|
||||
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
|
||||
</style>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
Flutter UI initializes, as well as behind your Flutter UI while its
|
||||
running.
|
||||
|
||||
This Theme is only used starting with V2 of Flutter's Android embedding. -->
|
||||
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
|
||||
<item name="android:windowBackground">?android:colorBackground</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- 允许访问 app 的缓存目录 -->
|
||||
<cache-path name="cache" path="." />
|
||||
<!-- 允许访问 app 的 files 目录 -->
|
||||
<files-path name="files" path="." />
|
||||
<!-- 允许访问外部下载目录 -->
|
||||
<external-path name="download" path="." />
|
||||
</paths>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
-->
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get()
|
||||
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||
|
||||
subprojects {
|
||||
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||
}
|
||||
subprojects {
|
||||
project.evaluationDependsOn(":app")
|
||||
}
|
||||
|
||||
tasks.register<Delete>("clean") {
|
||||
delete(rootProject.layout.buildDirectory)
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
#distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-all.zip
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
pluginManagement {
|
||||
val flutterSdkPath = run {
|
||||
val properties = java.util.Properties()
|
||||
file("local.properties").inputStream().use { properties.load(it) }
|
||||
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||
flutterSdkPath
|
||||
}
|
||||
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
||||
resolutionStrategy {
|
||||
eachPlugin {
|
||||
val pluginId = requested.id.id
|
||||
if (pluginId == "org.jetbrains.kotlin.android" || pluginId == "org.jetbrains.kotlin.jvm") {
|
||||
// 与 build.gradle.kts 中 kotlin 插件版本保持一致
|
||||
useVersion("2.2.20")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||
// 与 android/build.gradle.kts 中使用的 AGP 版本保持一致
|
||||
id("com.android.application") version "8.9.1" apply false
|
||||
// 与 build.gradle.kts 中 kotlin 插件版本保持一致
|
||||
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
|
||||
}
|
||||
|
||||
include(":app")
|
||||
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 8.0 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 1013 B |
|
After Width: | Height: | Size: 305 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 769 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 829 B |
|
After Width: | Height: | Size: 812 B |
|
After Width: | Height: | Size: 682 B |
|
After Width: | Height: | Size: 633 B |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 749 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 221 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 777 KiB |
|
After Width: | Height: | Size: 274 B |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 528 B |
|
After Width: | Height: | Size: 178 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,389 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>特殊作业扎点</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
||||
<style>
|
||||
body, html, #container {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: "微软雅黑";
|
||||
}
|
||||
#hint {
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
left: 10px;
|
||||
top: 10px;
|
||||
padding: 6px 10px;
|
||||
background: rgba(255,255,255,0.9);
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Baidu Map WebGL (保留你的 key) -->
|
||||
<script type="text/javascript"
|
||||
src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=OElqFYoKiAH8KFtph8ftLKF5NlNrbCUr"></script>
|
||||
<script src="./uni.webview.1.5.4.js"></script>
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<div id="container"></div>
|
||||
<div id="hint" style="display:none"></div>
|
||||
</body>
|
||||
|
||||
<script>
|
||||
// 地图与数据容器
|
||||
var map = null;
|
||||
var marker = null;
|
||||
var GSON_LON_LAT_WSG84 = []; // WGS84 多点 [[lon,lat,alt], ...]
|
||||
var GSON_LON_LAT_BD09 = []; // 转换后的 BD09 二维点 [[lng,lat],...]
|
||||
var convertor = null;
|
||||
|
||||
// ---------------------------
|
||||
// 通用通知宿主(Flutter / 原生 / web)
|
||||
// 会尝试多种桥接方式
|
||||
// data 可以是对象或字符串
|
||||
// ---------------------------
|
||||
function notifyHost(data) {
|
||||
try {
|
||||
// prefer passing object where supported
|
||||
if (window.JS && typeof window.JS.postMessage === 'function') {
|
||||
// webview_flutter JavaScriptChannel expects string
|
||||
var payload = (typeof data === 'string') ? data : JSON.stringify(data);
|
||||
window.JS.postMessage(payload);
|
||||
return;
|
||||
}
|
||||
if (window.flutter_inappwebview && typeof window.flutter_inappwebview.callHandler === 'function') {
|
||||
// flutter_inappwebview can accept objects
|
||||
window.flutter_inappwebview.callHandler('messageHandler', data);
|
||||
return;
|
||||
}
|
||||
if (window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.JS && typeof window.webkit.messageHandlers.JS.postMessage === 'function') {
|
||||
window.webkit.messageHandlers.JS.postMessage(data);
|
||||
return;
|
||||
}
|
||||
// fallback to uni (if present) to keep backward compatibility
|
||||
if (window.uni && typeof window.uni.postMessage === 'function') {
|
||||
window.uni.postMessage({data: data});
|
||||
return;
|
||||
}
|
||||
// last resort, console (useful for debugging)
|
||||
console.log('notifyHost:', data);
|
||||
} catch (e) {
|
||||
console.error('notifyHost error:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// 尝试从 URL 初始化(如果 Flutter 把参数拼在 URL 上)
|
||||
// 支持参数: longitude, latitude, GSON (JSON string, 已 encodeURIComponent)
|
||||
// ---------------------------
|
||||
function tryInitFromUrl() {
|
||||
try {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const lon = params.get('longitude');
|
||||
const lat = params.get('latitude');
|
||||
const gsonRaw = params.get('GSON'); // 预期是 encodeURIComponent(JSON.stringify([...]))
|
||||
var has = false;
|
||||
if (lon && lat) has = true;
|
||||
if (gsonRaw) has = true;
|
||||
if (!has) return false;
|
||||
|
||||
var gson = null;
|
||||
if (gsonRaw) {
|
||||
try {
|
||||
gson = JSON.parse(decodeURIComponent(gsonRaw));
|
||||
} catch (e) {
|
||||
// 如果直接是未 encode 的 JSON 字符串,也尝试解析
|
||||
try { gson = JSON.parse(gsonRaw); } catch (e2) { gson = null; }
|
||||
}
|
||||
}
|
||||
|
||||
// 使用从 url 获取到的数据执行初始化
|
||||
initWithData({
|
||||
longitude: parseFloat(lon),
|
||||
latitude: parseFloat(lat),
|
||||
GSON: gson
|
||||
});
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.warn('tryInitFromUrl error', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Flutter/宿主可调用的初始化函数
|
||||
// 支持两种调用方式:
|
||||
// 1) initWithData({longitude: xx, latitude: yy, GSON: [...]})
|
||||
// 2) initWithData(longitude, latitude, GSONArray)
|
||||
// GSONArray 结构应与原来一致([[lon,lat,alt], ...])
|
||||
// ---------------------------
|
||||
window.initWithData = function() {
|
||||
var args = arguments;
|
||||
var payload = {};
|
||||
if (args.length === 1 && typeof args[0] === 'object') {
|
||||
payload = args[0];
|
||||
} else {
|
||||
// try positional
|
||||
payload.longitude = args[0];
|
||||
payload.latitude = args[1];
|
||||
payload.GSON = args[2];
|
||||
}
|
||||
|
||||
try {
|
||||
if (!payload) payload = {};
|
||||
// default safe parse
|
||||
var lon = Number(payload.longitude) || 0;
|
||||
var lat = Number(payload.latitude) || 0;
|
||||
var gson = payload.GSON || [];
|
||||
|
||||
// ensure convertor exists
|
||||
if (!convertor && window.BMapGL && typeof BMapGL.Convertor === 'function') {
|
||||
convertor = new BMapGL.Convertor();
|
||||
}
|
||||
|
||||
// set global wgs84 list (if provided)
|
||||
if (Array.isArray(gson) && gson.length > 0) {
|
||||
GSON_LON_LAT_WSG84 = gson;
|
||||
}
|
||||
|
||||
// init map & polygon
|
||||
fnInitMap(lon, lat);
|
||||
if (GSON_LON_LAT_WSG84 && GSON_LON_LAT_WSG84.length > 0) {
|
||||
fnInitConvertorData(GSON_LON_LAT_WSG84);
|
||||
}
|
||||
|
||||
showHint('地图已初始化');
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('initWithData error', e);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
// 显示调试提示
|
||||
function showHint(text) {
|
||||
var el = document.getElementById('hint');
|
||||
if (!el) return;
|
||||
el.style.display = 'block';
|
||||
el.innerText = text;
|
||||
setTimeout(function(){ el.style.display = 'none'; }, 4000);
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// 页面加载
|
||||
// ---------------------------
|
||||
function onLoad() {
|
||||
// create convertor if possible
|
||||
if (window.BMapGL && typeof BMapGL.Convertor === 'function') {
|
||||
convertor = new BMapGL.Convertor();
|
||||
} else {
|
||||
console.warn('BMapGL.Convertor not ready yet.');
|
||||
}
|
||||
|
||||
// 创建地图对象(延迟绑定 center,等 init 时调用)
|
||||
map = new BMapGL.Map('container');
|
||||
map.enableScrollWheelZoom(true);
|
||||
map.setDisplayOptions({ building: false });
|
||||
map.addEventListener('click', MapClick);
|
||||
|
||||
// 如果 URL 带参数则自动初始化,否则等待宿主调用 initWithData(...)
|
||||
var ok = tryInitFromUrl();
|
||||
if (!ok) {
|
||||
showHint('等待宿主调用 initWithData(...) 初始化地图');
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// 点在多边形内判定(二维,只用 lon/lat)
|
||||
// polygon = [[lng,lat], ...]
|
||||
// point = [lng, lat]
|
||||
// ---------------------------
|
||||
function isPointInPolygon(point, polygon) {
|
||||
const x = point[0];
|
||||
const y = point[1];
|
||||
let inside = false;
|
||||
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
|
||||
const xi = polygon[i][0], yi = polygon[i][1];
|
||||
const xj = polygon[j][0], yj = polygon[j][1];
|
||||
const intersect = ((yi > y) !== (yj > y))
|
||||
&& (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
|
||||
if (intersect) inside = !inside;
|
||||
}
|
||||
return inside;
|
||||
}
|
||||
|
||||
// 地图点击处理
|
||||
function MapClick(e) {
|
||||
try {
|
||||
if (marker) map.removeOverlay(marker);
|
||||
marker = new BMapGL.Marker(new BMapGL.Point(e.latlng.lng, e.latlng.lat));
|
||||
const x = [e.latlng.lng, e.latlng.lat];
|
||||
let inside = (GSON_LON_LAT_BD09 && GSON_LON_LAT_BD09.length > 0) ? isPointInPolygon(x, GSON_LON_LAT_BD09) : true;
|
||||
if (!inside) {
|
||||
//alert("当前选择点位不在区域中!");
|
||||
notifyHost({type:'point_selected', ok:false, reason:'out_of_polygon', lng:e.latlng.lng, lat:e.latlng.lat});
|
||||
} else {
|
||||
map.addOverlay(marker);
|
||||
// 把 BD09 -> WGS84 转换后的点回传给宿主
|
||||
fnConvertorBd09ToWgs84Data2(e.latlng.lng, e.latlng.lat);
|
||||
notifyHost({type:'point_selected', ok:true, lng:e.latlng.lng, lat:e.latlng.lat});
|
||||
|
||||
// // 直接把BD09回传
|
||||
// notifyHost({type:'converted', longitue: e.latlng.lng, latitude: e.latlng.lat});
|
||||
// notifyHost({
|
||||
// type: 'point_selected',
|
||||
// ok: true,
|
||||
// lng: e.latlng.lng,
|
||||
// lat: e.latlng.lat
|
||||
// });
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('MapClick error', err);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// 将 WGS84 多点转换为 BD09 并绘制多边形
|
||||
// arr: [[lon,lat,...], ...] 注意原 arr (GSON_LON_LAT_WSG84)顺序是 lon, lat
|
||||
// ---------------------------
|
||||
function fnInitConvertorData(arr) {
|
||||
try {
|
||||
if (!convertor) convertor = new BMapGL.Convertor();
|
||||
var points = [];
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
var xi = arr[i][0], yi = arr[i][1];
|
||||
points.push(new BMapGL.Point(xi, yi));
|
||||
}
|
||||
convertor.translate(points, 1, 5, function(res) {
|
||||
if (!res || !res.points) {
|
||||
console.warn('convertor.translate returned no points', res);
|
||||
return;
|
||||
}
|
||||
GSON_LON_LAT_BD09 = [];
|
||||
var list = [];
|
||||
for (var p = 0; p < res.points.length; p++) {
|
||||
let item = res.points[p];
|
||||
GSON_LON_LAT_BD09.push([item.lng, item.lat]);
|
||||
list.push(new BMapGL.Point(item.lng, item.lat));
|
||||
}
|
||||
var polygon = new BMapGL.Polygon(list, {
|
||||
zIndex: 999,
|
||||
strokeColor: 'blue',
|
||||
strokeWeight: 5,
|
||||
strokeOpacity: 0.5
|
||||
});
|
||||
map.addOverlay(polygon);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('fnInitConvertorData error', e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// 初始化地图中心(longitude, latitude 为 WGS84)
|
||||
// ---------------------------
|
||||
function fnInitMap(longitude, latitude) {
|
||||
try {
|
||||
if (!convertor) convertor = new BMapGL.Convertor();
|
||||
var ponits = [ new BMapGL.Point(longitude, latitude) ];
|
||||
convertor.translate(ponits, 1, 5, function(res) {
|
||||
if (!res || !res.points || res.points.length === 0) {
|
||||
console.warn('fnInitMap: translate failed', res);
|
||||
return;
|
||||
}
|
||||
var pt = res.points[0];
|
||||
map.centerAndZoom(new BMapGL.Point(pt.lng, pt.lat), 18);
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('fnInitMap error', e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// BD09 -> WGS84 (JS 版算法),并把结果 post 给宿主
|
||||
// 注意: bdLat, bdLon 参数顺序(原函数输入顺序)
|
||||
// 返回 [wgsLat, wgsLon](跟原实现一致)
|
||||
// ---------------------------
|
||||
const bd09ToWgs84 = (bdLat, bdLon) => {
|
||||
const x_pi = (Math.PI * 3000.0) / 180.0;
|
||||
const x = bdLon - 0.0065;
|
||||
const y = bdLat - 0.006;
|
||||
const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
|
||||
const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
|
||||
const gcjLon = z * Math.cos(theta);
|
||||
const gcjLat = z * Math.sin(theta);
|
||||
|
||||
let dlat = transformlat(gcjLon - 105.0, gcjLat - 35.0);
|
||||
let dlng = transformlng(gcjLon - 105.0, gcjLat - 35.0);
|
||||
const radlat = (gcjLat / 180.0) * Math.PI;
|
||||
let magic = Math.sin(radlat);
|
||||
magic = 1 - 0.006693421622965943 * magic * magic;
|
||||
const sqrtmagic = Math.sqrt(magic);
|
||||
dlat = (dlat * 180.0) / (((6378245.0 * (1 - 0.006693421622965943)) / (magic * sqrtmagic)) * Math.PI);
|
||||
dlng = (dlng * 180.0) / ((6378245.0 / sqrtmagic) * Math.cos(radlat) * Math.PI);
|
||||
const mglat = gcjLat + dlat;
|
||||
const mglng = gcjLon + dlng;
|
||||
const wgsLon = gcjLon * 2 - mglng;
|
||||
const wgsLat = gcjLat * 2 - mglat;
|
||||
return [wgsLat, wgsLon];
|
||||
};
|
||||
|
||||
const transformlat = (lng, lat) => {
|
||||
let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
|
||||
ret += ((20.0 * Math.sin(6.0 * lng * Math.PI) + 20.0 * Math.sin(2.0 * lng * Math.PI)) * 2.0) / 3.0;
|
||||
ret += ((20.0 * Math.sin(lat * Math.PI) + 40.0 * Math.sin((lat / 3.0) * Math.PI)) * 2.0) / 3.0;
|
||||
ret += ((160.0 * Math.sin((lat / 12.0) * Math.PI) + 320 * Math.sin((lat * Math.PI) / 30.0)) * 2.0) / 3.0;
|
||||
return ret;
|
||||
};
|
||||
const transformlng = (lng, lat) => {
|
||||
let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
|
||||
ret += ((20.0 * Math.sin(6.0 * lng * Math.PI) + 20.0 * Math.sin(2.0 * lng * Math.PI)) * 2.0) / 3.0;
|
||||
ret += ((20.0 * Math.sin(lng * Math.PI) + 40.0 * Math.sin((lng / 3.0) * Math.PI)) * 2.0) / 3.0;
|
||||
ret += ((150.0 * Math.sin((lng / 12.0) * Math.PI) + 300.0 * Math.sin((lng / 30.0) * Math.PI)) * 2.0) / 3.0;
|
||||
return ret;
|
||||
};
|
||||
|
||||
// ---------------------------
|
||||
// 使用百度 convertor(如果可用)把 BD09 点转回 WGS84 并 postMessage 给宿主
|
||||
// 备用:也会调用 bd09ToWgs84 本地算法
|
||||
// ---------------------------
|
||||
function fnConvertorBd09ToWgs84Data2(lng, lat) {
|
||||
try {
|
||||
// first try convertor.translate from BMapGL
|
||||
if (convertor && typeof convertor.translate === 'function') {
|
||||
var pts = [ new BMapGL.Point(lng, lat) ];
|
||||
convertor.translate(pts, 5, 1, function(res) {
|
||||
if (res && res.points && res.points.length > 0) {
|
||||
var p = res.points[0];
|
||||
// res.points are in WGS84? depends on convert params; keep compatibility:
|
||||
notifyHost({type:'converted', longitue: p.lng, latitude: p.lat});
|
||||
return;
|
||||
}
|
||||
// fallback to local algorithm if convertor result absent
|
||||
var w = bd09ToWgs84(lat, lng);
|
||||
notifyHost({type:'converted', longitue: w[1], latitude: w[0]});
|
||||
});
|
||||
} else {
|
||||
var w = bd09ToWgs84(lat, lng);
|
||||
notifyHost({type:'converted', longitue: w[1], latitude: w[0]});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('fnConvertorBd09ToWgs84Data2 error', e);
|
||||
var w = bd09ToWgs84(lat, lng);
|
||||
notifyHost({type:'converted', longitue: w[1], latitude: w[0]});
|
||||
}
|
||||
}
|
||||
|
||||
// 兼容老方法名
|
||||
window.fnInitMap = fnInitMap;
|
||||
window.fnInitConvertorData = fnInitConvertorData;
|
||||
window.fnConvertorBd09ToWgs84Data2 = fnConvertorBd09ToWgs84Data2;
|
||||
</script>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1,137 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>地图</title>
|
||||
<!-- 天地图API -->
|
||||
<script src="https://api.tianditu.gov.cn/api?v=4.0&tk=e8a16137fd226a62a23cc7ba5c9c78ce" type="text/javascript"></script>
|
||||
<style>
|
||||
html, body { height: 100%; margin: 0; padding: 0; }
|
||||
#mapDiv { position: absolute; top: 0; left: 0; right: 0; bottom: 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body onload="onLoad()">
|
||||
<div id="mapDiv"></div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
var map;
|
||||
var zoom = 14;
|
||||
var currentMarker = null;
|
||||
|
||||
function getUrlParam(name) {
|
||||
if (window.__injectedParams && window.__injectedParams[name] !== undefined) {
|
||||
return window.__injectedParams[name].toString();
|
||||
}
|
||||
const reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
|
||||
const r = window.location.search.substr(1).match(reg);
|
||||
if (r != null) return decodeURI(r[2]);
|
||||
return "";
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
var imageURL = "https://t0.tianditu.gov.cn/img_w/wmts?" +
|
||||
"SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles" +
|
||||
"&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=e8a16137fd226a62a23cc7ba5c9c78ce";
|
||||
var lay = new T.TileLayer(imageURL, {minZoom: 1, maxZoom: 18});
|
||||
var config = {layers: [lay]};
|
||||
map = new T.Map("mapDiv", config);
|
||||
|
||||
var initLng = parseFloat(getUrlParam('longitude'));
|
||||
var initLat = parseFloat(getUrlParam('latitude'));
|
||||
if (isNaN(initLng) || isNaN(initLat) || initLng === 0 || initLat === 0) {
|
||||
initLng = 116.397428;
|
||||
initLat = 39.90923;
|
||||
}
|
||||
map.centerAndZoom(new T.LngLat(initLng, initLat), zoom);
|
||||
map.enableScrollWheelZoom();
|
||||
|
||||
// 始终开启点击标点功能
|
||||
addMapClick();
|
||||
}
|
||||
|
||||
function addMapClick() {
|
||||
map.addEventListener("click", MapClick);
|
||||
}
|
||||
|
||||
function MapClick(event) {
|
||||
var lng = event.lnglat.getLng();
|
||||
var lat = event.lnglat.getLat();
|
||||
|
||||
// 清除旧标记并添加新标记(使用默认图标)
|
||||
map.clearOverLays();
|
||||
var marker = new T.Marker(new T.LngLat(lng, lat));
|
||||
map.addOverLay(marker);
|
||||
|
||||
// 保存选中位置
|
||||
window.selectedLocation = {
|
||||
longitude: lng,
|
||||
latitude: lat
|
||||
};
|
||||
|
||||
// 发送位置信息给 Flutter
|
||||
sendLocationToFlutter(lat, lng);
|
||||
}
|
||||
|
||||
function sendLocationToFlutter(lat, lng) {
|
||||
var payload = {
|
||||
data: [
|
||||
{
|
||||
latitude: lat,
|
||||
longitude: lng
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
// Flutter WebView 桥接
|
||||
if (typeof window.flutterPostMessage === 'function') {
|
||||
window.flutterPostMessage(payload);
|
||||
return;
|
||||
}
|
||||
|
||||
// 备用桥接方法(uniapp 或小程序)
|
||||
uni.getEnv(function (res) {
|
||||
if (res.plus) {
|
||||
uni.postMessage({ data: { "longitude": lng, "latitude": lat } });
|
||||
} else {
|
||||
if (window.wx && window.wx.miniProgram) {
|
||||
try {
|
||||
window.wx.miniProgram.postMessage({ data: { "longitude": lng, "latitude": lat } });
|
||||
window.wx.miniProgram.navigateBack();
|
||||
} catch(e) {
|
||||
console.log('wx miniProgram error', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Flutter 获取选中位置的方法
|
||||
function getSelectedLocation() {
|
||||
try {
|
||||
if (window.selectedLocation) {
|
||||
return window.selectedLocation;
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
console.log('getSelectedLocation error', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Flutter 调用,设置地图中心和标记
|
||||
function setLocation(lng, lat) {
|
||||
try {
|
||||
map.centerAndZoom(new T.LngLat(lng, lat), zoom);
|
||||
var marker = new T.Marker(new T.LngLat(lng, lat));
|
||||
map.clearOverLays();
|
||||
map.addOverLay(marker);
|
||||
window.selectedLocation = { longitude: lng, latitude: lat };
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.log('setLocation error', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
|
@ -0,0 +1,3 @@
|
|||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
**/dgph
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
**/*sync/
|
||||
.sconsign.dblite
|
||||
.tags*
|
||||
**/.vagrant/
|
||||
**/DerivedData/
|
||||
Icon?
|
||||
**/Pods/
|
||||
**/.symlinks/
|
||||
profile
|
||||
xcuserdata
|
||||
**/.generated/
|
||||
Flutter/App.framework
|
||||
Flutter/Flutter.framework
|
||||
Flutter/Flutter.podspec
|
||||
Flutter/Generated.xcconfig
|
||||
Flutter/ephemeral/
|
||||
Flutter/app.flx
|
||||
Flutter/app.zip
|
||||
Flutter/flutter_assets/
|
||||
Flutter/flutter_export_environment.sh
|
||||
ServiceDefinitions.json
|
||||
Runner/GeneratedPluginRegistrant.*
|
||||
|
||||
# Exceptions to above rules.
|
||||
!default.mode1v3
|
||||
!default.mode2v3
|
||||
!default.pbxuser
|
||||
!default.perspectivev3
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '13.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
'Debug' => :debug,
|
||||
'Profile' => :release,
|
||||
'Release' => :release,
|
||||
}
|
||||
|
||||
def flutter_root
|
||||
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
|
||||
unless File.exist?(generated_xcode_build_settings_path)
|
||||
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
|
||||
end
|
||||
|
||||
File.foreach(generated_xcode_build_settings_path) do |line|
|
||||
matches = line.match(/FLUTTER_ROOT\=(.*)/)
|
||||
return matches[1].strip if matches
|
||||
end
|
||||
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
|
||||
end
|
||||
|
||||
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
|
||||
|
||||
flutter_ios_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
target 'RunnerTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,237 @@
|
|||
PODS:
|
||||
- BaiduMapKit/Base (6.6.4)
|
||||
- BaiduMapKit/Map (6.6.4):
|
||||
- BaiduMapKit/Base
|
||||
- BaiduMapKit/Utils (6.6.4):
|
||||
- BaiduMapKit/Base
|
||||
- camera_avfoundation (0.0.1):
|
||||
- Flutter
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- DKImagePickerController/Core (4.3.9):
|
||||
- DKImagePickerController/ImageDataManager
|
||||
- DKImagePickerController/Resource
|
||||
- DKImagePickerController/ImageDataManager (4.3.9)
|
||||
- DKImagePickerController/PhotoGallery (4.3.9):
|
||||
- DKImagePickerController/Core
|
||||
- DKPhotoGallery
|
||||
- DKImagePickerController/Resource (4.3.9)
|
||||
- DKPhotoGallery (0.0.19):
|
||||
- DKPhotoGallery/Core (= 0.0.19)
|
||||
- DKPhotoGallery/Model (= 0.0.19)
|
||||
- DKPhotoGallery/Preview (= 0.0.19)
|
||||
- DKPhotoGallery/Resource (= 0.0.19)
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Core (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Preview
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Model (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Preview (0.0.19):
|
||||
- DKPhotoGallery/Model
|
||||
- DKPhotoGallery/Resource
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- DKPhotoGallery/Resource (0.0.19):
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Flutter (1.0.0)
|
||||
- flutter_baidu_mapapi_base (3.9.0):
|
||||
- BaiduMapKit/Utils (= 6.6.4)
|
||||
- Flutter
|
||||
- flutter_baidu_mapapi_map (3.9.0):
|
||||
- BaiduMapKit/Map (= 6.6.4)
|
||||
- Flutter
|
||||
- flutter_baidu_mapapi_base
|
||||
- flutter_baidu_mapapi_utils (3.9.0):
|
||||
- BaiduMapKit/Utils (= 6.6.4)
|
||||
- Flutter
|
||||
- flutter_baidu_mapapi_base
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- flutter_new_badger (0.0.1):
|
||||
- Flutter
|
||||
- fluttertoast (0.0.2):
|
||||
- Flutter
|
||||
- geolocator_apple (1.2.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- mobile_scanner (7.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- nfc_manager (0.0.1):
|
||||
- Flutter
|
||||
- objective_c (0.0.1):
|
||||
- Flutter
|
||||
- open_file_ios (0.0.1):
|
||||
- Flutter
|
||||
- package_info_plus (0.4.5):
|
||||
- Flutter
|
||||
- pdfx (1.0.0):
|
||||
- Flutter
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- photo_manager (3.8.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- SDWebImage (5.21.1):
|
||||
- SDWebImage/Core (= 5.21.1)
|
||||
- SDWebImage/Core (5.21.1)
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- SwiftyGif (5.4.5)
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- video_compress (0.3.0):
|
||||
- Flutter
|
||||
- video_player_avfoundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- webview_flutter_wkwebview (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- camera_avfoundation (from `.symlinks/plugins/camera_avfoundation/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_baidu_mapapi_base (from `.symlinks/plugins/flutter_baidu_mapapi_base/ios`)
|
||||
- flutter_baidu_mapapi_map (from `.symlinks/plugins/flutter_baidu_mapapi_map/ios`)
|
||||
- flutter_baidu_mapapi_utils (from `.symlinks/plugins/flutter_baidu_mapapi_utils/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_new_badger (from `.symlinks/plugins/flutter_new_badger/ios`)
|
||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
|
||||
- nfc_manager (from `.symlinks/plugins/nfc_manager/ios`)
|
||||
- objective_c (from `.symlinks/plugins/objective_c/ios`)
|
||||
- open_file_ios (from `.symlinks/plugins/open_file_ios/ios`)
|
||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||
- pdfx (from `.symlinks/plugins/pdfx/ios`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- photo_manager (from `.symlinks/plugins/photo_manager/darwin`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- video_compress (from `.symlinks/plugins/video_compress/ios`)
|
||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
|
||||
|
||||
SPEC REPOS:
|
||||
trunk:
|
||||
- BaiduMapKit
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- SDWebImage
|
||||
- SwiftyGif
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
camera_avfoundation:
|
||||
:path: ".symlinks/plugins/camera_avfoundation/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_baidu_mapapi_base:
|
||||
:path: ".symlinks/plugins/flutter_baidu_mapapi_base/ios"
|
||||
flutter_baidu_mapapi_map:
|
||||
:path: ".symlinks/plugins/flutter_baidu_mapapi_map/ios"
|
||||
flutter_baidu_mapapi_utils:
|
||||
:path: ".symlinks/plugins/flutter_baidu_mapapi_utils/ios"
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_new_badger:
|
||||
:path: ".symlinks/plugins/flutter_new_badger/ios"
|
||||
fluttertoast:
|
||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||
geolocator_apple:
|
||||
:path: ".symlinks/plugins/geolocator_apple/darwin"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
mobile_scanner:
|
||||
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
||||
nfc_manager:
|
||||
:path: ".symlinks/plugins/nfc_manager/ios"
|
||||
objective_c:
|
||||
:path: ".symlinks/plugins/objective_c/ios"
|
||||
open_file_ios:
|
||||
:path: ".symlinks/plugins/open_file_ios/ios"
|
||||
package_info_plus:
|
||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||
pdfx:
|
||||
:path: ".symlinks/plugins/pdfx/ios"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
photo_manager:
|
||||
:path: ".symlinks/plugins/photo_manager/darwin"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
video_compress:
|
||||
:path: ".symlinks/plugins/video_compress/ios"
|
||||
video_player_avfoundation:
|
||||
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
|
||||
wakelock_plus:
|
||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||
webview_flutter_wkwebview:
|
||||
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
BaiduMapKit: 84991811cb07b24c6ead7d59022c13245427782c
|
||||
camera_avfoundation: 5675ca25298b6f81fa0a325188e7df62cc217741
|
||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_baidu_mapapi_base: 24dd82034374c6f52a73e90316834c63ff8d4f64
|
||||
flutter_baidu_mapapi_map: f799cc1bb3d39196b8d3d59399ca8635e690bd44
|
||||
flutter_baidu_mapapi_utils: 0c69394243d51e97f521f396e150aaaf31e84e29
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
flutter_new_badger: 133aaf93e9a5542bf905c8483d8b83c5ef4946ea
|
||||
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
||||
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
|
||||
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
|
||||
nfc_manager: f6d5609c09b4640b914a3dc67479a2e392965fd0
|
||||
objective_c: 89e720c30d716b036faf9c9684022048eee1eee2
|
||||
open_file_ios: 5ff7526df64e4394b4fe207636b67a95e83078bb
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
pdfx: 77f4dddc48361fbb01486fa2bdee4532cbb97ef3
|
||||
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
|
||||
photo_manager: 343d78032bf7ebe944d2ab9702204dc2eda07338
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||
video_compress: f2133a07762889d67f0711ac831faa26f956980e
|
||||
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||
webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d
|
||||
|
||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||