/* * Copyright (c) 2013-2015 Marco Ziccardi, Luca Bonato * Licensed under the MIT license. */ package me.ziccard.secureit.service; import me.ziccard.secureit.MonitorActivity; import me.ziccard.secureit.R; import me.ziccard.secureit.SecureItPreferences; import me.ziccard.secureit.async.MicrophoneTaskFactory; import me.ziccard.secureit.async.BluetoothServerTask; import me.ziccard.secureit.async.MicrophoneTaskFactory.RecordLimitExceeded; import me.ziccard.secureit.async.BluetoothServerTask.NoBluetoothException; import me.ziccard.secureit.async.upload.BluetoothPeriodicPositionUploaderTask; import me.ziccard.secureit.async.upload.ImagesUploaderTask; import me.ziccard.secureit.async.upload.PeriodicPositionUploaderTask; import android.annotation.SuppressLint; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.AsyncTask; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.telephony.SmsManager; import android.util.Log; import android.widget.Toast; @SuppressLint("HandlerLeak") public class UploadService extends Service { /** * Task used to upload position, is periodic, when we close the app * we need to stop the service and that task */ private AsyncTask<Void, Void, Void> positionTask = null; /** * To show a notification on service start */ private NotificationManager manager; /** * Acceleration detected message */ public static final int ACCELEROMETER_MESSAGE = 0; /** * Camera motion detected message */ public static final int CAMERA_MESSAGE = 1; /** * Mic noise detected message */ public static final int MICROPHONE_MESSAGE = 2; /** * True only if service has been alerted by the accelerometer */ private boolean already_alerted; /** * Object used to retrieve shared preferences */ private SecureItPreferences prefs = null; /** * Handler for incoming messages */ class MessageHandler extends Handler { @Override public void handleMessage(Message msg) { alert(msg.what); } } /** * Messenger interface used by clients to interact */ private final Messenger messenger = new Messenger(new MessageHandler()); /** * Called on service creation, sends a notification */ @Override public void onCreate() { manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); prefs = new SecureItPreferences(this); try { new BluetoothServerTask(this).start(); } catch (NoBluetoothException e) { Log.i("UploadService", "Background bluetooth server not started"); CharSequence text = "Background bluetooth server not started"; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(this, text, duration); toast.show(); } showNotification(); } /** * Called on service destroy, cancels persistent notification * and shows a toast */ @Override public void onDestroy() { // Cancel the persistent notification. manager.cancel(R.string.secure_service_started); if (positionTask!=null && !positionTask.isCancelled()) { positionTask.cancel(true); } // Tell the user we stopped. Toast.makeText(this, R.string.secure_service_stopped, Toast.LENGTH_SHORT).show(); } /** * When binding to the service, we return an interface to our messenger * for sending messages to the service. */ @Override public IBinder onBind(Intent intent) { return messenger.getBinder(); } /** * Show a notification while this service is running. */ @SuppressWarnings("deprecation") private void showNotification() { Intent toLaunch = new Intent(getApplicationContext(), MonitorActivity.class); toLaunch.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |Intent.FLAG_ACTIVITY_REORDER_TO_FRONT |Intent.FLAG_ACTIVITY_NEW_TASK); // In this sample, we'll use the same text for the ticker and the expanded notification CharSequence text = getText(R.string.secure_service_started); Notification notification = new Notification(R.drawable.ic_launcher, text, System.currentTimeMillis()); // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, toLaunch, PendingIntent.FLAG_UPDATE_CURRENT); notification.setLatestEventInfo(this, "SecureService", text, contentIntent); // Send the notification. // We use a string id because it is a unique number. We use it later to cancel. manager.notify(R.string.secure_service_started, notification); } /** * Sends an alert according to type of connectivity */ private void alert(int alertType) { /* * If we have already received an alert */ if (already_alerted) return; /* * Alse we set an alert has bee received */ already_alerted = true; /* * If remote communication with SecureIt back-end is required we * need to check the type of connectivity */ if (prefs.getRemoteActivation()) { ConnectivityManager cm = (ConnectivityManager)this.getSystemService(Context.CONNECTIVITY_SERVICE); boolean isConnected = false; boolean isWifi = false; NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); if (activeNetwork != null) { isConnected = activeNetwork.isConnectedOrConnecting(); isWifi = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI; } // Phone is connected if (isConnected) { int connectivityType = ImagesUploaderTask.NO_CONNECTIVITY; // through wireless if (isWifi) { CharSequence text = "WIFI: sending a lot of data"; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(this, text, duration); toast.show(); connectivityType = ImagesUploaderTask.WIFI_CONNECTIVITY; // through 3G } else { CharSequence text = "3G: sending a little of data"; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(this, text, duration); toast.show(); connectivityType = ImagesUploaderTask.MOBILE_CONNECTIVITY; } /* * Image uploader task according to connectivity type */ (new ImagesUploaderTask(this, connectivityType)).execute(); /* * Audio recorder and uploader task */ try { MicrophoneTaskFactory.makeRecorder(this).start(); } catch (RecordLimitExceeded e) { Log.e("UploadService", "An audio is being uploaded"); } /* * Periodic position uploader task */ positionTask = new PeriodicPositionUploaderTask(this); positionTask.execute(); } else { CharSequence text = "NO CONNECTIVITY: sending a bluetooth alert"; int duration = Toast.LENGTH_SHORT; Toast toast = Toast.makeText(this, text, duration); toast.show(); positionTask = new BluetoothPeriodicPositionUploaderTask(this); positionTask.execute(); } } /* * If SMS mode is on we send an SMS alert to the specified * number */ if (prefs.getSmsActivation()) { //get the manager SmsManager manager = SmsManager.getDefault(); manager.sendTextMessage(prefs.getSmsNumber(), null, prefs.getSMSText(), null, null); } } }