add: assist clip on edit side menu, alipay to donate
This commit is contained in:
@@ -8,10 +8,13 @@ import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.tool.IntentTool;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
|
||||
import moe.feng.alipay.zerosdk.AlipayZeroSdk;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/2.
|
||||
*/
|
||||
@@ -62,7 +65,22 @@ public class AboutActivity extends BaseActivity {
|
||||
|
||||
@ViewBinding.Click(R.id.donate)
|
||||
private void showDonateMeDialog() {
|
||||
|
||||
new MaterialDialog.Builder(this)
|
||||
.title(R.string.donate)
|
||||
.items("支付宝")
|
||||
.itemsCallback(new MaterialDialog.ListCallback() {
|
||||
@Override
|
||||
public void onSelection(MaterialDialog dialog, View itemView, int position, CharSequence text) {
|
||||
if (position == 0) {
|
||||
if (AlipayZeroSdk.hasInstalledAlipayClient(AboutActivity.this)) {
|
||||
AlipayZeroSdk.startAlipayClient(AboutActivity.this, "aex04370fwjf8angrv1te9e");
|
||||
} else {
|
||||
Toast.makeText(AboutActivity.this, "未安装支付宝", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.share)
|
||||
@@ -72,12 +90,12 @@ public class AboutActivity extends BaseActivity {
|
||||
|
||||
@ViewBinding.Click(R.id.icon)
|
||||
private void lol() {
|
||||
Toast.makeText(this, "略略略", Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(this, R.string.text_lll, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.developer)
|
||||
private void hhh() {
|
||||
Toast.makeText(this, "这是软件开发者(。・・)ノ", Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(this, R.string.text_it_is_the_developer_of_app, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void setClipText(CharSequence label, CharSequence text) {
|
||||
|
||||
@@ -26,7 +26,7 @@ public class App extends Application {
|
||||
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Thread.setDefaultUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
|
||||
Thread.currentThread().setUncaughtExceptionHandler(new CrashHandler(ErrorReportActivity.class));
|
||||
instance = this;
|
||||
stateObserver = new StateObserver(PreferenceManager.getDefaultSharedPreferences(this));
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
|
||||
import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class AssistModeSwitchService extends Service {
|
||||
String action = intent.getStringExtra("switch");
|
||||
if (action != null) {
|
||||
if (action.equals("assistMode")) {
|
||||
ActionPerformService.setAssistModeEnable(!ActionPerformService.isAssistModeEnable());
|
||||
Assistant.setAssistModeEnable(!Assistant.isAssistModeEnable());
|
||||
} else {
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_NOTIFICATION, false);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ public class DocumentActivity extends BaseActivity {
|
||||
markdownView.loadMarkdown(FileUtils.readString(getResources().openRawResource(R.raw.document)));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
markdownView.setText("文档加载失败/(ㄒoㄒ)/~~");
|
||||
markdownView.setText(R.string.text_load_failed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,14 @@ import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.SparseArray;
|
||||
import android.view.View;
|
||||
|
||||
import com.afollestad.materialdialogs.DialogAction;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.jecelyin.editor.v2.Pref;
|
||||
import com.jecelyin.editor.v2.common.Command;
|
||||
import com.jecelyin.editor.v2.common.SaveListener;
|
||||
import com.jecelyin.editor.v2.ui.EditorDelegate;
|
||||
@@ -20,6 +21,9 @@ import com.jecelyin.editor.v2.view.menu.MenuDef;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.editor920.Editor920Activity;
|
||||
import com.stardust.scriptdroid.ui.AssistClipListRecyclerView;
|
||||
import com.stardust.scriptdroid.ui.EditSideMenuFragment;
|
||||
import com.stardust.scriptdroid.ui.FunctionListRecyclerView;
|
||||
import com.stardust.scriptdroid.widget.ToolbarMenuItem;
|
||||
import com.stardust.util.SparseArrayEntries;
|
||||
import com.stardust.view.ViewBinder;
|
||||
@@ -33,6 +37,8 @@ import java.io.File;
|
||||
|
||||
public class EditActivity extends Editor920Activity {
|
||||
|
||||
private static final String KEY_EDIT_ACTIVITY_FIRST_USE = "KEY_EDIT_ACTIVITY_FIRST_USE";
|
||||
|
||||
public static void editFile(Context context, String path) {
|
||||
editFile(context, null, path);
|
||||
}
|
||||
@@ -46,6 +52,7 @@ public class EditActivity extends Editor920Activity {
|
||||
private String mName;
|
||||
private File mFile;
|
||||
private View mView;
|
||||
private DrawerLayout mDrawerLayout;
|
||||
private EditorDelegate mEditorDelegate;
|
||||
private SparseArray<ToolbarMenuItem> mMenuMap;
|
||||
|
||||
@@ -57,6 +64,24 @@ public class EditActivity extends Editor920Activity {
|
||||
setUpEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
openDrawerIfFirstUse();
|
||||
}
|
||||
|
||||
private void openDrawerIfFirstUse() {
|
||||
if (Pref.def().getBoolean(KEY_EDIT_ACTIVITY_FIRST_USE, true)) {
|
||||
mDrawerLayout.postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDrawerLayout.openDrawer(GravityCompat.END);
|
||||
}
|
||||
}, 1000);
|
||||
Pref.def().edit().putBoolean(KEY_EDIT_ACTIVITY_FIRST_USE, false).apply();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIntent() {
|
||||
String path = getIntent().getStringExtra("path");
|
||||
mName = getIntent().getStringExtra("name");
|
||||
@@ -73,15 +98,35 @@ public class EditActivity extends Editor920Activity {
|
||||
private void setUpUI() {
|
||||
setTheme(R.style.EditorTheme);
|
||||
mView = View.inflate(this, R.layout.activity_edit, null);
|
||||
mDrawerLayout = (DrawerLayout) mView.findViewById(R.id.drawer_layout);
|
||||
setContentView(mView);
|
||||
initMenuItem();
|
||||
initSideMenuFragment();
|
||||
setUpToolbar();
|
||||
initMenuItem();
|
||||
ViewBinder.bind(this);
|
||||
}
|
||||
|
||||
private void initSideMenuFragment() {
|
||||
EditSideMenuFragment.setFragment(EditActivity.this, R.id.fragment_edit_side_menu)
|
||||
.setOnFunctionClickListener(new FunctionListRecyclerView.OnFunctionClickListener() {
|
||||
@Override
|
||||
public void onClick(FunctionListRecyclerView.Function function, int position) {
|
||||
insertText(function.name);
|
||||
mDrawerLayout.closeDrawer(GravityCompat.END);
|
||||
}
|
||||
})
|
||||
.setOnClipClickListener(new AssistClipListRecyclerView.OnClipClickListener() {
|
||||
@Override
|
||||
public void onClick(String clip, int position) {
|
||||
insertText(clip);
|
||||
mDrawerLayout.closeDrawer(GravityCompat.END);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void setUpEditor() {
|
||||
if (mFile != null) {
|
||||
Pref.getInstance(this).setReadOnly(false);
|
||||
mEditorDelegate = new EditorDelegate(0, mFile, 0, null);
|
||||
EditorView editorView = (EditorView) findViewById(R.id.editor);
|
||||
mEditorDelegate.setEditorView(editorView);
|
||||
@@ -127,7 +172,7 @@ public class EditActivity extends Editor920Activity {
|
||||
}
|
||||
|
||||
private void run() {
|
||||
Snackbar.make(mView, "开始运行", Snackbar.LENGTH_SHORT).show();
|
||||
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
|
||||
@@ -137,7 +182,7 @@ public class EditActivity extends Editor920Activity {
|
||||
public void run() {
|
||||
setMenuStatus(R.id.run, MenuDef.STATUS_NORMAL);
|
||||
if (e != null)
|
||||
Snackbar.make(mView, "错误: " + e.getMessage(), Snackbar.LENGTH_INDEFINITE).show();
|
||||
Snackbar.make(mView, getString(R.string.text_error) + ": " + e.getMessage(), Snackbar.LENGTH_INDEFINITE).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -211,4 +256,8 @@ public class EditActivity extends Editor920Activity {
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doCommand(Command command) {
|
||||
mEditorDelegate.doCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ public class ErrorReportActivity extends BaseActivity {
|
||||
final String errorDetail = getIntent().getStringExtra("error");
|
||||
new MaterialDialog.Builder(this)
|
||||
.content(message)
|
||||
.positiveText("退出")
|
||||
.negativeText("复制调试信息")
|
||||
.positiveText(R.string.text_exit)
|
||||
.negativeText(R.string.text_copy_debug_info)
|
||||
.onPositive(new MaterialDialog.SingleButtonCallback() {
|
||||
@Override
|
||||
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
|
||||
|
||||
@@ -88,7 +88,7 @@ public class MainActivity extends BaseActivity implements FileChooserDialog.File
|
||||
private void setUpUI() {
|
||||
mDrawerLayout = (DrawerLayout) View.inflate(this, R.layout.activity_main, null);
|
||||
setContentView(mDrawerLayout);
|
||||
SlideMenuFragment.init(this, R.id.fragment_slide_menu);
|
||||
SlideMenuFragment.setFragment(this, R.id.fragment_slide_menu);
|
||||
mAddFilePanel = $(R.id.bottom_menu);
|
||||
|
||||
setUpToolbar();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.stardust.scriptdroid.droid;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.scriptdroid.droid.script.DuktapeJavaScriptEngine;
|
||||
import com.stardust.scriptdroid.droid.script.JavaScriptEngine;
|
||||
@@ -24,7 +26,7 @@ public class Droid {
|
||||
@Override
|
||||
public void onRunFinished(Object result, Exception e) {
|
||||
if (e != null) {
|
||||
RUNTIME.toast("错误: " + e.getMessage());
|
||||
RUNTIME.toast(App.getApp().getString(R.string.text_error) + ": " + e.getMessage());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -59,7 +61,7 @@ public class Droid {
|
||||
public void runScript(final String script, OnRunFinishedListener listener, RunningConfig config) {
|
||||
if (config.runInNewThread) {
|
||||
new Thread(new RunScriptRunnable(script, listener, config)).start();
|
||||
}else {
|
||||
} else {
|
||||
new RunScriptRunnable(script, listener, config).run();
|
||||
}
|
||||
|
||||
@@ -70,6 +72,11 @@ public class Droid {
|
||||
return JAVA_SCRIPT_ENGINE.stopAll();
|
||||
}
|
||||
|
||||
|
||||
public void ensureNotStopped() {
|
||||
JAVA_SCRIPT_ENGINE.ensureNotStopped();
|
||||
}
|
||||
|
||||
private void checkFile(File file) {
|
||||
if (file == null) {
|
||||
throw new NullPointerException("file = null");
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.stardust.scriptdroid.droid.assist;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public interface AssistClipList {
|
||||
|
||||
interface OnClipChangedListener {
|
||||
void onClipRemove(int position);
|
||||
|
||||
void onClipInsert(int position);
|
||||
|
||||
void onChange();
|
||||
}
|
||||
|
||||
int size();
|
||||
|
||||
String get(int i);
|
||||
|
||||
void add(String clip);
|
||||
|
||||
void setOnClipChangedListener(OnClipChangedListener listener);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.stardust.scriptdroid.droid.assist;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class Assistant {
|
||||
public static final String KEY_ASSIST_MODE_ENABLE = "ASSIST_MODE_ENABLE";
|
||||
|
||||
|
||||
private static boolean assistModeEnable;
|
||||
private static AssistClipList assistClipList = SharedPrefAssistClipList.getInstance();
|
||||
|
||||
public static boolean isAssistModeEnable() {
|
||||
return assistModeEnable;
|
||||
}
|
||||
|
||||
public static void setAssistModeEnable(boolean assistModeEnable) {
|
||||
Assistant.assistModeEnable = assistModeEnable;
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_ENABLE, assistModeEnable);
|
||||
}
|
||||
|
||||
public static void performAssistance(AccessibilityEvent event) {
|
||||
if (!assistModeEnable) {
|
||||
return;
|
||||
}
|
||||
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED || event.getEventType() == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED) {
|
||||
AccessibilityNodeInfo nodeInfo = event.getSource();
|
||||
if (nodeInfo == null) {
|
||||
return;
|
||||
}
|
||||
nodeInfo.refresh();
|
||||
Rect rect = getBoundsInScreen(nodeInfo);
|
||||
saveAndAlertBounds(rect);
|
||||
nodeInfo.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
private static Rect getBoundsInScreen(AccessibilityNodeInfo nodeInfo) {
|
||||
Rect rect = new Rect();
|
||||
nodeInfo.getBoundsInScreen(rect);
|
||||
return rect;
|
||||
}
|
||||
|
||||
private static void saveAndAlertBounds(Rect rect) {
|
||||
String str = rect.toString().replace('-', ',').replace(" ", "").substring(4);
|
||||
assistClipList.add(str);
|
||||
Toast.makeText(App.getApp(), str, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
|
||||
static {
|
||||
assistModeEnable = PreferenceManager.getDefaultSharedPreferences(App.getApp()).getBoolean(KEY_ASSIST_MODE_ENABLE, false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.stardust.scriptdroid.droid.assist;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.stardust.scriptdroid.App;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class SharedPrefAssistClipList implements AssistClipList {
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
|
||||
private static SharedPrefAssistClipList instance = new SharedPrefAssistClipList(App.getApp());
|
||||
private OnClipChangedListener mOnClipChangedListener;
|
||||
|
||||
public static SharedPrefAssistClipList getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static final int MAX_SIZE = 10;
|
||||
private static final String SHARED_PREF_NAME = "SharedPrefAssistClipList";
|
||||
private SharedPreferences mSharedPreferences;
|
||||
private List<String> mAssistClipList = new LinkedList<>();
|
||||
|
||||
public SharedPrefAssistClipList(Context context) {
|
||||
mSharedPreferences = context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE);
|
||||
readFromSharedPref();
|
||||
}
|
||||
|
||||
private void readFromSharedPref() {
|
||||
Type type = new TypeToken<List<String>>() {
|
||||
}.getType();
|
||||
List<String> l = GSON.fromJson(mSharedPreferences.getString(SHARED_PREF_NAME, ""), type);
|
||||
if (l != null)
|
||||
mAssistClipList.addAll(l);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int size() {
|
||||
return mAssistClipList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized String get(int i) {
|
||||
return mAssistClipList.get(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void add(String clip) {
|
||||
mAssistClipList.add(0, clip);
|
||||
notifyInsert();
|
||||
if (mAssistClipList.size() > MAX_SIZE) {
|
||||
mAssistClipList.remove(mAssistClipList.size() - 1);
|
||||
notifyRemove();
|
||||
}
|
||||
syncWithSharedPref();
|
||||
}
|
||||
|
||||
private void notifyRemove() {
|
||||
if (mOnClipChangedListener != null)
|
||||
mOnClipChangedListener.onClipRemove(mAssistClipList.size());
|
||||
}
|
||||
|
||||
private void notifyInsert() {
|
||||
if (mOnClipChangedListener != null) {
|
||||
mOnClipChangedListener.onClipInsert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnClipChangedListener(OnClipChangedListener listener) {
|
||||
mOnClipChangedListener = listener;
|
||||
}
|
||||
|
||||
private void syncWithSharedPref() {
|
||||
mSharedPreferences.edit().putString(SHARED_PREF_NAME, GSON.toJson(mAssistClipList)).apply();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import android.widget.Toast;
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.Action;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionFactory;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
@@ -32,6 +33,7 @@ public class DroidRuntime implements IDroidRuntime {
|
||||
|
||||
private final Object mLock = new Object();
|
||||
private boolean mActionPerformResult;
|
||||
private boolean mActionPerformResultUpToDate;
|
||||
private Handler mUIHandler;
|
||||
|
||||
public static DroidRuntime getRuntime() {
|
||||
@@ -143,17 +145,22 @@ public class DroidRuntime implements IDroidRuntime {
|
||||
toast(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
throw new PermissionDeniedException(App.getApp().getString(R.string.text_no_accessibility_permission));
|
||||
}
|
||||
ensureNotStopped();
|
||||
ActionPerformService.setAction(action);
|
||||
synchronized (mLock) {
|
||||
try {
|
||||
mLock.wait();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
throw new PermissionDeniedException("已停止运行");
|
||||
}
|
||||
}
|
||||
return mActionPerformResult;
|
||||
}
|
||||
|
||||
private void ensureNotStopped() {
|
||||
Droid.getInstance().ensureNotStopped();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void toast(final String text) {
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
package com.stardust.scriptdroid.droid.runtime.action;
|
||||
|
||||
import android.accessibilityservice.AccessibilityService;
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.runtime.DroidRuntime;
|
||||
import com.stardust.view.accessibility.AccessibilityServiceUtils;
|
||||
|
||||
@@ -28,7 +24,6 @@ import java.util.List;
|
||||
public class ActionPerformService extends AccessibilityService {
|
||||
|
||||
private static final String TAG = "ActionPerformService";
|
||||
public static final String KEY_ASSIST_MODE_ENABLE = "ASSIST_MODE_ENABLE";
|
||||
private static ActionPerformService instance;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -39,9 +34,6 @@ public class ActionPerformService extends AccessibilityService {
|
||||
public static final List<Action> actions = new ArrayList<>();
|
||||
private static int state = STATE_INACTIVE;
|
||||
|
||||
private static boolean assistModeEnable = false;
|
||||
|
||||
|
||||
public static void setActions(Collection<Action> collection) {
|
||||
synchronized (actions) {
|
||||
actions.clear();
|
||||
@@ -58,19 +50,10 @@ public class ActionPerformService extends AccessibilityService {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static boolean isAssistModeEnable() {
|
||||
return assistModeEnable;
|
||||
}
|
||||
|
||||
public static void setAssistModeEnable(boolean assistModeEnable) {
|
||||
ActionPerformService.assistModeEnable = assistModeEnable;
|
||||
App.getStateObserver().setState(KEY_ASSIST_MODE_ENABLE, assistModeEnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
||||
Log.v(TAG, "onAccessibilityEvent: state=" + state + " event=" + event);
|
||||
performAssistance(event);
|
||||
Assistant.performAssistance(event);
|
||||
if (state == STATE_INACTIVE)
|
||||
return;
|
||||
AccessibilityNodeInfo root = getRootInActiveWindow();
|
||||
@@ -108,27 +91,6 @@ public class ActionPerformService extends AccessibilityService {
|
||||
}
|
||||
}
|
||||
|
||||
private void performAssistance(AccessibilityEvent event) {
|
||||
if (!assistModeEnable) {
|
||||
return;
|
||||
}
|
||||
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_CLICKED || event.getEventType() == AccessibilityEvent.TYPE_VIEW_LONG_CLICKED) {
|
||||
AccessibilityNodeInfo nodeInfo = event.getSource();
|
||||
if (nodeInfo == null) {
|
||||
return;
|
||||
}
|
||||
nodeInfo.refresh();
|
||||
Log.v(TAG, "click: " + nodeInfo);
|
||||
Rect rect = new Rect();
|
||||
nodeInfo.getBoundsInScreen(rect);
|
||||
String str = rect.toString().replace('-', ',').replace(" ", "").substring(4);
|
||||
ClipboardManager manager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
|
||||
manager.setPrimaryClip(ClipData.newPlainText("", str));
|
||||
Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
|
||||
nodeInfo.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInterrupt() {
|
||||
|
||||
@@ -140,10 +102,6 @@ public class ActionPerformService extends AccessibilityService {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
static {
|
||||
assistModeEnable = PreferenceManager.getDefaultSharedPreferences(App.getApp()).getBoolean(KEY_ASSIST_MODE_ENABLE, false);
|
||||
}
|
||||
|
||||
public static void disable() {
|
||||
if (instance != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
instance.disableSelf();
|
||||
|
||||
@@ -1,18 +1,15 @@
|
||||
package com.stardust.scriptdroid.droid.script;
|
||||
|
||||
import android.util.Pair;
|
||||
|
||||
import com.efurture.script.JSTransformer;
|
||||
import com.furture.react.DuktapeEngine;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.runtime.api.IDroidRuntime;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -22,7 +19,7 @@ import java.util.Map;
|
||||
public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
|
||||
|
||||
private final List<Pair<DuktapeEngine, Thread>> mDuktapeEngineList = new ArrayList<>();
|
||||
private final Map<Thread, DuktapeEngine> mThreadDuktapeEngineMap = new Hashtable<>();
|
||||
private static final String INIT_SCRIPT;
|
||||
private Map<String, Object> mVariableMap = new HashMap<>();
|
||||
|
||||
@@ -53,10 +50,10 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
try {
|
||||
result = duktapeEngine.execute(JSTransformer.parse(new StringReader(script)));
|
||||
} catch (IOException e) {
|
||||
remove(duktapeEngine);
|
||||
remove(Thread.currentThread());
|
||||
throw e;
|
||||
}
|
||||
remove(duktapeEngine);
|
||||
remove(Thread.currentThread());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -69,33 +66,26 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
|
||||
}
|
||||
|
||||
private void remove(DuktapeEngine duktapeEngine) {
|
||||
duktapeEngine.destory();
|
||||
synchronized (mDuktapeEngineList) {
|
||||
Iterator<Pair<DuktapeEngine, Thread>> iterator = mDuktapeEngineList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Pair<DuktapeEngine, Thread> pair = iterator.next();
|
||||
if (pair.first == duktapeEngine) {
|
||||
stop(pair.first, pair.second);
|
||||
}
|
||||
iterator.remove();
|
||||
break;
|
||||
}
|
||||
private void remove(Thread thread) {
|
||||
synchronized (mThreadDuktapeEngineMap) {
|
||||
DuktapeEngine engine = mThreadDuktapeEngineMap.remove(thread);
|
||||
stop(engine, thread);
|
||||
}
|
||||
}
|
||||
|
||||
private void stop(DuktapeEngine engine, Thread thread) {
|
||||
if (engine != null)
|
||||
engine.destory();
|
||||
try {
|
||||
thread.interrupt();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
engine.destory();
|
||||
}
|
||||
|
||||
private void add(DuktapeEngine duktapeEngine, Thread thread) {
|
||||
synchronized (mDuktapeEngineList) {
|
||||
mDuktapeEngineList.add(0, new Pair<>(duktapeEngine, thread));
|
||||
synchronized (mThreadDuktapeEngineMap) {
|
||||
mThreadDuktapeEngineMap.put(thread, duktapeEngine);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,14 +97,20 @@ public class DuktapeJavaScriptEngine implements JavaScriptEngine {
|
||||
@Override
|
||||
public int stopAll() {
|
||||
int n;
|
||||
synchronized (mDuktapeEngineList) {
|
||||
for (Pair<DuktapeEngine, Thread> pair : mDuktapeEngineList) {
|
||||
stop(pair.first, pair.second);
|
||||
synchronized (mThreadDuktapeEngineMap) {
|
||||
for (Map.Entry<Thread, DuktapeEngine> entry : mThreadDuktapeEngineMap.entrySet()) {
|
||||
stop(entry.getValue(), entry.getKey());
|
||||
}
|
||||
n = mDuktapeEngineList.size();
|
||||
mDuktapeEngineList.clear();
|
||||
n = mThreadDuktapeEngineMap.size();
|
||||
mThreadDuktapeEngineMap.clear();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ensureNotStopped() {
|
||||
if (!mThreadDuktapeEngineMap.containsKey(Thread.currentThread())) {
|
||||
throw new RuntimeException(App.getApp().getString(R.string.text_script_stopped));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ public interface JavaScriptEngine {
|
||||
|
||||
int stopAll();
|
||||
|
||||
void ensureNotStopped();
|
||||
|
||||
class Init {
|
||||
public static final String INIT_SCRIPT = readInitScript();
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.stardust.scriptdroid.droid.script.file;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
|
||||
import java.io.File;
|
||||
@@ -12,7 +14,7 @@ import java.io.File;
|
||||
|
||||
public class ScriptFile {
|
||||
|
||||
public static final String DEFAULT_FOLDER = Environment.getExternalStorageDirectory() + "/脚本/";
|
||||
public static final String DEFAULT_FOLDER = Environment.getExternalStorageDirectory() + App.getApp().getString(R.string.folder_name);
|
||||
public String name;
|
||||
|
||||
public String path;
|
||||
|
||||
@@ -37,7 +37,6 @@ public class Editor920Activity extends IActivity {
|
||||
public void doCommand(Command command) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openFile(String s, String s1, int i) {
|
||||
|
||||
@@ -54,8 +53,10 @@ public class Editor920Activity extends IActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertText(CharSequence charSequence) {
|
||||
|
||||
public void insertText(CharSequence text) {
|
||||
Command c = new Command(Command.CommandEnum.INSERT_TEXT);
|
||||
c.object = text;
|
||||
doCommand(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,6 +6,8 @@ import android.content.ContentResolver;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
@@ -44,7 +46,7 @@ public class FileChooser {
|
||||
intent.setType(mimeType);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
try {
|
||||
mActivity.startActivityForResult(Intent.createChooser(intent, "选择一个文件"), FILE_CHOOSE);
|
||||
mActivity.startActivityForResult(Intent.createChooser(intent, mActivity.getString(R.string.text_choose_file)), FILE_CHOOSE);
|
||||
} catch (ActivityNotFoundException ex) {
|
||||
handler.handle(ex, mimeType);
|
||||
}
|
||||
|
||||
@@ -1,418 +0,0 @@
|
||||
package com.stardust.scriptdroid.shortcut;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ShortcutHelper {
|
||||
public final static String TAG = ShortcutHelper.class.getSimpleName();
|
||||
public static final String ACTION_DESKTOP_LINK = "com.scu.zqc.action.SHORTCUT";
|
||||
public static final String READ_SETTINGS = "com.android.launcher.permission.READ_SETTINGS";
|
||||
public static final String ACTION_INSTALL_SHORTCUT = "com.android.launcher.action.INSTALL_SHORTCUT";
|
||||
public static final String ACTION_UNINSTALL_SHORTCUT = "com.android.launcher.action.UNINSTALL_SHORTCUT";
|
||||
public static final String MAIN_ACTIVITY = "com.scu.shortcut.MainActivity";
|
||||
public static final String APP_STORE_URL = "http://m.app.so.com/?src=browser";
|
||||
public static final String EXTRA_DUPLICATE = "duplicate";
|
||||
|
||||
public static void addShortCut(final Context context, Bitmap src) {
|
||||
String appStoreShortcutName = context.getString(R.string.app_name);
|
||||
if (getIsAddShortCut(context, appStoreShortcutName)) {
|
||||
// uninstallShortcut(context, appStoreShortcutName);
|
||||
try {
|
||||
int size = (int) context.getResources().getDimension(android.R.dimen.app_icon_size);
|
||||
Bitmap scaledBitmap = Bitmap.createScaledBitmap(src, size, size, true);
|
||||
createFavLinkShortCut(context, appStoreShortcutName, APP_STORE_URL, scaledBitmap, false, true);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean uninstallShortcut(Context context, String name, Intent shortCut) {
|
||||
Intent intent = new Intent(ACTION_UNINSTALL_SHORTCUT);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortCut);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
|
||||
context.sendBroadcast(intent);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean createFavLinkShortCut(Context context, String name, String url, Parcelable icon,
|
||||
boolean isSendToQihooDesktop, boolean skipCheckExist) {
|
||||
if (context == null || TextUtils.isEmpty(url) || TextUtils.isEmpty(name) || icon == null) {
|
||||
return false;
|
||||
}
|
||||
// 先查询launcher页面是否已经生成其快捷方式
|
||||
if (getIsAddShortCut(context, name) && !skipCheckExist) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Intent shortcutIntent = getShortCutIntent(context, url, MAIN_ACTIVITY);
|
||||
shortcutIntent.setAction(ACTION_DESKTOP_LINK);
|
||||
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Intent installIntent = getInstallIntent(shortcutIntent, name, icon);
|
||||
|
||||
// 将创建快捷方式的intent指定到桌面应用程序包来处理.
|
||||
String deskPackageName = getLauncherPackageName(context);
|
||||
if (null != deskPackageName && !TextUtils.isEmpty(deskPackageName)) {
|
||||
installIntent.setPackage(deskPackageName);
|
||||
}
|
||||
|
||||
if (isSendToQihooDesktop) {
|
||||
installIntent.putExtra("from", context.getPackageName());
|
||||
}
|
||||
|
||||
context.sendBroadcast(installIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取正在运行桌面包名(注:存在多个桌面时且未指定默认桌面时,该方法返回Null,使用时需处理这个情况)
|
||||
*/
|
||||
public static String getLauncherPackageName(Context context) {
|
||||
try {
|
||||
final Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.addCategory(Intent.CATEGORY_HOME);
|
||||
final ResolveInfo res = context.getPackageManager().resolveActivity(intent, 0);
|
||||
if (res != null && res.activityInfo == null) {
|
||||
// should not happen. A home is always installed, isn't it?
|
||||
return null;
|
||||
}
|
||||
|
||||
if (res != null && ("android").equals(res.activityInfo.packageName)) {
|
||||
// 有多个桌面程序存在,且未指定默认项时;
|
||||
return null;
|
||||
} else {
|
||||
return res.activityInfo.packageName;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Intent getInstallIntent(Context context, Intent shortcutIntent, int name, int res) {
|
||||
Intent intent = getInstallIntent(shortcutIntent, context.getString(name), null);
|
||||
Parcelable icon = Intent.ShortcutIconResource.fromContext(context, res);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, icon);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private static Intent getInstallIntent(Intent shortcutIntent, String name, Parcelable iconResource) {
|
||||
Intent intent = new Intent(ACTION_INSTALL_SHORTCUT);
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
|
||||
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
if (Build.VERSION.SDK_INT < 11 || "SM-N9008V".equals(Build.MODEL)) {
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "添加");
|
||||
} else {
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, "\t");
|
||||
}
|
||||
} else {
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
|
||||
}
|
||||
if (iconResource != null) {
|
||||
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, iconResource);
|
||||
}
|
||||
intent.putExtra(EXTRA_DUPLICATE, false);
|
||||
return intent;
|
||||
}
|
||||
|
||||
//判断应用是否安装
|
||||
public static boolean isPkgInstalled(Context c, String pkgName) {
|
||||
PackageManager mPm = c.getPackageManager();
|
||||
if (mPm == null) {
|
||||
return false;
|
||||
}
|
||||
PackageInfo pkginfo = null;
|
||||
try {
|
||||
pkginfo = mPm.getPackageInfo(pkgName, 0);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
//e.printStackTrace();
|
||||
}
|
||||
return pkginfo == null ? false : true;
|
||||
}
|
||||
|
||||
public static Intent getShortCutIntent(Context context, String action, String className) {
|
||||
Intent shortcutIntent = new Intent(Intent.ACTION_MAIN);
|
||||
if ("NX511J".equals(Build.MODEL)) {
|
||||
shortcutIntent.setPackage(context.getPackageName());
|
||||
} else {
|
||||
shortcutIntent.setClassName(context, className);
|
||||
}
|
||||
shortcutIntent.setData(Uri.parse(action));
|
||||
shortcutIntent.putExtra("value", "test");
|
||||
return shortcutIntent;
|
||||
}
|
||||
|
||||
public static boolean createShortCutWithIntentInSilence(Context context, String name, Intent shortCutIntent, Parcelable icon, boolean isSendToQihooDesktop) {
|
||||
if (context == null || TextUtils.isEmpty(name) || icon == null) {
|
||||
return false;
|
||||
}
|
||||
// 先查询launcher页面是否已经生成其快捷方式
|
||||
if (getIsAddShortCut(context, name)) {
|
||||
return false;
|
||||
}
|
||||
Intent installIntent = getInstallIntent(shortCutIntent, name, icon);
|
||||
// 将创建快捷方式的intent指定到桌面应用程序包来处理.
|
||||
String deskPackageName = getLauncherPackageName(context);
|
||||
if (null != deskPackageName && !TextUtils.isEmpty(deskPackageName)) {
|
||||
installIntent.setPackage(deskPackageName);
|
||||
}
|
||||
if (isSendToQihooDesktop) {
|
||||
installIntent.putExtra("from", context.getPackageName());
|
||||
}
|
||||
context.sendBroadcast(installIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean createFavLinkShortCutWithShortcutIntent(Context context, String name, String url, Parcelable icon,
|
||||
boolean isSendToQihooDesktop, boolean skipCheckExist, Intent shortcutIntent) {
|
||||
|
||||
if (context == null || TextUtils.isEmpty(url) || TextUtils.isEmpty(name) || icon == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 先查询launcher页面是否已经生成其快捷方式
|
||||
if (getIsAddShortCut(context, name) && !skipCheckExist) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Intent installIntent = getInstallIntent(shortcutIntent, name, icon);
|
||||
|
||||
// 将创建快捷方式的intent指定到桌面应用程序包来处理.
|
||||
String deskPackageName = getLauncherPackageName(
|
||||
context);
|
||||
|
||||
if (null != deskPackageName && !TextUtils.isEmpty(deskPackageName)) {
|
||||
installIntent.setPackage(deskPackageName);
|
||||
}
|
||||
|
||||
if (isSendToQihooDesktop) {
|
||||
installIntent.putExtra("from", context.getPackageName());
|
||||
}
|
||||
|
||||
context.sendBroadcast(installIntent);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean getIsAddShortCut(Context context, String name) {
|
||||
// 如果只是按照title来比较是否存在的话可能存在重名应用,所以还需要根据intent这个字段一起判断。
|
||||
String intentTag = "com.scu.zqc";
|
||||
Cursor c = null;
|
||||
try {
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
String AUTHORITY = getAuthority(context);
|
||||
Log.d(TAG, "AUTHORITY = " + AUTHORITY);
|
||||
|
||||
if (null == AUTHORITY) {
|
||||
AUTHORITY = getSuitableAuthority(context);
|
||||
}
|
||||
|
||||
final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/favorites?notify=true");
|
||||
c = cr.query(CONTENT_URI, new String[]{"title", "iconResource"},
|
||||
"title=? and intent like ?", new String[]{name, "%" + intentTag + "%"}, null);
|
||||
|
||||
if (null != c && c.getCount() > 0) {
|
||||
Log.d(TAG, "the shortCut of" + name + "has been created!");
|
||||
return true;
|
||||
} else {
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
// 有的手机上需要用下面的方法才能获取到快捷方式是否存在
|
||||
AUTHORITY = getAuthorityFromPermission(context, READ_SETTINGS);
|
||||
final Uri CONTENT_URI_AUTHORITY = Uri.parse("content://" + AUTHORITY +
|
||||
"/favorites?notify=true");
|
||||
c = cr.query(CONTENT_URI_AUTHORITY, new String[]{"title", "iconResource"},
|
||||
"title=? and intent like ?", new String[]{name, "%" + intentTag + "%"}, null);
|
||||
|
||||
if (null != c && c.getCount() > 0) {
|
||||
Log.d(TAG, "the shortCut of" + name + "has been created!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "exception: " + e.getMessage());
|
||||
return getIsAddShortCutFromPermission(context, name);
|
||||
} finally {
|
||||
if (c != null) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean getIsAddShortCutFromPermission(Context context, String name) {
|
||||
Cursor c = null;
|
||||
String intentTag = context.getPackageName();
|
||||
String AUTHORITY = getAuthorityFromPermission(context, READ_SETTINGS);
|
||||
try {
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
final Uri CONTENT_URI_AUTHORITY = Uri.parse("content://" + AUTHORITY +
|
||||
"/favorites?notify=true");
|
||||
c = cr.query(CONTENT_URI_AUTHORITY, new String[]{"title", "iconResource"},
|
||||
"title=? and intent like ?", new String[]{name, "%" + intentTag + "%"}, null);
|
||||
if (null != c && c.getCount() > 0) {
|
||||
Log.d(TAG, "the shortCut of" + name + "has been created!");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// : handle exception
|
||||
Log.e(TAG, "exception: " + e.getMessage());
|
||||
} finally {
|
||||
if (null != c) {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过permission来找不同机型的Authority
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getAuthority(Context context) {
|
||||
String authority = ".launcher.settings";
|
||||
String authority2 = ".launcher2.settings";
|
||||
String authority3 = ".launcher3.settings";
|
||||
List<PackageInfo> packs = null;
|
||||
try {
|
||||
packs = context.getPackageManager().getInstalledPackages(
|
||||
PackageManager.GET_PROVIDERS);
|
||||
|
||||
for (PackageInfo pack : packs) {
|
||||
ProviderInfo[] providers = pack.providers;
|
||||
|
||||
if (null != providers) {
|
||||
for (ProviderInfo provider : providers) {
|
||||
if (!TextUtils.isEmpty(provider.authority) && (provider.authority.contains(authority) ||
|
||||
provider.authority.contains(authority2) ||
|
||||
provider.authority.contains(authority3))) {
|
||||
return provider.authority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (OutOfMemoryError e) {
|
||||
e.printStackTrace();
|
||||
packs = null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static String getAuthorityFromPermission(Context context,
|
||||
String permission) {
|
||||
if (permission == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
List<PackageInfo> packs = context.getPackageManager()
|
||||
.getInstalledPackages(PackageManager.GET_PROVIDERS);
|
||||
|
||||
if (packs != null) {
|
||||
for (PackageInfo pack : packs) {
|
||||
ProviderInfo[] providers = pack.providers;
|
||||
|
||||
if (providers != null) {
|
||||
for (ProviderInfo provider : providers) {
|
||||
if (permission.equals(provider.readPermission)) {
|
||||
return provider.authority;
|
||||
}
|
||||
|
||||
if (permission.equals(provider.writePermission)) {
|
||||
return provider.authority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取合适的Authority访问launcher数据库<br/>
|
||||
* 优先级:".launcher3.settings" > ".launcher2.settings" > ".launcher.settings" > ".settings"
|
||||
*/
|
||||
public static String getSuitableAuthority(Context context) {
|
||||
String AUTHORITY = null;
|
||||
String authority = ".launcher.settings";
|
||||
String authority2 = ".launcher2.settings";
|
||||
String authority3 = ".launcher3.settings";
|
||||
String authority4 = ".settings";
|
||||
|
||||
List<PackageInfo> packs = context.getPackageManager().getInstalledPackages(
|
||||
PackageManager.GET_PROVIDERS);
|
||||
|
||||
List<String> authorityList = new ArrayList<String>();
|
||||
for (PackageInfo pack : packs) {
|
||||
ProviderInfo[] providers = pack.providers;
|
||||
|
||||
if (null != providers) {
|
||||
for (ProviderInfo provider : providers) {
|
||||
if (!TextUtils.isEmpty(provider.authority) && (provider.authority.contains(authority)
|
||||
|| provider.authority.contains(authority2) ||
|
||||
provider.authority.contains(authority3))) {
|
||||
authorityList.add(provider.authority);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String AUTHORITY_TEMP_1 = null;
|
||||
String AUTHORITY_TEMP_2 = null;
|
||||
String AUTHORITY_TEMP_3 = null;
|
||||
|
||||
for (String item : authorityList) {
|
||||
if (item.contains(authority3) && TextUtils.isEmpty(AUTHORITY_TEMP_3)) {
|
||||
AUTHORITY_TEMP_3 = item;
|
||||
} else if (item.contains(authority2) && TextUtils.isEmpty(AUTHORITY_TEMP_2)) {
|
||||
AUTHORITY_TEMP_2 = item;
|
||||
} else if (item.contains(authority) && TextUtils.isEmpty(AUTHORITY_TEMP_1)) {
|
||||
AUTHORITY_TEMP_1 = item;
|
||||
}
|
||||
}
|
||||
if (!TextUtils.isEmpty(AUTHORITY_TEMP_3)) {
|
||||
AUTHORITY = AUTHORITY_TEMP_3;//优先适配launcher3
|
||||
} else if (!TextUtils.isEmpty(AUTHORITY_TEMP_2)) {
|
||||
AUTHORITY = AUTHORITY_TEMP_2;
|
||||
} else if (!TextUtils.isEmpty(AUTHORITY_TEMP_1)) {
|
||||
AUTHORITY = AUTHORITY_TEMP_1;
|
||||
}
|
||||
if (TextUtils.isEmpty(AUTHORITY)) {
|
||||
for (PackageInfo pack : packs) {
|
||||
ProviderInfo[] providers = pack.providers;
|
||||
|
||||
if (null != providers) {
|
||||
for (ProviderInfo provider : providers) {
|
||||
if (!TextUtils.isEmpty(provider.authority) && provider.authority.endsWith(authority4)) {
|
||||
return provider.authority;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return AUTHORITY;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,26 @@
|
||||
package com.stardust.scriptdroid.tile;
|
||||
|
||||
import android.os.Build;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
import android.support.annotation.RequiresApi;
|
||||
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/1/26.
|
||||
*/
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.N)
|
||||
public class BoundsAssistEnableTileService extends TileService {
|
||||
|
||||
public void onClick() {
|
||||
ActionPerformService.setAssistModeEnable(!ActionPerformService.isAssistModeEnable());
|
||||
Assistant.setAssistModeEnable(!Assistant.isAssistModeEnable());
|
||||
updateTile();
|
||||
}
|
||||
|
||||
private void updateTile() {
|
||||
getQsTile().setState(ActionPerformService.isAssistModeEnable() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
||||
getQsTile().setState(Assistant.isAssistModeEnable() ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
||||
getQsTile().updateTile();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Intent工具,用于Activity之间的跳转,调起其他应用程序等
|
||||
*/
|
||||
@@ -28,7 +30,7 @@ public class IntentTool {
|
||||
intent.putExtra(Intent.EXTRA_SUBJECT, title);
|
||||
if (content != null)
|
||||
intent.putExtra(Intent.EXTRA_TEXT, content);
|
||||
context.startActivity(Intent.createChooser(intent, "请选择邮件应用"));
|
||||
context.startActivity(Intent.createChooser(intent, context.getString(R.string.text_choose_email_app)));
|
||||
}
|
||||
|
||||
public static void goToMail(Context context, String sendTo) {
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.assist.AssistClipList;
|
||||
import com.stardust.scriptdroid.droid.assist.SharedPrefAssistClipList;
|
||||
import com.stardust.scriptdroid.widget.ExpandableRecyclerView;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class AssistClipListRecyclerView extends ExpandableRecyclerView {
|
||||
|
||||
public interface OnClipClickListener {
|
||||
void onClick(String clip, int position);
|
||||
}
|
||||
|
||||
private AssistClipList mAssistClipList = SharedPrefAssistClipList.getInstance();
|
||||
private OnClipClickListener mOnClipClickListener;
|
||||
|
||||
public AssistClipListRecyclerView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public AssistClipListRecyclerView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public AssistClipListRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
setAdapter(new Adapter());
|
||||
setOnChildClickListener(new OnChildClickListener() {
|
||||
@Override
|
||||
public void onClick(View view, int position) {
|
||||
if (mOnClipClickListener != null) {
|
||||
String clip = (String) ((ChildViewHolder) getChildViewHolder(view)).mTextView.getText();
|
||||
mOnClipClickListener.onClick(clip, position);
|
||||
}
|
||||
}
|
||||
});
|
||||
mAssistClipList.setOnClipChangedListener(new AssistClipList.OnClipChangedListener() {
|
||||
@Override
|
||||
public void onClipRemove(int position) {
|
||||
getAdapter().notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClipInsert(int position) {
|
||||
getAdapter().notifyItemInserted(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange() {
|
||||
getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setOnClipClickListener(OnClipClickListener onClipClickListener) {
|
||||
mOnClipClickListener = onClipClickListener;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
//防止因mAssistClipList持有OnClipChangedListener引用从而导致这个RecyclerView及其Context被引用,内存泄漏
|
||||
mAssistClipList.setOnClipChangedListener(null);
|
||||
}
|
||||
|
||||
private class Adapter extends ExpandableRecyclerView.DefaultTitleAdapter {
|
||||
|
||||
Adapter() {
|
||||
setIcon(R.drawable.ic_robot_head_green);
|
||||
setTitle(R.string.text_assist_clip);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.ViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ChildViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.assist_clip_list_recycler_view_item, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindChildViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
ChildViewHolder viewHolder = (ChildViewHolder) holder;
|
||||
viewHolder.mTextView.setText(mAssistClipList.get(position));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildItemCount() {
|
||||
return mAssistClipList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildItemViewType(int position) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class ChildViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
TextView mTextView;
|
||||
|
||||
ChildViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
mTextView = (TextView) itemView.findViewById(R.id.clip);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,9 @@ import android.support.v4.app.NotificationCompat;
|
||||
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.scriptdroid.droid.assist.Assistant;
|
||||
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.
|
||||
@@ -45,7 +44,7 @@ public class AssistModeSwitchNotification {
|
||||
}
|
||||
}
|
||||
});
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_ENABLE, new StateObserver.OnBooleanStateChangedListener() {
|
||||
App.getStateObserver().register(Assistant.KEY_ASSIST_MODE_ENABLE, new StateObserver.OnBooleanStateChangedListener() {
|
||||
@Override
|
||||
public void onStateChanged(Boolean newState) {
|
||||
if (enable) {
|
||||
@@ -79,7 +78,7 @@ public class AssistModeSwitchNotification {
|
||||
.setAutoCancel(false)
|
||||
.setSmallIcon(R.drawable.ic_robot_head)
|
||||
.setDeleteIntent(AssistModeSwitchService.getDeletePendingIntent())
|
||||
.setContentText(ActionPerformService.isAssistModeEnable() ?
|
||||
.setContentText(Assistant.isAssistModeEnable() ?
|
||||
App.getApp().getString(R.string.text_assist_mode_enabled) :
|
||||
App.getApp().getString(R.string.text_assist_mode_disabled))
|
||||
.setContentIntent(AssistModeSwitchService.getStartIntent())
|
||||
|
||||
@@ -1,20 +1,118 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.SwitchCompat;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.DocumentActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.view.ViewBinder;
|
||||
import com.stardust.view.ViewBinding;
|
||||
|
||||
import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class EditSideMenuFragment extends com.stardust.app.Fragment {
|
||||
|
||||
|
||||
private FunctionListRecyclerView.OnFunctionClickListener mOnFunctionClickListener;
|
||||
private AssistClipListRecyclerView.OnClipClickListener mOnClipClickListener;
|
||||
|
||||
public static EditSideMenuFragment setFragment(AppCompatActivity activity, int viewId) {
|
||||
EditSideMenuFragment fragment = new EditSideMenuFragment();
|
||||
activity.getSupportFragmentManager().beginTransaction().replace(viewId, fragment).commit();
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private SwitchCompat mAssistServiceSwitch, mAssistServiceNotificationSwitch;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View createView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return null;
|
||||
return inflater.inflate(R.layout.fragment_edit_side_menu, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (mAssistServiceSwitch == null) {
|
||||
setUpUI();
|
||||
}
|
||||
syncSwitchState();
|
||||
}
|
||||
|
||||
private void setUpUI() {
|
||||
setUpSwitchCompat();
|
||||
setUpFunctionList();
|
||||
setUpClipList();
|
||||
ViewBinder.bind(this);
|
||||
}
|
||||
|
||||
private void setUpClipList() {
|
||||
AssistClipListRecyclerView assistClipListRecyclerView = $(R.id.assist_clip_list);
|
||||
assistClipListRecyclerView.setOnClipClickListener(mOnClipClickListener);
|
||||
}
|
||||
|
||||
private void setUpFunctionList() {
|
||||
FunctionListRecyclerView functionListRecyclerView = $(R.id.function_list);
|
||||
functionListRecyclerView.setOnFunctionClickListener(mOnFunctionClickListener);
|
||||
|
||||
}
|
||||
|
||||
private void syncSwitchState() {
|
||||
mAssistServiceSwitch.setChecked(Assistant.isAssistModeEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(AssistModeSwitchNotification.isEnable());
|
||||
}
|
||||
|
||||
private void setUpSwitchCompat() {
|
||||
mAssistServiceSwitch = $(R.id.sw_assist_service);
|
||||
mAssistServiceNotificationSwitch = $(R.id.sw_assist_service_notification);
|
||||
App.getStateObserver().register(Assistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.syntax_and_api)
|
||||
private void startSyntaxHelpActivity() {
|
||||
startActivity(new Intent(getContext(), DocumentActivity.class));
|
||||
}
|
||||
|
||||
@ViewBinding.Check(R.id.sw_assist_service)
|
||||
private void setAssistServiceEnable(boolean enable) {
|
||||
Assistant.setAssistModeEnable(enable);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.assist_service)
|
||||
private void toggleAssistServiceSwitch() {
|
||||
mAssistServiceSwitch.toggle();
|
||||
}
|
||||
|
||||
@ViewBinding.Check(R.id.sw_assist_service_notification)
|
||||
private void setAssistServiceNotificationEnable(boolean enable) {
|
||||
AssistModeSwitchNotification.setEnable(enable);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.assist_service_notification)
|
||||
private void toggleAssistServiceNotificationSwitch() {
|
||||
mAssistServiceNotificationSwitch.toggle();
|
||||
}
|
||||
|
||||
public EditSideMenuFragment setOnFunctionClickListener(FunctionListRecyclerView.OnFunctionClickListener onFunctionClickListener) {
|
||||
mOnFunctionClickListener = onFunctionClickListener;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EditSideMenuFragment setOnClipClickListener(AssistClipListRecyclerView.OnClipClickListener onClipClickListener) {
|
||||
mOnClipClickListener = onClipClickListener;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
package com.stardust.scriptdroid.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.file.FileUtils;
|
||||
import com.stardust.scriptdroid.widget.ExpandableRecyclerView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class FunctionListRecyclerView extends ExpandableRecyclerView {
|
||||
|
||||
public interface OnFunctionClickListener {
|
||||
void onClick(Function function, int position);
|
||||
}
|
||||
|
||||
public static class Function {
|
||||
public String name;
|
||||
String description;
|
||||
|
||||
public Function(String name, String description) {
|
||||
this.description = description;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static final List<Function> FUNCTION_LIST = new ArrayList<>();
|
||||
|
||||
static {
|
||||
initFunctionList();
|
||||
}
|
||||
|
||||
private List<Function> mFunctionList;
|
||||
private OnFunctionClickListener mOnFunctionClickListener;
|
||||
|
||||
public FunctionListRecyclerView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public FunctionListRecyclerView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public FunctionListRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
setAdapter(new Adapter());
|
||||
setFunctionList(FUNCTION_LIST);
|
||||
setOnChildClickListener(new OnChildClickListener() {
|
||||
@Override
|
||||
public void onClick(View view, int position) {
|
||||
if (mOnFunctionClickListener != null) {
|
||||
mOnFunctionClickListener.onClick(mFunctionList.get(position), position);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setFunctionList(List<Function> functionList) {
|
||||
mFunctionList = functionList;
|
||||
}
|
||||
|
||||
public void setOnFunctionClickListener(OnFunctionClickListener onFunctionClickListener) {
|
||||
mOnFunctionClickListener = onFunctionClickListener;
|
||||
}
|
||||
|
||||
|
||||
private class Adapter extends ExpandableRecyclerView.DefaultTitleAdapter {
|
||||
|
||||
Adapter() {
|
||||
setIcon(R.drawable.ic_function_mathematical_green);
|
||||
setTitle(R.string.text_function);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.ViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {
|
||||
return new ChildViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.function_list_recycler_view_item, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindChildViewHolder(RecyclerView.ViewHolder holder, int position) {
|
||||
ChildViewHolder viewHolder = (ChildViewHolder) holder;
|
||||
Function function = mFunctionList.get(position);
|
||||
viewHolder.mFunctionName.setText(function.name);
|
||||
viewHolder.mDescription.setText(function.description);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildItemCount() {
|
||||
return mFunctionList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getChildItemViewType(int position) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class ChildViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
TextView mFunctionName, mDescription;
|
||||
|
||||
public ChildViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
mFunctionName = (TextView) itemView.findViewById(R.id.function_name);
|
||||
mDescription = (TextView) itemView.findViewById(R.id.description);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void initFunctionList() {
|
||||
String[] functions = FileUtils.readString(App.getApp().getResources().openRawResource(R.raw.edit_side_menu_functions)).split("\n");
|
||||
for (String f : functions) {
|
||||
String[] str = f.split(" ");
|
||||
FUNCTION_LIST.add(new Function(str[0], str[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
|
||||
import android.support.design.widget.Snackbar;
|
||||
|
||||
import com.afollestad.materialdialogs.MaterialDialog;
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.EditActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.ShortcutActivity;
|
||||
@@ -57,12 +58,12 @@ public abstract class ScriptFileOperation {
|
||||
public static class Run extends ScriptFileOperation {
|
||||
|
||||
static {
|
||||
addOperation("运行", R.drawable.ic_play_green, new Run());
|
||||
addOperation(App.getApp().getString(R.string.text_run), R.drawable.ic_play_green, new Run());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(ScriptListRecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
|
||||
Snackbar.make(recyclerView, "开始运行", Snackbar.LENGTH_SHORT).show();
|
||||
Snackbar.make(recyclerView, R.string.text_start_running, Snackbar.LENGTH_SHORT).show();
|
||||
ScriptFile scriptFile = scriptFileList.get(position);
|
||||
scriptFile.run();
|
||||
}
|
||||
@@ -71,7 +72,7 @@ public abstract class ScriptFileOperation {
|
||||
public static class Edit extends ScriptFileOperation {
|
||||
|
||||
static {
|
||||
//addOperation("编辑", R.drawable.ic_edit_green_48dp, new Edit());
|
||||
//addOperation(App.getApp().getString(R.string.text_edit)", R.drawable.ic_edit_green_48dp, new Edit());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -85,7 +86,7 @@ public abstract class ScriptFileOperation {
|
||||
public static class OpenByOtherApp extends ScriptFileOperation {
|
||||
|
||||
static {
|
||||
addOperation("用其他应用打开", R.drawable.ic_open_in_new_green_48dp, new OpenByOtherApp());
|
||||
addOperation(App.getApp().getString(R.string.text_open_by_other_apps), R.drawable.ic_open_in_new_green_48dp, new OpenByOtherApp());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,16 +101,16 @@ public abstract class ScriptFileOperation {
|
||||
public static class Rename extends ScriptFileOperation {
|
||||
|
||||
static {
|
||||
addOperation("重命名", R.drawable.ic_rename_green, new Rename());
|
||||
addOperation(App.getApp().getString(R.string.text_rename), R.drawable.ic_rename_green, new Rename());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(final ScriptListRecyclerView recyclerView, final ScriptFileList scriptFileList, final int position) {
|
||||
String oldName = scriptFileList.get(position).name;
|
||||
new MaterialDialog.Builder(recyclerView.getContext())
|
||||
.title("重命名")
|
||||
.checkBoxPrompt("同时重命名原文件", false, null)
|
||||
.input("输入新名称", oldName, new MaterialDialog.InputCallback() {
|
||||
.title(R.string.text_rename)
|
||||
.checkBoxPrompt(App.getApp().getString(R.string.text_rename_file_meanwhile), false, null)
|
||||
.input(App.getApp().getString(R.string.text_please_input_new_name), oldName, new MaterialDialog.InputCallback() {
|
||||
@Override
|
||||
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
|
||||
scriptFileList.rename(position, input.toString(), dialog.isPromptCheckBoxChecked());
|
||||
@@ -123,7 +124,7 @@ public abstract class ScriptFileOperation {
|
||||
public static class CreateShortcut extends ScriptFileOperation {
|
||||
|
||||
static {
|
||||
addOperation("创建桌面快捷方式", R.drawable.ic_shortcut_green, new CreateShortcut());
|
||||
addOperation(App.getApp().getString(R.string.text_send_shortcut), R.drawable.ic_shortcut_green, new CreateShortcut());
|
||||
}
|
||||
|
||||
|
||||
@@ -136,14 +137,14 @@ public abstract class ScriptFileOperation {
|
||||
.icon(R.drawable.script_droid)
|
||||
.extras(new Intent().putExtra("path", scriptFile.path))
|
||||
.send();
|
||||
Snackbar.make(recyclerView, "已创建", Snackbar.LENGTH_SHORT).show();
|
||||
Snackbar.make(recyclerView, R.string.text_already_create, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Remove extends ScriptFileOperation {
|
||||
|
||||
static {
|
||||
addOperation("删除", R.drawable.ic_delete_green_48dp, new Remove());
|
||||
addOperation(App.getApp().getString(R.string.text_delete), R.drawable.ic_delete_green_48dp, new Remove());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,13 +157,13 @@ public abstract class ScriptFileOperation {
|
||||
public static class Delete extends ScriptFileOperation {
|
||||
|
||||
static {
|
||||
addOperation("彻底删除", R.drawable.ic_delete_forever_green_48dp, new Delete());
|
||||
addOperation(App.getApp().getString(R.string.text_delete_absolutly), R.drawable.ic_delete_forever_green_48dp, new Delete());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operate(ScriptListRecyclerView recyclerView, ScriptFileList scriptFileList, int position) {
|
||||
boolean succeed = scriptFileList.deleteFromFileSystem(position);
|
||||
Snackbar.make(recyclerView, succeed ? "已删除" : "文件删除失败", Snackbar.LENGTH_SHORT).show();
|
||||
Snackbar.make(recyclerView, succeed ? R.string.text_already_delete : R.string.text_delete_failed, Snackbar.LENGTH_SHORT).show();
|
||||
recyclerView.getAdapter().notifyItemRemoved(position);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,12 +15,12 @@ import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.DocumentActivity;
|
||||
import com.stardust.scriptdroid.R;
|
||||
import com.stardust.scriptdroid.droid.Droid;
|
||||
import com.stardust.scriptdroid.droid.assist.Assistant;
|
||||
import com.stardust.scriptdroid.droid.runtime.action.ActionPerformService;
|
||||
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.KEY_ASSIST_MODE_ENABLE;
|
||||
import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIST_MODE_NOTIFICATION;
|
||||
|
||||
/**
|
||||
@@ -30,7 +30,7 @@ import static com.stardust.scriptdroid.ui.AssistModeSwitchNotification.KEY_ASSIS
|
||||
public class SlideMenuFragment extends Fragment {
|
||||
|
||||
|
||||
public static void init(AppCompatActivity activity, int viewId) {
|
||||
public static void setFragment(AppCompatActivity activity, int viewId) {
|
||||
SlideMenuFragment fragment = new SlideMenuFragment();
|
||||
activity.getSupportFragmentManager().beginTransaction().replace(viewId, fragment).commit();
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
mAutoOperateServiceSwitch.setChecked(ActionPerformService.isEnable());
|
||||
}
|
||||
}, 450);
|
||||
mAssistServiceSwitch.setChecked(ActionPerformService.isAssistModeEnable());
|
||||
mAssistServiceSwitch.setChecked(Assistant.isAssistModeEnable());
|
||||
mAssistServiceNotificationSwitch.setChecked(AssistModeSwitchNotification.isEnable());
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ 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(Assistant.KEY_ASSIST_MODE_ENABLE, mAssistServiceSwitch);
|
||||
App.getStateObserver().register(KEY_ASSIST_MODE_NOTIFICATION, mAssistServiceNotificationSwitch);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ public class SlideMenuFragment extends Fragment {
|
||||
|
||||
@ViewBinding.Check(R.id.sw_assist_service)
|
||||
private void setAssistServiceEnable(boolean enable) {
|
||||
ActionPerformService.setAssistModeEnable(enable);
|
||||
Assistant.setAssistModeEnable(enable);
|
||||
}
|
||||
|
||||
@ViewBinding.Click(R.id.assist_service)
|
||||
@@ -115,9 +115,9 @@ public class SlideMenuFragment extends Fragment {
|
||||
private void stopAllRunningScripts() {
|
||||
int n = Droid.getInstance().stopAll();
|
||||
if (n > 0)
|
||||
Snackbar.make(getActivityContentView(), "已停止" + n + "个正在运行的脚本", Snackbar.LENGTH_SHORT).show();
|
||||
Snackbar.make(getActivityContentView(), String.format(getString(R.string.text_already_stop_n_scripts), n), Snackbar.LENGTH_SHORT).show();
|
||||
else
|
||||
Snackbar.make(getActivityContentView(), "没有正在运行的脚本", Snackbar.LENGTH_SHORT).show();
|
||||
Snackbar.make(getActivityContentView(), R.string.text_no_running_script, Snackbar.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.stardust.scriptdroid.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/4.
|
||||
*/
|
||||
|
||||
public class ExpandableRecyclerView extends RecyclerView {
|
||||
|
||||
public void setOnChildClickListener(OnChildClickListener onChildClickListener) {
|
||||
mOnChildClickListener = onChildClickListener;
|
||||
}
|
||||
|
||||
public interface OnChildClickListener {
|
||||
|
||||
void onClick(View view, int position);
|
||||
}
|
||||
|
||||
|
||||
private OnClickListener mOnTitleClickListener = new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toggle();
|
||||
}
|
||||
|
||||
};
|
||||
private OnClickListener mOnChildClickListenerWrapper = new OnClickListener() {
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (mOnChildClickListener != null) {
|
||||
mOnChildClickListener.onClick(v, getChildViewHolder(v).getAdapterPosition() - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
private boolean mExpanded;
|
||||
private OnChildClickListener mOnChildClickListener;
|
||||
|
||||
public ExpandableRecyclerView(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public ExpandableRecyclerView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ExpandableRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
|
||||
}
|
||||
|
||||
public void toggle() {
|
||||
if (isExpanded()) {
|
||||
collapse();
|
||||
} else {
|
||||
expand();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isExpanded() {
|
||||
return mExpanded;
|
||||
}
|
||||
|
||||
public void expand() {
|
||||
mExpanded = true;
|
||||
((Adapter) getAdapter()).notifyExpanded();
|
||||
}
|
||||
|
||||
public void collapse() {
|
||||
mExpanded = false;
|
||||
((Adapter) getAdapter()).notifyCollapsed();
|
||||
}
|
||||
|
||||
public abstract class Adapter extends RecyclerView.Adapter<ViewHolder> {
|
||||
|
||||
protected static final int VIEW_TYPE_TITLE = 1;
|
||||
|
||||
public void notifyExpanded() {
|
||||
notifyItemChanged(0);
|
||||
int n = getItemCount();
|
||||
for (int i = 1; i < n; i++) {
|
||||
notifyItemInserted(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyCollapsed() {
|
||||
int n = getChildItemCount();
|
||||
for (int i = 0; i < n; i++) {
|
||||
notifyItemRemoved(1);
|
||||
}
|
||||
notifyItemChanged(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mExpanded ? getChildItemCount() + 1 : 1;
|
||||
}
|
||||
|
||||
protected abstract int getChildItemCount();
|
||||
|
||||
@Override
|
||||
public int getItemViewType(int position) {
|
||||
return position == 0 ? VIEW_TYPE_TITLE : getChildItemViewType(position - 1);
|
||||
}
|
||||
|
||||
protected abstract int getChildItemViewType(int position);
|
||||
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
if (viewType == VIEW_TYPE_TITLE) {
|
||||
ViewHolder holder = onCreateTitleViewHolder(parent);
|
||||
holder.itemView.setOnClickListener(mOnTitleClickListener);
|
||||
return holder;
|
||||
} else {
|
||||
ViewHolder holder = onCreateChildViewHolder(parent, viewType);
|
||||
holder.itemView.setOnClickListener(mOnChildClickListenerWrapper);
|
||||
return holder;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract ViewHolder onCreateTitleViewHolder(ViewGroup parent);
|
||||
|
||||
protected abstract ViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType);
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
if (holder.getItemViewType() == VIEW_TYPE_TITLE) {
|
||||
onBindTitleViewHolder(holder);
|
||||
} else {
|
||||
onBindChildViewHolder(holder, position - 1);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void onBindChildViewHolder(ViewHolder holder, int position);
|
||||
|
||||
protected abstract void onBindTitleViewHolder(ViewHolder holder);
|
||||
|
||||
}
|
||||
|
||||
public abstract class DefaultTitleAdapter extends Adapter {
|
||||
|
||||
private int mIconResId = -1;
|
||||
private String mTitle;
|
||||
|
||||
public void setIcon(int iconResId) {
|
||||
mIconResId = iconResId;
|
||||
}
|
||||
|
||||
public void setTitle(int resId) {
|
||||
mTitle = getContext().getString(resId);
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
mTitle = title;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RecyclerView.ViewHolder onCreateTitleViewHolder(ViewGroup parent) {
|
||||
return new TitleViewHolder(LayoutInflater.from(getContext()).inflate(R.layout.expanded_recycler_view_default_title, parent, false));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onBindTitleViewHolder(RecyclerView.ViewHolder holder) {
|
||||
TitleViewHolder viewHolder = (TitleViewHolder) holder;
|
||||
viewHolder.mExpandHint.setImageResource(isExpanded() ? R.drawable.ic_expanded : R.drawable.ic_collapsed);
|
||||
}
|
||||
|
||||
|
||||
private class TitleViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
ImageView mExpandHint;
|
||||
|
||||
TitleViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
mExpandHint = (ImageView) itemView.findViewById(R.id.expand_hint);
|
||||
((TextView) itemView.findViewById(R.id.title)).setText(mTitle);
|
||||
if (mIconResId != -1) {
|
||||
((ImageView) itemView.findViewById(R.id.icon)).setImageResource(mIconResId);
|
||||
} else {
|
||||
itemView.findViewById(R.id.icon).setVisibility(GONE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import com.stardust.scriptdroid.App;
|
||||
import com.stardust.scriptdroid.R;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
@@ -26,7 +27,7 @@ public class CrashHandler implements UncaughtExceptionHandler {
|
||||
try {
|
||||
Log.e("CrashHandler", "Uncaught Exception!!!");
|
||||
ex.printStackTrace();
|
||||
String t = "很抱歉,程序遇到未知错误,即将停止运行\n错误代码:" + ex.toString();
|
||||
String t = App.getApp().getString(R.string.sorry_for_crash) + ex.toString();
|
||||
Intent intent = new Intent(App.getApp(), this.mErrorReportClass);
|
||||
intent.putExtra("message", t);
|
||||
intent.putExtra("error", throwableToString(ex));
|
||||
|
||||
@@ -4,10 +4,10 @@ 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;
|
||||
import java.util.Vector;
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/2/3.
|
||||
@@ -115,7 +115,7 @@ public class StateObserver {
|
||||
private List<OnStateChangedListener> getListenerListOrCreateIfNotExists(String key) {
|
||||
List<OnStateChangedListener> listeners = mKeyStateListenersMap.get(key);
|
||||
if (listeners == null) {
|
||||
listeners = new ArrayList<>();
|
||||
listeners = new Vector<>();
|
||||
mKeyStateListenersMap.put(key, listeners);
|
||||
}
|
||||
return listeners;
|
||||
|
||||
Reference in New Issue
Block a user