最近在配置flutter開發環境的時候,出現了很多問題。
我是下載的 flutter源碼 ,切換到了stable
分支,當前版本號爲 1.22.6
。Android Studio
版本爲最新的穩定版 4.1.2
。
問題1
明明安裝了android studio,但是 flutter doctor
一直顯示 Android Studio
沒有安裝
[!] Android Studio (not installed)
使用如下命令設置一下即可解決
flutter config --android-studio-dir=$your-android-studio-directory
通過後文的分析,發現flutter
在linux
環境下默認搜索如下路徑
- ~/AndroidStudio{major.minor}/system/.home (major.minor表示版本號,例如4.1, 3.3等)
- /opt/android-studio
- ~/android-studio
如果不是這幾個默認安裝路徑,那就需要手動設置 android-studio-dir
問題2
明明安裝了 flutter和dart
插件,但是 flutter doctor
命令一直提示檢測不到這兩個插件,google搜了一下,沒有任何能解決這個問題的方案,好在有源碼,那我們就能自己解決了。
[!] Android Studio
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
以前從來沒看過flutter的代碼,我們如何開始呢?先看錯誤提示,於是我們可以根據錯誤提示的字符串來進行搜索,根據編程經驗插件名稱肯定是動態寫入的,於是我們試試搜索 plugin not installed
@debian-ts:~/tools/flutter$ rg 'plugin not installed'
packages/flutter_tools/lib/src/intellij/intellij.dart
44: '$title plugin not installed; this adds $title specific functionality.'));
packages/flutter_tools/test/general.shard/intellij/intellij_test.dart
88: expect(message.message, contains('Dart plugin not installed'));
92: expect(message.message, contains('Flutter plugin not installed'));
搜到了兩個文件,很明顯邏輯應該是在 packages/flutter_tools/lib/src/intellij/intellij.dart
這個文件中,我們打開看一下,發現 validatePackage
函數是用來做插件檢測的
void validatePackage(
List<ValidationMessage> messages,
List<String> packageNames,
String title, {
Version minVersion,
})
搜一下誰調用了這個函數
@debian-ts:~/tools/flutter$ rg validatePackage
packages/flutter_tools/lib/src/doctor.dart
749: plugins.validatePackage(messages, <String>['flutter-intellij', 'flutter-intellij.jar'],
751: plugins.validatePackage(messages, <String>['Dart'], 'Dart');
packages/flutter_tools/lib/src/android/android_studio_validator.dart
45: plugins.validatePackage(
51: plugins.validatePackage(messages, <String>['Dart'], 'Dart');
packages/flutter_tools/test/general.shard/intellij/intellij_test.dart
59: plugins.validatePackage(messages, <String>['Dart'], 'Dart');
60: plugins.validatePackage(messages,
81: plugins.validatePackage(messages, <String>['Dart'], 'Dart');
82: plugins.validatePackage(messages,
packages/flutter_tools/lib/src/intellij/intellij.dart
19: void validatePackage(
很明顯 packages/flutter_tools/lib/src/android/android_studio_validator.dart
這個文件中有相應的邏輯,打開文件一看發現邏輯非常清晰
final IntelliJPlugins plugins = IntelliJPlugins(_studio.pluginsPath);
plugins.validatePackage(
messages,
<String>['flutter-intellij', 'flutter-intellij.jar'],
'Flutter',
minVersion: IntelliJPlugins.kMinFlutterPluginVersion,
);
plugins.validatePackage(messages, <String>['Dart'], 'Dart');
插件的目錄是 _studio.pluginsPath
,我們先來調試一下,在上述部分代碼前加入一行調試代碼
print("****** ${_studio.pluginsPath}");
現在我們要重新編譯flutter tool,然後看看這個 _studio.pluginsPath
到底是什麼值,如何重新編譯呢?只要刪除 $flutter_sdk/bin/cache/flutter_tools.stamp
文件,再執行 flutter doctor
命令就能自動觸發重新編譯了。
@debian-ts:~/tools/flutter$ rm bin/cache/flutter_tools.stamp
@debian-ts:~/tools/flutter$ flutter doctor
Building flutter tool...
Doctor summary (to see all details, run flutter doctor -v):
******~/.AndroidStudio0.0/config/plugins
[✓] Flutter (Channel stable, 1.22.6, on Linux, locale en_US.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
[!] Android Studio
✗ Flutter plugin not installed; this adds Flutter specific functionality.
✗ Dart plugin not installed; this adds Dart specific functionality.
看到結果真是大喫一驚,竟然是 ~/.AndroidStudio0.0/config/plugins
,什麼鬼!
既然知道了路徑,那麼第一種解決辦法就產生了,在我使用的 debian buster
系統上,Android Studio 4.1.2
的插件安裝目錄爲 ~/.local/share/Google/AndroidStudio4.1
,我們創建一個指向這個地方的軟鏈接即可。
解決方案1
@debian-ts:~/tools/flutter$ mkdir -p ~/.AndroidStudio0.0/config
@debian-ts:~/tools/flutter$ ln -s ~/.local/share/Google/AndroidStudio4.1 ~/.AndroidStudio0.0/config/plugins
創建軟鏈接之後,執行 flutter doctor
,果然沒問題了。
很明顯我們不能止步於此,這個方案是能解決問題,但是有點太奇怪了。那麼我們繼續分析,看樣子是 flutter
沒有識別到 android studio
,跟第一個問題很像,第一個問題中我們必須用參數 --android-studio-dir
手動指定 android studio
的目錄。 即使我們手動指定了安裝目錄,flutter
知道android studio
安裝了,但是識別出來的版本號仍然是0.0
,那是爲什麼呢?
還是老樣子,從 --android-stdio-dir
選項來入手分析,我們搜索 android-studio-dir
,查看讀取的這個選項在哪個地方用到了,具體過程就不詳述了。我們發現檢測 android studio
的邏輯在 packages/flutter_tools/lib/src/android/android_studio.dart
文件中,
static List<AndroidStudio> allInstalled() =>
globals.platform.isMacOS ? _allMacOS() : _allLinuxOrWindows();
檢測插件的邏輯在 packages/flutter_tools/lib/src/intellij/intellij.dart
文件的 _hasPackage
方法中
bool _hasPackage(String packageName) {
final String packagePath = globals.fs.path.join(pluginsPath, packageName);
if (packageName.endsWith('.jar')) {
return globals.fs.isFileSync(packagePath);
}
return globals.fs.isDirectorySync(packagePath);
}
pluginsPath
的獲取在 packages/flutter_tools/lib/src/android/android_studio.dart
中,最終發現,總之這個插件路徑的判斷邏輯漏洞很多。再查看一下 master
上的最新代碼,看看官方是否有改進,發現沒什麼改進,但是官方改變了 flutter doctor
的輸出,在 master
的版本上,根本就不會提示插件未安裝的警告。所以我們得到第二個解決辦法
解決方案2
直接忽略 flutter doctor
的未安裝flutter
和dart
插件的警告,沒什麼用,只要你的 Android Studio
確實安裝了能正常開發即可。
問題3
正常創建了flutter application
,在命令行執行 flutter run
沒有任何問題, Android Studio
能看到手機設備已經連接,但是選擇不了。
這個問題就沒有辦法解決了,很愁人,有知道的大佬望不吝賜教。照理說都是穩定版,不應該這麼多坑呀。