Skip to content

Commit

Permalink
feat(android_intent_plus): support for intent as URI (#2970)
Browse files Browse the repository at this point in the history
Co-authored-by: Miguel Beltran <m@beltran.work>
  • Loading branch information
jaumard and miquelbeltran authored May 31, 2024
1 parent 23fe3ef commit e453087
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.Nullable;
import java.net.URISyntaxException;

/** Forms and launches intents. */
public final class IntentSender {
Expand Down Expand Up @@ -175,4 +176,8 @@ Intent buildIntent(

return intent;
}

public Intent parse(String uri) throws URISyntaxException {
return Intent.parseUri(uri, Intent.URI_INTENT_SCHEME);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Map;

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

if ("launch".equalsIgnoreCase(call.method)) {
if ("parseAndLaunch".equalsIgnoreCase(call.method)) {
try {
intent = sender.parse(call.argument("uri"));
sender.send(intent);
result.success(null);
} catch (URISyntaxException e) {
result.error("parse_error", "Failed to parse URI", e.getMessage());
}
} else if ("launch".equalsIgnoreCase(call.method)) {

if (intent != null && !sender.canResolveActivity(intent)) {
Log.i(TAG, "Cannot resolve explicit intent, falling back to implicit");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ void main() {
(Widget widget) =>
widget is Text && widget.data!.startsWith('Tap here'),
),
findsNWidgets(4),
findsNWidgets(5),
);
} else {
expect(
Expand Down Expand Up @@ -64,6 +64,18 @@ void main() {
await intent.launch();
}, skip: !Platform.isAndroid);

testWidgets('Parse and Launch should not throw', (WidgetTester tester) async {
const intent = 'intent:#Intent;'
'action=android.intent.action.SET_ALARM;'
'B.android.intent.extra.alarm.SKIP_UI=true;'
'S.android.intent.extra.alarm.MESSAGE=Create%20a%20Flutter%20app;'
'i.android.intent.extra.alarm.MINUTES=30;'
'i.android.intent.extra.alarm.HOUR=21;'
'end';

AndroidIntent.parseAndLaunch(intent);
}, skip: !Platform.isAndroid);

testWidgets('LaunchChooser should not throw', (WidgetTester tester) async {
const intent = AndroidIntent(
action: 'android.intent.action.SEND',
Expand Down
16 changes: 16 additions & 0 deletions packages/android_intent_plus/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class MyHomePage extends StatelessWidget {
child: const Text(
'Tap here to set an alarm\non weekdays at 9:30pm.'),
),
ElevatedButton(
onPressed: _parseAndLaunch,
child: const Text('Tap here to set an alarm\n based on URI'),
),
ElevatedButton(
onPressed: _openChooser,
child: const Text('Tap here to launch Intent with Chooser'),
Expand Down Expand Up @@ -111,6 +115,18 @@ class MyHomePage extends StatelessWidget {
);
intent.sendBroadcast();
}

void _parseAndLaunch() {
const intent = 'intent:#Intent;'
'action=android.intent.action.SET_ALARM;'
'B.android.intent.extra.alarm.SKIP_UI=true;'
'S.android.intent.extra.alarm.MESSAGE=Create%20a%20Flutter%20app;'
'i.android.intent.extra.alarm.MINUTES=30;'
'i.android.intent.extra.alarm.HOUR=21;'
'end';

AndroidIntent.parseAndLaunch(intent);
}
}

/// Launches intents to specific Android activities.
Expand Down
13 changes: 13 additions & 0 deletions packages/android_intent_plus/lib/android_intent.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,19 @@ class AndroidIntent {
await _channel.invokeMethod<void>('launch', _buildArguments());
}

/// Parse and Launch the intent in format.
///
/// Equivalent of native android Intent.parseUri(URI, Intent.URI_INTENT_SCHEME)
/// This works only on Android platforms.
static Future<void> parseAndLaunch(String uri) async {
if (!const LocalPlatform().isAndroid) {
return;
}

await const MethodChannel(_kChannelName)
.invokeMethod<void>('parseAndLaunch', {'uri': uri});
}

/// Launch the intent with 'createChooser(intent, title)'.
///
/// This works only on Android platforms.
Expand Down

0 comments on commit e453087

Please sign in to comment.