@@ -7,6 +7,10 @@ import java.util.*
77import android.content.res.Configuration
88import android.content.res.Resources
99import java.io.File
10+ import android.content.Intent
11+ import android.content.ComponentName
12+ import android.net.Uri
13+ import android.os.Build
1014
1115// 从Resource解析字符串,实现输出内容多语言
1216class ShellTranslation (val context : Context ) {
@@ -33,10 +37,271 @@ class ShellTranslation(val context: Context) {
3337 }
3438 }
3539
40+ private fun onAm (args : String ) {
41+ val ctx = context
42+ if (args.isEmpty()) return
43+
44+ val tokens = splitArgs(args)
45+ if (tokens.isEmpty()) return
46+
47+ val cmd = tokens[0 ].lowercase(Locale .US )
48+ val subArgs = args.substring(cmd.length).trim()
49+
50+ try {
51+ val intent = parseIntentArgs(subArgs)
52+
53+ when (cmd) {
54+ " start" -> {
55+ intent.addFlags(Intent .FLAG_ACTIVITY_NEW_TASK )
56+
57+ if ((Intent .ACTION_SEND == intent.action
58+ || Intent .ACTION_SEND_MULTIPLE == intent.action)
59+ && intent.component == null
60+ ) {
61+ val chooser = Intent .createChooser(intent, null )
62+ chooser.addFlags(Intent .FLAG_ACTIVITY_NEW_TASK )
63+ ctx.startActivity(chooser)
64+ } else {
65+ ctx.startActivity(intent)
66+ }
67+ }
68+
69+ " startservice" -> {
70+ if (Build .VERSION .SDK_INT >= 26 ) {
71+ ctx.startForegroundService(intent)
72+ } else {
73+ ctx.startService(intent)
74+ }
75+ }
76+
77+ " broadcast" -> {
78+ ctx.sendBroadcast(intent)
79+ }
80+ }
81+ } catch (e: Exception ) {
82+ e.printStackTrace()
83+ }
84+ }
85+
86+ private fun parseIntentArgs (args : String ): Intent {
87+ val intent = Intent ()
88+ val tokens = splitArgs(args)
89+
90+ var i = 0
91+ while (i < tokens.size) {
92+ when (tokens[i]) {
93+
94+ // action
95+ " -a" -> {
96+ if (i + 1 < tokens.size) {
97+ intent.action = tokens[++ i]
98+ }
99+ }
100+
101+ // data uri
102+ " -d" -> {
103+ if (i + 1 < tokens.size) {
104+ intent.data = Uri .parse(tokens[++ i])
105+ }
106+ }
107+
108+ // mime type
109+ " -t" -> {
110+ if (i + 1 < tokens.size) {
111+ intent.type = tokens[++ i]
112+ }
113+ }
114+
115+ // component
116+ " -n" -> {
117+ if (i + 1 < tokens.size) {
118+ val cn = tokens[++ i].split(" /" , limit = 2 )
119+ if (cn.size == 2 ) {
120+ intent.component = ComponentName (cn[0 ], cn[1 ])
121+ }
122+ }
123+ }
124+
125+ // package
126+ " -p" -> {
127+ if (i + 1 < tokens.size) {
128+ intent.`package` = tokens[++ i]
129+ }
130+ }
131+
132+ // category
133+ " -c" -> {
134+ if (i + 1 < tokens.size) {
135+ intent.addCategory(tokens[++ i])
136+ }
137+ }
138+
139+ // flags
140+ " -f" -> {
141+ if (i + 1 < tokens.size) {
142+ val v = tokens[++ i]
143+ val flags = if (v.startsWith(" 0x" )) {
144+ v.substring(2 ).toInt(16 )
145+ } else {
146+ v.toInt()
147+ }
148+ intent.addFlags(flags)
149+ }
150+ }
151+
152+ // String extra
153+ " --es" -> {
154+ if (i + 2 < tokens.size) {
155+ val key = tokens[++ i]
156+ val value = tokens[++ i]
157+ intent.putExtra(key, value)
158+ }
159+ }
160+
161+ // int extra
162+ " --ei" -> {
163+ if (i + 2 < tokens.size) {
164+ val key = tokens[++ i]
165+ try {
166+ intent.putExtra(key, tokens[++ i].toInt())
167+ } catch (_: Exception ) {}
168+ }
169+ }
170+
171+ // long extra
172+ " --el" -> {
173+ if (i + 2 < tokens.size) {
174+ val key = tokens[++ i]
175+ try {
176+ intent.putExtra(key, tokens[++ i].toLong())
177+ } catch (_: Exception ) {}
178+ }
179+ }
180+
181+ // boolean extra
182+ " --ez" -> {
183+ if (i + 2 < tokens.size) {
184+ val key = tokens[++ i]
185+ intent.putExtra(key, tokens[++ i].toBoolean())
186+ }
187+ }
188+
189+ // float extra
190+ " --ef" -> {
191+ if (i + 2 < tokens.size) {
192+ val key = tokens[++ i]
193+ try {
194+ intent.putExtra(key, tokens[++ i].toFloat())
195+ } catch (_: Exception ) {}
196+ }
197+ }
198+
199+ // double extra
200+ " --ed" -> {
201+ if (i + 2 < tokens.size) {
202+ val key = tokens[++ i]
203+ try {
204+ intent.putExtra(key, tokens[++ i].toDouble())
205+ } catch (_: Exception ) {}
206+ }
207+ }
208+
209+ // null string
210+ " --esn" -> {
211+ if (i + 1 < tokens.size) {
212+ intent.putExtra(tokens[++ i], null as String? )
213+ }
214+ }
215+
216+ // String[]
217+ " --esa" -> {
218+ if (i + 1 < tokens.size) {
219+ val key = tokens[++ i]
220+ val list = ArrayList <String >()
221+ while (i + 1 < tokens.size && ! tokens[i + 1 ].startsWith(" -" )) {
222+ list.add(tokens[++ i])
223+ }
224+ intent.putExtra(key, list.toTypedArray())
225+ }
226+ }
227+
228+ // int[]
229+ " --eia" -> {
230+ if (i + 1 < tokens.size) {
231+ val key = tokens[++ i]
232+ val list = ArrayList <Int >()
233+ while (i + 1 < tokens.size && ! tokens[i + 1 ].startsWith(" -" )) {
234+ try {
235+ list.add(tokens[++ i].toInt())
236+ } catch (_: Exception ) {}
237+ }
238+ intent.putExtra(key, list.toIntArray())
239+ }
240+ }
241+
242+ // grant uri permissions
243+ " --grant-read-uri-permission" -> {
244+ intent.addFlags(Intent .FLAG_GRANT_READ_URI_PERMISSION )
245+ }
246+
247+ " --grant-write-uri-permission" -> {
248+ intent.addFlags(Intent .FLAG_GRANT_WRITE_URI_PERMISSION )
249+ }
250+ }
251+ i++
252+ }
253+ return intent
254+ }
255+
256+ private fun splitArgs (args : String ): List <String > {
257+ val out = ArrayList <String >()
258+ val cur = StringBuilder ()
259+ var inQuote = false
260+ var quoteChar = ' \u0000 '
261+
262+ for (i in args.indices) {
263+ val c = args[i]
264+
265+ if (inQuote) {
266+ if (c == quoteChar) {
267+ inQuote = false
268+ } else {
269+ cur.append(c)
270+ }
271+ } else {
272+ when {
273+ c == ' "' || c == ' \' ' -> {
274+ inQuote = true
275+ quoteChar = c
276+ }
277+ c.isWhitespace() -> {
278+ if (cur.isNotEmpty()) {
279+ out .add(cur.toString())
280+ cur.setLength(0 )
281+ }
282+ }
283+ else -> cur.append(c)
284+ }
285+ }
286+ }
287+
288+ if (cur.isNotEmpty()) out .add(cur.toString())
289+ return out
290+ }
291+
36292 fun resolveRow (originRow : String ): String {
293+ val trimmed = originRow.trim()
294+ if (trimmed.startsWith(" am:[" , true ) && trimmed.endsWith(" ]" )) {
295+ val args = trimmed
296+ .removePrefix(" am:[" )
297+ .removeSuffix(" ]" )
298+ .trim()
299+
300+ if (args.isNotEmpty()) onAm(args)
301+ return " "
302+ }
37303 var result = originRow
38304 val res = appResources
39-
40305 resRegex.findAll(originRow).forEach { match ->
41306 val row = match.value // @string:notification_ui
42307 val separator = if (row.contains(" :" )) ' :' else ' /'
0 commit comments