1 package ro
.ieval
.fonbot
;
3 import static ro
.ieval
.fonbot
.R
.string
.*;
5 import java
.net
.MalformedURLException
;
7 import java
.util
.ArrayList
;
8 import java
.util
.Arrays
;
9 import java
.util
.Locale
;
11 import org
.eclipse
.jdt
.annotation
.NonNull
;
12 import org
.eclipse
.jdt
.annotation
.Nullable
;
14 import ro
.ieval
.fonbot
.Address
.Protocol
;
15 import android
.content
.Context
;
16 import android
.content
.Intent
;
17 import android
.content
.SharedPreferences
;
18 import android
.database
.Cursor
;
19 import android
.location
.LocationManager
;
20 import android
.media
.AudioManager
;
21 import android
.net
.Uri
;
22 import android
.os
.Handler
;
23 import android
.os
.Looper
;
24 import android
.preference
.PreferenceManager
;
25 import android
.provider
.ContactsContract
.PhoneLookup
;
26 import android
.telephony
.SmsManager
;
27 import android
.util
.Log
;
28 import android
.widget
.Toast
;
31 * Copyright © 2013 Marius Gavrilescu
33 * This file is part of FonBot.
35 * FonBot is free software: you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation, either version 3 of the License, or
38 * (at your option) any later version.
40 * FonBot is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
45 * You should have received a copy of the GNU General Public License
46 * along with FonBot. If not, see <http://www.gnu.org/licenses/>.
50 * Utility functions and enums used in various places.
52 * @author Marius Gavrilescu <marius@ieval.ro>
54 public final class Utils
{
56 * Enum of all FonBot commands.
58 * @author Marius Gavrilescu <marius@ieval.ro>
60 @SuppressWarnings("javadoc")
61 public static enum Command
{
62 TOAST
, ECHO
, SMS
, SMSQ
, FLASH
, WIFI
,
63 BLUETOOTH
, DIAL
, RING
, SPEAK
, VIBRATE
,
64 DIALOG
, LOCATION
, NOLOCATION
, RINGER
, NCFILE
,
65 PHOTO
, SETNOTIFICATION
, DELNOTIFICATION
, SETPASSWORD
, HELP
,
66 WIPE
, LOCK
, VIEW
, PLAY
, PAUSE
,
67 NEXT
, PREV
, BATT
, CALLLOG
, SMSLOG
,
68 LS
, RM
, CONTACTS
, DISABLE
, ENABLE
,
69 POLL
, HANGUP
, ANSWER
, LAUNCH
, DATA
,
70 GPS
, GLOCATION
, REBOOT
, NOTIFY
, SCREENCAP
,
71 TORCH
, GETFILE
, SH
, ROOTSH
75 * Enum of all message types. Each message type is a kind of notification which can be enabled/disabled by the user and directed to a certain address.
77 * @author Marius Gavrilescu <marius@ieval.ro>
80 public static enum MessageType
{
81 /** SMS notifications */
83 /** Phone state (idle, offhook or ringing) notifications */
85 /** Lockscreen failed password notifications */
87 /** Device admin enable/disable notifications */
89 /** Coarse battery status (low battery, ok battery) notifications */
91 /** Fine battery status notifications */
93 /** Headset plug/unplug notifications */
95 /** Phone booted notifications */
100 * Enum of wipe types. The two defined types are the data wipe (which does not include the SD card) and the full wipe (which includes the SD card).
102 * @author Marius Gavrilescu <marius@ieval.ro>
104 public static enum WipeType
{
105 /** Factory reset the phone, without touching the SD card */
107 /** Factory reset the phone and wipe the SD card too */
112 * Enum of ringer modes.
114 * @author Marius Gavrilescu <marius@ieval.ro>
116 public static enum RingerMode
{
119 /** Sound is off, vibrate is on */
121 /** Sound is off, vibrate is off */
126 * Enum of location providers
128 * @author Marius Gavrilescu <marius@ieval.ro>
130 public static enum LocationProvider
{
131 /** The network location provider */
133 /** The GPS location provider */
138 * Enum of toast lengths.
140 * @author Marius Gavrilescu <marius@ieval.ro>
142 private static enum ToastLength
{
150 * Enum of the values on and off. Used for boolean arguments.
152 * @author Marius Gavrilescu <marius@ieval.ro>
154 @SuppressWarnings("javadoc")
155 private static enum OnOff
{
160 * Enum of ongoing event types
162 * @author Marius Gavrilescu <marius@ieval.ro>
164 public static enum OngoingEvent
{
165 /** Location tracking is active. Registered by {@link Command#LOCATION}, unregistered by {@link Command#NOLOCATION} */
166 LOCATION(location_tracking_is_active
),
167 /** The phone is ringing. Registered/unregistered by {@link Command#RING} */
170 /** String resource: the event description */
171 public final int resource
;
174 * Constructs an OngoingEvent from its event description.
176 * @param resource the event description
178 private OngoingEvent(final int resource
) {
179 this.resource
=resource
;
183 /** Confirmation string for the {@link Command#WIPE WIPE} command. */
184 public static final String WIPE_CONFIRM_STRING
="I am aware this cannot be undone";
187 * Converts a Nullable object into a NonNull one.
189 * @param object the Nullable object to convert
190 * @return a NonNull object equivalent to the Nullable parameter
191 * @throws AssertionError if the given object is null
193 public static <T
> T
toNonNull(@Nullable T object
) throws AssertionError
{
195 throw new NullPointerException();
200 * Join an array of Objects with elements separated by a separator into a single string.
202 * @param separator the separator
203 * @param offset the offset into the array
204 * @param args the array of Objects to join
205 * @return the joined string
207 public static String
join(final String separator
,final int offset
,final Object
[] args
){
208 final StringBuilder sb
=new StringBuilder(240);
209 sb
.append(args
[offset
]);
210 for (int i
= offset
+1; i
< args
.length
; i
++) {
211 sb
.append(separator
);
214 return toNonNull(sb
.toString());
218 * Join an array of Objects with elements separated by a separator into a single string.
220 * @param separator the separator
221 * @param args the array of objects to join
222 * @return the joined string
224 public static String
join(final String separator
, final Object
[] args
){
225 return join(separator
,0,args
);
229 * Send a notification to the user.
231 * @param context Context instance
232 * @param type notification type
233 * @param resource String resource for the message text
235 public static void sendMessage(final Context context
, final MessageType type
, final int resource
){
236 sendMessage(context
, type
, toNonNull(context
.getString(resource
)));
240 * Send a notification to the user.
242 * @param context Context instance
243 * @param type notification type
244 * @param resource String resource for the message text
245 * @param args format parameters for the resource
247 public static void sendMessage(final Context context
, final MessageType type
, final int resource
, final Object
... args
){
248 sendMessage(context
, type
, toNonNull(context
.getString(resource
, args
)));
252 * Send a message to a certain Address.
254 * @param context Context instance
255 * @param address destination Address
256 * @param resource String resource for the message text
258 public static void sendMessage(final Context context
, final Address address
, final int resource
){
259 sendMessage(context
, address
, toNonNull(context
.getString(resource
)));
263 * Send a message to a certain Address.
265 * @param context Context instance
266 * @param address destination Address
267 * @param resource String resource for the message text
268 * @param args format parameters for the resource
270 public static void sendMessage(final Context context
, final Address address
, final int resource
, final Object
... args
){
271 sendMessage(context
, address
, toNonNull(context
.getString(resource
, args
)));
275 * Send a confirmation message to a certain Address. A confirm message is a message that:
276 * 1) Confers no information (except for confirming that the command was executed).
277 * 2) May be dropped if the user asked so.
279 * @param context Context instance
280 * @param address destination Address
281 * @param resource String resource for the message text
282 * @param args format parameters for the resource
284 public static void sendConfirmMessage(final Context context
, final Address address
, final int resource
, final Object
... args
){
285 final SharedPreferences sp
=PreferenceManager
.getDefaultSharedPreferences(context
);
286 if(address
.protocol
!= Protocol
.SMS
|| !sp
.getBoolean("expensive_sms", false))
287 sendMessage(context
, address
, resource
, args
);
291 * Send a notification to the user.
293 * @param context Context instance
294 * @param type notification type
295 * @param msg the notification text
297 public static void sendMessage(final Context context
, final MessageType type
,final String msg
){
298 final SharedPreferences sp
=PreferenceManager
.getDefaultSharedPreferences(context
);
299 final String address
=sp
.getString(type
.toString(),null);
302 sendMessage(context
, new Address(address
), msg
);
306 * Send a message to a certain Address.
308 * @param context Context instance
309 * @param address destination Address
310 * @param message the message text
312 public static void sendMessage(final Context context
, final Address address
, final String message
){
313 switch(address
.protocol
){
315 new HttpCallExecutableRunnable("/send", toNonNull(Arrays
.asList(new Header("X-Destination", toNonNull(address
.data
)))), context
, null, true, address
.requestId
== null ? message
: address
.requestId
+ " " + message
).execute();
319 new Handler(Looper
.getMainLooper()).post(new Runnable(){
322 final ArrayList
<String
> parts
= SmsManager
.getDefault().divideMessage(message
);
323 SmsManager
.getDefault().sendMultipartTextMessage(address
.data
, null, parts
, null, null);
329 final Intent intent
= new Intent(FonBotLocalActivity
.RESPONSE_RECEIVED_ACTION
);
330 intent
.putExtra(FonBotLocalActivity
.EXTRA_RESPONSE
, message
);
331 context
.sendBroadcast(intent
);
340 * Splits a string into words.
342 * @param string the string
343 * @return an array of words
345 public static String
[] shellwords(final String string
){
346 return toNonNull(string
.split("[ ]+(?=([^\"]*\"[^\"]*\")*[^\"]*$)"));//TODO: Make this handle backslash escapes
350 * Returns the name associated with a phone number.
352 * @param context Context instance
353 * @param number phone number to search for
354 * @return the name associated with this number, or null if the number was not found in the contacts.
356 public static @Nullable String
callerId(final Context context
, final String number
){
357 final Cursor cursor
=context
.getContentResolver().query(
358 Uri
.withAppendedPath(PhoneLookup
.CONTENT_FILTER_URI
, Uri
.encode(number
)),
359 new String
[]{PhoneLookup
.DISPLAY_NAME
},
364 if(cursor
.moveToFirst()){
365 final String name
=cursor
.getString(0);
374 * Registers an ongoing event.
376 * @param context Context instance
377 * @param event event to register
379 public static void registerOngoing(final Context context
, final OngoingEvent event
){
380 final Intent intent
=new Intent(context
, FonBotMainService
.class);
381 intent
.setAction(FonBotMainService
.ACTION_PUT_ONGOING
);
382 intent
.putExtra(FonBotMainService
.EXTRA_ONGOING_ID
, event
.ordinal());
383 context
.startService(intent
);
387 * Unregisters an ongoing event
389 * @param context Context instance
390 * @param event event to unregister
392 public static void unregisterOngoing(final Context context
, final OngoingEvent event
){
393 final Intent intent
=new Intent(context
, FonBotMainService
.class);
394 intent
.setAction(FonBotMainService
.ACTION_DELETE_ONGOING
);
395 intent
.putExtra(FonBotMainService
.EXTRA_ONGOING_ID
, event
.ordinal());
396 context
.startService(intent
);
400 * Gets the server URL according to the user preferences.
402 * @param context Context instance
403 * @param path URL path
404 * @return the server URL
405 * @throws MalformedURLException if the user preferences create an invalid URL
407 public static URL
getServerURL(final Context context
, final String path
) throws MalformedURLException
{
408 final String protocol
=PreferenceManager
.getDefaultSharedPreferences(context
).getString("protocol", "https");
409 final String hostname
=PreferenceManager
.getDefaultSharedPreferences(context
).getString("hostname", "fonbot.ieval.ro");
410 final int port
=Integer
.parseInt(PreferenceManager
.getDefaultSharedPreferences(context
).getString("port", "443"));
411 final URL url
=new URL(protocol
, hostname
, port
, path
);
416 * Executes a given command
418 * @param context Context instance
419 * @param cmd Command to execute
420 * @param args arguments for the command
421 * @param replyTo Address to send replies to
423 private static void processCommand(final Context context
, final Command cmd
,final String
[] args
,final Address replyTo
){
424 if(Heavy
.isCommandDisabled(context
, cmd
)){
425 sendMessage(context
, replyTo
, command_disabled
, cmd
.toString());
431 if(args
.length
< 1 || args
.length
> 2){
432 Heavy
.help(context
, replyTo
, toNonNull(Command
.TOAST
));
437 Heavy
.toast(context
, replyTo
, toNonNull(args
[0]));
440 switch(ToastLength
.valueOf(args
[1].toUpperCase(Locale
.ENGLISH
))){
442 Heavy
.toast(context
, replyTo
, toNonNull(args
[0]), Toast
.LENGTH_LONG
);
445 Heavy
.toast(context
, replyTo
, toNonNull(args
[0]), Toast
.LENGTH_SHORT
);
447 } catch(IllegalArgumentException e
){
448 sendMessage(context
, replyTo
, invalid_length_allowed_values_are
, join(", ",toNonNull(ToastLength
.values())));
455 Heavy
.help(context
, replyTo
, toNonNull(Command
.ECHO
));
458 sendMessage(context
, replyTo
, join(" ",args
));
463 Heavy
.help(context
, replyTo
, toNonNull(Command
.SMS
));
466 Heavy
.sms(context
, replyTo
, toNonNull(args
[0]), join(" ", 1, args
), false);
471 Heavy
.help(context
, replyTo
, toNonNull(Command
.SMSQ
));
474 Heavy
.sms(context
, replyTo
, toNonNull(args
[0]), join(" ", 1, args
), true);
478 if(args
.length
!= 1){
479 Heavy
.help(context
, replyTo
, toNonNull(Command
.FLASH
));
484 Heavy
.flash(context
, replyTo
, OnOff
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)) == OnOff
.ON
);
485 } catch(IllegalArgumentException e
) {
486 sendMessage(context
, replyTo
, could_not_parse_argument_allowed_values_are
, join(", ", toNonNull(OnOff
.values())));
492 Heavy
.help(context
, replyTo
, toNonNull(Command
.WIFI
));
496 Heavy
.wifi(context
, replyTo
);
499 Heavy
.wifi(context
, replyTo
, OnOff
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)) == OnOff
.ON
);
500 } catch(IllegalArgumentException e
) {
501 sendMessage(context
, replyTo
, could_not_parse_argument_allowed_values_are
, join(", ", toNonNull(OnOff
.values())));
508 Heavy
.help(context
, replyTo
, toNonNull(Command
.BLUETOOTH
));
512 Heavy
.bluetooth(context
, replyTo
);
515 Heavy
.bluetooth(context
, replyTo
, OnOff
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)) == OnOff
.ON
);
516 } catch(IllegalArgumentException e
) {
517 sendMessage(context
, replyTo
, could_not_parse_argument_allowed_values_are
, join(", ", toNonNull(OnOff
.values())));
524 Heavy
.help(context
, replyTo
, toNonNull(Command
.DIAL
));
527 Heavy
.dial(context
, replyTo
, toNonNull(args
[0]));
532 Heavy
.help(context
, replyTo
, toNonNull(Command
.RING
));
536 Heavy
.ring(context
, replyTo
);
539 Heavy
.ring(context
, replyTo
, OnOff
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)) == OnOff
.ON
);
540 } catch(IllegalArgumentException e
){
541 sendMessage(context
, replyTo
, could_not_parse_argument_allowed_values_are
, join(", ", toNonNull(OnOff
.values())));
548 Heavy
.help(context
, replyTo
, toNonNull(Command
.SPEAK
));
551 Heavy
.speak(context
, replyTo
, join(" ",args
));
556 Heavy
.help(context
, replyTo
, toNonNull(Command
.VIBRATE
));
561 ms
=Long
.parseLong(args
[0]);
562 } catch(NumberFormatException e
){
563 sendMessage(context
, replyTo
, could_not_parse_ms
);
566 Heavy
.vibrate(context
, replyTo
, ms
);
569 case DIALOG
://TODO: Should add an edittext
571 Heavy
.help(context
, replyTo
, toNonNull(Command
.DIALOG
));
574 final String
[] buttons
=new String
[args
.length
-1];
575 System
.arraycopy(args
,1,buttons
,0,buttons
.length
);
576 Heavy
.dialog(context
, replyTo
, toNonNull(args
[0]), buttons
);
580 if(args
.length
>3||args
.length
<1){
581 Heavy
.help(context
, replyTo
, toNonNull(Command
.LOCATION
));
585 final @NonNull String provider
;
587 switch(LocationProvider
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
))){
589 provider
=toNonNull(LocationManager
.GPS_PROVIDER
);
593 provider
=toNonNull(LocationManager
.NETWORK_PROVIDER
);
596 } catch(IllegalArgumentException e
){
597 sendMessage(context
, replyTo
, cannot_parse_provider_allowed_values_are
, join(", ",toNonNull(LocationProvider
.values())));
602 final float minDistance
;
606 minTime
=Long
.parseLong(args
[1]);
607 } catch (NumberFormatException e
){
608 sendMessage(context
, replyTo
, cannot_parse_min_time
);
616 minDistance
=Float
.parseFloat(args
[2]);
617 } catch (NumberFormatException e
){
618 sendMessage(context
, replyTo
, cannot_parse_min_distance
);
623 Heavy
.location(context
, replyTo
, provider
, minTime
, minDistance
);
627 Heavy
.nolocation(context
, replyTo
);
632 Heavy
.help(context
, replyTo
, toNonNull(Command
.RINGER
));
636 Heavy
.ringer(context
, replyTo
);
639 final RingerMode rm
=RingerMode
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
));
642 Heavy
.ringer(context
, replyTo
, AudioManager
.RINGER_MODE_NORMAL
);
645 Heavy
.ringer(context
, replyTo
, AudioManager
.RINGER_MODE_VIBRATE
);
648 Heavy
.ringer(context
, replyTo
, AudioManager
.RINGER_MODE_SILENT
);
651 } catch (IllegalArgumentException e
){
652 Utils
.sendMessage(context
, replyTo
, invalid_ringer_mode_valid_values_are
, join(", ",toNonNull(RingerMode
.values())));
659 Heavy
.help(context
, replyTo
, toNonNull(Command
.NCFILE
));
663 final int ncfilePort
;
665 ncfilePort
=Integer
.parseInt(args
[2]);
666 } catch (NumberFormatException e
){
667 sendMessage(context
, replyTo
, cannot_parse_port
);
670 Heavy
.ncfile(context
, replyTo
, toNonNull(args
[0]), toNonNull(args
[1]), ncfilePort
);
675 Heavy
.help(context
, replyTo
, toNonNull(Command
.PHOTO
));
679 final int cameraNumber
;
681 cameraNumber
=Integer
.parseInt(args
[0]);
682 } catch (NumberFormatException e
){
683 sendMessage(context
, replyTo
, cannot_parse_camera_number
);
689 photoPort
=Integer
.parseInt(args
[2]);
690 } catch (NumberFormatException e
){
691 sendMessage(context
, replyTo
, cannot_parse_port
);
694 Heavy
.photo(context
, replyTo
, cameraNumber
, toNonNull(args
[1]), photoPort
);
697 case SETNOTIFICATION
:
699 Heavy
.help(context
, replyTo
, toNonNull(Command
.SETNOTIFICATION
));
704 PreferenceManager
.getDefaultSharedPreferences(context
).edit()
705 .putString(MessageType
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)).toString(), replyTo
.toString())
707 sendConfirmMessage(context
, replyTo
, notification_enabled
);
708 } catch (IllegalArgumentException e
){
709 sendMessage(context
, replyTo
, messagetype_should_be_one_of
, join(", ",toNonNull(MessageType
.values())));
715 case DELNOTIFICATION
:
717 Heavy
.help(context
, replyTo
, toNonNull(Command
.DELNOTIFICATION
));
722 PreferenceManager
.getDefaultSharedPreferences(context
).edit()
723 .remove(MessageType
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)).toString())
725 sendConfirmMessage(context
, replyTo
, notification_disabled
);
726 } catch (IllegalArgumentException e
){
727 sendMessage(context
, replyTo
, messagetype_should_be_one_of
, join(", ",toNonNull(MessageType
.values())));
735 Heavy
.help(context
, replyTo
, toNonNull(Command
.SETPASSWORD
));
741 Heavy
.setPassword(context
, replyTo
);
743 Heavy
.setPassword(context
, replyTo
, toNonNull(args
[0]));
744 } catch (SecurityException e
){
745 sendMessage(context
, replyTo
, security_exception
, e
.getMessage());
751 Heavy
.help(context
, replyTo
, toNonNull(Command
.WIPE
));
755 if(!args
[1].equalsIgnoreCase(WIPE_CONFIRM_STRING
)){
756 sendMessage(context
, replyTo
, the_second_argument_to_wipe_must_be
, WIPE_CONFIRM_STRING
);
761 Heavy
.wipe(context
, toNonNull(WipeType
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
))));
762 } catch (IllegalArgumentException e
){
763 sendMessage(context
, replyTo
, wipetype_should_be_one_of
, join (", ",toNonNull(WipeType
.values())));
764 } catch (SecurityException e
){
765 sendMessage(context
, replyTo
, security_exception
, e
.getMessage());
771 Heavy
.lock(context
, replyTo
);
772 } catch (SecurityException e
){
773 sendMessage(context
, replyTo
, security_exception
, e
.getMessage());
779 Heavy
.help(context
, replyTo
, toNonNull(Command
.VIEW
));
783 Heavy
.view(context
, replyTo
, toNonNull(Uri
.parse(args
[0])));
787 Heavy
.musicPlayerCommand(context
, replyTo
, "play");
791 Heavy
.musicPlayerCommand(context
, replyTo
, "pause");
795 Heavy
.musicPlayerCommand(context
, replyTo
, "next");
799 Heavy
.musicPlayerCommand(context
, replyTo
, "previous");
803 Heavy
.batt(context
, replyTo
);
807 if (args
.length
> 1) {
808 Heavy
.help(context
, replyTo
, toNonNull(Command
.CALLLOG
));
812 if (args
.length
== 0)
813 Heavy
.calllog(context
, replyTo
, 5);
816 Heavy
.calllog(context
, replyTo
, Integer
.parseInt(args
[0]));
817 } catch (IllegalArgumentException e
){
818 sendMessage(context
, replyTo
, cannot_parse_count
);
824 if (args
.length
> 1) {
825 Heavy
.help(context
, replyTo
, toNonNull(Command
.SMSLOG
));
829 if (args
.length
== 0)
830 Heavy
.smslog(context
, replyTo
, 5);
833 Heavy
.smslog(context
, replyTo
, Integer
.parseInt(args
[0]));
834 } catch (IllegalArgumentException e
) {
835 sendMessage(context
, replyTo
, cannot_parse_count
);
841 if(args
.length
!= 1){
842 Heavy
.help(context
, replyTo
, toNonNull(Command
.HELP
));
847 Heavy
.help(context
, replyTo
, toNonNull(Command
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
))));
848 } catch (IllegalArgumentException e
) {
849 sendMessage(context
, replyTo
, no_such_command_command_list
, join(", ", toNonNull(Command
.values())));
854 if(args
.length
!= 1){
855 Heavy
.help(context
, replyTo
, toNonNull(Command
.LS
));
859 Heavy
.ls(context
, replyTo
, toNonNull(args
[0]));
863 if(args
.length
!= 1){
864 Heavy
.help(context
, replyTo
, toNonNull(Command
.RM
));
868 Heavy
.rm(context
, replyTo
, toNonNull(args
[0]));
872 if(args
.length
!= 1){
873 Heavy
.help(context
, replyTo
, toNonNull(Command
.CONTACTS
));
877 Heavy
.contacts(context
, replyTo
, toNonNull(args
[0]));
881 if(replyTo
.protocol
!= Protocol
.LOCAL
|| args
.length
!= 1){
882 Heavy
.help(context
, replyTo
, toNonNull(Command
.DISABLE
));
887 Heavy
.disable(context
, replyTo
, toNonNull(Command
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
))));
888 } catch (IllegalArgumentException e
){
889 sendMessage(context
, replyTo
, no_such_command_command_list
, join(", ", toNonNull(Command
.values())));
894 if(replyTo
.protocol
!= Protocol
.LOCAL
|| args
.length
!= 1){
895 Heavy
.help(context
, replyTo
, toNonNull(Command
.ENABLE
));
900 Heavy
.enable(context
, replyTo
, toNonNull(Command
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
))));
901 } catch (IllegalArgumentException e
){
902 sendMessage(context
, replyTo
, no_such_command_command_list
, join(", ", toNonNull(Command
.values())));
907 Heavy
.poll(context
, replyTo
);
911 Heavy
.hangup(context
, replyTo
);
915 Heavy
.answer(context
, replyTo
);
920 Heavy
.help(context
, replyTo
, toNonNull(Command
.LAUNCH
));
923 Heavy
.launch(context
, replyTo
, toNonNull(args
[0]));
928 Heavy
.help(context
, replyTo
, toNonNull(Command
.DATA
));
933 Heavy
.data(context
, replyTo
);
937 Heavy
.data(context
, replyTo
, OnOff
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)) == OnOff
.ON
);
938 } catch(IllegalArgumentException e
) {
939 sendMessage(context
, replyTo
, could_not_parse_argument_allowed_values_are
, join(", ", toNonNull(OnOff
.values())));
945 Heavy
.help(context
, replyTo
, toNonNull(Command
.GPS
));
950 Heavy
.gps(context
, replyTo
);
955 Heavy
.gps(context
, replyTo
, OnOff
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)) == OnOff
.ON
);
956 } catch(IllegalArgumentException e
) {
957 sendMessage(context
, replyTo
, could_not_parse_argument_allowed_values_are
, join(", ", toNonNull(OnOff
.values())));
963 Heavy
.help(context
, replyTo
, toNonNull(Command
.GLOCATION
));
968 Heavy
.glocation(context
, replyTo
);
973 Heavy
.glocation(context
, replyTo
, OnOff
.valueOf(args
[0].toUpperCase(Locale
.ENGLISH
)) == OnOff
.ON
);
974 } catch(IllegalArgumentException e
) {
975 sendMessage(context
, replyTo
, could_not_parse_argument_allowed_values_are
, join(", ", toNonNull(OnOff
.values())));
981 Heavy
.help(context
, replyTo
, toNonNull(Command
.REBOOT
));
985 Heavy
.reboot(context
, replyTo
, args
.length
==0?
null:args
[0]);
989 if(args
.length
!=1 && args
.length
!=3){
990 Heavy
.help(context
, replyTo
, toNonNull(Command
.NOTIFY
));
996 id
=Integer
.parseInt(args
[0]);
997 } catch (NumberFormatException e
){
998 sendMessage(context
, replyTo
, R
.string
.could_not_parse_id
);
1003 Heavy
.notify(context
, replyTo
, id
);
1005 Heavy
.notify(context
, replyTo
, id
, toNonNull(args
[1]), toNonNull(args
[2]));
1009 if(args
.length
!= 1){
1010 Heavy
.help(context
, replyTo
, toNonNull(Command
.SCREENCAP
));
1014 Heavy
.screencap(context
, replyTo
, args
[0]);
1018 Heavy
.torch(context
, replyTo
);
1022 if(args
.length
!= 3){
1023 Heavy
.help(context
, replyTo
, toNonNull(Command
.GETFILE
));
1027 final int getfilePort
;
1029 getfilePort
=Integer
.parseInt(args
[2]);
1030 } catch (NumberFormatException e
){
1031 sendMessage(context
, replyTo
, cannot_parse_port
);
1034 Heavy
.getfile(context
, replyTo
, toNonNull(args
[0]), toNonNull(args
[1]), getfilePort
);
1038 if(args
.length
== 0){
1039 Heavy
.help(context
, replyTo
, toNonNull(Command
.SH
));
1043 Heavy
.execute(context
, replyTo
, "sh", join(" ", args
));
1047 if(args
.length
== 0){
1048 Heavy
.help(context
, replyTo
, toNonNull(Command
.ROOTSH
));
1052 Heavy
.execute(context
, replyTo
, "su", join(" ", args
));
1059 * Executes a given command
1061 * @param context Context instance
1062 * @param cmd Command to execute
1063 * @param args arguments for the command
1064 * @param replyTo Address to send replies to
1066 public static void processCommand(final Context context
, final String cmd
,final String
[] args
,final Address replyTo
){
1067 final @NonNull Command command
;
1069 command
=toNonNull(Command
.valueOf(cmd
.toUpperCase(Locale
.ENGLISH
)));
1070 } catch (IllegalArgumentException e
){
1071 sendMessage(context
, replyTo
, unknown_command
, cmd
.toUpperCase(Locale
.ENGLISH
), e
.getMessage());
1076 processCommand(context
, command
,args
,replyTo
);
1077 } catch(Exception e
){
1078 sendMessage(context
, replyTo
, error_while_processing_command
, e
.getClass().getName(), e
.getMessage());
1079 Log
.w(Utils
.class.getName(), "Error while processing command", e
);