4 changed files with 40 additions and 10 deletions

No files matched your search

+2 -1
View File
@@ -5,7 +5,8 @@
<application
android:label="FruitShorts"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
android:icon="@mipmap/ic_launcher"
android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true"
+31 -4
View File
@@ -9,11 +9,13 @@ import 'package:flutter/foundation.dart';
class AppConfig {
const AppConfig._();
/// 真机默认使用的开发机局域网地址。
/// 真机默认使用的服务地址。
///
/// 这个地址跟着电脑所在的网络走,换网络后要用
/// `ipconfig getifaddr en0` 重新确认。默认值只改这一行。
static const String devHostBaseUrl = 'http://192.168.31.187:8081';
/// 当前指向公网服务;换地址时改这一行。
static const String devHostBaseUrl = 'http://39.162.50.99:8081';
/// 双网络探测的首选地址,当前与默认地址一致(公网服务)。
static const String lanBaseUrl = 'http://39.162.50.99:8081';
static const String _loopbackBaseUrl = 'http://127.0.0.1:8081';
@@ -59,6 +61,31 @@ class AppConfig {
static const Duration requestTimeout = Duration(seconds: 8);
/// 探测内网地址是否可达,可达则切换为内网直连,否则回落到公网地址。
///
/// Wi-Fi 下内网直连更快;移动数据下内网不可达,自动回落到公网端口映射。
static Future<void> probeAndApplyBaseUrl() async {
try {
final client = HttpClient()
..connectionTimeout = const Duration(seconds: 2);
final request = await client.getUrl(
Uri.parse('$lanBaseUrl/app/categories'),
);
final response = await request.close().timeout(const Duration(seconds: 2));
await response.drain<void>();
client.close(force: true);
if (response.statusCode == 200) {
applyRuntimeBaseUrl(lanBaseUrl);
return;
}
} catch (_) {
// 内网不可达,回落到公网。
}
applyRuntimeBaseUrl(
compiledBaseUrl.isNotEmpty ? compiledBaseUrl : defaultBaseUrl,
);
}
/// 后端返回的是相对路径(/files/...),这里补上服务地址。
static String mediaUrl(String path) {
if (path.isEmpty) return '';
+2
View File
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'app.dart';
import 'core/config/app_config.dart';
import 'core/config/server_endpoint.dart';
Future<void> main() async {
@@ -12,5 +13,6 @@ Future<void> main() async {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]),
ServerEndpoint.load(),
]);
await AppConfig.probeAndApplyBaseUrl();
runApp(const LumaDramaApp());
}
+5 -5
View File
@@ -57,13 +57,13 @@ void main() {
});
test('should_use_the_configured_lan_address_for_device_default', () {
expect(AppConfig.devHostBaseUrl, 'http://192.168.31.187:8081');
expect(AppConfig.devHostBaseUrl, 'http://39.162.50.99:8081');
});
test('should_apply_stored_url_only_when_debug_is_enabled', () async {
SharedPreferencesAsyncPlatform.instance =
InMemorySharedPreferencesAsync.withData({
ServerEndpoint.preferenceKey: ' http://192.168.31.187:8081/ ',
ServerEndpoint.preferenceKey: ' http://39.162.50.99:8081/ ',
});
final original = AppConfig.apiBaseUrl;
@@ -71,7 +71,7 @@ void main() {
expect(AppConfig.apiBaseUrl, original);
await ServerEndpoint.load(debug: true);
expect(AppConfig.apiBaseUrl, 'http://192.168.31.187:8081');
expect(AppConfig.apiBaseUrl, 'http://39.162.50.99:8081');
});
test('should_save_normalized_url_and_clear_override', () async {
@@ -82,12 +82,12 @@ void main() {
);
expect(
await ServerEndpoint.save(' http://192.168.31.187:8081/ '),
await ServerEndpoint.save(' http://39.162.50.99:8081/ '),
isTrue,
);
expect(
await SharedPreferencesAsync().getString(ServerEndpoint.preferenceKey),
'http://192.168.31.187:8081',
'http://39.162.50.99:8081',
);
await ServerEndpoint.clear();