Don't call pollServer from a BroadcastRecevier
[fonbot.git] / src / ro / ieval / fonbot / Utils.java
CommitLineData
8dfb76c9
MG
1package ro.ieval.fonbot;
2
3import static ro.ieval.fonbot.R.string.cannot_parse_count;
4import static ro.ieval.fonbot.R.string.cannot_parse_interval;
5import static ro.ieval.fonbot.R.string.cannot_parse_min_distance;
6import static ro.ieval.fonbot.R.string.cannot_parse_min_time;
7import static ro.ieval.fonbot.R.string.cannot_parse_port;
8import static ro.ieval.fonbot.R.string.cannot_parse_provider_allowed_values_are;
9import static ro.ieval.fonbot.R.string.command_disabled;
10import static ro.ieval.fonbot.R.string.could_not_parse_argument_allowed_values_are;
11import static ro.ieval.fonbot.R.string.could_not_parse_ms;
12import static ro.ieval.fonbot.R.string.error_while_processing_command;
13import static ro.ieval.fonbot.R.string.invalid_length_allowed_values_are;
14import static ro.ieval.fonbot.R.string.invalid_ringer_mode_valid_values_are;
15import static ro.ieval.fonbot.R.string.location_tracking_is_active;
16import static ro.ieval.fonbot.R.string.messagetype_should_be_one_of;
17import static ro.ieval.fonbot.R.string.no_such_command_command_list;
18import static ro.ieval.fonbot.R.string.notification_disabled;
19import static ro.ieval.fonbot.R.string.notification_enabled;
20import static ro.ieval.fonbot.R.string.ringing;
21import static ro.ieval.fonbot.R.string.security_exception;
22import static ro.ieval.fonbot.R.string.the_polling_service_is_running;
23import static ro.ieval.fonbot.R.string.the_second_argument_to_wipe_must_be;
24import static ro.ieval.fonbot.R.string.unknown_command;
25import static ro.ieval.fonbot.R.string.wipetype_should_be_one_of;
26
a97d31fb
MG
27import java.net.MalformedURLException;
28import java.net.URL;
8dfb76c9
MG
29import java.util.Arrays;
30import java.util.Locale;
31
32import org.eclipse.jdt.annotation.NonNull;
33import org.eclipse.jdt.annotation.Nullable;
34
35import ro.ieval.fonbot.Address.Protocol;
36import android.content.Context;
37import android.content.Intent;
38import android.content.SharedPreferences;
39import android.database.Cursor;
40import android.location.LocationManager;
41import android.media.AudioManager;
42import android.net.Uri;
43import android.preference.PreferenceManager;
44import android.provider.ContactsContract.PhoneLookup;
45import android.telephony.SmsManager;
46import android.util.Log;
47import android.widget.Toast;
48
49/*
50 * Copyright © 2013 Marius Gavrilescu
51 *
52 * This file is part of FonBot.
53 *
54 * FonBot is free software: you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
56 * the Free Software Foundation, either version 3 of the License, or
57 * (at your option) any later version.
58 *
59 * FonBot is distributed in the hope that it will be useful,
60 * but WITHOUT ANY WARRANTY; without even the implied warranty of
61 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
62 * GNU General Public License for more details.
63 *
64 * You should have received a copy of the GNU General Public License
65 * along with FonBot. If not, see <http://www.gnu.org/licenses/>.
66 */
67
68/**
69 * Utility functions and enums used in various places.
70 *
71 * @author Marius Gavrilescu <marius@ieval.ro>
72 */
73public final class Utils {
74 /**
75 * Enum of all FonBot commands.
76 *
77 * @author Marius Gavrilescu <marius@ieval.ro>
78 */
79 @SuppressWarnings("javadoc")
80 public static enum Command{
81 TOAST, ECHO, SMS, FLASH, WIFI,
82 BLUETOOTH, DIAL, RING, SPEAK, VIBRATE,
83 DIALOG, LOCATION, NOLOCATION, RINGER, NCFILE,
84 PHOTO, SETNOTIFICATION, DELNOTIFICATION, SETPASSWORD, HELP,
85 WIPE, LOCK, VIEW, PLAY, PAUSE,
86 NEXT, PREV, BATT, CALLLOG, SMSLOG,
87 LS, RM, CONTACTS, DISABLE, ENABLE,
88 POLL, HANGUP, ANSWER, LAUNCH, DATA,
89 GPS, GLOCATION, REBOOT, SHUTDOWN, NOTIFY
90 }
91
92 /**
93 * 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.
94 *
95 * @author Marius Gavrilescu <marius@ieval.ro>
96 *
97 */
98 public static enum MessageType{
99 /** SMS notifications */
100 SMS,
101 /** Phone state (idle, offhook or ringing) notifications */
102 PHONE_STATE,
103 /** Lockscreen failed password notifications */
104 WATCH_LOGIN,
105 /** Device admin enable/disable notifications */
106 ADMIN,
107 /** Coarse battery status (low battery, ok battery) notifications */
108 BATTERY,
109 /** Fine battery status notifications */
110 BATTERY_CHANGED,
111 /** Headset plug/unplug notifications */
112 HEADSET
113 }
114
115 /**
116 * 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).
117 *
118 * @author Marius Gavrilescu <marius@ieval.ro>
119 */
120 public static enum WipeType{
121 /** Factory reset the phone, without touching the SD card */
122 DATA,
123 /** Factory reset the phone and wipe the SD card too */
124 FULL
125 }
126
127 /**
128 * Enum of ringer modes.
129 *
130 * @author Marius Gavrilescu <marius@ieval.ro>
131 */
132 public static enum RingerMode{
133 /** Sound is on */
134 NORMAL,
135 /** Sound is off, vibrate is on */
136 VIBRATE,
137 /** Sound is off, vibrate is off */
138 SILENT
139 }
140
141 /**
142 * Enum of location providers
143 *
144 * @author Marius Gavrilescu <marius@ieval.ro>
145 */
146 public static enum LocationProvider{
147 /** The network location provider */
148 NETWORK,
149 /** The GPS location provider */
150 GPS
151 }
152
153 /**
154 * Enum of toast lengths.
155 *
156 * @author Marius Gavrilescu <marius@ieval.ro>
157 */
158 private static enum ToastLength{
159 /** Long toast */
160 LONG,
161 /** Short toast */
162 SHORT
163 }
164
165 /**
166 * Enum of the values on and off. Used for boolean arguments.
167 *
168 * @author Marius Gavrilescu <marius@ieval.ro>
169 */
170 @SuppressWarnings("javadoc")
171 private static enum OnOff{
172 ON, OFF
173 }
174
175 /**
176 * Enum of ongoing event types
177 *
178 * @author Marius Gavrilescu <marius@ieval.ro>
179 */
180 public static enum OngoingEvent{
181 /** Location tracking is active. Registered by {@link Command#LOCATION}, unregistered by {@link Command#NOLOCATION} */
182 LOCATION(location_tracking_is_active),
183 /** The phone is ringing. Registered/unregistered by {@link Command#RING} */
184 RING(ringing),
185 /** The polling alarm is on. Registered/unregistered by {@link Command#POLL} */
186 POLL(the_polling_service_is_running);
187
188 /** String resource: the event description */
189 public final int resource;
190
191 /**
192 * Constructs an OngoingEvent from its event description.
193 *
194 * @param resource the event description
195 */
196 private OngoingEvent(final int resource) {
197 this.resource=resource;
198 }
199 }
200
201 /** Confirmation string for the {@link Command#WIPE WIPE} command. */
202 public static final String WIPE_CONFIRM_STRING="I am aware this cannot be undone";
203
204 /**
205 * Converts a Nullable object into a NonNull one.
206 *
207 * @param object the Nullable object to convert
208 * @return a NonNull object equivalent to the Nullable parameter
209 * @throws AssertionError if the given object is null
210 */
211 public static <T> T toNonNull(@Nullable T object) throws AssertionError{
212 if(object==null){
213 Log.wtf(Utils.class.getName(), "toNonNull called with null");
214 throw new AssertionError("Log.wtf did not terminate the process");
215 }
216 return object;
217 }
218
219 /**
220 * Join an array of Objects with elements separated by a separator into a single string.
221 *
222 * @param separator the separator
223 * @param offset the offset into the array
224 * @param args the array of Objects to join
225 * @return the joined string
226 */
227 public static String join(final String separator,final int offset,final Object[] args){
228 final StringBuilder sb=new StringBuilder(240);
229 sb.append(args[offset]);
230 for (int i = offset+1; i < args.length; i++) {
231 sb.append(separator);
232 sb.append(args[i]);
233 }
234 return toNonNull(sb.toString());
235 }
236
237 /**
238 * Join an array of Objects with elements separated by a separator into a single string.
239 *
240 * @param separator the separator
241 * @param args the array of objects to join
242 * @return the joined string
243 */
244 public static String join(final String separator, final Object[] args){
245 return join(separator,0,args);
246 }
247
248 /**
249 * Send a notification to the user.
250 *
251 * @param context Context instance
252 * @param type notification type
253 * @param resource String resource for the message text
254 */
255 public static void sendMessage(final Context context, final MessageType type, final int resource){
256 sendMessage(context, type, toNonNull(context.getString(resource)));
257 }
258
259 /**
260 * Send a notification to the user.
261 *
262 * @param context Context instance
263 * @param type notification type
264 * @param resource String resource for the message text
265 * @param args format parameters for the resource
266 */
267 public static void sendMessage(final Context context, final MessageType type, final int resource, final Object... args){
268 sendMessage(context, type, toNonNull(context.getString(resource, args)));
269 }
270
271 /**
272 * Send a message to a certain Address.
273 *
274 * @param context Context instance
275 * @param address destination Address
276 * @param resource String resource for the message text
277 */
278 public static void sendMessage(final Context context, final Address address, final int resource){
279 sendMessage(context, address, toNonNull(context.getString(resource)));
280 }
281
282 /**
283 * Send a message to a certain Address.
284 *
285 * @param context Context instance
286 * @param address destination Address
287 * @param resource String resource for the message text
288 * @param args format parameters for the resource
289 */
290 public static void sendMessage(final Context context, final Address address, final int resource, final Object... args){
291 sendMessage(context, address, toNonNull(context.getString(resource, args)));
292 }
293
294 /**
295 * Send a notification to the user.
296 *
297 * @param context Context instance
298 * @param type notification type
299 * @param msg the notification text
300 */
301 public static void sendMessage(final Context context, final MessageType type,final String msg){
302 final SharedPreferences sp=PreferenceManager.getDefaultSharedPreferences(context);
303 final String address=sp.getString(type.toString(),null);
304 if(address==null)
305 return;
306 sendMessage(context, new Address(address), msg);
307 }
308
309 /**
310 * Send a message to a certain Address.
311 *
312 * @param context Context instance
313 * @param address destination Address
314 * @param message the message text
315 */
316 public static void sendMessage(final Context context, final Address address, final String message){
317 switch(address.protocol){
318 case HTTP:
2e5049c9 319 new HttpCallExecutableRunnable("/send", toNonNull(Arrays.asList(
b26f32d6 320 new Header("X-Destination", toNonNull(address.data)))), context, null, true, message).execute();
8dfb76c9
MG
321 break;
322
323 case SMS:
324 SmsManager.getDefault().sendTextMessage(address.data, null, message, null, null);
325 break;
326
327 case LOCAL:
328 final Intent intent = new Intent(FonBotLocalActivity.RESPONSE_RECEIVED_ACTION);
329 intent.putExtra(FonBotLocalActivity.EXTRA_RESPONSE, message);
330 context.sendBroadcast(intent);
331 break;
332
333 case NULL:
334 break;//blackhole
335 }
336 }
337
8dfb76c9
MG
338 /**
339 * Splits a string into words.
340 *
341 * @param string the string
342 * @return an array of words
343 */
344 public static String[] shellwords(final String string){
345 return toNonNull(string.split("[ ]+(?=([^\"]*\"[^\"]*\")*[^\"]*$)"));//TODO: Make this handle backslash escapes
346 }
347
348 /**
349 * Returns the name associated with a phone number.
350 *
351 * @param context Context instance
352 * @param number phone number to search for
353 * @return the name associated with this number, or null if the number was not found in the contacts.
354 */
355 public static @Nullable String callerId(final Context context, final String number){
356 final Cursor cursor=context.getContentResolver().query(
357 Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)),
358 new String[]{PhoneLookup.DISPLAY_NAME},
359 null,
360 null,
361 null);
362
363 if(cursor.moveToFirst()){
364 final String name=cursor.getString(0);
365 cursor.close();
366 return name;
367 }
368 cursor.close();
369 return null;
370 }
371
372 /**
373 * Registers an ongoing event.
374 *
375 * @param context Context instance
376 * @param event event to register
377 */
378 public static void registerOngoing(final Context context, final OngoingEvent event){
379 final Intent intent=new Intent(context, FonBotMainService.class);
380 intent.setAction(FonBotMainService.ACTION_PUT_ONGOING);
381 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
382 context.startService(intent);
383 }
384
385 /**
386 * Unregisters an ongoing event
387 *
388 * @param context Context instance
389 * @param event event to unregister
390 */
391 public static void unregisterOngoing(final Context context, final OngoingEvent event){
392 final Intent intent=new Intent(context, FonBotMainService.class);
393 intent.setAction(FonBotMainService.ACTION_DELETE_ONGOING);
394 intent.putExtra(FonBotMainService.EXTRA_ONGOING_ID, event.ordinal());
395 context.startService(intent);
396 }
397
a97d31fb
MG
398 /**
399 * Gets the server URL according to the user preferences.
400 *
401 * @param context Context instance
402 * @param path URL path
403 * @return the server URL
404 * @throws MalformedURLException if the user preferences create an invalid URL
405 */
406 public static URL getServerURL(final Context context, final String path) throws MalformedURLException{
9717b83e 407 final String hostname=PreferenceManager.getDefaultSharedPreferences(context).getString("hostname", "fonbot.ieval.ro");
a97d31fb 408 final int port=Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(context).getString("port", "7777"));
9717b83e 409 final URL url=new URL("https", hostname, port, path);
a97d31fb
MG
410 return url;
411 }
412
2e5049c9 413 /**
6b9507db 414 * Poll the server for pending commands. This function must not be called from BroadcastReceivers
2e5049c9
MG
415 *
416 * @param context Context instance
417 */
418 public static void pollServer(final Context context){
b26f32d6 419 new HttpCallExecutableRunnable("/get", null, context, new PollResultCallback(context), false).execute();
2e5049c9
MG
420 }
421
6b9507db
MG
422 /**
423 * Poll the server for pending commands from {@link FonBotMainService}. This function should be used from BroadcastReceviers instead of {@link #pollServer}
424 *
425 * @param context Context instance
426 */
427 public static void safePollServer(final Context context){
428 final Intent intent=new Intent(context, FonBotMainService.class);
429 intent.setAction(FonBotMainService.ACTION_TRIGGER_POLL);
430 context.startService(intent);
431 }
8dfb76c9
MG
432 /**
433 * Executes a given command
434 *
435 * @param context Context instance
436 * @param cmd Command to execute
437 * @param args arguments for the command
438 * @param replyTo Address to send replies to
439 */
440 private static void processCommand(final Context context, final Command cmd,final String[] args,final Address replyTo){
441 if(Heavy.isCommandDisabled(context, cmd)){
442 sendMessage(context, replyTo, command_disabled);
443 return;
444 }
445
446 switch(cmd){
447 case TOAST:
448 if(args.length < 1 || args.length > 2){
449 Heavy.help(context, replyTo, toNonNull(Command.TOAST));
450 break;
451 }
452
453 if(args.length==1)
454 Heavy.toast(context, replyTo, toNonNull(args[0]));
455 else {
456 try {
457 switch(ToastLength.valueOf(args[1].toUpperCase(Locale.ENGLISH))){
458 case LONG:
459 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_LONG);
460 break;
461 case SHORT:
462 Heavy.toast(context, replyTo, toNonNull(args[0]), Toast.LENGTH_SHORT);
463 }
464 } catch(IllegalArgumentException e){
465 sendMessage(context, replyTo, invalid_length_allowed_values_are, join(", ",toNonNull(ToastLength.values())));
466 }
467 }
468 break;
469
470 case ECHO:
471 if(args.length==0){
472 Heavy.help(context, replyTo, toNonNull(Command.ECHO));
473 break;
474 }
475 sendMessage(context, replyTo, join(" ",args));
476 break;
477
478 case SMS:
479 if(args.length < 2){
480 Heavy.help(context, replyTo, toNonNull(Command.SMS));
481 break;
482 }
483 Heavy.sms(context, replyTo, toNonNull(args[0]), join(" ", 1, args));
484 break;
485
486 case FLASH:
487 if(args.length != 1){
488 Heavy.help(context, replyTo, toNonNull(Command.FLASH));
489 break;
490 }
491
492 try {
493 Heavy.flash(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
494 } catch(IllegalArgumentException e) {
495 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
496 }
497 break;
498
499 case WIFI:
500 if(args.length>1){
501 Heavy.help(context, replyTo, toNonNull(Command.WIFI));
502 break;
503 }
504 if(args.length==0)
505 Heavy.wifi(context, replyTo);
506 else {
507 try {
508 Heavy.wifi(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
509 } catch(IllegalArgumentException e) {
510 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
511 }
512 }
513 break;
514
515 case BLUETOOTH:
516 if(args.length>1){
517 Heavy.help(context, replyTo, toNonNull(Command.BLUETOOTH));
518 break;
519 }
520 if(args.length==0)
521 Heavy.bluetooth(context, replyTo);
522 else {
523 try {
524 Heavy.bluetooth(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
525 } catch(IllegalArgumentException e) {
526 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
527 }
528 }
529 break;
530
531 case DIAL:
532 if(args.length!=1){
533 Heavy.help(context, replyTo, toNonNull(Command.DIAL));
534 break;
535 }
536 Heavy.dial(context, replyTo, toNonNull(args[0]));
537 break;
538
539 case RING:
540 if(args.length>1){
541 Heavy.help(context, replyTo, toNonNull(Command.RING));
542 break;
543 }
544 if(args.length==0)
545 Heavy.ring(context, replyTo);
546 else {
547 try {
548 Heavy.ring(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
549 } catch(IllegalArgumentException e){
550 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
551 }
552 }
553 break;
554
555 case SPEAK:
556 if(args.length==0){
557 Heavy.help(context, replyTo, toNonNull(Command.SPEAK));
558 break;
559 }
560 Heavy.speak(context, replyTo, join(" ",args));
561 break;
562
563 case VIBRATE:
564 if(args.length!=1){
565 Heavy.help(context, replyTo, toNonNull(Command.VIBRATE));
566 break;
567 }
568 final long ms;
569 try{
570 ms=Long.parseLong(args[0]);
571 } catch(NumberFormatException e){
572 sendMessage(context, replyTo, could_not_parse_ms);
573 break;
574 }
575 Heavy.vibrate(context, replyTo, ms);
576 break;
577
578 case DIALOG://TODO: Should add an edittext
579 if(args.length<1){
580 Heavy.help(context, replyTo, toNonNull(Command.DIALOG));
581 break;
582 }
583 final String[] buttons=new String[args.length-1];
584 System.arraycopy(args,1,buttons,0,buttons.length);
585 Heavy.dialog(context, replyTo, toNonNull(args[0]), buttons);
586 break;
587
588 case LOCATION:
589 if(args.length>3||args.length<1){
590 Heavy.help(context, replyTo, toNonNull(Command.LOCATION));
591 break;
592 }
593
594 final @NonNull String provider;
595 try{
596 switch(LocationProvider.valueOf(args[0].toUpperCase(Locale.ENGLISH))){
597 case GPS:
598 provider=toNonNull(LocationManager.GPS_PROVIDER);
599 break;
600 case NETWORK:
601 default:
602 provider=toNonNull(LocationManager.NETWORK_PROVIDER);
603 break;
604 }
605 } catch(IllegalArgumentException e){
606 sendMessage(context, replyTo, cannot_parse_provider_allowed_values_are, join(", ",toNonNull(LocationProvider.values())));
607 break;
608 }
609
610 final long minTime;
611 final float minDistance;
612
613 if(args.length>1)
614 try{
615 minTime=Long.parseLong(args[1]);
616 } catch (NumberFormatException e){
617 sendMessage(context, replyTo, cannot_parse_min_time);
618 break;
619 }
620 else
621 minTime=500;
622
623 if(args.length>2)
624 try{
625 minDistance=Float.parseFloat(args[2]);
626 } catch (NumberFormatException e){
627 sendMessage(context, replyTo, cannot_parse_min_distance);
628 break;
629 }
630 else
631 minDistance=0;
632 Heavy.location(context, replyTo, provider, minTime, minDistance);
633 break;
634
635 case NOLOCATION:
636 Heavy.nolocation(context, replyTo);
637 break;
638
639 case RINGER:
640 if(args.length>1){
641 Heavy.help(context, replyTo, toNonNull(Command.RINGER));
642 break;
643 }
644 if(args.length==0)
645 Heavy.ringer(context, replyTo);
646 else{
647 try{
648 final RingerMode rm=RingerMode.valueOf(args[0].toUpperCase(Locale.ENGLISH));
649 switch(rm){
650 case NORMAL:
651 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_NORMAL);
652 break;
653 case VIBRATE:
654 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_VIBRATE);
655 break;
656 case SILENT:
657 Heavy.ringer(context, replyTo, AudioManager.RINGER_MODE_SILENT);
658 break;
659 }
660 } catch (IllegalArgumentException e){
661 Utils.sendMessage(context, replyTo, invalid_ringer_mode_valid_values_are, join(", ",toNonNull(RingerMode.values())));
662 }
663 }
664 break;
665
666 case NCFILE:
667 if(args.length!=3){
668 Heavy.help(context, replyTo, toNonNull(Command.NCFILE));
669 break;
670 }
671
672 final int ncfilePort;
673 try{
674 ncfilePort=Integer.parseInt(args[2]);
675 } catch (NumberFormatException e){
676 sendMessage(context, replyTo, cannot_parse_port);
677 break;
678 }
679 Heavy.ncfile(context, replyTo, toNonNull(args[0]), toNonNull(args[1]), ncfilePort);
680 break;
681
682 case PHOTO:
683 if(args.length!=2){
684 Heavy.help(context, replyTo, toNonNull(Command.PHOTO));
685 break;
686 }
687 final int photoPort;
688 try{
689 photoPort=Integer.parseInt(args[1]);
690 } catch (NumberFormatException e){
691 sendMessage(context, replyTo, cannot_parse_port);
692 break;
693 }
694 Heavy.photo(context, replyTo, toNonNull(args[0]), photoPort);
695 break;
696
697 case SETNOTIFICATION:
698 if(args.length!=1){
699 Heavy.help(context, replyTo, toNonNull(Command.SETNOTIFICATION));
700 break;
701 }
702
703 try{
704 PreferenceManager.getDefaultSharedPreferences(context).edit()
705 .putString(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString(), replyTo.toString())
706 .commit();
707 sendMessage(context, replyTo, notification_enabled);
708 } catch (IllegalArgumentException e){
709 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
710 break;
711 }
712
713 break;
714
715 case DELNOTIFICATION:
716 if(args.length!=1){
717 Heavy.help(context, replyTo, toNonNull(Command.DELNOTIFICATION));
718 break;
719 }
720
721 try{
722 PreferenceManager.getDefaultSharedPreferences(context).edit()
723 .remove(MessageType.valueOf(args[0].toUpperCase(Locale.ENGLISH)).toString())
724 .commit();
725 sendMessage(context, replyTo, notification_disabled);
726 } catch (IllegalArgumentException e){
727 sendMessage(context, replyTo, messagetype_should_be_one_of, join(", ",toNonNull(MessageType.values())));
728 break;
729 }
730
731
732 break;
733 case SETPASSWORD:
734 if(args.length > 1){
735 Heavy.help(context, replyTo, toNonNull(Command.SETPASSWORD));
736 break;
737 }
738
739 try{
740 if(args.length==0)
741 Heavy.setPassword(context, replyTo);
742 else
743 Heavy.setPassword(context, replyTo, toNonNull(args[0]));
744 } catch (SecurityException e){
745 sendMessage(context, replyTo, security_exception+e.getMessage());
746 }
747 break;
748
749 case WIPE:
750 if(args.length!=2){
751 Heavy.help(context, replyTo, toNonNull(Command.WIPE));
752 break;
753 }
754
755 if(!args[1].equalsIgnoreCase(WIPE_CONFIRM_STRING)){
756 sendMessage(context, replyTo, the_second_argument_to_wipe_must_be, WIPE_CONFIRM_STRING);
757 break;
758 }
759
760 try{
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());
766 }
767 break;
768
769 case LOCK:
770 try{
771 Heavy.lock(context, replyTo);
772 } catch (SecurityException e){
773 sendMessage(context, replyTo, security_exception, e.getMessage());
774 }
775 break;
776
777 case VIEW:
778 if(args.length!=1){
779 Heavy.help(context, replyTo, toNonNull(Command.VIEW));
780 break;
781 }
782
783 Heavy.view(context, replyTo, toNonNull(Uri.parse(args[0])));
784 break;
785
786 case PLAY:
787 Heavy.musicPlayerCommand(context, replyTo, "play");
788 break;
789
790 case PAUSE:
791 Heavy.musicPlayerCommand(context, replyTo, "pause");
792 break;
793
794 case NEXT:
795 Heavy.musicPlayerCommand(context, replyTo, "next");
796 break;
797
798 case PREV:
799 Heavy.musicPlayerCommand(context, replyTo, "previous");
800 break;
801
802 case BATT:
803 Heavy.batt(context, replyTo);
804 break;
805
806 case CALLLOG:
807 if (args.length > 1) {
808 Heavy.help(context, replyTo, toNonNull(Command.CALLLOG));
809 break;
810 }
811
812 if (args.length == 0)
813 Heavy.calllog(context, replyTo, 5);
814 else {
815 try {
816 Heavy.calllog(context, replyTo, Integer.parseInt(args[0]));
817 } catch (IllegalArgumentException e){
818 sendMessage(context, replyTo, cannot_parse_count);
819 }
820 }
821 break;
822
823 case SMSLOG:
824 if (args.length > 1) {
825 Heavy.help(context, replyTo, toNonNull(Command.SMSLOG));
826 break;
827 }
828
829 if (args.length == 0)
830 Heavy.smslog(context, replyTo, 5);
831 else {
832 try {
833 Heavy.smslog(context, replyTo, Integer.parseInt(args[0]));
834 } catch (IllegalArgumentException e) {
835 sendMessage(context, replyTo, cannot_parse_count);
836 }
837 }
838 break;
839
840 case HELP:
841 if(args.length != 1){
842 Heavy.help(context, replyTo, toNonNull(Command.HELP));
843 break;
844 }
845
846 try {
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())));
850 }
851 break;
852
853 case LS:
854 if(args.length != 1){
855 Heavy.help(context, replyTo, toNonNull(Command.LS));
856 break;
857 }
858
859 Heavy.ls(context, replyTo, toNonNull(args[0]));
860 break;
861
862 case RM:
863 if(args.length != 1){
864 Heavy.help(context, replyTo, toNonNull(Command.RM));
865 break;
866 }
867
868 Heavy.rm(context, replyTo, toNonNull(args[0]));
869 break;
870
871 case CONTACTS:
872 if(args.length != 1){
873 Heavy.help(context, replyTo, toNonNull(Command.CONTACTS));
874 break;
875 }
876
877 Heavy.contacts(context, replyTo, toNonNull(args[0]));
878 break;
879
880 case DISABLE:
881 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
882 Heavy.help(context, replyTo, toNonNull(Command.DISABLE));
883 break;
884 }
885
886 try{
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())));
890 }
891 break;
892
893 case ENABLE:
894 if(replyTo.protocol != Protocol.LOCAL || args.length != 1){
895 Heavy.help(context, replyTo, toNonNull(Command.ENABLE));
896 break;
897 }
898
899 try{
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())));
903 }
904 break;
905
906 case POLL:
907 if(args.length>1){
908 Heavy.help(context, replyTo, toNonNull(Command.POLL));
909 break;
910 }
911
912 if(args.length==0){
913 Heavy.poll(context, replyTo);
914 break;
915 }
916
917 final long interval;
918 try{
919 interval=Long.parseLong(args[0]);
920 } catch(NumberFormatException e){
921 sendMessage(context, replyTo, cannot_parse_interval);
922 break;
923 }
924
925 Heavy.poll(context, replyTo, interval);
926 break;
927
928 case HANGUP:
929 Heavy.hangup(context, replyTo);
930 break;
931
932 case ANSWER:
933 Heavy.answer(context, replyTo);
934 break;
935
936 case LAUNCH:
937 if(args.length!=1){
938 Heavy.help(context, replyTo, toNonNull(Command.LAUNCH));
939 break;
940 }
941 Heavy.launch(context, replyTo, toNonNull(args[0]));
942 break;
943
944 case DATA:
945 if(args.length>1){
946 Heavy.help(context, replyTo, toNonNull(Command.DATA));
947 break;
948 }
949
950 if(args.length==0){
951 Heavy.data(context, replyTo);
952 break;
953 }
954 try {
955 Heavy.data(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())));
958 }
959 break;
960
961 case GPS:
962 if(args.length>1){
963 Heavy.help(context, replyTo, toNonNull(Command.GPS));
964 break;
965 }
966
967 if(args.length==0){
968 Heavy.gps(context, replyTo);
969 break;
970 }
971
972 try {
973 Heavy.gps(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())));
976 }
977 break;
978
979 case GLOCATION:
980 if(args.length>1){
981 Heavy.help(context, replyTo, toNonNull(Command.GLOCATION));
982 break;
983 }
984
985 if(args.length==0){
986 Heavy.glocation(context, replyTo);
987 break;
988 }
989
990 try {
991 Heavy.glocation(context, replyTo, OnOff.valueOf(args[0].toUpperCase(Locale.ENGLISH)) == OnOff.ON);
992 } catch(IllegalArgumentException e) {
993 sendMessage(context, replyTo, could_not_parse_argument_allowed_values_are, join(", ", toNonNull(OnOff.values())));
994 }
995 break;
996
997 case REBOOT:
998 if(args.length>1){
999 Heavy.help(context, replyTo, toNonNull(Command.REBOOT));
1000 break;
1001 }
1002
1003 Heavy.reboot(context, replyTo, args.length==0?null:args[0]);
1004 break;
1005
1006 case SHUTDOWN:
1007 //TODO: implement command
1008 break;
1009
1010 case NOTIFY:
1011 if(args.length!=1 && args.length!=3){
1012 Heavy.help(context, replyTo, toNonNull(Command.NOTIFY));
1013 }
1014
1015 final int id;
1016 try{
1017 id=Integer.parseInt(args[0]);
1018 } catch (NumberFormatException e){
1019 sendMessage(context, replyTo, R.string.could_not_parse_id);
1020 break;
1021 }
1022
1023 if(args.length==1)
1024 Heavy.notify(context, replyTo, id);
1025 else
1026 Heavy.notify(context, replyTo, id, toNonNull(args[1]), toNonNull(args[2]));
1027 break;
1028 }
1029
1030 }
1031
1032 /**
1033 * Executes a given command
1034 *
1035 * @param context Context instance
1036 * @param cmd Command to execute
1037 * @param args arguments for the command
1038 * @param replyTo Address to send replies to
1039 */
1040 public static void processCommand(final Context context, final String cmd,final String[] args,final Address replyTo){
1041 final @NonNull Command command;
1042 try{
1043 command=toNonNull(Command.valueOf(cmd.toUpperCase(Locale.ENGLISH)));
1044 } catch (IllegalArgumentException e){
1045 sendMessage(context, replyTo, unknown_command, cmd.toUpperCase(Locale.ENGLISH), e.getMessage());
1046 return;
1047 }
1048
1049 try{
1050 processCommand(context, command,args,replyTo);
1051 } catch(Exception e){
1052 sendMessage(context, replyTo, error_while_processing_command, e.getClass().getName(), e.getMessage());
1053 Log.w(Utils.class.getName(), "Error while processing command", e);
1054 }
1055 }
1056}
This page took 0.068945 seconds and 4 git commands to generate.