Do not connect to server when user/pass is missing
[fonbot.git] / src / ro / ieval / fonbot / FonBotMainService.java
index a751d231c434173188b16dcd6a6037273eb83430..5508557d749fcc5699312dbc54e2e1144710acf0 100644 (file)
@@ -3,12 +3,16 @@ package ro.ieval.fonbot;
 import static ro.ieval.fonbot.R.string.*;
 import static ro.ieval.fonbot.Utils.toNonNull;
 
+import java.net.SocketTimeoutException;
 import java.util.Collections;
-import java.util.HashSet;
+import java.util.EnumSet;
 import java.util.Set;
 
+import javax.net.ssl.SSLException;
+
 import org.eclipse.jdt.annotation.Nullable;
 
+import ro.ieval.fonbot.Address.Protocol;
 import ro.ieval.fonbot.Utils.OngoingEvent;
 
 import android.app.Notification;
@@ -17,10 +21,12 @@ import android.app.PendingIntent;
 import android.app.Service;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.ConnectivityManager;
 import android.os.IBinder;
 import android.preference.PreferenceManager;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.content.LocalBroadcastManager;
+import android.util.Log;
 
 /*
  * Copyright © 2013 Marius Gavrilescu
@@ -62,6 +68,32 @@ public final class FonBotMainService extends Service {
                }
        }
 
+       /**
+        * Runnable that continously long polls the server for commands
+        *
+        * @author Marius Gavrilescu <marius@ieval.ro>
+        */
+       private final class LongPollRunnable implements Runnable{
+               public void run(){
+                       final ConnectivityManager man=(ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
+                       final HttpCallExecutableRunnable runnable=new HttpCallExecutableRunnable("/get", null, FonBotMainService.this, new PollResultCallback(FonBotMainService.this), false);
+
+                       Log.d("LongPollRunnable", "Long polling started");
+                       while(man.getActiveNetworkInfo() != null && man.getActiveNetworkInfo().isConnected())
+                               try {
+                                       runnable.doRun();
+                               } catch (final SocketTimeoutException e){
+                                       Log.d("LongPollRunnable", "Socket timeout, refreshing connection");
+                               } catch (final SSLException e){
+                                       Log.d("LongPollRunnable", "Got SSLException, refreshing connection");
+                               } catch (final Exception ex){
+                                       ex.printStackTrace();
+                                       break;
+                               }
+                       Log.d("LongPollRunnable", "Long polling stopped");
+               }
+       }
+
        /**
         * Broadcast action: add an ongoing event
         */
@@ -70,6 +102,22 @@ public final class FonBotMainService extends Service {
         * Broadcast action: remove an ongoing event
         */
        public static final String ACTION_DELETE_ONGOING="ro.ieval.fonbot.FonBotMainService.ACTION_DELETE_ONGOING";
+
+       /**
+        * Broadcast action: process a command received via SMS
+        */
+       public static final String ACTION_PROCESS_COMMAND="ro.ieval.fonbot.FonBotMainService.ACTION_PROCESS_COMMAND";
+
+       /**
+        * Extra: command line
+        */
+       public static final String EXTRA_COMMAND_LINE="ro.ieval.fonbot.FonBotMainService.EXTRA_COMMAND_LINE";
+
+       /**
+        * Extra: SMS originating address
+        */
+       public static final String EXTRA_SMS_ORIGIN_ADDRESS="ro.ieval.fonbot.FonBotMainService.EXTRA_SMS_ORIGIN_ADDRESS";
+
        /**
         * Extra: ongoing event id
         *
@@ -88,7 +136,6 @@ public final class FonBotMainService extends Service {
        private static final IntentFilter DYNAMIC_BROADCAST_FILTER=new IntentFilter();
 
        static{
-               DYNAMIC_BROADCAST_FILTER.addAction(Intent.ACTION_SCREEN_ON);
                DYNAMIC_BROADCAST_FILTER.addAction(Intent.ACTION_BATTERY_CHANGED);
                DYNAMIC_BROADCAST_FILTER.addAction(Intent.ACTION_HEADSET_PLUG);
        }
@@ -100,7 +147,13 @@ public final class FonBotMainService extends Service {
        /**
         * Set of ongoing events.
         */
-       private final Set<OngoingEvent> ongoing=new HashSet<OngoingEvent>(10);
+       private final Set<OngoingEvent> ongoing=EnumSet.noneOf(OngoingEvent.class);
+
+       /** true if running in foreground, false otherwise */
+       private boolean isForeground = false;
+
+       /** Thread that runs a {@link LongPollRunnable} */
+       private Thread longPollThread;
 
        /**
         * Get the set of ongoing events.
@@ -130,20 +183,46 @@ public final class FonBotMainService extends Service {
 
        @Override
        public int onStartCommand(final @Nullable Intent intent, final int flags, final int startId) {
-               if(intent!=null && intent.getAction()==ACTION_PUT_ONGOING && intent.hasExtra(EXTRA_ONGOING_ID)){
+               final boolean showOngoing=PreferenceManager.getDefaultSharedPreferences(this).getBoolean("ongoing", false);
+               boolean updateNotification = false;
+               if(intent!=null && intent.getAction()==ACTION_PUT_ONGOING && intent.hasExtra(EXTRA_ONGOING_ID) && showOngoing){
                        ongoing.add(OngoingEvent.values()[intent.getIntExtra(EXTRA_ONGOING_ID, 0)]);
                        LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(ACTION_ONGOING_UPDATE));
+                       updateNotification=true;
                }
-               if(intent!=null && intent.getAction()==ACTION_DELETE_ONGOING && intent.hasExtra(EXTRA_ONGOING_ID)){
+               if(intent!=null && intent.getAction()==ACTION_DELETE_ONGOING && intent.hasExtra(EXTRA_ONGOING_ID) && showOngoing){
                        ongoing.remove(OngoingEvent.values()[intent.getIntExtra(EXTRA_ONGOING_ID, 0)]);
                        LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(ACTION_ONGOING_UPDATE));
+                       updateNotification=true;
                }
+               if(intent!=null && intent.getAction()==ACTION_PROCESS_COMMAND) {
+                       final String cmdline = intent.getStringExtra(EXTRA_COMMAND_LINE);
+                       final String origin  = intent.getStringExtra(EXTRA_SMS_ORIGIN_ADDRESS);
+                       final Address address= new Address(toNonNull(Protocol.SMS), origin);//NOPMD variable depends on originAddress
+                       final String[] words=Utils.shellwords(toNonNull(cmdline));
+                       final String[] args=new String[words.length-1];//NOPMD variable size depends on words.length
+                       System.arraycopy(words, 1, args, 0, args.length);
+
+                       Utils.processCommand(this, toNonNull(words[0]), args, toNonNull(address));
+               }
+
+               final String user=PreferenceManager.getDefaultSharedPreferences(this).getString("username", null);
+               final String password=PreferenceManager.getDefaultSharedPreferences(this).getString("password", null);
+               final boolean has_user_pass = user != null && password != null && user.length() > 0 && password.length() > 0;
+               if((longPollThread == null || !longPollThread.isAlive()) && has_user_pass){
+                       longPollThread = new Thread(new LongPollRunnable());
+                       longPollThread.start();
+               }
+
+               ExecutableRunnable.retryTasks();
 
                final boolean runForeground=PreferenceManager.getDefaultSharedPreferences(this).getBoolean("foreground", false);
                if(!runForeground)
                        stopForeground(true);
 
-               if(runForeground||!ongoing.isEmpty()){
+               final NotificationManager man=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+               final boolean shouldNotify=runForeground||!ongoing.isEmpty();
+               if(shouldNotify && (updateNotification || runForeground != isForeground)){
                        final Intent mainIntent=new Intent(this, FonBotMainActivity.class);
                        mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        final NotificationCompat.Builder builder=new NotificationCompat.Builder(this).
@@ -154,26 +233,24 @@ public final class FonBotMainService extends Service {
                                        setContentIntent(PendingIntent.getActivity(this, 0, mainIntent, 0)).
                                        setOngoing(true);
 
-                       final Notification notification;
-                       if(ongoing.isEmpty())
-                               notification=builder.build();
-                       else {
+                       if(showOngoing && !ongoing.isEmpty()) {
                                final NotificationCompat.InboxStyle inboxBuilder=new NotificationCompat.InboxStyle(builder);
 
                                for(final OngoingEvent event : ongoing)
                                        inboxBuilder.addLine(getString(event.resource));
 
-                               notification=inboxBuilder.build();
                        }
+                       final Notification notification=builder.build();
 
                        if(runForeground)
-                               startForeground(1337, builder.build());
-                       else{
-                               final NotificationManager man=(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
+                               startForeground(1337, notification);
+                       else
                                man.notify(1337, notification);
-                       }
                }
 
+               if(!shouldNotify)
+                       man.cancel(1337);
+               isForeground=runForeground;
                return START_STICKY;
        }
 }
This page took 0.013708 seconds and 4 git commands to generate.