@@ -9,11 +9,25 @@ class Xcrun {
9
9
/// A return value of `true` doesn't mean the app is visible. The app might
10
10
/// be in the background, but still in memory.
11
11
static Future <bool > isAppRunning (String appBundleId) async {
12
- final result = await Process .run (
13
- "sh" ,
14
- ["-c" , "xcrun simctl spawn booted launchctl list | grep \" $appBundleId \" " ],
15
- );
12
+ // final result = await Process.run(
13
+ // "sh",
14
+ // [
15
+ // "-c",
16
+ // "xcrun simctl spawn booted launchctl list | grep \"$appBundleId\"",
17
+ // ],
18
+ // runInShell: true,
19
+ // );
20
+
21
+ // final result = await Process.run("sh", [
22
+ // "-c",
23
+ // "xcrun simctl spawn booted launchctl list | grep \"$appBundleId\"",
24
+ // ]);
25
+
26
+ final result = await _runInShell ([
27
+ "xcrun simctl spawn booted launchctl list | grep \" $appBundleId \" " ,
28
+ ]);
16
29
final output = result.stdout;
30
+ print ("Is app running? ${output != null && output is String && output .isNotEmpty }" );
17
31
return output != null && output is String && output.isNotEmpty;
18
32
}
19
33
@@ -28,18 +42,24 @@ class Xcrun {
28
42
void Function (String )? onLog,
29
43
void Function (String )? onError,
30
44
}) async {
31
- final result = await Process .start ("xcrun" , [
32
- "simctl" ,
33
- "spawn" ,
34
- "booted" ,
35
- "log" ,
36
- "stream" ,
37
- "--level" ,
38
- "debug" ,
39
- // Only log things related to the desired app.
40
- "--predicate" ,
41
- "(eventMessage CONTAINS '$appBundleId ' OR eventMessage CONTAINS 'flutter')" ,
42
- ]);
45
+ // This command doesn't work when run with a "sh -c". It also doesn't
46
+ // work when concatenating the args into a single string.
47
+ final result = await Process .start (
48
+ "xcrun" ,
49
+ [
50
+ "simctl" ,
51
+ "spawn" ,
52
+ "booted" ,
53
+ "log" ,
54
+ "stream" ,
55
+ "--level" ,
56
+ "debug" ,
57
+ // Only log things related to the desired app.
58
+ "--predicate" ,
59
+ "(eventMessage CONTAINS '$appBundleId ' OR eventMessage CONTAINS 'flutter')" ,
60
+ ],
61
+ runInShell: true ,
62
+ );
43
63
44
64
result.stdout.transform (utf8.decoder).listen (onLog);
45
65
result.stderr.transform (utf8.decoder).listen (onError);
@@ -52,8 +72,8 @@ class Xcrun {
52
72
///
53
73
/// This is useful, for example, when you want to connect to the Dart VM service
54
74
/// running in a debug Flutter app on an iOS device.
55
- static Future <void > forwardTcpPort (int port) async {
56
- await Process . run ( "xcrun" , [ "simctl" , "port" , "forward" , "booted" , "$port :$port " ]);
75
+ static Future <void > forwardTcpPort (int port) {
76
+ return _runInShell ([ "xcrun" , "simctl" , "port" , "forward" , "booted" , "$port :$port " ]);
57
77
}
58
78
59
79
/// Tells iOS to launch the given Universal Link, which might launch an app, if
@@ -62,13 +82,16 @@ class Xcrun {
62
82
/// The structure of the deep link is determined by the given app.
63
83
static Future <void > launchAppWithUniversalLink ({
64
84
required String universalLink,
65
- }) async {
66
- // Not sure why we need to dispatch through a shell, but if we try to
67
- // run the xcrun command directly, the deep link doesn't launch.
68
- await Process .run ("sh" , [
69
- "-c" ,
70
- "xcrun simctl openurl booted \" $universalLink \" " ,
71
- ]);
85
+ }) {
86
+ // Note: This command only works when run with "sh" and the
87
+ // command as a single string. If the command is passed as
88
+ // individual arguments, it doesn't work. If the command is
89
+ // run without "sh" and `runInShell` is `true`, it won't work.
90
+ return _runInShell (["xcrun simctl openurl booted \" $universalLink \" " ]);
91
+ // return Process.run(
92
+ // "sh",
93
+ // ["-c", "xcrun simctl openurl booted \"$universalLink\""],
94
+ // );
72
95
}
73
96
74
97
/// Waits for the app with the given [appBundleId] to appear in memory.
@@ -98,11 +121,37 @@ class Xcrun {
98
121
99
122
/// Kills the app with the given [appBundleId] ID, e.g., `com.acme.myapp` .
100
123
static Future <void > killApp (String appBundleId) async {
101
- await Process .run ("xcrun" , ["simctl" , "terminate" , "booted" , appBundleId]);
124
+ // final result = await _runInShell(["xcrun", "simctl", "terminate", "booted", appBundleId]);
125
+ final result = await Process .run (
126
+ "xcrun" ,
127
+ ["simctl" , "terminate" , "booted" , appBundleId],
128
+ runInShell: true ,
129
+ );
130
+ print ("Killed app - exit code: ${result .exitCode }" );
102
131
}
103
132
104
133
/// Clears all logs in the iOS log stream.
105
134
static Future <void > clearLogcat () async {
106
- await Process .run ("xcrun" , ["simctl" , "spawn" , "booted" , "log" , "erase" ]);
135
+ await _runInShell (["xcrun" , "simctl" , "spawn" , "booted" , "log" , "erase" ]);
136
+ }
137
+
138
+ static Future <Process > _startInShell (List <String > commandAndArgs) {
139
+ return Process .start ("sh" , ["-c" , ...commandAndArgs]);
140
+
141
+ // return Process.start(
142
+ // commandAndArgs.first,
143
+ // commandAndArgs.length > 1 ? commandAndArgs.sublist(1) : [],
144
+ // runInShell: true,
145
+ // );
146
+ }
147
+
148
+ static Future <ProcessResult > _runInShell (List <String > commandAndArgs) {
149
+ print ("Sending shell command: '${commandAndArgs .join (" " )}'" );
150
+ return Process .run ("sh" , ["-c" , ...commandAndArgs]);
151
+ // return Process.run(
152
+ // commandAndArgs.first,
153
+ // commandAndArgs.length > 1 ? commandAndArgs.sublist(1) : [],
154
+ // runInShell: true,
155
+ // );
107
156
}
108
157
}
0 commit comments