fix memory leak

This commit is contained in:
hyb1996
2017-02-15 21:58:31 +08:00
parent e2d5efa710
commit 1463011b7b
47 changed files with 193 additions and 102 deletions

View File

@@ -5,6 +5,8 @@ import android.app.Application;
import android.os.Bundle;
import android.preference.PreferenceManager;
import com.squareup.leakcanary.LeakCanary;
import com.stardust.scriptdroid.bounds_assist.BoundsAssistant;
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformAccessibilityDelegate;
import com.stardust.scriptdroid.record.AccessibilityRecorderDelegate;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
@@ -35,6 +37,12 @@ public class App extends Application {
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
LeakCanary.install(this);
if (!BuildConfig.DEBUG)
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
instance = new WeakReference<>(this);
@@ -43,9 +51,12 @@ public class App extends Application {
initAccessibilityServiceDelegates();
}
private void initAccessibilityServiceDelegates() {
AccessibilityWatchDogService.addDelegateIfNeeded(100, ActionPerformAccessibilityDelegate.class);
AccessibilityWatchDogService.addDelegateIfNeeded(200, AccessibilityRecorderDelegate.getInstance());
AccessibilityWatchDogService.addDelegateIfNeeded(300, BoundsAssistant.class);
}
private void registerActivityLifecycleCallback() {

View File

@@ -1,5 +1,6 @@
package com.stardust.scriptdroid.bounds_assist;
import android.accessibilityservice.AccessibilityService;
import android.graphics.Rect;
import android.preference.PreferenceManager;
import android.view.accessibility.AccessibilityEvent;
@@ -10,15 +11,16 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.service.AccessibilityDelegate;
/**
* Created by Stardust on 2017/2/4.
*/
public class BoundsAssistant {
public static final String KEY_BOUNDS_ASSIST_ENABLE = "ASSIST_MODE_ENABLE";
public class BoundsAssistant implements AccessibilityDelegate {
public static final String KEY_BOUNDS_ASSIST_ENABLE = "ASSIST_MODE_ENABLE";
private static boolean assistModeEnable;
private static BoundsAssistClipList boundsAssistClipList = SharedPrefBoundsAssistClipList.getInstance();
@@ -43,7 +45,7 @@ public class BoundsAssistant {
.show();
}
public static void performAssistance(AccessibilityEvent event) {
private static void performAssistance(AccessibilityEvent event) {
if (!assistModeEnable) {
return;
}
@@ -59,6 +61,12 @@ public class BoundsAssistant {
}
}
@Override
public boolean onAccessibilityEvent(AccessibilityService service, AccessibilityEvent event) {
performAssistance(event);
return false;
}
public static Rect getBoundsInScreen(AccessibilityNodeInfo nodeInfo) {
Rect rect = new Rect();
nodeInfo.getBoundsInScreen(rect);
@@ -80,4 +88,5 @@ public class BoundsAssistant {
assistModeEnable = PreferenceManager.getDefaultSharedPreferences(App.getApp()).getBoolean(KEY_BOUNDS_ASSIST_ENABLE, false);
}
}

View File

@@ -13,6 +13,7 @@ import com.stardust.scriptdroid.file.FileUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.Serializable;
import timber.log.Timber;
@@ -30,7 +31,7 @@ public class Droid {
public static final String UI = "\"ui\";";
public interface OnRunFinishedListener {
public interface OnRunFinishedListener extends Serializable {
void onRunFinished(Object result, Exception e);
}

View File

@@ -16,44 +16,52 @@ import static com.stardust.scriptdroid.droid.Droid.JAVA_SCRIPT_ENGINE;
public class ScriptExecuteActivity extends Activity {
private static String script;
private static Droid.OnRunFinishedListener onRunFinishedListener;
private static RunningConfig runningConfig;
private static final String EXTRA_SCRIPT = "EXTRA_SCRIPT";
private static final String EXTRA_ON_RUN_FINISHED_LISTENER = "EXTRA_ON_RUN_FINISHED_LISTENER";
private Object mResult;
private String mScript;
private Droid.OnRunFinishedListener mOnRunFinishedListener;
public static void runScript(String script, Droid.OnRunFinishedListener listener, RunningConfig config) {
ScriptExecuteActivity.script = script;
ScriptExecuteActivity.onRunFinishedListener = listener;
ScriptExecuteActivity.runningConfig = config;
App.getApp().startActivity(new Intent(App.getApp(), ScriptExecuteActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
App.getApp().startActivity(new Intent(App.getApp(), ScriptExecuteActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_SCRIPT, script)
.putExtra(EXTRA_ON_RUN_FINISHED_LISTENER, listener));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handleIntent(getIntent());
runScript();
}
private void handleIntent(Intent intent) {
mScript = intent.getStringExtra(EXTRA_SCRIPT);
mOnRunFinishedListener = (Droid.OnRunFinishedListener) intent.getSerializableExtra(EXTRA_ON_RUN_FINISHED_LISTENER);
}
private void runScript() {
JAVA_SCRIPT_ENGINE.set("activity", Activity.class, this);
try {
mResult = JAVA_SCRIPT_ENGINE.execute(script);
mResult = JAVA_SCRIPT_ENGINE.execute(mScript);
} catch (Exception e) {
onRunFinishedListener.onRunFinished(null, e);
mOnRunFinishedListener.onRunFinished(null, e);
finish();
}
}
@Override
public void finish() {
onRunFinishedListener.onRunFinished(mResult, null);
mOnRunFinishedListener.onRunFinished(mResult, null);
super.finish();
}
@Override
protected void onDestroy() {
super.onDestroy();
JAVA_SCRIPT_ENGINE.set("activity", Activity.class, null);
JAVA_SCRIPT_ENGINE.removeAndDestroy(Thread.currentThread());
}
}

View File

@@ -29,6 +29,7 @@ public class ActionRecordNotificationHandleService extends Service {
private static final int ACTION_STOP = 17771;
private static final int ACTION_START_OR_PAUSE = 17772;
private static final int ACTION_DELETE = 17773;
private static final int ACTION_REDO = 17774;
public static PendingIntent getStartOrPauseIntent() {
Intent intent = new Intent(App.getApp(), ActionRecordNotificationHandleService.class)
@@ -51,6 +52,15 @@ public class ActionRecordNotificationHandleService extends Service {
return PendingIntent.getService(App.getApp(), ACTION_DELETE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
public static PendingIntent getRedoIntent() {
Intent intent = new Intent(App.getApp(), ActionRecordNotificationHandleService.class)
.putExtra(EXTRA_INTENT_VALID, true)
.putExtra(EXTRA_ACTION, ACTION_REDO);
return PendingIntent.getService(App.getApp(), ACTION_REDO, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
boolean intentValid = intent.getBooleanExtra(EXTRA_INTENT_VALID, false);
@@ -65,16 +75,23 @@ public class ActionRecordNotificationHandleService extends Service {
switch (action) {
case ACTION_STOP:
stopRecord();
collapseNotificationBar();
break;
case ACTION_START_OR_PAUSE:
startOrPauseRecord();
collapseNotificationBar();
break;
case ACTION_DELETE:
ActionRecordSwitchNotification.cancelNotification();
stopRecordIfNeeded();
break;
case ACTION_REDO:
redoRecord();
break;
}
collapseNotificationBar();
}
private void collapseNotificationBar() {
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
}
@@ -115,9 +132,18 @@ public class ActionRecordNotificationHandleService extends Service {
}
}
private void redoRecord() {
if (AccessibilityRecorderDelegate.getInstance().getState() != STOPPED) {
AccessibilityRecorderDelegate.getInstance().stopRecord();
ActionRecordSwitchView.getInstance().setState(STOPPED);
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View File

@@ -33,4 +33,9 @@ public class ActionRecordSwitchNotification {
NotificationManager notificationManager = (NotificationManager) App.getApp().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(NOTIFY_ID, notification);
}
public static void cancelNotification() {
NotificationManager notificationManager = (NotificationManager) App.getApp().getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.cancel(NOTIFY_ID);
}
}

View File

@@ -50,5 +50,7 @@ public class ActionRecordSwitchView extends RemoteViews {
private void setUpOnClick() {
setOnClickPendingIntent(R.id.stop, ActionRecordNotificationHandleService.getStopIntent());
setOnClickPendingIntent(R.id.start_or_pause, ActionRecordNotificationHandleService.getStartOrPauseIntent());
setOnClickPendingIntent(R.id.close, ActionRecordNotificationHandleService.getDeleteIntent());
setOnClickPendingIntent(R.id.redo, ActionRecordNotificationHandleService.getRedoIntent());
}
}

View File

@@ -62,6 +62,8 @@ public class ActionRecorder {
@Override
public void onAccessibilityEvent(AccessibilityEvent event, StringBuilder sb) {
AccessibilityNodeInfo source = event.getSource();
if (source == null)
return;
String bounds = boundsToString(getBoundsInScreen(source));
source.recycle();
onAccessibilityEvent(event, bounds, sb);

View File

@@ -8,6 +8,7 @@ import android.view.accessibility.AccessibilityEvent;
import com.stardust.scriptdroid.App;
import com.stardust.view.accessibility.AccessibilityServiceUtils;
import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
@@ -21,7 +22,7 @@ public class AccessibilityWatchDogService extends AccessibilityService {
private static final String TAG = "AccessibilityWatchDog";
private static final SortedMap<Integer, AccessibilityDelegate> mDelegates = new TreeMap<>();
private static AccessibilityWatchDogService instance;
private static WeakReference<AccessibilityWatchDogService> instance;
public static void addDelegate(AccessibilityDelegate delegate, int uniquePriority) {
synchronized (mDelegates) {
@@ -62,7 +63,9 @@ public class AccessibilityWatchDogService extends AccessibilityService {
}
public static AccessibilityWatchDogService getInstance() {
return instance;
if (instance == null)
return null;
return instance.get();
}
@Override
@@ -85,12 +88,12 @@ public class AccessibilityWatchDogService extends AccessibilityService {
super.onServiceConnected();
// FIXME: 2017/2/12 有时在无障碍中开启服务后这里不会调用服务也不会运行安卓的BUG???
Log.v(TAG, "onServiceConnected");
instance = this;
instance = new WeakReference<>(this);
}
public static void disable() {
if (instance != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
instance.disableSelf();
if (instance != null && instance.get() != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
instance.get().disableSelf();
} else {
AccessibilityServiceUtils.goToAccessibilitySetting(App.getApp());
}

View File

@@ -1,7 +1,9 @@
package com.stardust.scriptdroid.ui.edit;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
@@ -18,6 +20,7 @@ import com.jecelyin.editor.v2.common.SaveListener;
import com.jecelyin.editor.v2.ui.EditorDelegate;
import com.jecelyin.editor.v2.view.EditorView;
import com.jecelyin.editor.v2.view.menu.MenuDef;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.droid.Droid;
@@ -40,6 +43,18 @@ public class EditActivity extends Editor920Activity {
private static final String KEY_EDIT_ACTIVITY_FIRST_USE = "KEY_EDIT_ACTIVITY_FIRST_USE";
private static final String ACTION_ON_RUN_FINISHED = "ACTION_ON_RUN_FINISHED";
private static final String EXTRA_EXCEPTION = "EXTRA_EXCEPTION";
private static final Droid.OnRunFinishedListener ON_RUN_FINISHED_LISTENER = new Droid.OnRunFinishedListener() {
@Override
public void onRunFinished(Object result, Exception e) {
App.getApp().sendBroadcast(new Intent(ACTION_ON_RUN_FINISHED)
.putExtra(EXTRA_EXCEPTION, e));
}
};
public static void editFile(Context context, String path) {
editFile(context, null, path);
}
@@ -57,12 +72,24 @@ public class EditActivity extends Editor920Activity {
private DrawerLayout mDrawerLayout;
private EditorDelegate mEditorDelegate;
private SparseArray<ToolbarMenuItem> mMenuMap;
private BroadcastReceiver mOnRunFinishedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(ACTION_ON_RUN_FINISHED)) {
setMenuStatus(R.id.run, MenuDef.STATUS_NORMAL);
Exception e = (Exception) intent.getSerializableExtra(EXTRA_EXCEPTION);
if (e != null)
Snackbar.make(mView, getString(R.string.text_error) + ": " + e.getMessage(), Snackbar.LENGTH_INDEFINITE).show();
}
}
};
public void onCreate(Bundle b) {
super.onCreate(b);
handleIntent();
setUpUI();
setUpEditor();
registerReceiver(mOnRunFinishedReceiver, new IntentFilter(ACTION_ON_RUN_FINISHED));
}
@Override
@@ -175,19 +202,7 @@ public class EditActivity extends Editor920Activity {
private void run() {
Snackbar.make(mView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
setMenuStatus(R.id.run, MenuDef.STATUS_DISABLED);
Droid.getInstance().runScriptFile(mFile, new Droid.OnRunFinishedListener() {
@Override
public void onRunFinished(Object result, final Exception e) {
runOnUiThread(new Runnable() {
@Override
public void run() {
setMenuStatus(R.id.run, MenuDef.STATUS_NORMAL);
if (e != null)
Snackbar.make(mView, getString(R.string.text_error) + ": " + e.getMessage(), Snackbar.LENGTH_INDEFINITE).show();
}
});
}
});
Droid.getInstance().runScriptFile(mFile, ON_RUN_FINISHED_LISTENER);
}
@ViewBinding.Click(R.id.undo)
@@ -261,4 +276,10 @@ public class EditActivity extends Editor920Activity {
public void doCommand(Command command) {
mEditorDelegate.doCommand(command);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(mOnRunFinishedReceiver);
}
}

View File

@@ -125,7 +125,7 @@ public class IssueReportActivity extends IssueReporterActivity {
@Override
protected String getGuestToken() {
return "f32d789662645640ff22e240b80f5d76117181a1";
return "899ce4e559f7c3fad7a3a34a05777724758550de";
}
}

View File

@@ -284,7 +284,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
public static void onActionRecordStopped(Context context, String script) {
Intent intent = new Intent(context, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED)
.putExtra(ARGUMENT_SCRIPT, script);
context.startActivity(intent);