Skip to content

Commit

Permalink
Merge branch 'main' into miquelbeltran/2831
Browse files Browse the repository at this point in the history
  • Loading branch information
miquelbeltran authored Apr 17, 2024
2 parents 0948acf + fd0511c commit a3f78cf
Show file tree
Hide file tree
Showing 25 changed files with 273 additions and 658 deletions.
20 changes: 20 additions & 0 deletions packages/package_info_plus/package_info_plus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,26 @@ See https://github.com/fluttercommunity/plus_plugins/issues/309
There was an [issue](https://github.com/flutter/flutter/issues/73652) in Flutter, which is already resolved since Flutter 3.3.
If your project was created before Flutter 3.3 you need to migrate the project according to [this guide] (https://docs.flutter.dev/release/breaking-changes/windows-version-information) first to get correct version with `package_info_plus`

### Web

In a web environment, the package uses the `version.json` file that it is generated in the build process.

#### Accessing the `version.json`

The package tries to locate the `version.json` using three methods:

1. Using the provided `baseUrl` in the `fromPlatform()` method.
2. Checking the configured `assets` folder in the Flutter web configuration.
3. Checking the path where the application is installed.

See the documentation at the method `fromPlatform()` to learn more.

#### CORS `version.json` access

It could be possible that the plugin cannot access the `version.json` file because the server is preventing it.
This can be due a CORS issue, and it is known to happen when hosting the Flutter code on Firebase Hosting.
Ensure that your CORS Firebase configuration allows it.

## Learn more

- [API Documentation](https://pub.dev/documentation/package_info_plus/latest/package_info_plus/package_info_plus-library.html)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ class PackageInfoPlugin : MethodCallHandler, FlutterPlugin {
val signingInfo = packageInfo.signingInfo ?: return null

if (signingInfo.hasMultipleSigners()) {
signatureToSha1(signingInfo.apkContentsSigners.first().toByteArray())
signatureToSha256(signingInfo.apkContentsSigners.first().toByteArray())
} else {
signatureToSha1(signingInfo.signingCertificateHistory.first().toByteArray())
signatureToSha256(signingInfo.signingCertificateHistory.first().toByteArray())
}
} else {
val packageInfo = pm.getPackageInfo(
Expand All @@ -108,7 +108,7 @@ class PackageInfoPlugin : MethodCallHandler, FlutterPlugin {
if (signatures.isNullOrEmpty() || packageInfo.signatures.first() == null) {
null
} else {
signatureToSha1(signatures.first().toByteArray())
signatureToSha256(signatures.first().toByteArray())
}
}
} catch (e: PackageManager.NameNotFoundException) {
Expand All @@ -120,8 +120,8 @@ class PackageInfoPlugin : MethodCallHandler, FlutterPlugin {

// Credits https://gist.github.com/scottyab/b849701972d57cf9562e
@Throws(NoSuchAlgorithmException::class)
private fun signatureToSha1(sig: ByteArray): String {
val digest = MessageDigest.getInstance("SHA1")
private fun signatureToSha256(sig: ByteArray): String {
val digest = MessageDigest.getInstance("SHA-256")
digest.update(sig)
val hashText = digest.digest()
return bytesToHex(hashText)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ class PackageInfo {
/// Docs about CFBundleVersion: https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleversion
final String buildNumber;

/// The build signature. Empty string on iOS, signing key signature (hex) on Android.
/// The build signature.
/// Empty string on iOS.
/// SHA-256 signing key signature (hex) on Android.
final String buildSignature;

/// The installer store. Indicates through which store this application was installed.
Expand Down
51 changes: 38 additions & 13 deletions packages/share_plus/share_plus/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@
A Flutter plugin to share content from your Flutter app via the platform's
share dialog.

Wraps the `ACTION_SEND` Intent on Android and `UIActivityViewController`
on iOS.
Wraps the `ACTION_SEND` Intent on Android, `UIActivityViewController`
on iOS, or equivalent platform content sharing methods.

## Platform Support

| Android | iOS | MacOS | Web | Linux | Windows |
| :-----: | :-: | :---: | :-: | :---: | :----: |
|||||||
| Method | Android | iOS | MacOS | Web | Linux | Windows |
| :-----------: | :-----: | :-: | :---: | :-: | :---: | :----: |
| `share` |||||||
| `shareUri` ||| | | | |
| `shareXFiles` ||||| ||

Also compatible with Windows and Linux by using "mailto" to share text via Email.

Expand All @@ -28,15 +30,15 @@ Sharing files is not supported on Linux.

To use this plugin, add `share_plus` as a [dependency in your pubspec.yaml file](https://plus.fluttercommunity.dev/docs/overview).

## Example

Import the library.

```dart
import 'package:share_plus/share_plus.dart';
```

Then invoke the static `share` method anywhere in your Dart code.
### Share Text

Invoke the static `share()` method anywhere in your Dart code.

```dart
Share.share('check out my website https://example.com');
Expand All @@ -49,16 +51,18 @@ sharing to email.
Share.share('check out my website https://example.com', subject: 'Look what I made!');
```

If you are interested in the action your user performed with the share sheet, you can instead use the `shareWithResult` method.
`share()` returns `status` object that allows to check the result of user action in the share sheet.

```dart
final result = await Share.shareWithResult('check out my website https://example.com');
final result = await Share.share('check out my website https://example.com');
if (result.status == ShareResultStatus.success) {
print('Thank you for sharing my website!');
}
```

### Share Files

To share one or multiple files, invoke the static `shareXFiles` method anywhere in your Dart code. The method returns a `ShareResult`. Optionally, you can pass `subject`, `text` and `sharePositionOrigin`.

```dart
Expand All @@ -77,7 +81,6 @@ if (result.status == ShareResultStatus.dismissed) {
}
```


On web, you can use `SharePlus.shareXFiles()`. This uses the [Web Share API](https://web.dev/web-share/)
if it's available. Otherwise it falls back to downloading the shared files.
See [Can I Use - Web Share API](https://caniuse.com/web-share) to understand
Expand All @@ -89,6 +92,24 @@ package.
Share.shareXFiles([XFile('assets/hello.txt')], text: 'Great picture');
```

### Share URI

iOS supports fetching metadata from a URI when shared using `UIActivityViewController`.
This special method is only properly supported on iOS.

```dart
Share.shareUri(uri: uri);
```

### Share Results

All three methods return a `ShareResult` object which contains the following information:

- `status`: a `ShareResultStatus`
- `raw`: a `String` describing the share result, e.g. the opening app ID.

Note: `status` will be `ShareResultStatus.unavailable` if the platform does not support identifying the user action.

## Known Issues

### Sharing data created with XFile.fromData
Expand All @@ -103,9 +124,13 @@ Alternatively, don't use `XFile.fromData` and instead write the data down to a `

### Mobile platforms (Android and iOS)

#### Facebook limitations (WhatsApp, Instagram, Facebook Messenger)
#### Meta (WhatsApp, Instagram, Facebook Messenger) and similar apps

Due to restrictions set up by Meta/Facebook this plugin isn't capable of sharing data reliably to Facebook related apps on Android and iOS. This includes eg. sharing text to the Facebook Messenger. If you require this functionality please check the native Facebook Sharing SDK ([https://developers.facebook.com/docs/sharing](https://developers.facebook.com/docs/sharing)) or search for other Flutter plugins implementing this SDK. More information can be found in [this issue](https://github.com/fluttercommunity/plus_plugins/issues/413).

Due to restrictions set up by Facebook this plugin isn't capable of sharing data reliably to Facebook related apps on Android and iOS. This includes eg. sharing text to the Facebook Messenger. If you require this functionality please check the native Facebook Sharing SDK ([https://developers.facebook.com/docs/sharing](https://developers.facebook.com/docs/sharing)) or search for other Flutter plugins implementing this SDK. More information can be found in [this issue](https://github.com/fluttercommunity/plus_plugins/issues/413).
Other apps may also give problems when attempting to share content to them.
We cannot warranty that a 3rd party app will properly implement the share functionality.
Therefore, all bugs reported regarding compatibility with a specific app will be closed.

#### Localization in Apple platforms

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package dev.fluttercommunity.plus.share

import android.os.Build
import io.flutter.BuildConfig
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import java.io.IOException
Expand All @@ -14,41 +15,42 @@ internal class MethodCallHandler(
override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
expectMapArguments(call)

// The user used a *WithResult method
val isResultRequested = call.method.endsWith("WithResult")
// We don't attempt to return a result if the current API version doesn't support it
val isWithResult =
isResultRequested && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1
Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1

if (isWithResult && !manager.setCallback(result)) return
if (isWithResult)
manager.setCallback(result)

try {
when (call.method) {
"shareUri" -> {
share.share(
call.argument<Any>("uri") as String, subject = null, withResult = false
call.argument<Any>("uri") as String,
subject = null,
withResult = isWithResult,
)
success(isWithResult, isResultRequested, result)
success(isWithResult, result)
}

"share", "shareWithResult" -> {
"share" -> {
share.share(
call.argument<Any>("text") as String,
call.argument<Any>("subject") as String?,
isWithResult,
)
success(isWithResult, isResultRequested, result)
success(isWithResult, result)
}

"shareFiles", "shareFilesWithResult" -> {
"shareFiles" -> {
share.shareFiles(
call.argument<List<String>>("paths")!!,
call.argument<List<String>?>("mimeTypes"),
call.argument<String?>("text"),
call.argument<String?>("subject"),
isWithResult,
)
success(isWithResult, isResultRequested, result)
success(isWithResult, result)
}

else -> result.notImplemented()
Expand All @@ -61,15 +63,10 @@ internal class MethodCallHandler(

private fun success(
isWithResult: Boolean,
isResultRequested: Boolean,
result: MethodChannel.Result
) {
if (!isWithResult) {
if (isResultRequested) {
result.success("dev.fluttercommunity.plus/share/unavailable")
} else {
result.success(null)
}
result.success("dev.fluttercommunity.plus/share/unavailable")
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,22 @@ internal class ShareSuccessManager(private val context: Context) : ActivityResul
* Set result callback that will wait for the share-sheet to close and get either
* the componentname of the chosen option or an empty string on dismissal.
*/
fun setCallback(callback: MethodChannel.Result): Boolean {
fun setCallback(callback: MethodChannel.Result) {
return if (isCalledBack.compareAndSet(true, false)) {
// Prepare all state for new share
SharePlusPendingIntent.result = ""
isCalledBack.set(false)
this.callback = callback
true
} else {
callback.error(
"Share callback error",
"prior share-sheet did not call back, did you await it? Maybe use non-result variant",
null,
)
false
// Ensure no deadlocks.
// Return result of any waiting call.
// e.g. user called to `share` but did not await for result.
this.callback?.success(RESULT_UNAVAILABLE)

// Prepare all state for new share
SharePlusPendingIntent.result = ""
isCalledBack.set(false)
this.callback = callback
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,15 @@ void main() {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

testWidgets('Can launch share', (WidgetTester tester) async {
expect(Share.share('message', subject: 'title'), completes);
}, skip: Platform.isMacOS);

testWidgets('Can launch share in MacOS', (WidgetTester tester) async {
// Check isNotNull because we cannot wait for ShareResult
expect(Share.share('message', subject: 'title'), isNotNull);
}, skip: !Platform.isMacOS);

testWidgets('Can launch shareWithResult', (WidgetTester tester) async {
expect(Share.shareWithResult('message', subject: 'title'), isNotNull);
});

testWidgets('Can launch shareUri', (WidgetTester tester) async {
// Check isNotNull because we cannot wait for ShareResult
expect(Share.shareUri(Uri.parse('https://example.com')), isNotNull);
}, skip: !Platform.isAndroid && !Platform.isIOS);

testWidgets('Can shareXFile created using File.fromData()',
(WidgetTester tester) async {
final bytes = Uint8List.fromList([1, 2, 3, 4, 5, 6, 7, 8]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>11.0</string>
<string>12.0</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@
535124FC9BB266447EC60189 /* Pods-RunnerTests.release.xcconfig */,
A8F8F8E1F770CE9853568BC6 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
Expand Down Expand Up @@ -215,7 +214,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
331C8080294A63A400263BE5 = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
10 changes: 6 additions & 4 deletions packages/share_plus/share_plus/example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,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>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
Expand All @@ -24,6 +26,8 @@
<string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
Expand All @@ -41,11 +45,9 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSPhotoLibraryUsageDescription</key>
<string>Load photos for sharing functionality</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
Loading

0 comments on commit a3f78cf

Please sign in to comment.