From 3fb16518e4787fa04891ca5d7007a1578148148d Mon Sep 17 00:00:00 2001
From: hyb1996 <946994919@qq.com>
Date: Sat, 4 Feb 2017 10:14:58 +0800
Subject: [PATCH] fix: switch state sync problem
---
app/src/main/AndroidManifest.xml | 2 +-
.../com/stardust/UIActionPerformActivity.java | 50 -------
.../java/com/stardust/scriptdroid/App.java | 9 ++
.../scriptdroid/AssistModeSwitchService.java | 11 +-
.../EditAndRunIntentActivity.java | 2 +-
.../runtime/action/ActionPerformService.java | 10 +-
.../ui/AssistModeSwitchNotification.java | 53 +++++---
.../scriptdroid/ui/EditSideMenuFragment.java | 20 +++
.../scriptdroid/ui/SlideMenuFragment.java | 28 +---
.../java/com/stardust/util/CrashHandler.java | 1 +
.../java/com/stardust/util/StateObserver.java | 125 ++++++++++++++++++
11 files changed, 205 insertions(+), 106 deletions(-)
delete mode 100644 app/src/main/java/com/stardust/UIActionPerformActivity.java
rename app/src/main/java/com/stardust/{ => scriptdroid}/EditAndRunIntentActivity.java (95%)
create mode 100644 app/src/main/java/com/stardust/scriptdroid/ui/EditSideMenuFragment.java
create mode 100644 app/src/main/java/com/stardust/util/StateObserver.java
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 85fc7dc2..471e75c0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -80,7 +80,7 @@
diff --git a/app/src/main/java/com/stardust/UIActionPerformActivity.java b/app/src/main/java/com/stardust/UIActionPerformActivity.java
deleted file mode 100644
index 25865fda..00000000
--- a/app/src/main/java/com/stardust/UIActionPerformActivity.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.stardust;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-
-import com.stardust.scriptdroid.App;
-import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
-
-
-/**
- * Created by Stardust on 2017/1/31.
- */
-
-public class UIActionPerformActivity extends AppCompatActivity {
-
-
- private static volatile UIAction action;
-
- public static void performAction(UIAction action) {
- if (UIActionPerformActivity.action != null) {
- return;
- }
- UIActionPerformActivity.action = action;
- App.getApp().startActivity(new Intent(App.getApp(), UIActionPerformActivity.class));
- }
-
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- DroidRuntime.setContext(this);
- action.setActivity(this).run();
- }
-
-
- public abstract static class UIAction implements Runnable {
-
- protected Activity mActivity;
-
- public UIAction setActivity(Activity activity) {
- mActivity = activity;
- return this;
- }
-
- }
-
-
-}
diff --git a/app/src/main/java/com/stardust/scriptdroid/App.java b/app/src/main/java/com/stardust/scriptdroid/App.java
index 8d2e3d0f..39eef9df 100644
--- a/app/src/main/java/com/stardust/scriptdroid/App.java
+++ b/app/src/main/java/com/stardust/scriptdroid/App.java
@@ -1,8 +1,10 @@
package com.stardust.scriptdroid;
import android.app.Application;
+import android.preference.PreferenceManager;
import com.stardust.util.CrashHandler;
+import com.stardust.util.StateObserver;
/**
* Created by Stardust on 2017/1/27.
@@ -11,14 +13,21 @@ import com.stardust.util.CrashHandler;
public class App extends Application {
private static App instance;
+ private static StateObserver stateObserver;
public static App getApp() {
return instance;
}
+ public static StateObserver getStateObserver() {
+ return stateObserver;
+ }
+
+
public void onCreate() {
super.onCreate();
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
instance = this;
+ stateObserver = new StateObserver(PreferenceManager.getDefaultSharedPreferences(this));
}
}
diff --git a/app/src/main/java/com/stardust/scriptdroid/AssistModeSwitchService.java b/app/src/main/java/com/stardust/scriptdroid/AssistModeSwitchService.java
index 9e5f4c66..c523d7c3 100644
--- a/app/src/main/java/com/stardust/scriptdroid/AssistModeSwitchService.java
+++ b/app/src/main/java/com/stardust/scriptdroid/AssistModeSwitchService.java
@@ -7,7 +7,8 @@ import android.os.IBinder;
import android.support.annotation.Nullable;
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
-import com.stardust.scriptdroid.ui.AssistModeSwitchNotification;
+
+import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
/**
* Created by Stardust on 2017/2/2.
@@ -18,19 +19,19 @@ public class AssistModeSwitchService extends Service {
Intent intent = new Intent(App.getApp(), AssistModeSwitchService.class)
.putExtra("intentValid", true)
.putExtra("switch", "assistMode");
- return PendingIntent.getService(App.getApp(), 0, intent, 0);
+ return PendingIntent.getService(App.getApp(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
boolean intentValid = intent.getBooleanExtra("intentValid", false);
if (intentValid) {
- String action = intent.getStringExtra("action");
+ String action = intent.getStringExtra("switch");
if (action != null) {
if (action.equals("assistMode")) {
ActionPerformService.setAssistModeEnable(!ActionPerformService.isAssistModeEnable());
} else {
- AssistModeSwitchNotification.setEnable(false);
+ App.getStateObserver().setState(KEY_ASSIST_MODE_NOTIFICATION, false);
}
}
}
@@ -48,6 +49,6 @@ public class AssistModeSwitchService extends Service {
Intent deleteIntent = new Intent(App.getApp(), AssistModeSwitchService.class)
.putExtra("intentValid", true)
.putExtra("switch", "assistModeNotification");
- return PendingIntent.getService(App.getApp(), 0, deleteIntent, 0);
+ return PendingIntent.getService(App.getApp(), 0, deleteIntent, PendingIntent.FLAG_ONE_SHOT);
}
}
diff --git a/app/src/main/java/com/stardust/EditAndRunIntentActivity.java b/app/src/main/java/com/stardust/scriptdroid/EditAndRunIntentActivity.java
similarity index 95%
rename from app/src/main/java/com/stardust/EditAndRunIntentActivity.java
rename to app/src/main/java/com/stardust/scriptdroid/EditAndRunIntentActivity.java
index 2f05de55..87ab924c 100644
--- a/app/src/main/java/com/stardust/EditAndRunIntentActivity.java
+++ b/app/src/main/java/com/stardust/scriptdroid/EditAndRunIntentActivity.java
@@ -1,4 +1,4 @@
-package com.stardust;
+package com.stardust.scriptdroid;
import android.content.Intent;
import android.os.Bundle;
diff --git a/app/src/main/java/com/stardust/scriptdroid/droid/runtime/action/ActionPerformService.java b/app/src/main/java/com/stardust/scriptdroid/droid/runtime/action/ActionPerformService.java
index c07a9f23..0caccb08 100644
--- a/app/src/main/java/com/stardust/scriptdroid/droid/runtime/action/ActionPerformService.java
+++ b/app/src/main/java/com/stardust/scriptdroid/droid/runtime/action/ActionPerformService.java
@@ -3,7 +3,6 @@ package com.stardust.scriptdroid.droid.runtime.action;
import android.accessibilityservice.AccessibilityService;
import android.content.ClipData;
import android.content.ClipboardManager;
-import android.content.Intent;
import android.graphics.Rect;
import android.os.Build;
import android.preference.PreferenceManager;
@@ -28,12 +27,8 @@ import java.util.List;
public class ActionPerformService extends AccessibilityService {
-
- public static final String ACTION_CHANGE_ASSIST_MODE = App.getApp().getPackageName() + ".ACTION_CHANGE_ASSIST_MODE";
-
-
private static final String TAG = "ActionPerformService";
- private static final String KEY_ASSIST_MODE_ENABLE = "ASSIST_MODE_ENABLE";
+ public static final String KEY_ASSIST_MODE_ENABLE = "ASSIST_MODE_ENABLE";
private static ActionPerformService instance;
@SuppressWarnings("unchecked")
@@ -69,8 +64,7 @@ public class ActionPerformService extends AccessibilityService {
public static void setAssistModeEnable(boolean assistModeEnable) {
ActionPerformService.assistModeEnable = assistModeEnable;
- PreferenceManager.getDefaultSharedPreferences(App.getApp()).edit().putBoolean(KEY_ASSIST_MODE_ENABLE, assistModeEnable).apply();
- App.getApp().sendBroadcast(new Intent(ACTION_CHANGE_ASSIST_MODE).putExtra("enable", assistModeEnable));
+ App.getStateObserver().setState(KEY_ASSIST_MODE_ENABLE, assistModeEnable);
}
@Override
diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/AssistModeSwitchNotification.java b/app/src/main/java/com/stardust/scriptdroid/ui/AssistModeSwitchNotification.java
index 22f39687..f1779e4e 100644
--- a/app/src/main/java/com/stardust/scriptdroid/ui/AssistModeSwitchNotification.java
+++ b/app/src/main/java/com/stardust/scriptdroid/ui/AssistModeSwitchNotification.java
@@ -10,6 +10,9 @@ import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.AssistModeSwitchService;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
+import com.stardust.util.StateObserver;
+
+import static com.stardust.scriptdroid.droid.runtime.action.ActionPerformService.KEY_ASSIST_MODE_ENABLE;
/**
* Created by Stardust on 2017/2/2.
@@ -18,19 +21,46 @@ import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
public class AssistModeSwitchNotification {
private static final int NOTIFY_ID = 11126;
- private static final String KEY_ASSIST_MODE_NOTIFICATION = "KEY_ASSIST_MODE_NOTIFICATION";
+ public static final String KEY_ASSIST_MODE_NOTIFICATION = "KEY_ASSIST_MODE_NOTIFICATION";
private static boolean enable = false;
private static Notification notification;
- static {
- readPreference();
- }
-
public static boolean isEnable() {
return enable;
}
+ static {
+ App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, new StateObserver.OnBooleanStateChangedListener() {
+ @Override
+ public void onStateChanged(Boolean newState) {
+ setEnable(newState);
+ }
+
+ @Override
+ public void initState(Boolean state) {
+ enable = state;
+ if (enable) {
+ showNotification();
+ }
+ }
+ });
+ App.getStateObserver().register(KEY_ASSIST_MODE_ENABLE, new StateObserver.OnBooleanStateChangedListener() {
+ @Override
+ public void onStateChanged(Boolean newState) {
+ if (enable) {
+ setEnable(false);
+ setEnable(true);
+ }
+ }
+
+ @Override
+ public void initState(Boolean state) {
+
+ }
+ });
+ }
+
public static void setEnable(boolean enable) {
if (AssistModeSwitchNotification.enable == enable)
return;
@@ -43,13 +73,6 @@ public class AssistModeSwitchNotification {
}
}
- public static void notifyAssistModeChanged() {
- if (enable) {
- setEnable(false);
- setEnable(true);
- }
- }
-
private static void showNotification() {
notification = new NotificationCompat.Builder(App.getApp())
@@ -74,10 +97,4 @@ public class AssistModeSwitchNotification {
notificationManager.cancel(NOTIFY_ID);
}
-
- private static void readPreference() {
- enable = PreferenceManager.getDefaultSharedPreferences(App.getApp()).getBoolean(KEY_ASSIST_MODE_NOTIFICATION, false);
- setEnable(enable);
- }
-
}
diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/EditSideMenuFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/EditSideMenuFragment.java
new file mode 100644
index 00000000..24ba7a5e
--- /dev/null
+++ b/app/src/main/java/com/stardust/scriptdroid/ui/EditSideMenuFragment.java
@@ -0,0 +1,20 @@
+package com.stardust.scriptdroid.ui;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Created by Stardust on 2017/2/4.
+ */
+
+public class EditSideMenuFragment extends com.stardust.app.Fragment {
+
+ @Nullable
+ @Override
+ public View createView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ return null;
+ }
+}
diff --git a/app/src/main/java/com/stardust/scriptdroid/ui/SlideMenuFragment.java b/app/src/main/java/com/stardust/scriptdroid/ui/SlideMenuFragment.java
index ab78b10e..89b652d7 100644
--- a/app/src/main/java/com/stardust/scriptdroid/ui/SlideMenuFragment.java
+++ b/app/src/main/java/com/stardust/scriptdroid/ui/SlideMenuFragment.java
@@ -1,9 +1,6 @@
package com.stardust.scriptdroid.ui;
-import android.content.BroadcastReceiver;
-import android.content.Context;
import android.content.Intent;
-import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
@@ -14,6 +11,7 @@ import android.view.View;
import android.view.ViewGroup;
import com.stardust.app.Fragment;
+import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.DocumentActivity;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.Droid;
@@ -22,7 +20,8 @@ import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
import com.stardust.view.accessibility.AccessibilityServiceUtils;
-import static com.stardust.scriptdroid.droid.runtime.action.ActionPerformService.ACTION_CHANGE_ASSIST_MODE;
+import static com.stardust.scriptdroid.droid.runtime.action.ActionPerformService.KEY_ASSIST_MODE_ENABLE;
+import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
/**
* Created by Stardust on 2017/1/30.
@@ -37,7 +36,6 @@ public class SlideMenuFragment extends Fragment {
}
private SwitchCompat mAutoOperateServiceSwitch, mAssistServiceSwitch, mAssistServiceNotificationSwitch;
- private Receiver mReceiver = new Receiver();
@Nullable
@Override
@@ -51,9 +49,6 @@ public class SlideMenuFragment extends Fragment {
if (mAutoOperateServiceSwitch == null) {
setUpSwitchCompat();
ViewBinder.bind(this);
- IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_CHANGE_ASSIST_MODE);
- getContext().registerReceiver(mReceiver, filter);
}
syncSwitchState();
}
@@ -73,6 +68,8 @@ public class SlideMenuFragment extends Fragment {
mAutoOperateServiceSwitch = $(R.id.sw_auto_operate_service);
mAssistServiceSwitch = $(R.id.sw_assist_service);
mAssistServiceNotificationSwitch = $(R.id.sw_assist_service_notification);
+ App.getStateObserver().register(KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
+ App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
}
@ViewBinding.Click(R.id.syntax_and_api)
@@ -97,7 +94,6 @@ public class SlideMenuFragment extends Fragment {
@ViewBinding.Check(R.id.sw_assist_service)
private void setAssistServiceEnable(boolean enable) {
ActionPerformService.setAssistModeEnable(enable);
- AssistModeSwitchNotification.notifyAssistModeChanged();
}
@ViewBinding.Click(R.id.assist_service)
@@ -126,21 +122,7 @@ public class SlideMenuFragment extends Fragment {
@Override
public void onDestroy() {
- getContext().unregisterReceiver(mReceiver);
super.onDestroy();
}
- private class Receiver extends BroadcastReceiver {
-
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(ACTION_CHANGE_ASSIST_MODE)) {
- AssistModeSwitchNotification.notifyAssistModeChanged();
- mAssistServiceSwitch.setChecked(intent.getBooleanExtra("enable", false));
- }
- }
- }
-
-
}
diff --git a/app/src/main/java/com/stardust/util/CrashHandler.java b/app/src/main/java/com/stardust/util/CrashHandler.java
index 9006246d..3e513fe8 100644
--- a/app/src/main/java/com/stardust/util/CrashHandler.java
+++ b/app/src/main/java/com/stardust/util/CrashHandler.java
@@ -41,6 +41,7 @@ public class CrashHandler implements UncaughtExceptionHandler {
public static String throwableToString(Throwable throwable) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
+ throwable.printStackTrace();
throwable.printStackTrace(pw);
return sw.toString();
}
diff --git a/app/src/main/java/com/stardust/util/StateObserver.java b/app/src/main/java/com/stardust/util/StateObserver.java
new file mode 100644
index 00000000..0517889e
--- /dev/null
+++ b/app/src/main/java/com/stardust/util/StateObserver.java
@@ -0,0 +1,125 @@
+package com.stardust.util;
+
+import android.content.SharedPreferences;
+import android.support.v7.widget.SwitchCompat;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by Stardust on 2017/2/3.
+ */
+
+public class StateObserver {
+
+ public interface OnStateChangedListener {
+
+ void onStateChanged(T newState);
+
+ void initState(T state);
+ }
+
+
+ public static abstract class SimpleOnStateChangedListener implements OnStateChangedListener {
+
+ @Override
+ public void initState(T state) {
+ onStateChanged(state);
+ }
+ }
+
+ public interface OnBooleanStateChangedListener extends OnStateChangedListener {
+
+ }
+
+ public static abstract class SimpleOnBooleanStateChangedListener implements OnBooleanStateChangedListener {
+
+ @Override
+ public void initState(Boolean state) {
+ onStateChanged(state);
+ }
+ }
+
+
+ private final Map> mKeyStateListenersMap = new HashMap<>();
+ private SharedPreferences mSharedPreferences;
+
+ public StateObserver(SharedPreferences sharedPreferences) {
+ mSharedPreferences = sharedPreferences;
+ }
+
+ public void register(final String key, SwitchCompat switchCompat) {
+ final WeakReference switchCompatWeakReference = new WeakReference<>(switchCompat);
+ register(key, new SimpleOnBooleanStateChangedListener() {
+ @Override
+ public void onStateChanged(Boolean newState) {
+ if (switchCompatWeakReference.get() != null) {
+ switchCompatWeakReference.get().setChecked(newState);
+ } else {
+ unregister(key, this);
+ }
+ }
+ });
+ }
+
+ public void register(String key, OnStateChangedListener listener) {
+ T initialState = readState(key, listener);
+ if (initialState != null)
+ listener.initState(initialState);
+ synchronized (mKeyStateListenersMap) {
+ getListenerListOrCreateIfNotExists(key).add(listener);
+ }
+ }
+
+
+ private void unregister(String key, OnStateChangedListener stateChangedListener) {
+ synchronized (mKeyStateListenersMap) {
+ List listeners = mKeyStateListenersMap.get(key);
+ if (listeners == null) {
+ return;
+ }
+ listeners.remove(stateChangedListener);
+ }
+ }
+
+ public void setState(String key, T state) {
+ synchronized (mKeyStateListenersMap) {
+ List listeners = mKeyStateListenersMap.get(key);
+ if (listeners == null || listeners.isEmpty()) {
+ return;
+ }
+ if (listeners.get(0) instanceof OnBooleanStateChangedListener) {
+ mSharedPreferences.edit().putBoolean(key, (Boolean) state).apply();
+ notifyBooleanStateChanged(listeners, (Boolean) state);
+ }
+ }
+ }
+
+ private void notifyBooleanStateChanged(List listeners, boolean state) {
+ for (OnStateChangedListener listener : listeners) {
+ listener.onStateChanged(state);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected T readState(String key, OnStateChangedListener listener) {
+ if (listener instanceof OnBooleanStateChangedListener) {
+ return mSharedPreferences.contains(key) ? (T) Boolean.valueOf(mSharedPreferences.getBoolean(key, false)) : null;
+ }
+ return null;
+ }
+
+ private List getListenerListOrCreateIfNotExists(String key) {
+ List listeners = mKeyStateListenersMap.get(key);
+ if (listeners == null) {
+ listeners = new ArrayList<>();
+ mKeyStateListenersMap.put(key, listeners);
+ }
+ return listeners;
+ }
+
+
+}