Skip to content

Commit e453087

Browse files
feat(android_intent_plus): support for intent as URI (#2970)
Co-authored-by: Miguel Beltran <[email protected]>
1 parent 23fe3ef commit e453087

File tree

5 files changed

+57
-2
lines changed

5 files changed

+57
-2
lines changed

packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/IntentSender.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import android.text.TextUtils;
1111
import android.util.Log;
1212
import androidx.annotation.Nullable;
13+
import java.net.URISyntaxException;
1314

1415
/** Forms and launches intents. */
1516
public final class IntentSender {
@@ -175,4 +176,8 @@ Intent buildIntent(
175176

176177
return intent;
177178
}
179+
180+
public Intent parse(String uri) throws URISyntaxException {
181+
return Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
182+
}
178183
}

packages/android_intent_plus/android/src/main/java/dev/fluttercommunity/plus/androidintent/MethodCallHandlerImpl.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import io.flutter.plugin.common.MethodChannel;
1515
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
1616
import io.flutter.plugin.common.MethodChannel.Result;
17+
import java.net.URISyntaxException;
1718
import java.util.ArrayList;
1819
import java.util.Map;
1920

@@ -91,7 +92,15 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
9192
sender.buildIntent(
9293
action, flags, category, data, arguments, packageName, componentName, type);
9394

94-
if ("launch".equalsIgnoreCase(call.method)) {
95+
if ("parseAndLaunch".equalsIgnoreCase(call.method)) {
96+
try {
97+
intent = sender.parse(call.argument("uri"));
98+
sender.send(intent);
99+
result.success(null);
100+
} catch (URISyntaxException e) {
101+
result.error("parse_error", "Failed to parse URI", e.getMessage());
102+
}
103+
} else if ("launch".equalsIgnoreCase(call.method)) {
95104

96105
if (intent != null && !sender.canResolveActivity(intent)) {
97106
Log.i(TAG, "Cannot resolve explicit intent, falling back to implicit");

packages/android_intent_plus/example/integration_test/android_intent_plus_test.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ void main() {
2525
(Widget widget) =>
2626
widget is Text && widget.data!.startsWith('Tap here'),
2727
),
28-
findsNWidgets(4),
28+
findsNWidgets(5),
2929
);
3030
} else {
3131
expect(
@@ -64,6 +64,18 @@ void main() {
6464
await intent.launch();
6565
}, skip: !Platform.isAndroid);
6666

67+
testWidgets('Parse and Launch should not throw', (WidgetTester tester) async {
68+
const intent = 'intent:#Intent;'
69+
'action=android.intent.action.SET_ALARM;'
70+
'B.android.intent.extra.alarm.SKIP_UI=true;'
71+
'S.android.intent.extra.alarm.MESSAGE=Create%20a%20Flutter%20app;'
72+
'i.android.intent.extra.alarm.MINUTES=30;'
73+
'i.android.intent.extra.alarm.HOUR=21;'
74+
'end';
75+
76+
AndroidIntent.parseAndLaunch(intent);
77+
}, skip: !Platform.isAndroid);
78+
6779
testWidgets('LaunchChooser should not throw', (WidgetTester tester) async {
6880
const intent = AndroidIntent(
6981
action: 'android.intent.action.SEND',

packages/android_intent_plus/example/lib/main.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class MyHomePage extends StatelessWidget {
6969
child: const Text(
7070
'Tap here to set an alarm\non weekdays at 9:30pm.'),
7171
),
72+
ElevatedButton(
73+
onPressed: _parseAndLaunch,
74+
child: const Text('Tap here to set an alarm\n based on URI'),
75+
),
7276
ElevatedButton(
7377
onPressed: _openChooser,
7478
child: const Text('Tap here to launch Intent with Chooser'),
@@ -111,6 +115,18 @@ class MyHomePage extends StatelessWidget {
111115
);
112116
intent.sendBroadcast();
113117
}
118+
119+
void _parseAndLaunch() {
120+
const intent = 'intent:#Intent;'
121+
'action=android.intent.action.SET_ALARM;'
122+
'B.android.intent.extra.alarm.SKIP_UI=true;'
123+
'S.android.intent.extra.alarm.MESSAGE=Create%20a%20Flutter%20app;'
124+
'i.android.intent.extra.alarm.MINUTES=30;'
125+
'i.android.intent.extra.alarm.HOUR=21;'
126+
'end';
127+
128+
AndroidIntent.parseAndLaunch(intent);
129+
}
114130
}
115131

116132
/// Launches intents to specific Android activities.

packages/android_intent_plus/lib/android_intent.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,19 @@ class AndroidIntent {
150150
await _channel.invokeMethod<void>('launch', _buildArguments());
151151
}
152152

153+
/// Parse and Launch the intent in format.
154+
///
155+
/// Equivalent of native android Intent.parseUri(URI, Intent.URI_INTENT_SCHEME)
156+
/// This works only on Android platforms.
157+
static Future<void> parseAndLaunch(String uri) async {
158+
if (!const LocalPlatform().isAndroid) {
159+
return;
160+
}
161+
162+
await const MethodChannel(_kChannelName)
163+
.invokeMethod<void>('parseAndLaunch', {'uri': uri});
164+
}
165+
153166
/// Launch the intent with 'createChooser(intent, title)'.
154167
///
155168
/// This works only on Android platforms.

0 commit comments

Comments
 (0)