S22 本機測試發現的 bug 修復(path, 改名要很小心)

This commit is contained in:
2026-04-18 13:56:52 +08:00
parent b5051db50b
commit caaa6c4fa8
7 changed files with 184 additions and 17 deletions
+38 -12
View File
@@ -1,12 +1,21 @@
import java.util.Properties
import java.io.FileInputStream
// 1. 在 android 區塊上方讀取 key.properties 設定檔
val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}
plugins { plugins {
id("com.android.application") id("com.android.application")
id("kotlin-android") id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin") id("dev.flutter.flutter-gradle-plugin")
} }
android { android {
namespace = "tw.com.gex.homehunter.home_hunter" namespace = "tw.com.gex.house_hunter"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion ndkVersion = flutter.ndkVersion
@@ -16,29 +25,46 @@ android {
} }
kotlinOptions { kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString() // 修正原本的 jvmTarget 警告,改用較新的寫法
freeCompilerArgs += "-Xjvm-default=all"
jvmTarget = "17"
} }
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId = "tw.com.gex.house_hunter"
applicationId = "tw.com.gex.homehunter.home_hunter"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode versionCode = flutter.versionCode
versionName = flutter.versionName versionName = flutter.versionName
} }
// 2. 定義簽署配置 (這一段非常重要)
signingConfigs {
create("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
keyPassword = keystoreProperties.getProperty("keyPassword")
storePassword = keystoreProperties.getProperty("storePassword")
// 處理 storeFile 的路徑
val path = keystoreProperties.getProperty("storeFile")
if (path != null) {
storeFile = file(path)
}
}
}
buildTypes { buildTypes {
release { getByName("release") {
// TODO: Add your own signing config for the release build. // 3. 修正:將簽署配置從 "debug" 改為我們上面定義的 "release"
// Signing with the debug keys for now, so `flutter run --release` works. signingConfig = signingConfigs.getByName("release")
signingConfig = signingConfigs.getByName("debug")
// 下面這兩項在初次成功打包前建議先設為 false
isMinifyEnabled = false
isShrinkResources = false
} }
} }
} }
flutter { flutter {
source = "../.." source = "../.."
} }
+8 -3
View File
@@ -1,9 +1,16 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <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_COARSE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<application <application
android:label="house_hunter" android:label="看房筆記"
android:name="${applicationName}" android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"> android:icon="@mipmap/ic_launcher">
<activity <activity
@@ -45,6 +52,4 @@
<data android:mimeType="text/plain"/> <data android:mimeType="text/plain"/>
</intent> </intent>
</queries> </queries>
<uses-permission android:name="android.permission.INTERNET"/>
</manifest> </manifest>
@@ -1,4 +1,4 @@
package tw.com.gex.homehunter.home_hunter package tw.com.gex.house_hunter
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.android.FlutterActivity
+1
View File
@@ -1,2 +1,3 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true android.useAndroidX=true
kotlin.incremental=false
+30 -1
View File
@@ -6,14 +6,40 @@ import 'package:uuid/uuid.dart';
import 'dart:io'; import 'dart:io';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'dart:convert'; // 補上這行,json.decode 才能運作 import 'dart:convert'; // 補上這行,json.decode 才能運作
// import 'package:device_info_plus/device_info_plus.dart'; // [修正] 補上裝置資訊引用
import 'package:shared_preferences/shared_preferences.dart'; // [新增]
class HouseNoteApiService { class HouseNoteApiService {
final GenericApiService _apiService = GenericApiService(); final GenericApiService _apiService = GenericApiService();
static String? _cachedUserId;
// 替代 _getDeviceId 的方案:獲取本地生成的唯一 User ID
Future<String> _getAppUserId() async {
if (_cachedUserId != null) return _cachedUserId!;
final prefs = await SharedPreferences.getInstance();
// 嘗試從本地記憶體讀取舊有的 ID
String? localId = prefs.getString('app_user_unique_id');
if (localId == null) {
// 第一次安裝,產生一個新的隨機 ID
localId = const Uuid().v4(); //
await prefs.setString('app_user_unique_id', localId);
}
_cachedUserId = localId;
return localId;
}
// 獲取所有房屋列表 // 獲取所有房屋列表
Future<List<House>> fetchHouses() async { Future<List<House>> fetchHouses() async {
String userId = await _getAppUserId();
// 格式:當前頁^每頁筆數^排序欄位^*^^^過濾欄位^過濾值
// 我們在 queryFilter 的最後方加上 device_id 的過濾條件
String queryFilter = "1^100^created_at^*^^^device_id^$userId";
// 依據建立時間降冪排序 // 依據建立時間降冪排序
String queryFilter = "1^100^created_at^*^^^"; // String queryFilter = "1^100^created_at^*^^^";
return await _apiService.fetchList<House>( return await _apiService.fetchList<House>(
tableName: "hhp_houses", tableName: "hhp_houses",
pk: "id", pk: "id",
@@ -24,8 +50,11 @@ class HouseNoteApiService {
// 創建新物件 (UUID 在前端生成) // 創建新物件 (UUID 在前端生成)
Future<List<House>> createHouse(House house) async { Future<List<House>> createHouse(House house) async {
String userId = await _getAppUserId();
final Map<String, dynamic> data = { final Map<String, dynamic> data = {
"id": house.id, "id": house.id,
"device_id": userId, // 【關鍵】寫入手機識別碼
"title": house.title, "title": house.title,
"address": house.address, "address": house.address,
"latitude": house.latitude, "latitude": house.latitude,
+104
View File
@@ -113,6 +113,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.2.0" version: "2.2.0"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.dev"
source: hosted
version: "7.0.1"
file_selector_linux: file_selector_linux:
dependency: transitive dependency: transitive
description: description:
@@ -373,6 +381,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.1"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.dev"
source: hosted
version: "2.3.0"
petitparser: petitparser:
dependency: transitive dependency: transitive
description: description:
@@ -381,6 +413,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.0.2" version: "7.0.2"
platform:
dependency: transitive
description:
name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.dev"
source: hosted
version: "3.1.6"
plugin_platform_interface: plugin_platform_interface:
dependency: transitive dependency: transitive
description: description:
@@ -397,6 +437,62 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.5.0" version: "6.5.0"
shared_preferences:
dependency: "direct main"
description:
name: shared_preferences
sha256: c3025c5534b01739267eb7d76959bbc25a6d10f6988e1c2a3036940133dd10bf
url: "https://pub.dev"
source: hosted
version: "2.5.5"
shared_preferences_android:
dependency: transitive
description:
name: shared_preferences_android
sha256: e8d4762b1e2e8578fc4d0fd548cebf24afd24f49719c08974df92834565e2c53
url: "https://pub.dev"
source: hosted
version: "2.4.23"
shared_preferences_foundation:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f"
url: "https://pub.dev"
source: hosted
version: "2.5.6"
shared_preferences_linux:
dependency: transitive
description:
name: shared_preferences_linux
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
shared_preferences_platform_interface:
dependency: transitive
description:
name: shared_preferences_platform_interface
sha256: "649dc798a33931919ea356c4305c2d1f81619ea6e92244070b520187b5140ef9"
url: "https://pub.dev"
source: hosted
version: "2.4.2"
shared_preferences_web:
dependency: transitive
description:
name: shared_preferences_web
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
url: "https://pub.dev"
source: hosted
version: "2.4.3"
shared_preferences_windows:
dependency: transitive
description:
name: shared_preferences_windows
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
url: "https://pub.dev"
source: hosted
version: "2.4.1"
sky_engine: sky_engine:
dependency: transitive dependency: transitive
description: flutter description: flutter
@@ -490,6 +586,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.1" version: "1.1.1"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
xml: xml:
dependency: transitive dependency: transitive
description: description:
+2
View File
@@ -44,6 +44,8 @@ dependencies:
uuid: ^4.4.0 uuid: ^4.4.0
http: ^1.2.1 http: ^1.2.1
image_picker: ^1.1.2 image_picker: ^1.1.2
# device_info_plus: ^10.1.0 # 新增此套件
shared_preferences: ^2.3.5 # 代替讀取硬體識別碼
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: