mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Move Sync to foreground service
This commit is contained in:
@@ -16,37 +16,30 @@
|
|||||||
~
|
~
|
||||||
~ You should have received a copy of the GNU General Public License along
|
~ You should have received a copy of the GNU General Public License along
|
||||||
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
~ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-->
|
-->
|
||||||
|
<manifest package="org.isoron.uhabits"
|
||||||
<manifest
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.isoron.uhabits"
|
android:versionCode="28"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
android:versionName="1.7.1">
|
||||||
android:versionCode="28"
|
|
||||||
android:versionName="1.7.1">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.VIBRATE"/>
|
<uses-permission android:name="android.permission.VIBRATE"/>
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="18"/>
|
android:maxSdkVersion="18"/>
|
||||||
|
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||||
android:maxSdkVersion="18"/>
|
android:maxSdkVersion="18"/>
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||||
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name="HabitsApplication"
|
android:name=".HabitsApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:backupAgent=".HabitsBackupAgent"
|
android:backupAgent=".HabitsBackupAgent"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/main_activity_title"
|
android:label="@string/main_activity_title"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppBaseTheme">
|
android:theme="@style/AppBaseTheme">
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="com.google.android.backup.api_key"
|
android:name="com.google.android.backup.api_key"
|
||||||
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw"/>
|
android:value="AEdPqrEAAAAI6aeWncbnMNo8E5GWeZ44dlc5cQ7tCROwFhOtiw"/>
|
||||||
@@ -64,6 +57,7 @@
|
|||||||
android:targetActivity=".activities.habits.list.ListHabitsActivity">
|
android:targetActivity=".activities.habits.list.ListHabitsActivity">
|
||||||
<intent-filter android:label="@string/app_name">
|
<intent-filter android:label="@string/app_name">
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity-alias>
|
</activity-alias>
|
||||||
@@ -75,7 +69,6 @@
|
|||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
android:value=".activities.habits.list.ListHabitsActivity"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.settings.SettingsActivity"
|
android:name=".activities.settings.SettingsActivity"
|
||||||
android:label="@string/settings">
|
android:label="@string/settings">
|
||||||
@@ -83,12 +76,10 @@
|
|||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".activities.habits.list.ListHabitsActivity"/>
|
android:value=".activities.habits.list.ListHabitsActivity"/>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.intro.IntroActivity"
|
android:name=".activities.intro.IntroActivity"
|
||||||
android:label=""
|
android:label=""
|
||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".widgets.HabitPickerDialog"
|
android:name=".widgets.HabitPickerDialog"
|
||||||
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
android:theme="@style/Theme.AppCompat.Light.Dialog">
|
||||||
@@ -96,7 +87,6 @@
|
|||||||
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.about.AboutActivity"
|
android:name=".activities.about.AboutActivity"
|
||||||
android:label="@string/about">
|
android:label="@string/about">
|
||||||
@@ -116,7 +106,6 @@
|
|||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_checkmark_info"/>
|
android:resource="@xml/widget_checkmark_info"/>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.HistoryWidgetProvider"
|
android:name=".widgets.HistoryWidgetProvider"
|
||||||
android:label="@string/history">
|
android:label="@string/history">
|
||||||
@@ -128,7 +117,6 @@
|
|||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_history_info"/>
|
android:resource="@xml/widget_history_info"/>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.ScoreWidgetProvider"
|
android:name=".widgets.ScoreWidgetProvider"
|
||||||
android:label="@string/habit_strength">
|
android:label="@string/habit_strength">
|
||||||
@@ -140,7 +128,6 @@
|
|||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_score_info"/>
|
android:resource="@xml/widget_score_info"/>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.StreakWidgetProvider"
|
android:name=".widgets.StreakWidgetProvider"
|
||||||
android:label="@string/streaks">
|
android:label="@string/streaks">
|
||||||
@@ -152,7 +139,6 @@
|
|||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_streak_info"/>
|
android:resource="@xml/widget_streak_info"/>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".widgets.FrequencyWidgetProvider"
|
android:name=".widgets.FrequencyWidgetProvider"
|
||||||
android:label="@string/frequency">
|
android:label="@string/frequency">
|
||||||
@@ -164,33 +150,35 @@
|
|||||||
android:name="android.appwidget.provider"
|
android:name="android.appwidget.provider"
|
||||||
android:resource="@xml/widget_frequency_info"/>
|
android:resource="@xml/widget_frequency_info"/>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".receivers.ReminderReceiver">
|
<receiver android:name=".receivers.ReminderReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
<receiver android:name=".receivers.WidgetReceiver">
|
<receiver android:name=".receivers.WidgetReceiver">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
|
||||||
<action android:name="org.isoron.uhabits.ACTION_TOGGLE_REPETITION"/>
|
<action android:name="org.isoron.uhabits.ACTION_TOGGLE_REPETITION"/>
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="org.isoron.uhabits"
|
android:host="org.isoron.uhabits"
|
||||||
android:scheme="content"/>
|
android:scheme="content"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
|
||||||
<action android:name="org.isoron.uhabits.ACTION_ADD_REPETITION"/>
|
<action android:name="org.isoron.uhabits.ACTION_ADD_REPETITION"/>
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="org.isoron.uhabits"
|
android:host="org.isoron.uhabits"
|
||||||
android:scheme="content"/>
|
android:scheme="content"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
|
||||||
<action android:name="org.isoron.uhabits.ACTION_REMOVE_REPETITION"/>
|
<action android:name="org.isoron.uhabits.ACTION_REMOVE_REPETITION"/>
|
||||||
|
|
||||||
<data
|
<data
|
||||||
android:host="org.isoron.uhabits"
|
android:host="org.isoron.uhabits"
|
||||||
android:scheme="content"/>
|
android:scheme="content"/>
|
||||||
@@ -211,8 +199,7 @@
|
|||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action
|
<action android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING"/>
|
||||||
android:name="com.twofortyfouram.locale.intent.action.EDIT_SETTING"/>
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
@@ -232,8 +219,14 @@
|
|||||||
android:grantUriPermissions="true">
|
android:grantUriPermissions="true">
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/file_paths" />
|
android:resource="@xml/file_paths"/>
|
||||||
</provider>
|
</provider>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".sync.SyncService"
|
||||||
|
android:enabled="true"
|
||||||
|
android:exported="false">
|
||||||
|
</service>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
|
||||||
|
</manifest>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.activities.habits.list;
|
package org.isoron.uhabits.activities.habits.list;
|
||||||
|
|
||||||
|
import android.content.*;
|
||||||
import android.os.*;
|
import android.os.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
@@ -47,8 +48,6 @@ public class ListHabitsActivity extends BaseActivity
|
|||||||
|
|
||||||
private MidnightTimer midnightTimer;
|
private MidnightTimer midnightTimer;
|
||||||
|
|
||||||
private SyncManager syncManager;
|
|
||||||
|
|
||||||
public ListHabitsComponent getListHabitsComponent()
|
public ListHabitsComponent getListHabitsComponent()
|
||||||
{
|
{
|
||||||
return component;
|
return component;
|
||||||
@@ -84,7 +83,9 @@ public class ListHabitsActivity extends BaseActivity
|
|||||||
rootView.setController(controller, selectionMenu);
|
rootView.setController(controller, selectionMenu);
|
||||||
|
|
||||||
midnightTimer = component.getMidnightTimer();
|
midnightTimer = component.getMidnightTimer();
|
||||||
syncManager = app.getComponent().getSyncManager();
|
|
||||||
|
if(prefs.isSyncFeatureEnabled())
|
||||||
|
startService(new Intent(this, SyncService.class));
|
||||||
|
|
||||||
setScreen(screen);
|
setScreen(screen);
|
||||||
controller.onStartup();
|
controller.onStartup();
|
||||||
@@ -93,7 +94,6 @@ public class ListHabitsActivity extends BaseActivity
|
|||||||
@Override
|
@Override
|
||||||
protected void onPause()
|
protected void onPause()
|
||||||
{
|
{
|
||||||
syncManager.stopListening();
|
|
||||||
midnightTimer.onPause();
|
midnightTimer.onPause();
|
||||||
screen.onDettached();
|
screen.onDettached();
|
||||||
adapter.cancelRefresh();
|
adapter.cancelRefresh();
|
||||||
@@ -107,7 +107,6 @@ public class ListHabitsActivity extends BaseActivity
|
|||||||
screen.onAttached();
|
screen.onAttached();
|
||||||
rootView.postInvalidate();
|
rootView.postInvalidate();
|
||||||
midnightTimer.onResume();
|
midnightTimer.onResume();
|
||||||
syncManager.startListening();
|
|
||||||
|
|
||||||
if (prefs.getTheme() == ThemeSwitcher.THEME_DARK &&
|
if (prefs.getTheme() == ThemeSwitcher.THEME_DARK &&
|
||||||
prefs.isPureBlackEnabled() != pureBlack)
|
prefs.isPureBlackEnabled() != pureBlack)
|
||||||
|
|||||||
@@ -242,9 +242,10 @@ public class Preferences
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (key.equals("pref_sticky_notifications"))
|
if (key.equals("pref_sticky_notifications"))
|
||||||
{
|
|
||||||
for (Listener l : listeners) l.onNotificationsChanged();
|
for (Listener l : listeners) l.onNotificationsChanged();
|
||||||
}
|
|
||||||
|
if (key.equals("pref_feature_sync"))
|
||||||
|
for (Listener l : listeners) l.onSyncFeatureChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeListener(Listener listener)
|
public void removeListener(Listener listener)
|
||||||
@@ -306,5 +307,7 @@ public class Preferences
|
|||||||
default void onCheckmarkOrderChanged() {}
|
default void onCheckmarkOrderChanged() {}
|
||||||
|
|
||||||
default void onNotificationsChanged() {}
|
default void onNotificationsChanged() {}
|
||||||
|
|
||||||
|
default void onSyncFeatureChanged() {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ import com.getpebble.android.kit.util.*;
|
|||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.commands.*;
|
import org.isoron.uhabits.commands.*;
|
||||||
import org.isoron.uhabits.models.*;
|
import org.isoron.uhabits.models.*;
|
||||||
|
import org.isoron.uhabits.preferences.*;
|
||||||
|
import org.isoron.uhabits.sync.*;
|
||||||
import org.isoron.uhabits.tasks.*;
|
import org.isoron.uhabits.tasks.*;
|
||||||
import org.isoron.uhabits.utils.*;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
@@ -51,6 +53,8 @@ public class PebbleReceiver extends PebbleDataReceiver
|
|||||||
|
|
||||||
private HabitList filteredHabits;
|
private HabitList filteredHabits;
|
||||||
|
|
||||||
|
private Preferences prefs;
|
||||||
|
|
||||||
public PebbleReceiver()
|
public PebbleReceiver()
|
||||||
{
|
{
|
||||||
super(WATCHAPP_UUID);
|
super(WATCHAPP_UUID);
|
||||||
@@ -69,9 +73,14 @@ public class PebbleReceiver extends PebbleDataReceiver
|
|||||||
HabitsApplication app =
|
HabitsApplication app =
|
||||||
(HabitsApplication) context.getApplicationContext();
|
(HabitsApplication) context.getApplicationContext();
|
||||||
|
|
||||||
commandRunner = app.getComponent().getCommandRunner();
|
AppComponent component = app.getComponent();
|
||||||
taskRunner = app.getComponent().getTaskRunner();
|
commandRunner = component.getCommandRunner();
|
||||||
allHabits = app.getComponent().getHabitList();
|
taskRunner = component.getTaskRunner();
|
||||||
|
allHabits = component.getHabitList();
|
||||||
|
prefs = component.getPreferences();
|
||||||
|
|
||||||
|
if(prefs.isSyncFeatureEnabled())
|
||||||
|
context.startService(new Intent(context, SyncService.class));
|
||||||
|
|
||||||
HabitMatcher build = new HabitMatcherBuilder()
|
HabitMatcher build = new HabitMatcherBuilder()
|
||||||
.setArchivedAllowed(false)
|
.setArchivedAllowed(false)
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import android.util.*;
|
|||||||
|
|
||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.intents.*;
|
import org.isoron.uhabits.intents.*;
|
||||||
|
import org.isoron.uhabits.preferences.*;
|
||||||
|
import org.isoron.uhabits.sync.*;
|
||||||
|
|
||||||
import dagger.*;
|
import dagger.*;
|
||||||
|
|
||||||
@@ -59,6 +61,10 @@ public class WidgetReceiver extends BroadcastReceiver
|
|||||||
|
|
||||||
IntentParser parser = app.getComponent().getIntentParser();
|
IntentParser parser = app.getComponent().getIntentParser();
|
||||||
WidgetController controller = component.getWidgetController();
|
WidgetController controller = component.getWidgetController();
|
||||||
|
Preferences prefs = app.getComponent().getPreferences();
|
||||||
|
|
||||||
|
if(prefs.isSyncFeatureEnabled())
|
||||||
|
context.startService(new Intent(context, SyncService.class));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,17 +26,13 @@ import android.util.*;
|
|||||||
import org.isoron.uhabits.*;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.commands.*;
|
import org.isoron.uhabits.commands.*;
|
||||||
import org.isoron.uhabits.preferences.*;
|
import org.isoron.uhabits.preferences.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.json.*;
|
import org.json.*;
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.security.*;
|
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.security.cert.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.inject.*;
|
import javax.inject.*;
|
||||||
import javax.net.ssl.*;
|
|
||||||
|
|
||||||
import io.socket.client.*;
|
import io.socket.client.*;
|
||||||
import io.socket.client.Socket;
|
import io.socket.client.Socket;
|
||||||
@@ -58,8 +54,10 @@ public class SyncManager implements CommandRunner.Listener
|
|||||||
|
|
||||||
public static final String EVENT_POST_EVENT = "postEvent";
|
public static final String EVENT_POST_EVENT = "postEvent";
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private String clientId;
|
private String clientId;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private String groupKey;
|
private String groupKey;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@@ -69,16 +67,17 @@ public class SyncManager implements CommandRunner.Listener
|
|||||||
private LinkedList<Event> pendingConfirmation;
|
private LinkedList<Event> pendingConfirmation;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private List<Event> pendingEmit;
|
private LinkedList<Event> pendingEmit;
|
||||||
|
|
||||||
private boolean readyToEmit = false;
|
private boolean readyToEmit = false;
|
||||||
|
|
||||||
private Context context;
|
@NonNull
|
||||||
|
|
||||||
private final Preferences prefs;
|
private final Preferences prefs;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private CommandRunner commandRunner;
|
private CommandRunner commandRunner;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
private CommandParser commandParser;
|
private CommandParser commandParser;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -87,24 +86,60 @@ public class SyncManager implements CommandRunner.Listener
|
|||||||
@NonNull CommandRunner commandRunner,
|
@NonNull CommandRunner commandRunner,
|
||||||
@NonNull CommandParser commandParser)
|
@NonNull CommandParser commandParser)
|
||||||
{
|
{
|
||||||
this.context = context;
|
|
||||||
this.prefs = prefs;
|
this.prefs = prefs;
|
||||||
this.commandRunner = commandRunner;
|
this.commandRunner = commandRunner;
|
||||||
this.commandParser = commandParser;
|
this.commandParser = commandParser;
|
||||||
|
|
||||||
pendingConfirmation = new LinkedList<>();
|
pendingConfirmation = new LinkedList<>();
|
||||||
pendingEmit = Event.getAll();
|
pendingEmit = new LinkedList<>(Event.getAll());
|
||||||
|
|
||||||
groupKey = prefs.getSyncKey();
|
groupKey = prefs.getSyncKey();
|
||||||
clientId = prefs.getSyncClientId();
|
clientId = prefs.getSyncClientId();
|
||||||
String serverURL = prefs.getSyncAddress();
|
String serverURL = prefs.getSyncAddress();
|
||||||
|
|
||||||
Log.d("SyncManager", clientId);
|
Log.d("SyncManager", clientId);
|
||||||
|
connect(context, serverURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCommandExecuted(@NonNull Command command,
|
||||||
|
@Nullable Long refreshKey)
|
||||||
|
{
|
||||||
|
if (command.isRemote()) return;
|
||||||
|
|
||||||
|
JSONObject msg = command.toJson();
|
||||||
|
Long now = new Date().getTime();
|
||||||
|
Event e = new Event(command.getId(), now, msg.toString());
|
||||||
|
e.save();
|
||||||
|
|
||||||
|
Log.i("SyncManager", "Adding to outbox: " + msg.toString());
|
||||||
|
|
||||||
|
pendingEmit.add(e);
|
||||||
|
if (readyToEmit) emitPending();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startListening()
|
||||||
|
{
|
||||||
|
if (!prefs.isSyncFeatureEnabled()) return;
|
||||||
|
if (groupKey.isEmpty()) return;
|
||||||
|
|
||||||
|
socket.connect();
|
||||||
|
commandRunner.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopListening()
|
||||||
|
{
|
||||||
|
commandRunner.removeListener(this);
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void connect(@AppContext @NonNull Context context, String serverURL)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IO.setDefaultSSLContext(getCACertSSLContext());
|
IO.setDefaultSSLContext(SSLUtils.getCACertSSLContext(context));
|
||||||
socket = IO.socket(serverURL);
|
socket = IO.socket(serverURL);
|
||||||
|
|
||||||
logSocketEvent(socket, EVENT_CONNECT, "Connected");
|
logSocketEvent(socket, EVENT_CONNECT, "Connected");
|
||||||
logSocketEvent(socket, EVENT_CONNECT_TIMEOUT, "Connect timeout");
|
logSocketEvent(socket, EVENT_CONNECT_TIMEOUT, "Connect timeout");
|
||||||
logSocketEvent(socket, EVENT_CONNECTING, "Connecting...");
|
logSocketEvent(socket, EVENT_CONNECTING, "Connecting...");
|
||||||
@@ -130,38 +165,6 @@ public class SyncManager implements CommandRunner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCommandExecuted(@NonNull Command command,
|
|
||||||
@Nullable Long refreshKey)
|
|
||||||
{
|
|
||||||
if(command.isRemote()) return;
|
|
||||||
|
|
||||||
JSONObject msg = command.toJson();
|
|
||||||
Long now = new Date().getTime();
|
|
||||||
Event e = new Event(command.getId(), now, msg.toString());
|
|
||||||
e.save();
|
|
||||||
|
|
||||||
Log.i("SyncManager", "Adding to outbox: " + msg.toString());
|
|
||||||
|
|
||||||
pendingEmit.add(e);
|
|
||||||
if (readyToEmit) emitPending();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startListening()
|
|
||||||
{
|
|
||||||
if(!prefs.isSyncFeatureEnabled()) return;
|
|
||||||
if(groupKey.isEmpty()) return;
|
|
||||||
|
|
||||||
socket.connect();
|
|
||||||
commandRunner.addListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stopListening()
|
|
||||||
{
|
|
||||||
commandRunner.removeListener(this);
|
|
||||||
socket.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void emitPending()
|
private void emitPending()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -181,33 +184,6 @@ public class SyncManager implements CommandRunner.Listener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SSLContext getCACertSSLContext()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
InputStream caInput = context.getAssets().open("cacert.pem");
|
|
||||||
Certificate ca = cf.generateCertificate(caInput);
|
|
||||||
|
|
||||||
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
ks.load(null, null);
|
|
||||||
ks.setCertificateEntry("ca", ca);
|
|
||||||
|
|
||||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
|
|
||||||
TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
tmf.init(ks);
|
|
||||||
|
|
||||||
SSLContext ctx = SSLContext.getInstance("TLS");
|
|
||||||
ctx.init(null, tmf.getTrustManagers(), null);
|
|
||||||
|
|
||||||
return ctx;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void logSocketEvent(Socket socket, String event, final String msg)
|
private void logSocketEvent(Socket socket, String event, final String msg)
|
||||||
{
|
{
|
||||||
socket.on(event, args ->
|
socket.on(event, args ->
|
||||||
@@ -283,6 +259,8 @@ public class SyncManager implements CommandRunner.Listener
|
|||||||
public void call(Object... args)
|
public void call(Object... args)
|
||||||
{
|
{
|
||||||
readyToEmit = false;
|
readyToEmit = false;
|
||||||
|
for(Event e : pendingConfirmation) pendingEmit.add(e);
|
||||||
|
pendingConfirmation.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
81
app/src/main/java/org/isoron/uhabits/sync/SyncService.java
Normal file
81
app/src/main/java/org/isoron/uhabits/sync/SyncService.java
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.sync;
|
||||||
|
|
||||||
|
import android.app.*;
|
||||||
|
import android.content.*;
|
||||||
|
import android.os.*;
|
||||||
|
import android.support.v7.app.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.preferences.*;
|
||||||
|
|
||||||
|
public class SyncService extends Service implements Preferences.Listener
|
||||||
|
{
|
||||||
|
private SyncManager syncManager;
|
||||||
|
|
||||||
|
private Preferences prefs;
|
||||||
|
|
||||||
|
public SyncService()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate()
|
||||||
|
{
|
||||||
|
Intent notificationIntent = new Intent(this, SyncService.class);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
|
||||||
|
|
||||||
|
Notification notification = new NotificationCompat.Builder(this)
|
||||||
|
.setContentTitle("Loop Habit Tracker")
|
||||||
|
.setContentText("Sync service running")
|
||||||
|
.setSmallIcon(R.drawable.ic_notification)
|
||||||
|
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
startForeground(99999, notification);
|
||||||
|
|
||||||
|
HabitsApplication app = (HabitsApplication) getApplicationContext();
|
||||||
|
syncManager = app.getComponent().getSyncManager();
|
||||||
|
syncManager.startListening();
|
||||||
|
|
||||||
|
prefs = app.getComponent().getPreferences();
|
||||||
|
prefs.addListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSyncFeatureChanged()
|
||||||
|
{
|
||||||
|
if(!prefs.isSyncFeatureEnabled()) stopSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy()
|
||||||
|
{
|
||||||
|
syncManager.stopListening();
|
||||||
|
}
|
||||||
|
}
|
||||||
61
app/src/main/java/org/isoron/uhabits/utils/SSLUtils.java
Normal file
61
app/src/main/java/org/isoron/uhabits/utils/SSLUtils.java
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||||
|
*
|
||||||
|
* This file is part of Loop Habit Tracker.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 3 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* Loop Habit Tracker is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.isoron.uhabits.utils;
|
||||||
|
|
||||||
|
import android.content.*;
|
||||||
|
import android.support.annotation.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.security.*;
|
||||||
|
import java.security.cert.Certificate;
|
||||||
|
import java.security.cert.*;
|
||||||
|
|
||||||
|
import javax.net.ssl.*;
|
||||||
|
|
||||||
|
public abstract class SSLUtils
|
||||||
|
{
|
||||||
|
public static SSLContext getCACertSSLContext(@NonNull Context context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||||
|
InputStream caInput = context.getAssets().open("cacert.pem");
|
||||||
|
Certificate ca = cf.generateCertificate(caInput);
|
||||||
|
|
||||||
|
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
|
ks.load(null, null);
|
||||||
|
ks.setCertificateEntry("ca", ca);
|
||||||
|
|
||||||
|
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
|
||||||
|
TrustManagerFactory.getDefaultAlgorithm());
|
||||||
|
tmf.init(ks);
|
||||||
|
|
||||||
|
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||||
|
ctx.init(null, tmf.getTrustManagers(), null);
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user