Commit c187f9e4 authored by akwizgran's avatar akwizgran

Added sliders for setting alarm and keepalive intervals.

parent 66d170d8
......@@ -14,5 +14,6 @@ android {
dependencies {
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:design:23.2.1'
compile 'org.jetbrains:annotations-java5:15.0'
}
......@@ -12,15 +12,15 @@ interface Constants {
String EXTRA_WIFI_LOCK = "org.briarproject.snooze.EXTRA_WIFI_LOCK";
String EXTRA_ALARM_TYPE = "org.briarproject.snooze.EXTRA_ALARM_TYPE";
String EXTRA_ALARM_INTERVAL_MS = "org.briarproject.snooze.EXTRA_ALARM_INTERVAL_MS";
String EXTRA_KEEPALIVE_INTERVAL_MS = "org.briarproject.snooze.EXTRA_KEEPALIVE_INTERVAL_MS";
int ALARM_INTERVAL_MS = 5 * 1000;
String EXTRA_ALARM_TYPE = "org.briarproject.snooze.EXTRA_ALARM_TYPE";
int SOCKET_TIMEOUT_MS = 2 * 60 * 1000;
int CONNECT_TIMEOUT_MS = 30 * 1000;
int RECONNECT_DELAY_MS = 10 * 1000;
int KEEPALIVE_INTERVAL_MS = 60 * 1000;
}
package org.briarproject.snooze;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import org.briarproject.snooze.Logger.LogListener;
import static android.content.Context.CLIPBOARD_SERVICE;
import static android.view.View.FOCUS_DOWN;
import static android.widget.Toast.LENGTH_SHORT;
public class LogFragment extends Fragment implements LogListener {
private ScrollView outputScrollView;
private TextView outputTextView;
private volatile Logger log = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
log = ((SnoozeApplication) getContext().getApplicationContext()).getLogger();
View layout = inflater.inflate(R.layout.fragment_log, container, false);
outputScrollView = (ScrollView) layout.findViewById(R.id.outputScrollView);
outputTextView = (TextView) layout.findViewById(R.id.outputTextView);
(layout.findViewById(R.id.clearLogButton)).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onClickClearLogButton();
}
});
layout.findViewById(R.id.copyLogButton).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onClickCopyLogButton();
}
});
StringBuilder sb = new StringBuilder();
for (String message : log.addListener(this)) sb.append(stripDate(message)).append('\n');
outputTextView.setText(sb.toString());
return layout;
}
private String stripDate(String message) {
return message.replaceFirst("[^ ]+ ", "");
}
@Override
public void onDestroyView() {
super.onDestroyView();
log.removeListener(this);
}
@Override
public void onMessageLogged(String message) {
outputTextView.append(stripDate(message) + '\n');
outputScrollView.post(new Runnable() {
@Override
public void run() {
outputScrollView.fullScroll(FOCUS_DOWN);
}
});
}
public void onClickClearLogButton() {
log.clear();
outputTextView.setText("");
}
public void onClickCopyLogButton() {
ClipboardManager cp = (ClipboardManager) getContext().getSystemService(CLIPBOARD_SERVICE);
String text = outputTextView.getText().toString();
cp.setPrimaryClip(ClipData.newPlainText(getString(R.string.app_name), text));
Toast.makeText(getContext(), R.string.copied_to_clipboard, LENGTH_SHORT).show();
}
}
......@@ -6,7 +6,6 @@ import android.os.PowerManager;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
......@@ -28,7 +27,7 @@ class NetworkClient extends Thread {
NetworkClient(String host, int port, int keepaliveIntervalMs, Context appContext) {
this.host = host;
this.port = port;
keepaliveIntervalSecs = (keepaliveIntervalMs / 1000) & 0xffff;
keepaliveIntervalSecs = (keepaliveIntervalMs / 1000);
log = ((SnoozeApplication) appContext).getLogger();
PowerManager pm = (PowerManager) appContext.getSystemService(POWER_SERVICE);
wakeLock = pm.newWakeLock(PARTIAL_WAKE_LOCK, LOCK_TAG);
......@@ -47,7 +46,7 @@ class NetworkClient extends Thread {
s.connect(new InetSocketAddress(host, port), CONNECT_TIMEOUT_MS);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
InputStream in = s.getInputStream();
log.log("Connected");
log.log("Requesting keepalives every " + keepaliveIntervalSecs + " seconds");
out.writeShort(keepaliveIntervalSecs);
out.flush();
for (int read = 0; read != -1 && !isInterrupted(); read = in.read(buf)) {
......
package org.briarproject.snooze;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import static org.briarproject.snooze.AlarmType.TIMER;
import static org.briarproject.snooze.Constants.ACTION_START;
import static org.briarproject.snooze.Constants.EXTRA_ALARM_INTERVAL_MS;
import static org.briarproject.snooze.Constants.EXTRA_ALARM_TYPE;
import static org.briarproject.snooze.Constants.EXTRA_FOREGROUND_SERVICE;
import static org.briarproject.snooze.Constants.EXTRA_KEEPALIVE_INTERVAL_MS;
import static org.briarproject.snooze.Constants.EXTRA_WAKE_LOCK;
import static org.briarproject.snooze.Constants.EXTRA_WIFI_LOCK;
public class SettingsFragment extends Fragment {
private AlarmType alarmType = TIMER;
private TextView alarmIntervalTextView, keepaliveIntervalTextView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View layout = inflater.inflate(R.layout.fragment_settings, container, false);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(),
R.array.alarm_types, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Spinner alarmTypeSpinner = (Spinner) layout.findViewById(R.id.alarmTypeSpinner);
alarmTypeSpinner.setAdapter(adapter);
alarmTypeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View v, int position, long id) {
alarmType = AlarmType.values()[position];
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
alarmIntervalTextView = (TextView) layout.findViewById(R.id.alarmIntervalTextView);
alarmIntervalTextView.setText(getString(R.string.interval, 1));
((SeekBar) layout.findViewById(R.id.alarmIntervalSeekBar)).setOnSeekBarChangeListener(
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
alarmIntervalTextView.setText(getString(R.string.interval, progress + 1));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
keepaliveIntervalTextView = (TextView) layout.findViewById(R.id.keepaliveIntervalTextView);
keepaliveIntervalTextView.setText(getString(R.string.interval, 1));
((SeekBar) layout.findViewById(R.id.keepaliveIntervalSeekBar)).setOnSeekBarChangeListener(
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
keepaliveIntervalTextView.setText(getString(R.string.interval,
progress + 1));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
layout.findViewById(R.id.applySettingsButton).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onClickApplySettingsButton();
}
});
return layout;
}
public void onClickApplySettingsButton() {
View layout = getView();
boolean foreground =
((Switch) layout.findViewById(R.id.foregroundServiceSwitch)).isChecked();
boolean wakeLock = ((Switch) layout.findViewById(R.id.wakeLockSwitch)).isChecked();
boolean wifiLock = ((Switch) layout.findViewById(R.id.wifiLockSwitch)).isChecked();
int alarmIntervalMins =
((SeekBar) layout.findViewById(R.id.alarmIntervalSeekBar)).getProgress() + 1;
int keepaliveIntervalMins =
((SeekBar) layout.findViewById(R.id.keepaliveIntervalSeekBar)).getProgress() + 1;
Intent i = new Intent(getContext(), SnoozeService.class);
i.setAction(ACTION_START);
i.putExtra(EXTRA_FOREGROUND_SERVICE, foreground);
i.putExtra(EXTRA_WAKE_LOCK, wakeLock);
i.putExtra(EXTRA_WIFI_LOCK, wifiLock);
i.putExtra(EXTRA_ALARM_INTERVAL_MS, alarmIntervalMins * 60 * 1000);
i.putExtra(EXTRA_KEEPALIVE_INTERVAL_MS, keepaliveIntervalMins * 60 * 1000);
i.putExtra(EXTRA_ALARM_TYPE, alarmType.name());
getContext().startService(i);
}
}
package org.briarproject.snooze;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import android.util.Log;
import org.briarproject.snooze.Logger.LogListener;
import static android.view.View.FOCUS_DOWN;
import static android.widget.Toast.LENGTH_SHORT;
import static org.briarproject.snooze.AlarmType.TIMER;
import static org.briarproject.snooze.Constants.ACTION_START;
import static org.briarproject.snooze.Constants.EXTRA_ALARM_TYPE;
import static org.briarproject.snooze.Constants.EXTRA_FOREGROUND_SERVICE;
import static org.briarproject.snooze.Constants.EXTRA_WAKE_LOCK;
import static org.briarproject.snooze.Constants.EXTRA_WIFI_LOCK;
public class SnoozeActivity extends AppCompatActivity implements LogListener,
OnItemSelectedListener {
private ScrollView outputScrollView;
private TextView outputTextView;
private AlarmType alarmType = TIMER;
public class SnoozeActivity extends AppCompatActivity {
private volatile Logger log = null;
......@@ -41,68 +19,41 @@ public class SnoozeActivity extends AppCompatActivity implements LogListener,
log = ((SnoozeApplication) getApplication()).getLogger();
log.log("Activity created");
setContentView(R.layout.activity_snooze);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.alarm_types, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
Spinner alarmTypeSpinner = (Spinner) findViewById(R.id.alarmTypeSpinner);
alarmTypeSpinner.setAdapter(adapter);
alarmTypeSpinner.setOnItemSelectedListener(this);
outputScrollView = (ScrollView) findViewById(R.id.outputScrollView);
outputTextView = (TextView) findViewById(R.id.outputTextView);
StringBuilder sb = new StringBuilder();
for (String message : log.addListener(this)) sb.append(message).append('\n');
outputTextView.setText(sb.toString());
String[] pageTitles = {getString(R.string.settings), getString(R.string.log)};
TabAdapter adapter = new TabAdapter(getSupportFragmentManager(), pageTitles);
ViewPager viewPager = ((ViewPager) findViewById(R.id.viewPager));
viewPager.setAdapter(adapter);
((TabLayout) findViewById(R.id.tabLayout)).setupWithViewPager(viewPager);
}
@Override
protected void onDestroy() {
super.onDestroy();
log.log("Activity destroyed");
log.removeListener(this);
}
@Override
public void onMessageLogged(String message) {
outputTextView.append(message + '\n');
outputScrollView.post(new Runnable() {
@Override
public void run() {
outputScrollView.fullScroll(FOCUS_DOWN);
}
});
}
private static class TabAdapter extends FragmentPagerAdapter {
public void onClickApplySettingsButton(View v) {
boolean foreground = ((Switch) findViewById(R.id.foregroundServiceSwitch)).isChecked();
boolean wakeLock = ((Switch) findViewById(R.id.wakeLockSwitch)).isChecked();
boolean wifiLock = ((Switch) findViewById(R.id.wifiLockSwitch)).isChecked();
Intent i = new Intent(this, SnoozeService.class);
i.setAction(ACTION_START);
i.putExtra(EXTRA_FOREGROUND_SERVICE, foreground);
i.putExtra(EXTRA_WAKE_LOCK, wakeLock);
i.putExtra(EXTRA_WIFI_LOCK, wifiLock);
i.putExtra(EXTRA_ALARM_TYPE, alarmType.name());
startService(i);
}
private final String[] pageTitles;
public void onClickCopyLogButton(View v) {
ClipboardManager cp = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
String text = outputTextView.getText().toString();
cp.setPrimaryClip(ClipData.newPlainText(getString(R.string.app_name), text));
Toast.makeText(this, R.string.copied_to_clipboard, LENGTH_SHORT).show();
}
private TabAdapter(FragmentManager fm, String[] pageTitles) {
super(fm);
this.pageTitles = pageTitles;
}
public void onClickClearLogButton(View view) {
log.clear();
outputTextView.setText("");
}
@Override
public Fragment getItem(int position) {
return position == 0 ? new SettingsFragment() : new LogFragment();
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
alarmType = AlarmType.values()[position];
}
@Override
public int getCount() {
return 2;
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
@Override
public String getPageTitle(int position) {
return pageTitles[position];
}
}
}
......@@ -17,12 +17,12 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static org.briarproject.snooze.AlarmType.STOP;
import static org.briarproject.snooze.Constants.ACTION_ALARM;
import static org.briarproject.snooze.Constants.ACTION_START;
import static org.briarproject.snooze.Constants.ALARM_INTERVAL_MS;
import static org.briarproject.snooze.Constants.EXTRA_ALARM_INTERVAL_MS;
import static org.briarproject.snooze.Constants.EXTRA_ALARM_TYPE;
import static org.briarproject.snooze.Constants.EXTRA_FOREGROUND_SERVICE;
import static org.briarproject.snooze.Constants.EXTRA_KEEPALIVE_INTERVAL_MS;
import static org.briarproject.snooze.Constants.EXTRA_WAKE_LOCK;
import static org.briarproject.snooze.Constants.EXTRA_WIFI_LOCK;
import static org.briarproject.snooze.Constants.KEEPALIVE_INTERVAL_MS;
public class SnoozeService extends Service {
......@@ -36,6 +36,7 @@ public class SnoozeService extends Service {
private WifiManager.WifiLock wifiLock = null;
private NetworkClient networkClient = null;
private Alarm alarm = null;
private int alarmIntervalMs = 60 * 1000, keepaliveIntervalMs = 60 * 1000;
private volatile Logger log = null;
......@@ -58,6 +59,8 @@ public class SnoozeService extends Service {
boolean newForeground = i.getBooleanExtra(EXTRA_FOREGROUND_SERVICE, false);
boolean newWakeLock = i.getBooleanExtra(EXTRA_WAKE_LOCK, false);
boolean newWifiLock = i.getBooleanExtra(EXTRA_WIFI_LOCK, false);
alarmIntervalMs = i.getIntExtra(EXTRA_ALARM_INTERVAL_MS, -1);
keepaliveIntervalMs = i.getIntExtra(EXTRA_KEEPALIVE_INTERVAL_MS, -1);
AlarmType newAlarmType = AlarmType.valueOf(i.getStringExtra(EXTRA_ALARM_TYPE));
log.log("Setting alarm " + newAlarmType);
if (newForeground && !foreground) startForegroundService();
......@@ -156,8 +159,7 @@ public class SnoozeService extends Service {
if (networkClient != null) networkClient.interrupt();
String host = getString(R.string.host);
int port = getResources().getInteger(R.integer.port);
networkClient = new NetworkClient(host, port, KEEPALIVE_INTERVAL_MS,
getApplicationContext());
networkClient = new NetworkClient(host, port, keepaliveIntervalMs, getApplicationContext());
networkClient.start();
}
......@@ -171,6 +173,6 @@ public class SnoozeService extends Service {
private void setAlarm() {
if (alarm == null) throw new IllegalStateException();
alarm.setAlarm(ALARM_INTERVAL_MS, MILLISECONDS);
alarm.setAlarm(alarmIntervalMs, MILLISECONDS);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="12dp"
android:orientation="vertical"
tools:context="org.briarproject.snooze.SnoozeActivity">
<Switch
android:id="@+id/foregroundServiceSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_foreground_service"/>
<Switch
android:id="@+id/wakeLockSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_permanent_wake_lock"/>
<Switch
android:id="@+id/wifiLockSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_wifi_lock"/>
<Spinner
android:id="@+id/alarmTypeSpinner"
<android.support.design.widget.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"/>
android:layout_height="wrap_content"/>
<Button
android:id="@+id/applySettingsButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClickApplySettingsButton"
android:text="@string/apply_settings"/>
<ScrollView
android:id="@+id/outputScrollView"
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="8dp">
<TextView
android:id="@+id/outputTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/clearLogButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClickClearLogButton"
android:text="@string/clear_log"/>
<Button
android:id="@+id/copyLogButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="onClickCopyLogButton"
android:text="@string/copy_log"/>
android:layout_weight="1"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
android:orientation="vertical"
tools:context="org.briarproject.snooze.LogFragment">
<ScrollView
android:id="@+id/outputScrollView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="8dp">
<TextView
android:id="@+id/outputTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/clearLogButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/clear_log"/>
<Button
android:id="@+id/copyLogButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/copy_log"/>
</LinearLayout>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp"
tools:context="org.briarproject.snooze.SettingsFragment">
<Switch
android:id="@+id/foregroundServiceSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_foreground_service"/>
<Switch
android:id="@+id/wakeLockSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_permanent_wake_lock"/>
<Switch
android:id="@+id/wifiLockSwitch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/use_wifi_lock"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="4dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="6"
android:text="@string/alarm_interval"/>
<SeekBar
android:id="@+id/alarmIntervalSeekBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="7"
android:max="14"/>
<TextView
android:id="@+id/alarmIntervalTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
tools:text="1 min"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="4dp">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="6"
android:text="@string/keepalive_interval"/>
<SeekBar