diff --git a/CHANGELOG b/CHANGELOG index 38b8599f..4cd1387c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,60 @@ +/** 0.1.0 beta 8 build 108 / 18 January 2017 / fa3d445584fb29d4fd227c84a58274c48a5339aa **/ + +fa3d445 update to build 108 (beta 8) +3a438ee for #137 #211 ensure MonitorActivity state is in sync with MonitorService - this allows you to leave and re-exit the monitor activity with bg service still running - this should also improve cases where activity crases but monitoservice is still live +e206c56 show the localized "password" in web interface +ded33f2 for #162, implement pause/resume handling of camera preview +a58f7ed more on #111 to keep screen on, to keep camera active +d3ef157 if running, don't update string with timer message +a8ef1cc work on #111 disable battery opt to allow full background mode +c7d694b update localizations from transifex +2373f2a add camera sensitivity config to onboarding +985f14e update camera sensitivty config UI +e54a6ee for #213 re-implemented time windows for notifications +47395d9 initial work on camera sensitivity config #146 #85 #212 +52f9627 require a password for the web server +72b03f4 Merge branch 'mig5-192_use_Save_message_for_remote_number' +0d1fc97 Merge branch '192_use_Save_message_for_remote_number' of https://github.com/mig5/haven into mig5-192_use_Save_message_for_remote_number +ee6aade Merge branch 'christxph-ck/ui-improvements' +e49a3ee Merge branch 'ck/ui-improvements' of https://github.com/christxph/haven into christxph-ck/ui-improvements +69e7fc6 Merge branch 'percy-g2-bug-fix' +ee0f2fe Darken overlay by 5% +7fb8940 Add Toolbar back button in EventActivity +e84ccc6 Add semi-transparent overlay to camera preview to improve text/icon readability +07b8940 Replace png icons with VectorDrawables +6e24045 Force transparent background because API<=16 defaults to a black one +53d0418 Fix camera images can be upside down from rare camera. +1baf43d Merge pull request #4 from guardianproject/master +913b893 Merge branch 'percy-g2-settings-p2' +e7fa68e Merge branch 'settings-p2' of https://github.com/percy-g2/haven into percy-g2-settings-p2 +9e1ef72 Merge branch 'percy-g2-settings-p1' +d3ff765 don't require touchscreens (support chromebooks, RPi's, TVs) +0071417 Merge branch 'settings-p1' of https://github.com/percy-g2/haven into percy-g2-settings-p1 +f166f34 fix marking of not required features to support tablets +78d6196 Merge branch 'fat-tire-misc_small_fixes' +e21f837 re-enable password masking +81db4fb Merge branch 'misc_small_fixes' of https://github.com/fat-tire/haven into fat-tire-misc_small_fixes +111e9e7 Merge pull request #204 from fat-tire/hide_password +a1b9105 Don't show passwords on screen +54da36d Lint: Misc fixes (see below) Still not a big cleanup but little bits +df07c6d Merge pull request #199 from WangQiru/master +4dd82c3 Minor change +f522de6 Merge pull request #3 from guardianproject/master +ec13b57 Updated Chinese translation +79b5293 adding in code of conduct into the project +968a5e6 Merge pull request #191 from kushaldas/fpf +d9c5281 Merge pull request #196 from FREEWING-JP/japanese-translation +6a1fb24 Merge pull request #197 from FREEWING-JP/fix_hard_coded_string +bd0ef70 Fix Hard coded string +32904c8 Update Japanese translation +4c08a2a Use 'Save Number' dialog for Remote Signal number rather than Register +3d9daaf Fixes the abbreviation of FPF +6e658a8 The summary with string formatting marker. +1fa9dfa Address https://github.com/guardianproject/haven/issues/187 +b654559 Merge pull request #2 from guardianproject/master + + /** 0.1.0 beta 7 build 107 / 2 January 2017 / 615265bec5d50f8fe8eb829a20f6cadd77a8c869 **/ 615265b update to build 107 diff --git a/build.gradle b/build.gradle index e7ff27eb..10c7a27a 100644 --- a/build.gradle +++ b/build.gradle @@ -69,7 +69,7 @@ android { defaultConfig { applicationId "org.havenapp.main" - versionCode 107 + versionCode 108 versionName getVersionName() archivesBaseName = "Haven-$versionName" minSdkVersion 16 diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 7a0a20f0..0c0340e4 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -21,6 +21,8 @@ + + 0) + { + findPreference(PreferenceManager.NOTIFICATION_TIME).setSummary(preferences.getNotificationTimeMs()/60000 + " " + getString(R.string.minutes)); + } + Preference prefCameraSensitivity = findPreference(PreferenceManager.CAMERA_SENSITIVITY); prefCameraSensitivity.setOnPreferenceClickListener(preference -> { startActivity(new Intent(mActivity, CameraConfigureActivity.class)); @@ -133,6 +143,12 @@ public void onCreatePreferencesFix(Bundle bundle, String s) { return true; }); + Preference prefDisableBatteryOpt = findPreference(PreferenceManager.DISABLE_BATTERY_OPT); + prefDisableBatteryOpt.setOnPreferenceClickListener(preference -> { + requestChangeBatteryOptimizations(); + return true; + }); + checkSignalUsername(); ((EditTextPreference) findPreference(PreferenceManager.VERIFY_SIGNAL)).setText(""); askForPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE, 1); @@ -286,6 +302,21 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin askForPermission(Manifest.permission.READ_PHONE_STATE, 6); } setPhoneNumber(); + break; + case PreferenceManager.NOTIFICATION_TIME: + try + { + String text = ((EditTextPreference)findPreference(PreferenceManager.NOTIFICATION_TIME)).getText(); + int notificationTimeMs = Integer.parseInt(text)*60000; + preferences.setNotificationTimeMs(notificationTimeMs); + findPreference(PreferenceManager.NOTIFICATION_TIME).setSummary(preferences.getNotificationTimeMs()/60000 + " " + getString(R.string.minutes)); + + } + catch (NumberFormatException ne) + { + //error parsing user value + } + break; case PreferenceManager.REMOTE_ACCESS_ONION: { String text = ((EditTextPreference) findPreference(PreferenceManager.REMOTE_ACCESS_ONION)).getText(); @@ -411,4 +442,20 @@ public void onTimeSet(TimePickerDialog view, int hourOfDay, int minute, int seco int delaySeconds = second + minute * 60 + hourOfDay * 60 * 60; preferences.setTimerDelay(delaySeconds); } + + private void requestChangeBatteryOptimizations () + { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Intent intent = new Intent(); + String packageName = getActivity().getPackageName(); + PowerManager pm = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE); + if (pm.isIgnoringBatteryOptimizations(packageName)) + intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS); + else { + intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + intent.setData(Uri.parse("package:" + packageName)); + } + getActivity().startActivity(intent); + } + } } diff --git a/src/main/java/org/havenapp/main/model/Event.java b/src/main/java/org/havenapp/main/model/Event.java index 7b158b53..c7e36459 100644 --- a/src/main/java/org/havenapp/main/model/Event.java +++ b/src/main/java/org/havenapp/main/model/Event.java @@ -18,8 +18,6 @@ public class Event extends SugarRecord { @Ignore private ArrayList mEventTriggers; - public final static long EVENT_WINDOW_TIME = 1000 * 60 * 5; //1 minutes - public Event () { mStartTime = new Date(); @@ -48,14 +46,5 @@ public ArrayList getEventTriggers () return mEventTriggers; } - /** - * Are we within the time window of this event, or should we start a new event? - */ - public boolean insideEventWindow (Date now) - { - if (mEventTriggers.size() == 0) - return now.getTime() - mStartTime.getTime() <= EVENT_WINDOW_TIME; - else - return now.getTime() - mEventTriggers.get(mEventTriggers.size()-1).getTriggerTime().getTime() <= EVENT_WINDOW_TIME; - } + } diff --git a/src/main/java/org/havenapp/main/service/MonitorService.java b/src/main/java/org/havenapp/main/service/MonitorService.java index c6aab0ed..3b4f4a2d 100644 --- a/src/main/java/org/havenapp/main/service/MonitorService.java +++ b/src/main/java/org/havenapp/main/service/MonitorService.java @@ -75,11 +75,17 @@ public class MonitorService extends Service { private AmbientLightMonitor mLightMonitor = null; private boolean mIsRunning = false; + /** * Last Event instances */ private Event mLastEvent; + /** + * Last sent notification time + */ + private Date mLastNotification; + /** * Handler for incoming messages */ @@ -257,14 +263,17 @@ private void stopSensors () public synchronized void alert(int alertType, String path) { Date now = new Date(); - boolean isNewEvent = false; + boolean doNotification = false; - if (mLastEvent == null || (!mLastEvent.insideEventWindow(now))) - { + if (mLastEvent == null) { mLastEvent = new Event(); mLastEvent.save(); - - isNewEvent = true; + doNotification = true; + } + else + { + //check if time window is within configured notification time window + doNotification = !((now.getTime()-mLastNotification.getTime()) recips = new ArrayList<>(); - StringTokenizer st = new StringTokenizer(mPrefs.getSmsNumber(),","); - while (st.hasMoreTokens()) - recips.add(st.nextToken()); + if (doNotification) { + + mLastNotification = new Date(); + /* + * If SMS mode is on we send an SMS or Signal alert to the specified + * number + */ + StringBuilder alertMessage = new StringBuilder(); + alertMessage.append(getString(R.string.intrusion_detected, eventTrigger.getStringType(this))); + + if (mPrefs.getSignalUsername() != null) { + //since this is a secure channel, we can add the Onion address + if (mPrefs.getRemoteAccessActive() && (!TextUtils.isEmpty(mPrefs.getRemoteAccessOnion()))) { + alertMessage.append(" http://").append(mPrefs.getRemoteAccessOnion()) + .append(':').append(WebServer.LOCAL_PORT); + } + + SignalSender sender = SignalSender.getInstance(this, mPrefs.getSignalUsername()); + ArrayList recips = new ArrayList<>(); + StringTokenizer st = new StringTokenizer(mPrefs.getSmsNumber(), ","); + while (st.hasMoreTokens()) + recips.add(st.nextToken()); + + String attachment = null; + if (eventTrigger.getType() == EventTrigger.CAMERA) { + attachment = eventTrigger.getPath(); + } else if (eventTrigger.getType() == EventTrigger.MICROPHONE) { + attachment = eventTrigger.getPath(); + } + + sender.sendMessage(recips, alertMessage.toString(), attachment); + } else if (mPrefs.getSmsActivation()) { + SmsManager manager = SmsManager.getDefault(); + + StringTokenizer st = new StringTokenizer(mPrefs.getSmsNumber(), ","); + while (st.hasMoreTokens()) + manager.sendTextMessage(st.nextToken(), null, alertMessage.toString(), null, null); - String attachment = null; - if (eventTrigger.getType() == EventTrigger.CAMERA) - { - attachment = eventTrigger.getPath(); } - else if (eventTrigger.getType() == EventTrigger.MICROPHONE) - { - attachment = eventTrigger.getPath(); - } - - sender.sendMessage(recips,alertMessage.toString(), attachment); - } - else if (mPrefs.getSmsActivation() && isNewEvent) - { - SmsManager manager = SmsManager.getDefault(); - - StringTokenizer st = new StringTokenizer(mPrefs.getSmsNumber(),","); - while (st.hasMoreTokens()) - manager.sendTextMessage(st.nextToken(), null, alertMessage.toString(), null, null); - } } diff --git a/src/main/java/org/havenapp/main/service/WebServer.java b/src/main/java/org/havenapp/main/service/WebServer.java index f04fd79e..a4dc6dab 100644 --- a/src/main/java/org/havenapp/main/service/WebServer.java +++ b/src/main/java/org/havenapp/main/service/WebServer.java @@ -5,6 +5,7 @@ import android.text.TextUtils; import android.util.Log; +import org.havenapp.main.R; import org.havenapp.main.model.Event; import org.havenapp.main.model.EventTrigger; @@ -152,7 +153,7 @@ private void showLogin (StringBuffer page) { page.append("
" + "
\n" + - " \n" + + " \n" + " \n" + "\n" + " \n" + diff --git a/src/main/java/org/havenapp/main/ui/CameraConfigureActivity.java b/src/main/java/org/havenapp/main/ui/CameraConfigureActivity.java index c513bcef..e90a36e0 100644 --- a/src/main/java/org/havenapp/main/ui/CameraConfigureActivity.java +++ b/src/main/java/org/havenapp/main/ui/CameraConfigureActivity.java @@ -17,37 +17,22 @@ package org.havenapp.main.ui; import android.Manifest; -import android.content.Intent; import android.content.pm.PackageManager; -import android.graphics.Camera; import android.os.Bundle; -import android.os.CountDownTimer; -import android.os.Environment; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; -import android.util.Log; import android.view.MenuItem; import android.view.View; -import android.widget.Button; import android.widget.SeekBar; -import android.widget.TextView; - -import com.wdullaer.materialdatetimepicker.time.TimePickerDialog; import org.havenapp.main.PreferenceManager; import org.havenapp.main.R; -import org.havenapp.main.SettingsActivity; -import org.havenapp.main.service.MonitorService; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; public class CameraConfigureActivity extends AppCompatActivity { - + private PreferenceManager preferences = null; private boolean mIsMonitoring = false; @@ -84,7 +69,7 @@ public void onClick(View v) { } }); - SeekBar sBar = ((SeekBar)findViewById(R.id.seekCameraSensitivity)); + SeekBar sBar = ((SeekBar) findViewById(R.id.seekCameraSensitivity)); sBar.setProgress(preferences.getCameraSensitivity()); sBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override @@ -120,43 +105,18 @@ else if (camera.equals(PreferenceManager.BACK)) } - - private void initMonitor() { - - mIsMonitoring = true; - //ensure folder exists and will not be scanned by the gallery app - - try { - File fileImageDir = new File(Environment.getExternalStorageDirectory(), preferences.getImagePath()); - fileImageDir.mkdirs(); - new FileOutputStream(new File(fileImageDir, ".nomedia")).write(0); - } catch (IOException e) { - Log.e("Monitor", "unable to init media storage directory", e); - } - - //Do something after 100ms - startService(new Intent(CameraConfigureActivity.this, MonitorService.class)); - - } - /** * Closes the monitor activity and unset session properties */ private void close() { - stopService(new Intent(this, MonitorService.class)); - if (preferences != null) { - preferences.unsetAccessToken(); - preferences.unsetDelegatedAccessToken(); - preferences.unsetPhoneId(); - } finish(); } @Override - public boolean onOptionsItemSelected (MenuItem item) { - switch (item.getItemId()){ + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { case android.R.id.home: close(); break; diff --git a/src/main/java/org/havenapp/main/ui/CameraFragment.java b/src/main/java/org/havenapp/main/ui/CameraFragment.java index 26e79e7b..69e751e2 100644 --- a/src/main/java/org/havenapp/main/ui/CameraFragment.java +++ b/src/main/java/org/havenapp/main/ui/CameraFragment.java @@ -51,6 +51,7 @@ public void onCreate(Bundle savedInstanceState) { @Override public void onPause() { super.onPause(); + preview.setVisibility(View.GONE); } @Override @@ -58,6 +59,7 @@ public void onResume() { super.onResume(); initCamera (); + } public void resetCamera () @@ -101,6 +103,10 @@ public void onProcess(Bitmap oldBitmap, Bitmap newBitmap, Bitmap rawBitmap, }); } } + else + { + preview.setVisibility(View.VISIBLE); + } } public void onSensorChanged(SensorEvent event) { diff --git a/src/main/java/org/havenapp/main/ui/PPAppIntro.java b/src/main/java/org/havenapp/main/ui/PPAppIntro.java index 8f1bfaea..a89df5ea 100644 --- a/src/main/java/org/havenapp/main/ui/PPAppIntro.java +++ b/src/main/java/org/havenapp/main/ui/PPAppIntro.java @@ -46,8 +46,9 @@ protected void onCreate(Bundle savedInstanceState) { cs2.showButton(getString(R.string.action_configure), new View.OnClickListener() { @Override public void onClick(View v) { - startActivity(new Intent(PPAppIntro.this,MicrophoneConfigureActivity.class)); startActivity(new Intent(PPAppIntro.this,AccelConfigureActivity.class)); + startActivity(new Intent(PPAppIntro.this,MicrophoneConfigureActivity.class)); + startActivity(new Intent(PPAppIntro.this,CameraConfigureActivity.class)); } }); diff --git a/src/main/res/layout/activity_camera_configure.xml b/src/main/res/layout/activity_camera_configure.xml index 0108cdaa..04620beb 100644 --- a/src/main/res/layout/activity_camera_configure.xml +++ b/src/main/res/layout/activity_camera_configure.xml @@ -27,21 +27,35 @@ android:layout_marginTop="60dp" android:visibility="gone" /> - + + + @@ -64,5 +78,6 @@ /> + \ No newline at end of file diff --git a/src/main/res/values-es/strings.xml b/src/main/res/values-es/strings.xml index 59b837e1..f33d1b6a 100644 --- a/src/main/res/values-es/strings.xml +++ b/src/main/res/values-es/strings.xml @@ -1,4 +1,5 @@ + Guardar Configurar... @@ -20,6 +21,9 @@ Enviar SMS o mensaje de alerta por Signal + ++12125551212 + Seleccionar la cámara @@ -46,6 +50,7 @@ Terminar + Acceso remoto Habilitar acceso remoto via Tor Onion Service Dirección del servicio Onion de Orbot Contraseña @@ -58,7 +63,7 @@ Inicio de Sesión Haven Niveles de sonido actuales - Nivel de movimiento acutal + Nivel de movimiento actual Desliza la barra para cambiar el nivel de detección Haz ruido! @@ -84,7 +89,7 @@ Presión Cargando Compartir evento - Mensaje de texto de Haven + Mensaje de texto de Haven Enviar mensaje de texto Verificar Registro @@ -94,6 +99,7 @@ Cancelar Registrarse con Signal Registra un número de teléfono nuevo (+12125551212) con Signal para enviar notificaciones seguras. NO USES TU NÚMERO PRINCIPAL DE SIGNAL. + +12125551212 Licencias... Luz ambiental @@ -101,5 +107,11 @@ Movimiento (Cámara) Micrófono Alimentación USB + Bump (Acelerómetro) Desconocido - + + Configuraciòn + Esta función requiere Orbot instalado: La aplicación de Tor para dispositivos Android. + + Numero de telefono remoto para enviar mensajes de notificaciones + diff --git a/src/main/res/values-ru/strings.xml b/src/main/res/values-ru/strings.xml index c9b22343..c3cbe6cc 100644 --- a/src/main/res/values-ru/strings.xml +++ b/src/main/res/values-ru/strings.xml @@ -1,8 +1,6 @@ - Запуск - Остановить + Сохранить - Удалённый доступ Настроить... Haven @@ -15,26 +13,10 @@ Чувствительность к звукам - - Чувствительность движения камеры - - Установка времени задержки - - Использовать микрофон для обнаружения звука - - - - Выбрать камеру - - - - Активировать вспышку - - Отправлять SMS или сигналы оповещений @@ -43,50 +25,31 @@ +79125551212 - - Код для остановки приложения - - - - Запуск - - Выбрать камеру - - Низкая - Средняя - Высокая - Отключить - - - - Передняя - Задняя - Отключить - - Haven включен - Haven отключен - Haven заметил срабатывание датчика (Тип: %s) Активное событие Настройки Добро пожаловать в Haven + \"Now when the ark of human fate,\nLong baffled by the wayward wind,\nIs drifting with its peopled freight,\nSAFE HAVEN on the heights to find...\"\n-George Meredith + Haven предназначен для людей, которые хотят следить за проникновением в свой дом, офис, гостиничный номер или другое личное пространство Превратите дополнительный телефон в детектор движения, звука, вибрации и света, наблюдая за неожиданными гостями и злоумышленниками + Получайте уведомления о проникновениях мгновенно, а также доступ к журналам удаленно или лично позже + Ваш Haven готов Активируйте приложение в любое время, используя кнопку действия > на главном экране - Закончить - Расположите камеру для захвата движения или установите телефон в любом месте, чтобы просто слушать звук + Закончить + Удалённый доступ Включить удаленный доступ через службу Tor Onion Адрес службы Onion от Orbot Установка удаленного пароля @@ -142,5 +105,22 @@ Движение (камера) Микрофон Питание USB + Толчок (акселерометр) Неизвестный - + + Настройки + Для этой функции требуется наличие приложения Orbot: Tor for Android + + Номер удалённого телефона для приёма оповещений + Введите номер удалённого телефона, на который будут отсылаться оповещения + Исходящий телефонный номер в Signal + Коснитесь для верификации номера в Signal + Введите номер, на который будет отослано тестовое сообщение + Протестировать оповещения... + Адрес службы + Номер в Signal (локальный) + Номер для оповещений (удалённый) + Сенсоры + Оповещения + + diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 123d7dcd..ed64218d 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -129,4 +129,15 @@ Notifications Camera Sensitivity + + Notification Time Interval + Only send notifications at configured interval + Enter time (minutes) to limit notifications. \'0\' to send every notification. + minutes(s) + Keep Watch! + Select camera and use the slider to adjust motion detection sensitivity + Disable Battery Optimizations + Allow app to run when screen is off + + diff --git a/src/main/res/xml/settings.xml b/src/main/res/xml/settings.xml index f671a885..406fc4d8 100644 --- a/src/main/res/xml/settings.xml +++ b/src/main/res/xml/settings.xml @@ -5,6 +5,12 @@ android:key="config_delay_time" android:title="@string/timer_delay_label" /> + + + + + + +