1
0
Fork 0
mirror of https://github.com/syncthing/syncthing-android.git synced 2024-12-23 03:11:30 +00:00

Use Dagger to inject SharedPreferences

This commit is contained in:
Felix Ableitner 2017-10-04 00:19:30 +09:00
parent 61d1119889
commit e184c43c3a
12 changed files with 127 additions and 45 deletions

View file

@ -33,6 +33,8 @@ dependencies {
compile 'com.annimon:stream:1.1.8'
compile 'com.android.volley:volley:1.0.0'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile "com.google.dagger:dagger:2.11"
annotationProcessor "com.google.dagger:dagger-compiler:2.11"
androidTestCompile 'com.android.support.test:rules:1.0.1'
androidTestCompile 'com.android.support:support-annotations:26.1.0'
}

View file

@ -0,0 +1,29 @@
package com.nutomic.syncthingandroid;
import com.nutomic.syncthingandroid.activities.FirstStartActivity;
import com.nutomic.syncthingandroid.activities.FolderPickerActivity;
import com.nutomic.syncthingandroid.activities.MainActivity;
import com.nutomic.syncthingandroid.service.DeviceStateHolder;
import com.nutomic.syncthingandroid.service.EventProcessor;
import com.nutomic.syncthingandroid.service.SyncthingRunnable;
import com.nutomic.syncthingandroid.service.SyncthingService;
import com.nutomic.syncthingandroid.util.Languages;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {SyncthingModule.class})
public interface DaggerComponent {
void inject(SyncthingApp app);
void inject(MainActivity activity);
void inject(FirstStartActivity activity);
void inject(FolderPickerActivity activity);
void inject(Languages languages);
void inject(SyncthingService service);
void inject(DeviceStateHolder deviceStateHolder);
void inject(EventProcessor eventProcessor);
void inject(SyncthingRunnable syncthingRunnable);
}

View file

@ -5,11 +5,21 @@ import android.os.StrictMode;
import com.nutomic.syncthingandroid.util.Languages;
import javax.inject.Inject;
public class SyncthingApp extends Application {
@Inject DaggerComponent mComponent;
@Override
public void onCreate() {
super.onCreate();
DaggerDaggerComponent.builder()
.syncthingModule(new SyncthingModule(this))
.build()
.inject(this);
new Languages(this).setLanguage(this);
// Set VM policy to avoid crash when sending folder URI to file manager.
@ -19,4 +29,8 @@ public class SyncthingApp extends Application {
.build();
StrictMode.setVmPolicy(policy);
}
public DaggerComponent component() {
return mComponent;
}
}

View file

@ -0,0 +1,25 @@
package com.nutomic.syncthingandroid;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class SyncthingModule {
private final SyncthingApp mApp;
public SyncthingModule(SyncthingApp app) {
mApp = app;
}
@Provides
@Singleton
public SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(mApp);
}
}

View file

