mirror of
https://github.com/syncthing/syncthing-android.git
synced 2024-11-26 22:31:16 +00:00
Move all notification handling into common file
This commit is contained in:
parent
e184c43c3a
commit
4c2b325676
10 changed files with 189 additions and 157 deletions
|
@ -3,8 +3,11 @@ package com.nutomic.syncthingandroid;
|
||||||
import com.nutomic.syncthingandroid.activities.FirstStartActivity;
|
import com.nutomic.syncthingandroid.activities.FirstStartActivity;
|
||||||
import com.nutomic.syncthingandroid.activities.FolderPickerActivity;
|
import com.nutomic.syncthingandroid.activities.FolderPickerActivity;
|
||||||
import com.nutomic.syncthingandroid.activities.MainActivity;
|
import com.nutomic.syncthingandroid.activities.MainActivity;
|
||||||
|
import com.nutomic.syncthingandroid.receiver.AppConfigReceiver;
|
||||||
import com.nutomic.syncthingandroid.service.DeviceStateHolder;
|
import com.nutomic.syncthingandroid.service.DeviceStateHolder;
|
||||||
import com.nutomic.syncthingandroid.service.EventProcessor;
|
import com.nutomic.syncthingandroid.service.EventProcessor;
|
||||||
|
import com.nutomic.syncthingandroid.service.NotificationHandler;
|
||||||
|
import com.nutomic.syncthingandroid.service.RestApi;
|
||||||
import com.nutomic.syncthingandroid.service.SyncthingRunnable;
|
import com.nutomic.syncthingandroid.service.SyncthingRunnable;
|
||||||
import com.nutomic.syncthingandroid.service.SyncthingService;
|
import com.nutomic.syncthingandroid.service.SyncthingService;
|
||||||
import com.nutomic.syncthingandroid.util.Languages;
|
import com.nutomic.syncthingandroid.util.Languages;
|
||||||
|
@ -26,4 +29,7 @@ public interface DaggerComponent {
|
||||||
void inject(DeviceStateHolder deviceStateHolder);
|
void inject(DeviceStateHolder deviceStateHolder);
|
||||||
void inject(EventProcessor eventProcessor);
|
void inject(EventProcessor eventProcessor);
|
||||||
void inject(SyncthingRunnable syncthingRunnable);
|
void inject(SyncthingRunnable syncthingRunnable);
|
||||||
|
void inject(NotificationHandler notificationHandler);
|
||||||
|
void inject(AppConfigReceiver appConfigReceiver);
|
||||||
|
void inject(RestApi restApi);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ package com.nutomic.syncthingandroid;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import com.nutomic.syncthingandroid.service.NotificationHandler;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
|
@ -22,4 +24,10 @@ public class SyncthingModule {
|
||||||
public SharedPreferences getPreferences() {
|
public SharedPreferences getPreferences() {
|
||||||
return PreferenceManager.getDefaultSharedPreferences(mApp);
|
return PreferenceManager.getDefaultSharedPreferences(mApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
public NotificationHandler getNotificationHandler() {
|
||||||
|
return new NotificationHandler(mApp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
package com.nutomic.syncthingandroid.activities;
|
package com.nutomic.syncthingandroid.activities;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
|
|
||||||
import com.nutomic.syncthingandroid.R;
|
import com.nutomic.syncthingandroid.R;
|
||||||
import com.nutomic.syncthingandroid.service.SyncthingService;
|
import com.nutomic.syncthingandroid.service.NotificationHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows restart dialog.
|
* Shows restart dialog.
|
||||||
|
@ -20,8 +14,6 @@ import com.nutomic.syncthingandroid.service.SyncthingService;
|
||||||
*/
|
*/
|
||||||
public class RestartActivity extends SyncthingActivity {
|
public class RestartActivity extends SyncthingActivity {
|
||||||
|
|
||||||
public static final int NOTIFICATION_RESTART = 2;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -48,20 +40,7 @@ public class RestartActivity extends SyncthingActivity {
|
||||||
* Creates a notification prompting the user to restart the app.
|
* Creates a notification prompting the user to restart the app.
|
||||||
*/
|
*/
|
||||||
private void createRestartNotification() {
|
private void createRestartNotification() {
|
||||||
Intent intent = new Intent(this, SyncthingService.class)
|
new NotificationHandler(getService()).showRestartNotification();
|
||||||
.setAction(SyncthingService.ACTION_RESTART);
|
|
||||||
PendingIntent pi = PendingIntent.getService(this, 0, intent, 0);
|
|
||||||
|
|
||||||
Notification n = new NotificationCompat.Builder(this)
|
|
||||||
.setContentTitle(getString(R.string.restart_title))
|
|
||||||
.setContentText(getString(R.string.restart_notification_text))
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_notify)
|
|
||||||
.setContentIntent(pi)
|
|
||||||
.build();
|
|
||||||
n.flags |= Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
|
|
||||||
NotificationManager nm = (NotificationManager)
|
|
||||||
getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
nm.notify(NOTIFICATION_RESTART, n);
|
|
||||||
getApi().setRestartPostponed();
|
getApi().setRestartPostponed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,25 +1,21 @@
|
||||||
package com.nutomic.syncthingandroid.receiver;
|
package com.nutomic.syncthingandroid.receiver;
|
||||||
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
|
|
||||||
import com.nutomic.syncthingandroid.R;
|
import com.nutomic.syncthingandroid.SyncthingApp;
|
||||||
import com.nutomic.syncthingandroid.activities.MainActivity;
|
import com.nutomic.syncthingandroid.service.NotificationHandler;
|
||||||
import com.nutomic.syncthingandroid.service.SyncthingService;
|
import com.nutomic.syncthingandroid.service.SyncthingService;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Broadcast-receiver to control and configure SyncThing remotely
|
* Broadcast-receiver to control and configure SyncThing remotely
|
||||||
*
|
*
|
||||||
* Created by sqrt-1764 on 25.03.16.
|
* Created by sqrt-1764 on 25.03.16.
|
||||||
*/
|
*/
|
||||||
public class AppConfigReceiver extends BroadcastReceiver {
|
public class AppConfigReceiver extends BroadcastReceiver {
|
||||||
private static final int ID_NOTIFICATION_BACKGROUND_ACTIVE = 3;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start the Syncthing-Service
|
* Start the Syncthing-Service
|
||||||
|
@ -33,8 +29,11 @@ public class AppConfigReceiver extends BroadcastReceiver {
|
||||||
*/
|
*/
|
||||||
public static final String ACTION_STOP = "com.nutomic.syncthingandroid.action.STOP";
|
public static final String ACTION_STOP = "com.nutomic.syncthingandroid.action.STOP";
|
||||||
|
|
||||||
|
@Inject NotificationHandler mNotificationHandler;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
((SyncthingApp) context.getApplicationContext()).component().inject(this);
|
||||||
switch (intent.getAction()) {
|
switch (intent.getAction()) {
|
||||||
case ACTION_START:
|
case ACTION_START:
|
||||||
context.startService(new Intent(context, SyncthingService.class));
|
context.startService(new Intent(context, SyncthingService.class));
|
||||||
|
@ -42,31 +41,7 @@ public class AppConfigReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
case ACTION_STOP:
|
case ACTION_STOP:
|
||||||
if (SyncthingService.alwaysRunInBackground(context)) {
|
if (SyncthingService.alwaysRunInBackground(context)) {
|
||||||
final String msg = context.getString(R.string.appconfig_receiver_background_enabled);
|
mNotificationHandler.showStopSyncthingWarningNotification();
|
||||||
|
|
||||||
Context appContext = context.getApplicationContext();
|
|
||||||
|
|
||||||
NotificationCompat.Builder nb = new NotificationCompat.Builder(context)
|
|
||||||
.setContentText(msg)
|
|
||||||
.setTicker(msg)
|
|
||||||
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
|
|
||||||
.setContentTitle(context.getText(context.getApplicationInfo().labelRes))
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_notify)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
.setContentIntent(PendingIntent.getActivity(appContext,
|
|
||||||
0,
|
|
||||||
new Intent(appContext, MainActivity.class),
|
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT));
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
nb.setCategory(Notification.CATEGORY_ERROR); // Only supported in API 21 or better
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationManager nm =
|
|
||||||
(NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
|
|
||||||
nm.notify(ID_NOTIFICATION_BACKGROUND_ACTIVE, nb.build());
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
context.stopService(new Intent(context, SyncthingService.class));
|
context.stopService(new Intent(context, SyncthingService.class));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.nutomic.syncthingandroid.service;
|
package com.nutomic.syncthingandroid.service;
|
||||||
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -9,8 +7,6 @@ import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
import com.annimon.stream.Stream;
|
||||||
|
@ -56,6 +52,7 @@ public class EventProcessor implements SyncthingService.OnWebGuiAvailableListene
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final RestApi mApi;
|
private final RestApi mApi;
|
||||||
@Inject SharedPreferences mPreferences;
|
@Inject SharedPreferences mPreferences;
|
||||||
|
@Inject NotificationHandler mNotificationHandler;
|
||||||
|
|
||||||
public EventProcessor(Context context, RestApi api) {
|
public EventProcessor(Context context, RestApi api) {
|
||||||
((SyncthingApp) context.getApplicationContext()).component().inject(this);
|
((SyncthingApp) context.getApplicationContext()).component().inject(this);
|
||||||
|
@ -200,20 +197,9 @@ public class EventProcessor implements SyncthingService.OnWebGuiAvailableListene
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notify(String text, PendingIntent pi) {
|
private void notify(String text, PendingIntent pi) {
|
||||||
NotificationManager nm = (NotificationManager)
|
|
||||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
Notification n = new NotificationCompat.Builder(mContext)
|
|
||||||
.setContentTitle(mContext.getString(R.string.app_name))
|
|
||||||
.setContentText(text)
|
|
||||||
.setStyle(new NotificationCompat.BigTextStyle()
|
|
||||||
.bigText(text))
|
|
||||||
.setContentIntent(pi)
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_notify)
|
|
||||||
.setAutoCancel(true)
|
|
||||||
.build();
|
|
||||||
// HACK: Use a random, deterministic ID between 1000 and 2000 to avoid duplicate
|
// HACK: Use a random, deterministic ID between 1000 and 2000 to avoid duplicate
|
||||||
// notifications.
|
// notifications.
|
||||||
int notificationId = 1000 + text.hashCode() % 1000;
|
int notificationId = 1000 + text.hashCode() % 1000;
|
||||||
nm.notify(notificationId, n);
|
mNotificationHandler.showEventNotification(text, pi, notificationId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
package com.nutomic.syncthingandroid.service;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
|
||||||
|
import com.nutomic.syncthingandroid.R;
|
||||||
|
import com.nutomic.syncthingandroid.SyncthingApp;
|
||||||
|
import com.nutomic.syncthingandroid.activities.FirstStartActivity;
|
||||||
|
import com.nutomic.syncthingandroid.activities.MainActivity;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
public class NotificationHandler {
|
||||||
|
|
||||||
|
private static final int ID_PERSISTENT = 1;
|
||||||
|
private static final int ID_RESTART = 2;
|
||||||
|
private static final int ID_STOP_BACKGROUND_WARNING = 3;
|
||||||
|
private static final int ID_CRASH = 9;
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
@Inject SharedPreferences mPreferences;
|
||||||
|
private final NotificationManager mNotificationManager;
|
||||||
|
|
||||||
|
public NotificationHandler(Context context) {
|
||||||
|
((SyncthingApp) context.getApplicationContext()).component().inject(this);
|
||||||
|
mContext = context;
|
||||||
|
mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows or hides the persistent notification based on running state and
|
||||||
|
* {@link SyncthingService#PREF_NOTIFICATION_TYPE}.
|
||||||
|
*/
|
||||||
|
public void updatePersistentNotification(SyncthingService service, SyncthingService.State currentState) {
|
||||||
|
String type = mPreferences.getString(SyncthingService.PREF_NOTIFICATION_TYPE, "low_priority");
|
||||||
|
boolean foreground = mPreferences.getBoolean(SyncthingService.PREF_FOREGROUND_SERVICE, false);
|
||||||
|
if ("none".equals(type) && foreground) {
|
||||||
|
// foreground priority requires any notification
|
||||||
|
// so this ensures that we either have a "default" or "low_priority" notification,
|
||||||
|
// but not "none".
|
||||||
|
type = "low_priority";
|
||||||
|
}
|
||||||
|
if ((currentState == SyncthingService.State.ACTIVE || currentState == SyncthingService.State.STARTING) &&
|
||||||
|
!type.equals("none")) {
|
||||||
|
// Launch FirstStartActivity instead of MainActivity so we can request permission if
|
||||||
|
// necessary.
|
||||||
|
PendingIntent pi = PendingIntent.getActivity(mContext, 0,
|
||||||
|
new Intent(mContext, FirstStartActivity.class), 0);
|
||||||
|
NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
|
||||||
|
.setContentTitle(mContext.getString(R.string.syncthing_active))
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notify)
|
||||||
|
.setOngoing(true)
|
||||||
|
.setContentIntent(pi);
|
||||||
|
if (type.equals("low_priority"))
|
||||||
|
builder.setPriority(NotificationCompat.PRIORITY_MIN);
|
||||||
|
|
||||||
|
if (foreground) {
|
||||||
|
builder.setContentText(mContext.getString(R.string.syncthing_active_foreground));
|
||||||
|
service.startForeground(ID_PERSISTENT, builder.build());
|
||||||
|
} else {
|
||||||
|
service.stopForeground(false); // ensure no longer running with foreground priority
|
||||||
|
mNotificationManager.notify(ID_PERSISTENT, builder.build());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ensure no longer running with foreground priority
|
||||||
|
cancelPersistentNotification(service);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelPersistentNotification(SyncthingService service) {
|
||||||
|
service.stopForeground(false);
|
||||||
|
mNotificationManager.cancel(ID_PERSISTENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showCrashedNotification(Intent intent) {
|
||||||
|
if (mPreferences.getBoolean("notify_crashes", false)) {
|
||||||
|
Notification n = new NotificationCompat.Builder(mContext)
|
||||||
|
.setContentTitle(mContext.getString(R.string.notification_crash_title))
|
||||||
|
.setContentText(mContext.getString(R.string.notification_crash_text))
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notify)
|
||||||
|
.setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0))
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.build();
|
||||||
|
mNotificationManager.notify(ID_CRASH, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showEventNotification(String text, PendingIntent pi, int id) {
|
||||||
|
Notification n = new NotificationCompat.Builder(mContext)
|
||||||
|
.setContentTitle(mContext.getString(R.string.app_name))
|
||||||
|
.setContentText(text)
|
||||||
|
.setStyle(new NotificationCompat.BigTextStyle()
|
||||||
|
.bigText(text))
|
||||||
|
.setContentIntent(pi)
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notify)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.build();
|
||||||
|
mNotificationManager.notify(id, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showRestartNotification() {
|
||||||
|
Intent intent = new Intent(mContext, SyncthingService.class)
|
||||||
|
.setAction(SyncthingService.ACTION_RESTART);
|
||||||
|
PendingIntent pi = PendingIntent.getService(mContext, 0, intent, 0);
|
||||||
|
|
||||||
|
Notification n = new NotificationCompat.Builder(mContext)
|
||||||
|
.setContentTitle(mContext.getString(R.string.restart_title))
|
||||||
|
.setContentText(mContext.getString(R.string.restart_notification_text))
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notify)
|
||||||
|
.setContentIntent(pi)
|
||||||
|
.build();
|
||||||
|
n.flags |= Notification.FLAG_ONLY_ALERT_ONCE | Notification.FLAG_AUTO_CANCEL;
|
||||||
|
mNotificationManager.notify(ID_RESTART, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelRestartNotification() {
|
||||||
|
mNotificationManager.cancel(ID_RESTART);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showStopSyncthingWarningNotification() {
|
||||||
|
final String msg = mContext.getString(R.string.appconfig_receiver_background_enabled);
|
||||||
|
NotificationCompat.Builder nb = new NotificationCompat.Builder(mContext)
|
||||||
|
.setContentText(msg)
|
||||||
|
.setTicker(msg)
|
||||||
|
.setStyle(new NotificationCompat.BigTextStyle().bigText(msg))
|
||||||
|
.setContentTitle(mContext.getText(mContext.getApplicationInfo().labelRes))
|
||||||
|
.setSmallIcon(R.drawable.ic_stat_notify)
|
||||||
|
.setAutoCancel(true)
|
||||||
|
.setContentIntent(PendingIntent.getActivity(mContext, 0,
|
||||||
|
new Intent(mContext, MainActivity.class),
|
||||||
|
PendingIntent.FLAG_UPDATE_CURRENT));
|
||||||
|
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
nb.setCategory(Notification.CATEGORY_ERROR);
|
||||||
|
}
|
||||||
|
mNotificationManager.notify(ID_STOP_BACKGROUND_WARNING, nb.build());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package com.nutomic.syncthingandroid.service;
|
package com.nutomic.syncthingandroid.service;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -17,6 +16,7 @@ import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
import com.nutomic.syncthingandroid.BuildConfig;
|
import com.nutomic.syncthingandroid.BuildConfig;
|
||||||
|
import com.nutomic.syncthingandroid.SyncthingApp;
|
||||||
import com.nutomic.syncthingandroid.activities.RestartActivity;
|
import com.nutomic.syncthingandroid.activities.RestartActivity;
|
||||||
import com.nutomic.syncthingandroid.http.GetRequest;
|
import com.nutomic.syncthingandroid.http.GetRequest;
|
||||||
import com.nutomic.syncthingandroid.http.PostConfigRequest;
|
import com.nutomic.syncthingandroid.http.PostConfigRequest;
|
||||||
|
@ -43,6 +43,8 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides functions to interact with the syncthing REST API.
|
* Provides functions to interact with the syncthing REST API.
|
||||||
*/
|
*/
|
||||||
|
@ -100,8 +102,11 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
*/
|
*/
|
||||||
private final HashMap<String, Model> mCachedModelInfo = new HashMap<>();
|
private final HashMap<String, Model> mCachedModelInfo = new HashMap<>();
|
||||||
|
|
||||||
|
@Inject NotificationHandler mNotificationHandler;
|
||||||
|
|
||||||
public RestApi(Context context, URL url, String apiKey, OnApiAvailableListener apiListener,
|
public RestApi(Context context, URL url, String apiKey, OnApiAvailableListener apiListener,
|
||||||
OnConfigChangedListener configListener) {
|
OnConfigChangedListener configListener) {
|
||||||
|
((SyncthingApp) context.getApplicationContext()).component().inject(this);
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mUrl = url;
|
mUrl = url;
|
||||||
mApiKey = apiKey;
|
mApiKey = apiKey;
|
||||||
|
@ -195,13 +200,8 @@ public class RestApi implements SyncthingService.OnWebGuiAvailableListener,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops syncthing and cancels notification.
|
|
||||||
*/
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
NotificationManager nm = (NotificationManager)
|
mNotificationHandler.cancelRestartNotification();
|
||||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
nm.cancel(RestartActivity.NOTIFICATION_RESTART);
|
|
||||||
mRestartPostponed = false;
|
mRestartPostponed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,16 @@
|
||||||
package com.nutomic.syncthingandroid.service;
|
package com.nutomic.syncthingandroid.service;
|
||||||
|
|
||||||
import android.app.Notification;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.nutomic.syncthingandroid.R;
|
|
||||||
import com.nutomic.syncthingandroid.SyncthingApp;
|
import com.nutomic.syncthingandroid.SyncthingApp;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
@ -50,7 +45,6 @@ public class SyncthingRunnable implements Runnable {
|
||||||
private static final String TAG_KILL = "SyncthingRunnableKill";
|
private static final String TAG_KILL = "SyncthingRunnableKill";
|
||||||
private static final String BINARY_NAME = "libsyncthing.so";
|
private static final String BINARY_NAME = "libsyncthing.so";
|
||||||
private static final int LOG_FILE_MAX_LINES = 10;
|
private static final int LOG_FILE_MAX_LINES = 10;
|
||||||
private static final int NOTIFICATION_ID_CRASH = 9;
|
|
||||||
|
|
||||||
private static final AtomicReference<Process> mSyncthing = new AtomicReference<>();
|
private static final AtomicReference<Process> mSyncthing = new AtomicReference<>();
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
|
@ -59,6 +53,7 @@ public class SyncthingRunnable implements Runnable {
|
||||||
private final File mLogFile;
|
private final File mLogFile;
|
||||||
@Inject SharedPreferences mPreferences;
|
@Inject SharedPreferences mPreferences;
|
||||||
private final boolean mUseRoot;
|
private final boolean mUseRoot;
|
||||||
|
@Inject NotificationHandler mNotificationHandler;
|
||||||
|
|
||||||
public enum Command {
|
public enum Command {
|
||||||
generate, // Generate keys, a config file and immediately exit.
|
generate, // Generate keys, a config file and immediately exit.
|
||||||
|
@ -146,22 +141,10 @@ public class SyncthingRunnable implements Runnable {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.w(TAG, "Syncthing has crashed (exit code " + ret + ")");
|
Log.w(TAG, "Syncthing has crashed (exit code " + ret + ")");
|
||||||
if (mPreferences.getBoolean("notify_crashes", false)) {
|
|
||||||
// Show notification to inform user about crash.
|
// Show notification to inform user about crash.
|
||||||
Intent intent = new Intent();
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||||
intent.setAction(android.content.Intent.ACTION_VIEW);
|
|
||||||
intent.setDataAndType(Uri.fromFile(mLogFile), "text/plain");
|
intent.setDataAndType(Uri.fromFile(mLogFile), "text/plain");
|
||||||
Notification n = new NotificationCompat.Builder(mContext)
|
mNotificationHandler.showCrashedNotification(intent);
|
||||||
.setContentTitle(mContext.getString(R.string.notification_crash_title))
|
|
||||||
.setContentText(mContext.getString(R.string.notification_crash_text))
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_notify)
|
|
||||||
.setContentIntent(PendingIntent.getActivity(mContext, 0, intent, 0))
|
|
||||||
.setAutoCancel(true)
|
|
||||||
.build();
|
|
||||||
NotificationManager nm = (NotificationManager)
|
|
||||||
mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
|
||||||
nm.notify(NOTIFICATION_ID_CRASH, n);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IOException | InterruptedException e) {
|
} catch (IOException | InterruptedException e) {
|
||||||
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
|
Log.e(TAG, "Failed to execute syncthing binary or read output", e);
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package com.nutomic.syncthingandroid.service;
|
package com.nutomic.syncthingandroid.service;
|
||||||
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.app.PendingIntent;
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -16,7 +14,6 @@ import android.os.IBinder;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.app.NotificationCompat;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
@ -25,7 +22,6 @@ import com.annimon.stream.Stream;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.nutomic.syncthingandroid.R;
|
import com.nutomic.syncthingandroid.R;
|
||||||
import com.nutomic.syncthingandroid.SyncthingApp;
|
import com.nutomic.syncthingandroid.SyncthingApp;
|
||||||
import com.nutomic.syncthingandroid.activities.FirstStartActivity;
|
|
||||||
import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask;
|
import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask;
|
||||||
import com.nutomic.syncthingandroid.model.Folder;
|
import com.nutomic.syncthingandroid.model.Folder;
|
||||||
import com.nutomic.syncthingandroid.receiver.NetworkReceiver;
|
import com.nutomic.syncthingandroid.receiver.NetworkReceiver;
|
||||||
|
@ -95,12 +91,10 @@ public class SyncthingService extends Service implements
|
||||||
public static final String PREF_SYNC_ONLY_CHARGING = "sync_only_charging";
|
public static final String PREF_SYNC_ONLY_CHARGING = "sync_only_charging";
|
||||||
public static final String PREF_RESPECT_BATTERY_SAVING = "respect_battery_saving";
|
public static final String PREF_RESPECT_BATTERY_SAVING = "respect_battery_saving";
|
||||||
public static final String PREF_USE_ROOT = "use_root";
|
public static final String PREF_USE_ROOT = "use_root";
|
||||||
private static final String PREF_NOTIFICATION_TYPE = "notification_type";
|
public static final String PREF_NOTIFICATION_TYPE = "notification_type";
|
||||||
public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running";
|
public static final String PREF_USE_WAKE_LOCK = "wakelock_while_binary_running";
|
||||||
public static final String PREF_FOREGROUND_SERVICE = "run_as_foreground_service";
|
public static final String PREF_FOREGROUND_SERVICE = "run_as_foreground_service";
|
||||||
|
|
||||||
private static final int NOTIFICATION_ACTIVE = 1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback for when the Syncthing web interface becomes first available after service start.
|
* Callback for when the Syncthing web interface becomes first available after service start.
|
||||||
*/
|
*/
|
||||||
|
@ -149,6 +143,8 @@ public class SyncthingService extends Service implements
|
||||||
private final NetworkReceiver mNetworkReceiver = new NetworkReceiver();
|
private final NetworkReceiver mNetworkReceiver = new NetworkReceiver();
|
||||||
private final BroadcastReceiver mPowerSaveModeChangedReceiver = new PowerSaveModeChangedReceiver();
|
private final BroadcastReceiver mPowerSaveModeChangedReceiver = new PowerSaveModeChangedReceiver();
|
||||||
|
|
||||||
|
@Inject NotificationHandler mNotificationHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object that can be locked upon when accessing mCurrentState
|
* Object that can be locked upon when accessing mCurrentState
|
||||||
* Currently used to male onDestroy() and PollWebGuiAvailableTaskImpl.onPostExcecute() tread-safe
|
* Currently used to male onDestroy() and PollWebGuiAvailableTaskImpl.onPostExcecute() tread-safe
|
||||||
|
@ -220,53 +216,10 @@ public class SyncthingService extends Service implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shows or hides the persistent notification based on running state and
|
|
||||||
* {@link #PREF_NOTIFICATION_TYPE}.
|
|
||||||
*/
|
|
||||||
private void updateNotification() {
|
|
||||||
String type = mPreferences.getString(PREF_NOTIFICATION_TYPE, "low_priority");
|
|
||||||
boolean foreground = mPreferences.getBoolean(PREF_FOREGROUND_SERVICE, false);
|
|
||||||
if ("none".equals(type) && foreground) {
|
|
||||||
// foreground priority requires any notification
|
|
||||||
// so this ensures that we either have a "default" or "low_priority" notification,
|
|
||||||
// but not "none".
|
|
||||||
type = "low_priority";
|
|
||||||
}
|
|
||||||
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
||||||
if ((mCurrentState == State.ACTIVE || mCurrentState == State.STARTING) &&
|
|
||||||
!type.equals("none")) {
|
|
||||||
Context appContext = getApplicationContext();
|
|
||||||
// Launch FirstStartActivity instead of MainActivity so we can request permission if
|
|
||||||
// necessary.
|
|
||||||
PendingIntent pi = PendingIntent.getActivity(appContext, 0,
|
|
||||||
new Intent(appContext, FirstStartActivity.class), 0);
|
|
||||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(appContext)
|
|
||||||
.setContentTitle(getString(R.string.syncthing_active))
|
|
||||||
.setSmallIcon(R.drawable.ic_stat_notify)
|
|
||||||
.setOngoing(true)
|
|
||||||
.setContentIntent(pi);
|
|
||||||
if (type.equals("low_priority"))
|
|
||||||
builder.setPriority(NotificationCompat.PRIORITY_MIN);
|
|
||||||
|
|
||||||
if (foreground) {
|
|
||||||
builder.setContentText(getString(R.string.syncthing_active_foreground));
|
|
||||||
startForeground(NOTIFICATION_ACTIVE, builder.build());
|
|
||||||
} else {
|
|
||||||
stopForeground(false); // ensure no longer running with foreground priority
|
|
||||||
nm.notify(NOTIFICATION_ACTIVE, builder.build());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// ensure no longer running with foreground priority
|
|
||||||
stopForeground(false);
|
|
||||||
nm.cancel(NOTIFICATION_ACTIVE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||||
if (key.equals(PREF_NOTIFICATION_TYPE) || key.equals(PREF_FOREGROUND_SERVICE))
|
if (key.equals(PREF_NOTIFICATION_TYPE) || key.equals(PREF_FOREGROUND_SERVICE))
|
||||||
updateNotification();
|
mNotificationHandler.updatePersistentNotification(this, mCurrentState);
|
||||||
else if (key.equals(PREF_SYNC_ONLY_CHARGING) || key.equals(PREF_SYNC_ONLY_WIFI)
|
else if (key.equals(PREF_SYNC_ONLY_CHARGING) || key.equals(PREF_SYNC_ONLY_WIFI)
|
||||||
|| key.equals(PREF_SYNC_ONLY_WIFI_SSIDS) || key.equals(PREF_RESPECT_BATTERY_SAVING)) {
|
|| key.equals(PREF_SYNC_ONLY_WIFI_SSIDS) || key.equals(PREF_RESPECT_BATTERY_SAVING)) {
|
||||||
updateState();
|
updateState();
|
||||||
|
@ -338,7 +291,6 @@ public class SyncthingService extends Service implements
|
||||||
pollWebGui();
|
pollWebGui();
|
||||||
mSyncthingRunnable = new SyncthingRunnable(SyncthingService.this, SyncthingRunnable.Command.main);
|
mSyncthingRunnable = new SyncthingRunnable(SyncthingService.this, SyncthingRunnable.Command.main);
|
||||||
new Thread(mSyncthingRunnable).start();
|
new Thread(mSyncthingRunnable).start();
|
||||||
updateNotification();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,9 +361,7 @@ public class SyncthingService extends Service implements
|
||||||
if (mApi != null)
|
if (mApi != null)
|
||||||
mApi.shutdown();
|
mApi.shutdown();
|
||||||
|
|
||||||
NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
mNotificationHandler.cancelPersistentNotification(this);
|
||||||
stopForeground(false);
|
|
||||||
nm.cancel(NOTIFICATION_ACTIVE);
|
|
||||||
|
|
||||||
Stream.of(mObservers).forEach(FolderObserver::stopWatching);
|
Stream.of(mObservers).forEach(FolderObserver::stopWatching);
|
||||||
mObservers.clear();
|
mObservers.clear();
|
||||||
|
@ -498,6 +448,7 @@ public class SyncthingService extends Service implements
|
||||||
*/
|
*/
|
||||||
private void onApiChange(State newState) {
|
private void onApiChange(State newState) {
|
||||||
mCurrentState = newState;
|
mCurrentState = newState;
|
||||||
|
mNotificationHandler.updatePersistentNotification(this, mCurrentState);
|
||||||
for (Iterator<OnApiChangeListener> i = mOnApiChangeListeners.iterator();
|
for (Iterator<OnApiChangeListener> i = mOnApiChangeListeners.iterator();
|
||||||
i.hasNext(); ) {
|
i.hasNext(); ) {
|
||||||
OnApiChangeListener listener = i.next();
|
OnApiChangeListener listener = i.next();
|
||||||
|
|
|
@ -8,7 +8,6 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.nutomic.syncthingandroid.R;
|
import com.nutomic.syncthingandroid.R;
|
||||||
import com.nutomic.syncthingandroid.service.SyncthingRunnable;
|
import com.nutomic.syncthingandroid.service.SyncthingRunnable;
|
||||||
import com.nutomic.syncthingandroid.util.Util;
|
|
||||||
|
|
||||||
import org.mindrot.jbcrypt.BCrypt;
|
import org.mindrot.jbcrypt.BCrypt;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
|
Loading…
Reference in a new issue