diff --git a/packages/android_intent_plus/CHANGELOG.md b/packages/android_intent_plus/CHANGELOG.md index c88a662927..b6348c264a 100644 --- a/packages/android_intent_plus/CHANGELOG.md +++ b/packages/android_intent_plus/CHANGELOG.md @@ -1,3 +1,7 @@ +## pre-release + +- Add launchChooser method, which uses Intent.createChooser internally. + ## 0.4.1 - Renamed Method Channel and changed Java package to avoid collision with android_intent diff --git a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java index 1b335c6007..d66e8a0269 100644 --- a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java +++ b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java @@ -59,6 +59,14 @@ void send(Intent intent) { } } + /** + * Like with {@code send}, creates and launches an intent with the given params, but wraps the + * {@code Intent} with {@code Intent.createChooser}. + */ + public void launchChooser(Intent intent, String title) { + send(Intent.createChooser(intent, title)); + } + /** * Verifies the given intent and returns whether the application context class can resolve it. * @@ -68,9 +76,9 @@ void send(Intent intent) { *

This currently only supports resolving activities. * * @param intent Fully built intent. - * @see #buildIntent(String, Integer, String, Uri, Bundle, String, ComponentName, String) * @return Whether the package manager found {@link android.content.pm.ResolveInfo} using its * {@link PackageManager#resolveActivity(Intent, int)} method. + * @see #buildIntent(String, Integer, String, Uri, Bundle, String, ComponentName, String) */ boolean canResolveActivity(Intent intent) { if (applicationContext == null) { diff --git a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java index c8343b4814..46ca514cd7 100644 --- a/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java +++ b/packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java @@ -92,6 +92,10 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) { if ("launch".equalsIgnoreCase(call.method)) { sender.send(intent); + result.success(null); + } else if ("launchChooser".equalsIgnoreCase(call.method)) { + String title = call.argument("chooserTitle"); + sender.launchChooser(intent, title); result.success(null); } else if ("canResolveActivity".equalsIgnoreCase(call.method)) { result.success(sender.canResolveActivity(intent)); diff --git a/packages/android_intent_plus/example/lib/main.dart b/packages/android_intent_plus/example/lib/main.dart index 472c434df8..9824f5af5b 100644 --- a/packages/android_intent_plus/example/lib/main.dart +++ b/packages/android_intent_plus/example/lib/main.dart @@ -65,8 +65,15 @@ class MyHomePage extends StatelessWidget { onPressed: _createAlarm, ), RaisedButton( - child: const Text('Tap here to test explicit intents.'), - onPressed: () => _openExplicitIntentsView(context)), + child: const Text( + 'Tap here to launch Intent with Chooser', + ), + onPressed: _openChooser, + ), + RaisedButton( + child: const Text('Tap here to test explicit intents.'), + onPressed: () => _openExplicitIntentsView(context), + ), ], ), ); @@ -80,6 +87,15 @@ class MyHomePage extends StatelessWidget { body: Center(child: body), ); } + + void _openChooser() { + final intent = const AndroidIntent( + action: 'android.intent.action.SEND', + type: 'plain/text', + data: 'text example', + ); + intent.launchChooser('Chose an app'); + } } /// Launches intents to specific Android activities. @@ -204,7 +220,7 @@ class ExplicitIntentsWidget extends StatelessWidget { 'Tap here to open Application Details', ), onPressed: _openApplicationDetails, - ) + ), ], ), ), diff --git a/packages/android_intent_plus/example/test_driver/android_intent_plus_e2e.dart b/packages/android_intent_plus/example/test_driver/android_intent_plus_e2e.dart index f234a169e5..b6d9aed169 100644 --- a/packages/android_intent_plus/example/test_driver/android_intent_plus_e2e.dart +++ b/packages/android_intent_plus/example/test_driver/android_intent_plus_e2e.dart @@ -24,7 +24,7 @@ void main() { (Widget widget) => widget is Text && widget.data.startsWith('Tap here'), ), - findsNWidgets(2), + findsNWidgets(3), ); } else { expect( @@ -49,6 +49,15 @@ void main() { })); }, skip: !Platform.isAndroid); + testWidgets('#launchChooser should not throw', (WidgetTester tester) async { + final intent = const AndroidIntent( + action: 'android.intent.action.SEND', + type: 'plain/text', + data: 'text example', + ); + await intent.launchChooser('title'); + }, skip: !Platform.isAndroid); + testWidgets('#canResolveActivity returns true when example Activity is found', (WidgetTester tester) async { final intent = AndroidIntent( diff --git a/packages/android_intent_plus/lib/android_intent.dart b/packages/android_intent_plus/lib/android_intent.dart index 93f6a3a98c..b939f0e375 100644 --- a/packages/android_intent_plus/lib/android_intent.dart +++ b/packages/android_intent_plus/lib/android_intent.dart @@ -138,6 +138,22 @@ class AndroidIntent { await _channel.invokeMethod('launch', _buildArguments()); } + /// Launch the intent with 'createChooser(intent, title)'. + /// + /// This works only on Android platforms. + Future launchChooser(String title) async { + if (!_platform.isAndroid) { + return; + } + + final buildArguments = _buildArguments(); + buildArguments['chooserTitle'] = title; + await _channel.invokeMethod( + 'launchChooser', + buildArguments, + ); + } + /// Check whether the intent can be resolved to an activity. /// /// This works only on Android platforms. diff --git a/packages/android_intent_plus/test/android_intent_test.dart b/packages/android_intent_plus/test/android_intent_test.dart index af96a9bc4a..d9c94e1a80 100644 --- a/packages/android_intent_plus/test/android_intent_test.dart +++ b/packages/android_intent_plus/test/android_intent_test.dart @@ -140,6 +140,21 @@ void main() { verifyZeroInteractions(mockChannel); }); }); + + group('launchChooser', () { + test('pass title', () async { + androidIntent = AndroidIntent.private( + action: 'action_view', + channel: mockChannel, + platform: FakePlatform(operatingSystem: 'android'), + ); + await androidIntent.launchChooser('title'); + verify(mockChannel.invokeMethod('launchChooser', { + 'action': 'action_view', + 'chooserTitle': 'title', + })); + }); + }); }); group('convertFlags ', () {