@ -6,7 +6,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
@ -15,13 +14,16 @@ import android.widget.Button;
import android.widget.Toast;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.service.SyncthingService;
import javax.inject.Inject;
public class FirstStartActivity extends Activity implements Button.OnClickListener {
private static final int REQUEST_WRITE_STORAGE = 142;
private SharedPreferences mPreferences;
@Inject SharedPreferences mPreferences;
/**
* Handles activity behaviour depending on {@link #isFirstStart()} and {@link #haveStoragePermission()}.
@ -29,8 +31,8 @@ public class FirstStartActivity extends Activity implements Button.OnClickListen
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((SyncthingApp) getApplication()).component().inject(this);
startService(new Intent(this, SyncthingService.class));
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
if (!isFirstStart()) {
if (haveStoragePermission()) {

View file

@ -11,7 +11,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.text.TextUtils;
@ -29,6 +28,7 @@ import android.widget.Toast;
import com.google.common.collect.Sets;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.service.SyncthingService;
import java.io.File;
@ -37,6 +37,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import javax.inject.Inject;
/**
* Activity that allows selecting a directory in the local file system.
*/
@ -52,10 +54,9 @@ public class FolderPickerActivity extends SyncthingActivity
public static final int DIRECTORY_REQUEST_CODE = 234;
private ListView mListView;
private FileAdapter mFilesAdapter;
private RootsAdapter mRootsAdapter;
@Inject SharedPreferences mPreferences;
/**
* Location of null means that the list of roots is displayed.
@ -75,6 +76,7 @@ public class FolderPickerActivity extends SyncthingActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((SyncthingApp) getApplication()).component().inject(this);
setContentView(R.layout.activity_folder_picker);
mListView = findViewById(android.R.id.list);
@ -120,8 +122,7 @@ public class FolderPickerActivity extends SyncthingActivity
}
// Add paths that might not be accessible to Syncthing.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (sp.getBoolean("advanced_folder_picker", false)) {
if (mPreferences.getBoolean("advanced_folder_picker", false)) {
Collections.addAll(roots, new File("/storage/").listFiles());
roots.add(new File("/"));
}

View file

@ -19,7 +19,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
@ -44,6 +43,7 @@ import android.widget.Toast;
import com.annimon.stream.function.Consumer;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.fragments.DeviceListFragment;
import com.nutomic.syncthingandroid.fragments.DrawerFragment;
import com.nutomic.syncthingandroid.fragments.FolderListFragment;
@ -54,6 +54,8 @@ import com.nutomic.syncthingandroid.util.Util;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import static java.lang.Math.min;
/**
@ -92,6 +94,7 @@ public class MainActivity extends StateDialogActivity
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
@Inject SharedPreferences mPreferences;
/**
* Handles various dialogs based on current state.
@ -121,9 +124,8 @@ public class MainActivity extends StateDialogActivity
private void showBatteryOptimizationDialogIfNecessary() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
return;
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
boolean dontShowAgain = sp.getBoolean("battery_optimization_dont_show_again", false);
boolean dontShowAgain = mPreferences.getBoolean("battery_optimization_dont_show_again", false);
if (dontShowAgain || mBatteryOptimizationsDialog != null ||
pm.isIgnoringBatteryOptimizations(getPackageName()) ||
mBatteryOptimizationDialogDismissed) {
@ -143,12 +145,12 @@ public class MainActivity extends StateDialogActivity
// crash reports).
Log.w(TAG, "Request ignore battery optimizations not supported", e);
Toast.makeText(this, R.string.dialog_disable_battery_optimizations_not_supported, Toast.LENGTH_LONG).show();
sp.edit().putBoolean("battery_optimization_dont_show_again", true).apply();
mPreferences.edit().putBoolean("battery_optimization_dont_show_again", true).apply();
}
})
.setNeutralButton(R.string.dialog_disable_battery_optimization_later, (d, i) -> mBatteryOptimizationDialogDismissed = true)
.setNegativeButton(R.string.dialog_disable_battery_optimization_dont_show_again, (d, i) ->
sp.edit().putBoolean("battery_optimization_dont_show_again", true).apply())
mPreferences.edit().putBoolean("battery_optimization_dont_show_again", true).apply())
.setOnCancelListener(d -> mBatteryOptimizationDialogDismissed = true)
.show();
}
@ -205,6 +207,7 @@ public class MainActivity extends StateDialogActivity
*/
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
((SyncthingApp) getApplication()).component().inject(this);
setContentView(R.layout.activity_main);
mDrawerLayout = findViewById(R.id.drawer_layout);

View file

@ -7,21 +7,19 @@ import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import com.google.common.base.Joiner;
import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.receiver.BatteryReceiver;
import com.nutomic.syncthingandroid.receiver.NetworkReceiver;
import com.nutomic.syncthingandroid.receiver.PowerSaveModeChangedReceiver;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
/**
* Holds information about the current wifi and charging state of the device.
*
@ -56,10 +54,10 @@ public class DeviceStateHolder {
}
private final Context mContext;
private final SharedPreferences mPreferences;
private final LocalBroadcastManager mBroadcastManager;
private final DeviceStateChangedReceiver mReceiver = new DeviceStateChangedReceiver();
private final OnDeviceStateChangedListener mListener;
@Inject SharedPreferences mPreferences;
private boolean mIsAllowedNetworkConnection = false;
private String mWifiSsid;
@ -67,8 +65,8 @@ public class DeviceStateHolder {
private boolean mIsPowerSaving = true;
public DeviceStateHolder(Context context, OnDeviceStateChangedListener listener) {
((SyncthingApp) context.getApplicationContext()).component().inject(this);
mContext = context;
mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
mBroadcastManager = LocalBroadcastManager.getInstance(mContext);
mBroadcastManager.registerReceiver(mReceiver, new IntentFilter(ACTION_DEVICE_STATE_CHANGED));
mListener = listener;

View file

@ -15,6 +15,7 @@ import android.util.Log;
import com.annimon.stream.Stream;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.activities.DeviceActivity;
import com.nutomic.syncthingandroid.activities.FolderActivity;
import com.nutomic.syncthingandroid.model.Device;
@ -24,6 +25,8 @@ import com.nutomic.syncthingandroid.model.Folder;
import java.io.File;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
/**
* Run by the syncthing service to convert syncthing events into local broadcasts.
*
@ -52,8 +55,10 @@ public class EventProcessor implements SyncthingService.OnWebGuiAvailableListene
private final Context mContext;
private final RestApi mApi;
@Inject SharedPreferences mPreferences;
public EventProcessor(Context context, RestApi api) {
((SyncthingApp) context.getApplicationContext()).component().inject(this);
mContext = context;
mApi = api;
}
@ -62,8 +67,7 @@ public class EventProcessor implements SyncthingService.OnWebGuiAvailableListene
public void run() {
// Restore the last event id if the event processor may have been restartet.
if (mLastEventId == 0) {
mLastEventId = PreferenceManager.getDefaultSharedPreferences(mContext)
.getLong(PREF_LAST_SYNC_ID, 0);
mLastEventId = mPreferences.getLong(PREF_LAST_SYNC_ID, 0);
}
// First check if the event number ran backwards.
@ -163,10 +167,7 @@ public class EventProcessor implements SyncthingService.OnWebGuiAvailableListene
mLastEventId = id;
// Store the last EventId in case we get killed
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
//noinspection CommitPrefEdits
sp.edit().putLong(PREF_LAST_SYNC_ID, mLastEventId).apply();
mPreferences.edit().putLong(PREF_LAST_SYNC_ID, mLastEventId).apply();
}
synchronized (mMainThreadHandler) {

View file

@ -9,7 +9,6 @@ import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Environment;
import android.os.PowerManager;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.text.TextUtils;
import android.util.Log;
@ -17,6 +16,7 @@ import android.util.Log;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -33,6 +33,8 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import javax.inject.Inject;
import eu.chainfire.libsuperuser.Shell;
/**
@ -55,7 +57,7 @@ public class SyncthingRunnable implements Runnable {
private final String mSyncthingBinary;
private String[] mCommand;
private final File mLogFile;
private final SharedPreferences mPreferences;
@Inject SharedPreferences mPreferences;
private final boolean mUseRoot;
public enum Command {
@ -70,10 +72,10 @@ public class SyncthingRunnable implements Runnable {
* @param command Which type of Syncthing command to execute.
*/
public SyncthingRunnable(Context context, Command command) {
((SyncthingApp) context.getApplicationContext()).component().inject(this);
mContext = context;
mSyncthingBinary = mContext.getApplicationInfo().nativeLibraryDir + "/" + BINARY_NAME;
mLogFile = new File(mContext.getExternalFilesDir(null), "syncthing.log");
mPreferences = PreferenceManager.getDefaultSharedPreferences(mContext);
mUseRoot = mPreferences.getBoolean(SyncthingService.PREF_USE_ROOT, false) && Shell.SU.available();
switch (command) {
case generate:
@ -93,7 +95,6 @@ public class SyncthingRunnable implements Runnable {
@Override
public void run() {
trimLogFile();
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
int ret;
// Make sure Syncthing is executable
try {
@ -114,7 +115,7 @@ public class SyncthingRunnable implements Runnable {
if (wakeLock != null)
wakeLock.acquire();
HashMap<String, String> targetEnv = buildEnvironment(sp);
HashMap<String, String> targetEnv = buildEnvironment();
process = setupAndLaunch(targetEnv);
mSyncthing.set(process);
@ -373,11 +374,11 @@ public class SyncthingRunnable implements Runnable {
}
}
private HashMap<String, String> buildEnvironment(SharedPreferences sp) {
private HashMap<String, String> buildEnvironment() {
HashMap<String, String> targetEnv = new HashMap<String, String>();
// Set home directory to data folder for web GUI folder picker.
targetEnv.put("HOME", Environment.getExternalStorageDirectory().getAbsolutePath());
targetEnv.put("STTRACE", sp.getString("sttrace", ""));
targetEnv.put("STTRACE", mPreferences.getString("sttrace", ""));
File externalFilesDir = mContext.getExternalFilesDir(null);
if (externalFilesDir != null)
targetEnv.put("STGUIASSETS", externalFilesDir.getAbsolutePath() + "/gui");
@ -386,13 +387,13 @@ public class SyncthingRunnable implements Runnable {
// Disable hash benchmark for faster startup.
// https://github.com/syncthing/syncthing/issues/4348
targetEnv.put("STHASHING", "minio");
if (sp.getBoolean("use_tor", false)) {
if (mPreferences.getBoolean("use_tor", false)) {
targetEnv.put("all_proxy", "socks5://localhost:9050");
targetEnv.put("ALL_PROXY_NO_FALLBACK", "1");
}
if (sp.getBoolean("use_legacy_hashing", false))
if (mPreferences.getBoolean("use_legacy_hashing", false))
targetEnv.put("STHASHING", "standard");
putCustomEnvironmentVariables(targetEnv, sp);
putCustomEnvironmentVariables(targetEnv, mPreferences);
return targetEnv;
}

View file

@ -24,6 +24,7 @@ import com.android.PRNGFixes;
import com.annimon.stream.Stream;
import com.google.common.io.Files;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp;
import com.nutomic.syncthingandroid.activities.FirstStartActivity;
import com.nutomic.syncthingandroid.http.PollWebGuiAvailableTask;
import com.nutomic.syncthingandroid.model.Folder;
@ -40,6 +41,8 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
/**
* Holds the native syncthing instance and provides an API to access it.
*/
@ -162,6 +165,8 @@ public class SyncthingService extends Service implements
private SyncthingRunnable mSyncthingRunnable;
@Inject SharedPreferences mPreferences;
/**
* Handles intents, either {@link #ACTION_RESTART}, or intents having
* {@link DeviceStateHolder#EXTRA_IS_ALLOWED_NETWORK_CONNECTION} or
@ -220,9 +225,8 @@ public class SyncthingService extends Service implements
* {@link #PREF_NOTIFICATION_TYPE}.
*/
private void updateNotification() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
String type = sp.getString(PREF_NOTIFICATION_TYPE, "low_priority");
boolean foreground = sp.getBoolean(PREF_FOREGROUND_SERVICE, false);
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,
@ -276,6 +280,7 @@ public class SyncthingService extends Service implements
public void onCreate() {
super.onCreate();
PRNGFixes.apply();
((SyncthingApp) getApplication()).component().inject(this);
mDeviceStateHolder = new DeviceStateHolder(SyncthingService.this, this::updateState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ -290,8 +295,7 @@ public class SyncthingService extends Service implements
new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
}
updateState();
PreferenceManager.getDefaultSharedPreferences(this)
.registerOnSharedPreferenceChangeListener(this);
mPreferences.registerOnSharedPreferenceChangeListener(this);
}
/**
@ -383,8 +387,7 @@ public class SyncthingService extends Service implements
}
}
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
sp.unregisterOnSharedPreferenceChangeListener(this);
mPreferences.unregisterOnSharedPreferenceChangeListener(this);
mDeviceStateHolder.shutdown();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
unregisterReceiver(mPowerSaveModeChangedReceiver);

View file

@ -13,6 +13,7 @@ import android.preference.PreferenceManager;
import android.text.TextUtils;
import com.nutomic.syncthingandroid.R;
import com.nutomic.syncthingandroid.SyncthingApp;
import java.util.Arrays;
import java.util.Collections;
@ -22,6 +23,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.inject.Inject;
/**
* Based on https://gitlab.com/fdroid/fdroidclient/blob/master/app/src/main/java/org/fdroid/fdroid/Languages.java
*/
@ -32,7 +35,7 @@ public final class Languages {
private static final Locale DEFAULT_LOCALE;
public static final String PREFERENCE_LANGUAGE = "pref_current_language";
private final SharedPreferences mPreferences;
@Inject SharedPreferences mPreferences;
private static Map<String, String> mAvailableLanguages;
static {
@ -40,6 +43,7 @@ public final class Languages {
}
public Languages(Context context) {
((SyncthingApp) context.getApplicationContext()).component().inject(this);
Map<String, String> tmpMap = new TreeMap<>();
List<Locale> locales = Arrays.asList(LOCALES_TO_TEST);
// Capitalize language names
@ -56,7 +60,6 @@ public final class Languages {
/* SYSTEM_DEFAULT is a fake one for displaying in a chooser menu. */
tmpMap.put(USE_SYSTEM_DEFAULT, context.getString(R.string.pref_language_default));
mAvailableLanguages = Collections.unmodifiableMap(tmpMap);
mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
}
/**