Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

Commit 08fd95c

Browse files
author
Chris Yang
authored
[Share] Support v2 android embedder. (#2156)
1 parent 017a57e commit 08fd95c

File tree

15 files changed

+273
-51
lines changed

15 files changed

+273
-51
lines changed

packages/share/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 0.6.3
2+
3+
* Support the v2 Android embedder.
4+
* Update to AndroidX.
5+
* Migrate to using the new e2e test binding.
6+
* Add a e2e test.
7+
18
## 0.6.2+4
29

310
* Define clang module for iOS.

packages/share/android/build.gradle

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,29 @@ android {
4545
disable 'InvalidPackage'
4646
}
4747
}
48+
49+
// TODO(cyanglaz): Remove this hack once androidx.lifecycle is included on stable. https://github.com/flutter/flutter/issues/42348
50+
afterEvaluate {
51+
def containsEmbeddingDependencies = false
52+
for (def configuration : configurations.all) {
53+
for (def dependency : configuration.dependencies) {
54+
if (dependency.group == 'io.flutter' &&
55+
dependency.name.startsWith('flutter_embedding') &&
56+
dependency.isTransitive())
57+
{
58+
containsEmbeddingDependencies = true
59+
break
60+
}
61+
}
62+
}
63+
if (!containsEmbeddingDependencies) {
64+
android {
65+
dependencies {
66+
def lifecycle_version = "1.1.1"
67+
api "android.arch.lifecycle:runtime:$lifecycle_version"
68+
api "android.arch.lifecycle:common:$lifecycle_version"
69+
api "android.arch.lifecycle:common-java8:$lifecycle_version"
70+
}
71+
}
72+
}
73+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2019 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.share;
6+
7+
import io.flutter.plugin.common.MethodCall;
8+
import io.flutter.plugin.common.MethodChannel;
9+
import java.util.Map;
10+
11+
/** Handles the method calls for the plugin. */
12+
class MethodCallHandler implements MethodChannel.MethodCallHandler {
13+
14+
private Share share;
15+
16+
MethodCallHandler(Share share) {
17+
this.share = share;
18+
}
19+
20+
@Override
21+
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
22+
if (call.method.equals("share")) {
23+
if (!(call.arguments instanceof Map)) {
24+
throw new IllegalArgumentException("Map argument expected");
25+
}
26+
// Android does not support showing the share sheet at a particular point on screen.
27+
share.share((String) call.argument("text"), (String) call.argument("subject"));
28+
result.success(null);
29+
} else {
30+
result.notImplemented();
31+
}
32+
}
33+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2019 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.share;
6+
7+
import android.app.Activity;
8+
import android.content.Intent;
9+
10+
/** Handles share intent. */
11+
class Share {
12+
13+
private Activity activity;
14+
15+
/**
16+
* Constructs a Share object. The {@code activity} is used to start the share intent. It might be
17+
* null when constructing the {@link Share} object and set to non-null when an activity is
18+
* available using {@link #setActivity(Activity)}.
19+
*/
20+
Share(Activity activity) {
21+
this.activity = activity;
22+
}
23+
24+
/**
25+
* Sets the activity when an activity is available. When the activity becomes unavailable, use
26+
* this method to set it to null.
27+
*/
28+
void setActivity(Activity activity) {
29+
this.activity = activity;
30+
}
31+
32+
void share(String text, String subject) {
33+
if (text == null || text.isEmpty()) {
34+
throw new IllegalArgumentException("Non-empty text expected");
35+
}
36+
37+
Intent shareIntent = new Intent();
38+
shareIntent.setAction(Intent.ACTION_SEND);
39+
shareIntent.putExtra(Intent.EXTRA_TEXT, text);
40+
shareIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
41+
shareIntent.setType("text/plain");
42+
Intent chooserIntent = Intent.createChooser(shareIntent, null /* dialog title optional */);
43+
if (activity != null) {
44+
activity.startActivity(chooserIntent);
45+
} else {
46+
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
47+
activity.startActivity(chooserIntent);
48+
}
49+
}
50+
}

packages/share/android/src/main/java/io/flutter/plugins/share/SharePlugin.java

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,68 @@
44

55
package io.flutter.plugins.share;
66

7-
import android.content.Intent;
8-
import io.flutter.plugin.common.MethodCall;
7+
import android.app.Activity;
8+
import io.flutter.embedding.engine.plugins.FlutterPlugin;
9+
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
10+
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
11+
import io.flutter.plugin.common.BinaryMessenger;
912
import io.flutter.plugin.common.MethodChannel;
1013
import io.flutter.plugin.common.PluginRegistry.Registrar;
11-
import java.util.Map;
1214

1315
/** Plugin method host for presenting a share sheet via Intent */
14-
public class SharePlugin implements MethodChannel.MethodCallHandler {
16+
public class SharePlugin implements FlutterPlugin, ActivityAware {
1517

1618
private static final String CHANNEL = "plugins.flutter.io/share";
19+
private MethodCallHandler handler;
20+
private Share share;
21+
private MethodChannel methodChannel;
1722

1823
public static void registerWith(Registrar registrar) {
19-
MethodChannel channel = new MethodChannel(registrar.messenger(), CHANNEL);
20-
SharePlugin instance = new SharePlugin(registrar);
21-
channel.setMethodCallHandler(instance);
24+
SharePlugin plugin = new SharePlugin();
25+
plugin.setUpChannel(registrar.activity(), registrar.messenger());
2226
}
2327

24-
private final Registrar mRegistrar;
28+
@Override
29+
public void onAttachedToEngine(FlutterPluginBinding binding) {
30+
setUpChannel(null, binding.getFlutterEngine().getDartExecutor());
31+
}
32+
33+
@Override
34+
public void onDetachedFromEngine(FlutterPluginBinding binding) {
35+
methodChannel.setMethodCallHandler(null);
36+
methodChannel = null;
37+
share = null;
38+
}
39+
40+
@Override
41+
public void onAttachedToActivity(ActivityPluginBinding binding) {
42+
share.setActivity(binding.getActivity());
43+
}
2544

26-
private SharePlugin(Registrar registrar) {
27-
this.mRegistrar = registrar;
45+
@Override
46+
public void onDetachedFromActivity() {
47+
tearDownChannel();
48+
}
49+
50+
@Override
51+
public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
52+
onAttachedToActivity(binding);
2853
}
2954

3055
@Override
31-
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
32-
if (call.method.equals("share")) {
33-
if (!(call.arguments instanceof Map)) {
34-
throw new IllegalArgumentException("Map argument expected");
35-
}
36-
// Android does not support showing the share sheet at a particular point on screen.
37-
share((String) call.argument("text"), (String) call.argument("subject"));
38-
result.success(null);
39-
} else {
40-
result.notImplemented();
41-
}
42-
}
43-
44-
private void share(String text, String subject) {
45-
if (text == null || text.isEmpty()) {
46-
throw new IllegalArgumentException("Non-empty text expected");
47-
}
48-
49-
Intent shareIntent = new Intent();
50-
shareIntent.setAction(Intent.ACTION_SEND);
51-
shareIntent.putExtra(Intent.EXTRA_TEXT, text);
52-
shareIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
53-
shareIntent.setType("text/plain");
54-
Intent chooserIntent = Intent.createChooser(shareIntent, null /* dialog title optional */);
55-
if (mRegistrar.activity() != null) {
56-
mRegistrar.activity().startActivity(chooserIntent);
57-
} else {
58-
chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
59-
mRegistrar.context().startActivity(chooserIntent);
60-
}
56+
public void onDetachedFromActivityForConfigChanges() {
57+
onDetachedFromActivity();
58+
}
59+
60+
private void setUpChannel(Activity activity, BinaryMessenger messenger) {
61+
methodChannel = new MethodChannel(messenger, CHANNEL);
62+
share = new Share(activity);
63+
handler = new MethodCallHandler(share);
64+
methodChannel.setMethodCallHandler(handler);
65+
}
66+
67+
private void tearDownChannel() {
68+
share.setActivity(null);
69+
methodChannel.setMethodCallHandler(null);
6170
}
6271
}

packages/share/example/android/app/src/main/AndroidManifest.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44
<uses-permission android:name="android.permission.INTERNET"/>
55

66
<application android:name="io.flutter.app.FlutterApplication" android:label="share_example" android:icon="@mipmap/ic_launcher">
7-
<activity android:name=".MainActivity"
7+
<activity android:name=".EmbeddingV1Activity"
88
android:launchMode="singleTop"
99
android:theme="@android:style/Theme.Black.NoTitleBar"
1010
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
1111
android:hardwareAccelerated="true"
1212
android:windowSoftInputMode="adjustResize">
13+
</activity>
14+
<activity android:name=".MainActivity"
15+
android:theme="@android:style/Theme.Black.NoTitleBar"
16+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
17+
android:hardwareAccelerated="true"
18+
android:windowSoftInputMode="adjustResize">
1319
<intent-filter>
1420
<action android:name="android.intent.action.MAIN"/>
1521
<category android:name="android.intent.category.LAUNCHER"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2017 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.shareexample;
6+
7+
import android.os.Bundle;
8+
import io.flutter.app.FlutterActivity;
9+
import io.flutter.plugins.GeneratedPluginRegistrant;
10+
11+
public class EmbeddingV1Activity extends FlutterActivity {
12+
13+
@Override
14+
protected void onCreate(Bundle savedInstanceState) {
15+
super.onCreate(savedInstanceState);
16+
GeneratedPluginRegistrant.registerWith(this);
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package io.flutter.plugins.shareexample;
2+
3+
import androidx.test.rule.ActivityTestRule;
4+
import dev.flutter.plugins.e2e.FlutterRunner;
5+
import org.junit.Rule;
6+
import org.junit.runner.RunWith;
7+
8+
@RunWith(FlutterRunner.class)
9+
public class EmbeddingV1ActivityTest {
10+
@Rule
11+
public ActivityTestRule<EmbeddingV1Activity> rule =
12+
new ActivityTestRule<>(EmbeddingV1Activity.class);
13+
}
Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
// Copyright 2017 The Chromium Authors. All rights reserved.
1+
// Copyright 2019 The Flutter Authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

55
package io.flutter.plugins.shareexample;
66

7-
import android.os.Bundle;
8-
import io.flutter.app.FlutterActivity;
9-
import io.flutter.plugins.GeneratedPluginRegistrant;
7+
import io.flutter.embedding.android.FlutterActivity;
8+
import io.flutter.embedding.engine.FlutterEngine;
9+
import io.flutter.plugins.share.SharePlugin;
1010

1111
public class MainActivity extends FlutterActivity {
12-
12+
// TODO(cyanglaz): Remove this once v2 of GeneratedPluginRegistrant rolls to stable.
13+
// https://github.com/flutter/flutter/issues/42694
1314
@Override
14-
protected void onCreate(Bundle savedInstanceState) {
15-
super.onCreate(savedInstanceState);
16-
GeneratedPluginRegistrant.registerWith(this);
15+
public void configureFlutterEngine(FlutterEngine flutterEngine) {
16+
super.configureFlutterEngine(flutterEngine);
17+
flutterEngine.getPlugins().add(new SharePlugin());
1718
}
1819
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2019 The Chromium Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
package io.flutter.plugins.shareexample;
6+
7+
import androidx.test.rule.ActivityTestRule;
8+
import dev.flutter.plugins.e2e.FlutterRunner;
9+
import org.junit.Rule;
10+
import org.junit.runner.RunWith;
11+
12+
@RunWith(FlutterRunner.class)
13+
public class MainActivityTest {
14+
@Rule public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);
15+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
org.gradle.jvmargs=-Xmx1536M
2+
android.enableR8=true
3+
android.useAndroidX=true
4+
android.enableJetifier=true

packages/share/example/pubspec.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,15 @@ dependencies:
77
share:
88
path: ../
99

10+
dev_dependencies:
11+
flutter_driver:
12+
sdk: flutter
13+
e2e: ^0.2.0
14+
1015
flutter:
1116
uses-material-design: true
17+
18+
environment:
19+
sdk: ">=2.0.0-dev.28.0 <3.0.0"
20+
flutter: ">=1.9.1+hotfix.2 <2.0.0"
21+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2019, the Chromium project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'dart:async';
6+
import 'dart:io';
7+
import 'package:flutter_driver/flutter_driver.dart';
8+
9+
Future<void> main() async {
10+
final FlutterDriver driver = await FlutterDriver.connect();
11+
final String result =
12+
await driver.requestData(null, timeout: const Duration(minutes: 1));
13+
driver.close();
14+
exit(result == 'pass' ? 0 : 1);
15+
}

packages/share/pubspec.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ description: Flutter plugin for sharing content via the platform share UI, using
33
the ACTION_SEND intent on Android and UIActivityViewController on iOS.
44
author: Flutter Team <[email protected]>
55
homepage: https://github.com/flutter/plugins/tree/master/packages/share
6-
version: 0.6.2+4
6+
version: 0.6.3
77

88
flutter:
99
plugin:
@@ -21,7 +21,8 @@ dev_dependencies:
2121
mockito: ^3.0.0
2222
flutter_test:
2323
sdk: flutter
24+
e2e: ^0.2.0
2425

2526
environment:
2627
sdk: ">=2.0.0-dev.28.0 <3.0.0"
27-
flutter: ">=1.6.0 <2.0.0"
28+
flutter: ">=1.6.7 <2.0.0"

0 commit comments

Comments
 (0)