1
0
mirror of https://github.com/flutter/packages.git synced 2025-07-08 20:22:36 +08:00

[file_selector] Endorse Android ()

Endorses the new Android implementation of `file_selector`, updating the README accordingly.

Also adjusts the example to better handle platform diffs, by hiding UI that doesn't work instead of just labelling it on the button. Left a TODO to improve how we determine what to hide once we have the API to do so.

Fixes https://github.com/flutter/flutter/issues/110098
This commit is contained in:
stuartmorgan
2023-07-01 06:53:14 -04:00
committed by GitHub
parent 6ab9a8bfb4
commit 41d5ca918d
29 changed files with 325 additions and 40 deletions

@ -159,6 +159,17 @@ updates:
- dependency-name: "*"
update-types: ["version-update:semver-minor", "version-update:semver-patch"]
- package-ecosystem: "gradle"
directory: "/packages/file_selector/file_selector/example/android/app"
commit-message:
prefix: "[file_selector]"
schedule:
interval: "weekly"
open-pull-requests-limit: 10
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-minor", "version-update:semver-patch"]
- package-ecosystem: "gradle"
directory: "/packages/file_selector/file_selector_android/android"
commit-message:

@ -53,6 +53,7 @@ packages/**/*_web/** @ditman
packages/camera/camera_android/** @camsim99
packages/camera/camera_android_camerax/** @camsim99
packages/espresso/** @reidbaker
packages/file_selector/file_selector_android/** @gmackall
packages/flutter_plugin_android_lifecycle/** @reidbaker
packages/google_maps_flutter/google_maps_flutter_android/** @reidbaker
packages/google_sign_in/google_sign_in_android/** @camsim99

@ -1,3 +1,7 @@
## 0.9.5
* Adds an endorsed Android implementation.
## 0.9.4
* Adds `getSaveLocation` and deprecates `getSavePath`.

@ -6,9 +6,9 @@
A Flutter plugin that manages files and interactions with file dialogs.
| | iOS | Linux | macOS | Web | Windows |
|-------------|---------|-------|--------|-----|-------------|
| **Support** | iOS 11+ | Any | 10.14+ | Any | Windows 10+ |
| | Android | iOS | Linux | macOS | Web | Windows |
|-------------|---------|---------|-------|--------|-----|-------------|
| **Support** | SDK 19+ | iOS 11+ | Any | 10.14+ | Any | Windows 10+ |
## Usage
@ -100,23 +100,25 @@ Different platforms support different type group filter options. To avoid
filters that cover all platforms you are targeting, or that you conditionally
pass different `XTypeGroup`s based on `Platform`.
| | iOS | Linux | macOS | Web | Windows |
|--------------------------|-----|-------|--------|-----|-------------|
| `extensions` | | ✔️ | ✔️ | ✔️ | ✔️ |
| `mimeTypes` | | ✔️ | ✔️† | ✔️ | |
| `uniformTypeIdentifiers` | ✔️ | | ✔️ | | |
| `webWildCards` | | | | ✔️ | |
| | Andoid | iOS | Linux | macOS | Web | Windows |
|--------------------------|--------|-----|-------|--------|-----|-------------|
| `extensions` | ✔️ | | ✔️ | ✔️ | ✔️ | ✔️ |
| `mimeTypes` | ✔️ | | ✔️ | ✔️† | ✔️ | |
| `uniformTypeIdentifiers` | | ✔️ | | ✔️ | | |
| `webWildCards` | | | | | ✔️ | |
† `mimeTypes` are not supported on version of macOS earlier than 11 (Big Sur).
### Features supported by platform
| Feature | Description | iOS | Linux | macOS | Windows | Web |
| ---------------------- |----------------------------------- |--------- | ---------- | -------- | ------------ | ----------- |
| Choose a single file | Pick a file/image | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Choose multiple files | Pick multiple files/images | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Choose a save location | Pick a directory to save a file in | ❌ | ✔️ | ✔️ | ✔️ | ❌ |
| Choose a directory | Pick a folder and get its path | ❌ | ✔️ | ✔️ | ✔️ | ❌ |
| Feature | Description | Android | iOS | Linux | macOS | Windows | Web |
| ---------------------- |----------------------------------- |---------|--------- | ---------- | -------- | ------------ | ----------- |
| Choose a single file | Pick a file/image | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Choose multiple files | Pick multiple files/images | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
| Choose a save location | Pick a directory to save a file in | ❌ | ❌ | ✔️ | ✔️ | ✔️ | ❌ |
| Choose a directory | Pick a directory and get its path | ✔️† | ❌ | ✔️ | ✔️ | ✔️ | ❌ |
† Choosing a directory is no supported on versions of Android before SDK 21 (Lollipop).
[example]:./example
[entitlement]: https://docs.flutter.dev/desktop#entitlements-and-the-app-sandbox

@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

@ -0,0 +1,71 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
namespace "dev.flutter.plugins.file_selector_example"
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
applicationId "dev.flutter.plugins.file_selector_example"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
minSdkVersion 19
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
}

@ -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,33 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="file_selector_example"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>

@ -0,0 +1,10 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package dev.flutter.plugins.file_selector_example
import io.flutter.embedding.android.FlutterActivity
class MainActivity: FlutterActivity() {
}

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

(image error) Size: 544 B

Binary file not shown.

After

(image error) Size: 442 B

Binary file not shown.

After

(image error) Size: 721 B

Binary file not shown.

After

(image error) Size: 1.0 KiB

Binary file not shown.

After

(image error) Size: 1.4 KiB

@ -0,0 +1,18 @@
<?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>
</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,18 @@
<?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>
</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,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,31 @@
buildscript {
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip

@ -0,0 +1,11 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

@ -50,7 +50,7 @@ class GetDirectoryPage extends StatelessWidget {
),
onPressed: _isIOS ? null : () => _getDirectoryPath(context),
child: const Text(
'Press to ask user to choose a directory (not supported on iOS).',
'Press to ask user to choose a directory.',
),
),
],

@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
/// Home Page of the application
@ -43,18 +46,25 @@ class HomePage extends StatelessWidget {
child: const Text('Open multiple images'),
onPressed: () => Navigator.pushNamed(context, '/open/images'),
),
// TODO(stuartmorgan): Replace these checks with support queries once
// https://github.com/flutter/flutter/issues/127328 is implemented.
if (kIsWeb || !(Platform.isAndroid || Platform.isIOS)) ...<Widget>[
const SizedBox(height: 10),
ElevatedButton(
style: style,
child: const Text('Save a file'),
onPressed: () => Navigator.pushNamed(context, '/save/text'),
),
],
if (!(kIsWeb || Platform.isIOS)) ...<Widget>[
const SizedBox(height: 10),
ElevatedButton(
style: style,
child: const Text('Open a get directory dialog'),
onPressed: () => Navigator.pushNamed(context, '/directory'),
),
],
if (!(kIsWeb || Platform.isAndroid || Platform.isIOS)) ...<Widget>[
const SizedBox(height: 10),
ElevatedButton(
style: style,
@ -63,6 +73,7 @@ class HomePage extends StatelessWidget {
Navigator.pushNamed(context, '/multi-directories'),
),
],
],
),
),
);

@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:file_selector/file_selector.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
@ -19,8 +20,8 @@ class OpenTextPage extends StatelessWidget {
// This demonstrates using an initial directory for the prompt, which should
// only be done in cases where the application can likely predict where the
// file would be. In most cases, this parameter should not be provided.
final String initialDirectory =
(await getApplicationDocumentsDirectory()).path;
final String? initialDirectory =
kIsWeb ? null : (await getApplicationDocumentsDirectory()).path;
final XFile? file = await openFile(
acceptedTypeGroups: <XTypeGroup>[typeGroup],
initialDirectory: initialDirectory,

@ -85,7 +85,7 @@ class SaveTextPage extends StatelessWidget {
),
onPressed: _isIOS ? null : () => _saveFile(),
child: const Text(
'Press to save a text file (not supported on iOS).',
'Press to save a text file.',
),
),
],

@ -3,7 +3,7 @@ description: Flutter plugin for opening and saving files, or selecting
directories, using native file selection UI.
repository: https://github.com/flutter/packages/tree/main/packages/file_selector/file_selector
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22
version: 0.9.4
version: 0.9.5
environment:
sdk: ">=2.18.0 <4.0.0"
@ -12,6 +12,8 @@ environment:
flutter:
plugin:
platforms:
android:
default_package: file_selector_android
ios:
default_package: file_selector_ios
linux:
@ -24,6 +26,7 @@ flutter:
default_package: file_selector_windows
dependencies:
file_selector_android: ^0.5.0
file_selector_ios: ^0.5.0
file_selector_linux: ^0.9.2
file_selector_macos: ^0.9.3

@ -1 +1,2 @@
[]
# Can't use Flutter integration tests due to native modal UI.
- file_selector