This commit is contained in:
hyb1996
2017-04-26 13:48:59 +08:00
parent 38fa3b3988
commit 6829c0659e
92 changed files with 3439 additions and 679 deletions

View File

@@ -10,13 +10,17 @@ import android.support.annotation.Keep;
import com.squareup.leakcanary.LeakCanary;
import com.stardust.app.SimpleActivityLifecycleCallbacks;
import com.stardust.app.VolumeChangeObserver;
import com.stardust.mi666.OCR;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.tool.CrashHandler;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.scriptdroid.tool.JsBeautifierFactory;
import com.stardust.scriptdroid.ui.error.ErrorReportActivity;
import com.stardust.theme.ThemeColor;
import com.stardust.theme.ThemeColorManager;
import com.stardust.util.ScreenMetrics;
import java.lang.ref.WeakReference;
/**
* Created by Stardust on 2017/1/27.
@@ -26,23 +30,25 @@ public class App extends Application {
private static final String TAG = "App";
private static App instance;
private static Activity currentActivity;
private static WeakReference<App> instance;
private static WeakReference<Activity> currentActivity;
public static App getApp() {
return instance;
return instance.get();
}
private VolumeChangeObserver mVolumeChangeObserver = new VolumeChangeObserver();
public void onCreate() {
super.onCreate();
instance = this;
instance = new WeakReference<>(this);
setUpDebugEnvironment();
init();
registerActivityLifecycleCallback();
}
private void setUpDebugEnvironment() {
if (LeakCanary.isInAnalyzerProcess(this)) {
return;
@@ -56,8 +62,10 @@ public class App extends Application {
ThemeColorManager.setDefaultThemeColor(new ThemeColor(getResources().getColor(R.color.colorPrimary), getResources().getColor(R.color.colorPrimaryDark), getResources().getColor(R.color.colorAccent)));
ThemeColorManager.init(this);
AutoJs.initInstance(this);
JsBeautifierFactory.initJsBeautify(this, "js/jsbeautify.js");
initVolumeChangeObserver();
startService(new Intent(this, AccessibilityWatchDogService.class));
OCR.init(this);
}
private void initVolumeChangeObserver() {
@@ -74,10 +82,6 @@ public class App extends Application {
private void registerActivityLifecycleCallback() {
registerActivityLifecycleCallbacks(new SimpleActivityLifecycleCallbacks() {
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
currentActivity = activity;
}
@Override
public void onActivityPaused(Activity activity) {
@@ -86,20 +90,17 @@ public class App extends Application {
@Override
public void onActivityResumed(Activity activity) {
currentActivity = activity;
ScreenMetrics.initIfNeeded(activity);
currentActivity = new WeakReference<>(activity);
}
@Override
public void onActivityStopped(Activity activity) {
currentActivity = null;
}
});
}
@Keep
public static Activity currentActivity() {
return currentActivity;
return currentActivity.get();
}
public static String getResString(int id) {

View File

@@ -46,7 +46,7 @@ public class Pref {
}
public static boolean isFirstGoToAccessibilitySetting() {
return getDisposableBoolean("isFirstGoToAccessibilitySetting", true);
return getDisposableBoolean("I miss you so much ...", true);
}
public static int oldVersion() {
@@ -77,7 +77,7 @@ public class Pref {
return App.getResString(id);
}
public static int MaxTextLengthForCodeCompletion() {
public static int getMaxTextLengthForCodeCompletion() {
try {
return Integer.parseInt(def().getString(App.getApp().getString(R.string.key_max_length_for_code_completion), "2000"));
} catch (NumberFormatException e) {

View File

@@ -0,0 +1,77 @@
package com.stardust.scriptdroid.external.floating_window;
import android.content.Context;
import android.content.ContextWrapper;
import android.support.annotation.Nullable;
import android.view.ContextThemeWrapper;
import android.view.View;
import com.stardust.enhancedfloaty.ResizableFloaty;
import com.stardust.enhancedfloaty.ResizableFloatyService;
import com.stardust.scriptdroid.R;
/**
* Created by Stardust on 2017/4/20.
*/
public class ConsoleFloaty extends ResizableFloaty {
private ContextWrapper mContextWrapper;
private View mResizer, mMoveCursor;
@Override
public View inflateCollapsedView(ResizableFloatyService service) {
ensureContextWrapper(service);
return View.inflate(mContextWrapper, R.layout.floating_window_collapse, null);
}
private void ensureContextWrapper(Context context) {
if (mContextWrapper == null) {
mContextWrapper = new ContextThemeWrapper(context, R.style.AppTheme);
}
}
@Override
public View inflateExpandedView(ResizableFloatyService service) {
ensureContextWrapper(service);
View view = View.inflate(mContextWrapper, R.layout.floating_console_expand, null);
setListeners(view, service);
return view;
}
private void setListeners(final View view, final ResizableFloatyService service) {
view.findViewById(R.id.close).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
service.stopSelf();
service.stopForeground(true);
}
});
view.findViewById(R.id.move_or_resize).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(mMoveCursor.getVisibility() == View.VISIBLE){
mMoveCursor.setVisibility(View.GONE);
mResizer.setVisibility(View.GONE);
}else {
mMoveCursor.setVisibility(View.VISIBLE);
mResizer.setVisibility(View.VISIBLE);
}
}
});
}
@Nullable
@Override
public View getResizerView(View expandedView) {
mResizer = expandedView.findViewById(R.id.resizer);
return mResizer;
}
@Nullable
@Override
public View getMoveCursorView(View expandedView) {
mMoveCursor = expandedView.findViewById(R.id.move_cursor);
return mMoveCursor;
}
}

View File

@@ -0,0 +1,16 @@
package com.stardust.scriptdroid.external.floating_window;
import android.content.Context;
import com.stardust.enhancedfloaty.ResizableFloatyService;
/**
* Created by Stardust on 2017/4/18.
*/
public class FloatingConsole {
public static void startFloatingService(Context context) {
ResizableFloatyService.startService(context, new ConsoleFloaty());
}
}

View File

@@ -186,7 +186,7 @@ public class RecordNavigatorContent implements NavigatorContent, Recorder.OnStat
@Override
public void onStop() {
MainActivity.onActionRecordStopped(mContext, mRecorder.getCode());
MainActivity.onRecordStop(mContext, mRecorder.getCode());
mRecorder = null;
}

View File

@@ -96,6 +96,7 @@ public class ScriptListNavigatorContent implements NavigatorContent {
int position = mFloatingScriptFileListView.getChildViewHolder((View) v.getParent()).getAdapterPosition();
ScriptFile file = mFloatingScriptFileListView.getAdapter().getScriptFileAt(position);
EditActivity.editFile(v.getContext(), file);
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_COLLAPSE_MENU));
}
});

View File

@@ -62,14 +62,15 @@ public class FloatingLayoutHierarchyView extends LayoutHierarchyView {
.customView(mNodeInfoView, false)
.theme(Theme.LIGHT)
.build();
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
if (mNodeInfoDialog.getWindow() != null)
mNodeInfoDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
EventBus.getDefault().post(new MessageEvent(HoverMenuService.MESSAGE_SHOW_AND_EXPAND_MENU));
HoverMenuService.postEvent(new MessageEvent(HoverMenuService.MESSAGE_SHOW_AND_EXPAND_MENU));
setVisibility(GONE);
return true;
}

View File

@@ -0,0 +1,71 @@
package com.stardust.scriptdroid.tool;
import android.graphics.Bitmap;
import android.graphics.Matrix;
/**
* Created by Stardust on 2017/4/22.
*/
public class BitmapTool {
public static Bitmap scaleBitmap(Bitmap origin, int newWidth, int newHeight) {
if (origin == null) {
return null;
}
int height = origin.getHeight();
int width = origin.getWidth();
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);// 使用后乘
return Bitmap.createBitmap(origin, 0, 0, width, height, matrix, false);
}
/*
public static MatOfDMatch matchesBitmaps(Bitmap bitmap1, Bitmap bitmap2) {
FeatureDetector detector = FeatureDetector.create(FeatureDetector.BRISK);
DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB);
DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING);
Mat descriptors1 = computeDescriptors(bitmap1, detector, descriptor);
Mat descriptors2 = computeDescriptors(bitmap2, detector, descriptor);
MatOfDMatch matches = new MatOfDMatch();
matcher.match(descriptors1, descriptors2, matches);
return matches;
}
private static Mat computeDescriptors(Bitmap bitmap, FeatureDetector detector, DescriptorExtractor descriptor) {
Mat mat = bitmapToMat(bitmap.copy(bitmap.getConfig(), true));
Mat descriptors = new Mat();
MatOfKeyPoint keyPoints1 = new MatOfKeyPoint();
detector.detect(mat, keyPoints1);
descriptor.compute(mat, keyPoints1, descriptors);
return descriptors;
}
private static Mat bitmapToMat(Bitmap bmp) {
Mat mat = new Mat(bmp.getWidth(), bmp.getHeight(), CvType.CV_8UC1);
Utils.bitmapToMat(bmp, mat);
return mat;
}
public static Core.MinMaxLocResult templateMatching(Bitmap bitmap, Bitmap tmp, int matchMethod) {
Mat img = bitmapToMat(bitmap);
Mat template = bitmapToMat(tmp);
// / Create the result matrix
int result_cols = img.cols() - template.cols() + 1;
int result_rows = img.rows() - template.rows() + 1;
Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
// / Do the Matching and Normalize
Imgproc.matchTemplate(img, template, result, matchMethod);
Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
// / Localizing the best match with minMaxLoc
Core.MinMaxLocResult mmr = Core.minMaxLoc(result);
return mmr;
}
*/
}

View File

@@ -14,7 +14,6 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Callable;
/**
* Created by Stardust on 2017/4/3.
@@ -24,14 +23,14 @@ public abstract class DrawableSaver {
private static final String PREFIX = "saved_drawable_";
protected Drawable mOriginalDrawble;
protected Drawable mOriginalDrawable;
private Context mContext;
private String mName;
public DrawableSaver(Context context, String name, Drawable originalDrawble) {
public DrawableSaver(Context context, String name, Drawable originalDrawable) {
mContext = context;
mName = PREFIX + name;
mOriginalDrawble = originalDrawble;
mOriginalDrawable = originalDrawable;
readImageAndApply();
}
@@ -89,7 +88,7 @@ public abstract class DrawableSaver {
}
public void reset() {
applyDrawableToView(mOriginalDrawble);
applyDrawableToView(mOriginalDrawable);
mContext.deleteFile(mName);
}

View File

@@ -0,0 +1,162 @@
package com.stardust.scriptdroid.tool;
/**
* Created by Stardust on 2017/4/23.
*/
import android.graphics.Bitmap;
import com.stardust.mi666.ocr.ColorDetector;
import com.stardust.mi666.ocr.SimpleTextDetector;
import java.util.HashMap;
import java.util.Map;
public class ImagePHash {
private static final String LOG_TAG = "ImagePHash";
private int width = 32;
private int height;
private int smallerWidth = 8;
private int smallerHeight;
public ImagePHash() {
this(32, 8);
}
public ImagePHash(int width, int smallerWidth) {
this(width, width, smallerWidth, smallerWidth);
}
public ImagePHash(int width, int height, int smallerWidth, int smallerHeight) {
this.width = width;
this.height = height;
this.smallerWidth = smallerWidth;
this.smallerHeight = smallerHeight;
initCoefficients();
}
public int distance(boolean[] s1, boolean[] s2) {
int counter = 0;
for (int k = 0; k < s1.length; k++) {
if (s1[k] != s2[k]) {
counter++;
}
}
return counter;
}
public boolean[] getHash(Bitmap img) {
double[][] vals = new double[width][height];
img = BitmapTool.scaleBitmap(img, width, height);
for (int x = 0; x < img.getWidth(); x++) {
for (int y = 0; y < img.getHeight(); y++) {
vals[x][y] = getBlue(img, x, y);
}
}
double[][] dctVals = applyDCT(vals);
double total = 0;
for (int x = 0; x < smallerWidth; x++) {
for (int y = 0; y < smallerHeight; y++) {
total += dctVals[x][y];
}
}
total -= dctVals[0][0];
double avg = total / (double) ((smallerWidth * smallerHeight) - 1);
boolean[] hash = new boolean[smallerWidth * smallerHeight];
int i = 0;
for (int x = 0; x < smallerWidth; x++) {
for (int y = 0; y < smallerHeight; y++) {
if (x != 0 && y != 0) {
hash[i++] = dctVals[x][y] > avg;
}
}
}
return hash;
}
private static int getBlue(Bitmap img, int x, int y) {
return img.getPixel(x, y) & 0xff;
}
private double[] c;
private double[] c2;
private void initCoefficients() {
c = new double[width];
c2 = new double[height];
for (int i = 1; i < width; i++) {
c[i] = 1;
}
for (int i = 1; i < height; i++) {
c2[i] = 1;
}
c[0] = 1 / Math.sqrt(2.0);
c2[0] = 1 / Math.sqrt(2.0);
}
private double[][] applyDCT(double[][] f) {
double[][] F = new double[width][height];
for (int u = 0; u < width; u++) {
for (int v = 0; v < height; v++) {
double sum = 0.0;
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
sum += Math.cos(((2 * i + 1) / (2.0 * width)) * u * Math.PI) * Math.cos(((2 * j + 1) / (2.0 * height)) * v * Math.PI) * (f[i][j]);
}
}
sum *= ((c[u] * c2[v]) / 4.0);
F[u][v] = sum;
}
}
return F;
}
public static class OCR implements com.stardust.mi666.ocr.OCR {
private SimpleTextDetector mSimpleTextDetector;
private Map<Character, boolean[]> mChars = new HashMap<>();
private ImagePHash mImagePHash;
public OCR(ColorDetector colorDetector, int size, int smallerSize) {
mSimpleTextDetector = new SimpleTextDetector(colorDetector);
mImagePHash = new ImagePHash(size, smallerSize);
}
public OCR(ColorDetector colorDetector, ImagePHash pHash) {
mSimpleTextDetector = new SimpleTextDetector(colorDetector);
mImagePHash = pHash;
}
@Override
public void addChar(char ch, Bitmap bitmap) {
mChars.put(ch, mImagePHash.getHash(mSimpleTextDetector.detect(bitmap)));
}
@Override
public char detect(Bitmap bitmap) {
bitmap = mSimpleTextDetector.detect(bitmap);
int min = Integer.MAX_VALUE;
boolean[] h = mImagePHash.getHash(bitmap);
char ch = ' ';
for (Map.Entry<Character, boolean[]> entry : mChars.entrySet()) {
int d = mImagePHash.distance(h, entry.getValue());
//Log.i(LOG_TAG, "char: " + entry.getKey() + " distance: " + d);
if (d < min) {
min = d;
ch = entry.getKey();
}
}
return ch;
}
}
}

View File

@@ -2,9 +2,6 @@ package com.stardust.scriptdroid.tool;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import com.stardust.app.OnActivityResultDelegate;
import com.stardust.scriptdroid.R;
@@ -22,6 +19,8 @@ public class ImageSelector implements OnActivityResultDelegate {
void onImageSelected(ImageSelector selector, InputStream path);
}
private static final String TAG = ImageSelector.class.getSimpleName();
private static final int REQUEST_CODE = "LOVE EATING".hashCode() >> 16;
private Activity mActivity;
private ImageSelectorCallback mCallback;

View File

@@ -0,0 +1,20 @@
package com.stardust.scriptdroid.tool;
import android.content.Context;
import android.widget.Toast;
import com.stardust.scriptdroid.R;
import com.stardust.util.IntentUtil;
/**
* Created by Stardust on 2017/4/12.
*/
public class IntentTool {
public static void browse(Context context, String url){
if (!IntentUtil.browse(context, url)) {
Toast.makeText(context, R.string.text_no_brower, Toast.LENGTH_SHORT).show();
}
}
}

View File

@@ -0,0 +1,25 @@
package com.stardust.scriptdroid.tool;
import android.annotation.SuppressLint;
import android.app.Application;
import com.stardust.autojs.script.JsBeautifier;
/**
* Created by Stardust on 2017/4/18.
*/
public class JsBeautifierFactory {
@SuppressLint("StaticFieldLeak")
private static JsBeautifier jsBeautifier;
public static JsBeautifier getJsBeautify() {
return jsBeautifier;
}
public static void initJsBeautify(Application context, String path) {
jsBeautifier = new JsBeautifier(context, path);
jsBeautifier.prepare();
}
}

View File

@@ -0,0 +1,26 @@
package com.stardust.scriptdroid.tool;
import android.content.Context;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.R;
/**
* Created by Stardust on 2017/4/18.
*/
public class MaterialDialogFactory {
public static MaterialDialog createProgress(Context context) {
return new MaterialDialog.Builder(context)
.progress(true, 0)
.cancelable(false)
.content(R.string.text_processing)
.build();
}
public static MaterialDialog showProgress(Context context) {
MaterialDialog dialog = createProgress(context);
dialog.show();
return dialog;
}
}

View File

@@ -0,0 +1,161 @@
package com.stardust.scriptdroid.tool;
import android.content.Context;
import android.preference.PreferenceManager;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.App;
import java.io.IOException;
import jackpal.androidterm.ShellTermSession;
import jackpal.androidterm.emulatorview.TermSession;
import jackpal.androidterm.util.TermSettings;
/**
* Created by Stardust on 2017/4/24.
*/
public class Shell {
private TermSession mTermSession;
private String mOutput;
public Shell(boolean root) {
this(App.getApp(), root ? "su\n" : "sh\n");
}
public Shell(Context context, String initialCommand) {
TermSettings settings = new TermSettings(context.getResources(), PreferenceManager.getDefaultSharedPreferences(context));
try {
mTermSession = new MyShellTermSession(settings, initialCommand);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public String execAndWaitFor(String command) {
mTermSession.write(command + "\n");
mOutput = null;
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return mOutput;
}
public String execAndWaitFor(String command, int millis) {
mTermSession.write(command + "\n");
mOutput = null;
synchronized (this) {
try {
wait(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
return mOutput;
}
public void exec(String command) {
mTermSession.write(command);
}
public void execute(String command) {
mTermSession.write(command);
}
public void Tap(int x, int y) {
execute("input tap " + x + " " + y);
}
public void Swipe(int x1, int y1, int x2, int y2) {
execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2);
}
public void Swipe(int x1, int y1, int x2, int y2, long duration) {
execute("input swipe " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + duration);
}
public void KeyCode(int keyCode) {
execute("input keyevent " + keyCode);
}
public void KeyCode(String keyCode) {
execute("input keyevent " + keyCode);
}
public void Home() {
KeyCode(3);
}
public void Back() {
KeyCode(4);
}
public void Power() {
KeyCode(26);
}
public void Up() {
KeyCode(19);
}
public void Down() {
KeyCode(20);
}
public void Left() {
KeyCode(21);
}
public void Right() {
KeyCode(22);
}
public void OK() {
KeyCode(23);
}
public void VolumeUp() {
KeyCode(24);
}
public void VolumeDown() {
KeyCode(25);
}
public void Menu() {
KeyCode(1);
}
public void Camera() {
KeyCode(27);
}
public void Text(String text) {
execute("input text " + text);
}
private class MyShellTermSession extends ShellTermSession {
public MyShellTermSession(TermSettings settings, String initialCommand) throws IOException {
super(settings, initialCommand);
}
@Override
protected void processInput(byte[] data, int offset, int count) {
mOutput = new String(data, offset, count);
synchronized (Shell.this) {
Shell.this.notifyAll();
}
appendToEmulator(data, offset, count);
}
}
}

View File

@@ -13,7 +13,7 @@ import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.stardust.pio.UncheckedIOException;
import com.stardust.scriptdroid.BuildConfig;
import java.lang.reflect.Type;
import java.util.List;
@@ -28,37 +28,40 @@ public class UpdateChecker implements Response.Listener<String>, Response.ErrorL
private RequestQueue mRequestQueue;
private static final String UPDATE_URL = "https://raw.githubusercontent.com/hyb1996/NoRootScriptDroid/master/version.json";
public interface Callback {
void onSuccess(CheckResult result);
void onSuccess(UpdateInfo result);
void onError(Exception exception);
}
private Callback mCallback;
private final int mTimeOut = 3000;
public static UpdateInfo savedResult;
public UpdateChecker(Context context, Callback callback) {
mCallback = callback;
private final int mTimeOut = 3000;
private Callback mCallback;
public UpdateChecker(Context context) {
mRequestQueue = Volley.newRequestQueue(context);
}
private CheckResult parse(String json) {
private UpdateInfo parse(String json) {
Gson gson = new Gson();
Type type = new TypeToken<CheckResult>() {
Type type = new TypeToken<UpdateInfo>() {
}.getType();
CheckResult result = gson.fromJson(json, type);
UpdateInfo result = gson.fromJson(json, type);
Log.i(LOG_TAG, result.toString());
return result;
}
public void check() {
public void check(final Callback callback) {
mCallback = callback;
StringRequest request = new StringRequest(Request.Method.GET, UPDATE_URL, this, this);
request.setRetryPolicy(new DefaultRetryPolicy(mTimeOut, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
request.setTag("update-check");
request.setShouldCache(false);
mRequestQueue.add(request);
}
@@ -66,12 +69,16 @@ public class UpdateChecker implements Response.Listener<String>, Response.ErrorL
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
mCallback.onError(error);
mCallback = null;
}
@Override
public void onResponse(String response) {
try {
CheckResult result = parse(response);
UpdateInfo result = parse(response);
savedResult = result;
if (mCallback == null)
return;
if (result.isValid()) {
mCallback.onSuccess(result);
} else {
@@ -81,13 +88,14 @@ public class UpdateChecker implements Response.Listener<String>, Response.ErrorL
e.printStackTrace();
mCallback.onError(e);
}
mCallback = null;
}
public void cancel() {
mRequestQueue.cancelAll("update-check");
}
public static class CheckResult {
public static class UpdateInfo {
public int versionCode;
public String releaseNotes;
@@ -95,25 +103,34 @@ public class UpdateChecker implements Response.Listener<String>, Response.ErrorL
public List<Download> downloads;
public List<OldVersion> oldVersions;
public int deprecated;
public String downloadUrl;
public boolean isValid() {
return downloads != null && !downloads.isEmpty() && versionCode > 0
&& !TextUtils.isEmpty(versionName) && !TextUtils.isEmpty(releaseNotes);
}
public OldVersion getOldVersion(int versionCode) {
for (OldVersion oldVersion : oldVersions) {
if (oldVersion.versionCode == versionCode) {
return oldVersion;
}
}
return null;
}
@Override
public String toString() {
return "CheckResult{" +
return "UpdateInfo{" +
"versionCode=" + versionCode +
", releaseNotes='" + releaseNotes + '\'' +
", versionName='" + versionName + '\'' +
", downloads=" + downloads +
", oldVersions=" + oldVersions +
", deprecated=" + deprecated +
", downloadUrl='" + downloadUrl + '\'' +
'}';
}
}
public static class OldVersion {

View File

@@ -0,0 +1,129 @@
package com.stardust.scriptdroid.tool;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.util.NetworkUtils;
/**
* Created by Stardust on 2017/4/9.
*/
public class VersionInfo {
private static final String KEY_DEPRECATED = "Still loving you...Can we go back...";
private static final String KEY_DEPRECATED_VERSION_CODE = "I miss you so much tonight...Baby don't let me cry...";
public interface OnReceiveUpdateResultCallback {
void onReceive(UpdateChecker.UpdateInfo info, boolean isCurrentVersionDeprecated);
}
private static VersionInfo instance = new VersionInfo();
public static VersionInfo getInstance() {
return instance;
}
private boolean mDeprecated = false;
private UpdateChecker.UpdateInfo mUpdateInfo;
private final int mReconnectTimes = 2;
private int mReconnectCount = 0;
private OnReceiveUpdateResultCallback mOnReceiveUpdateResultCallback;
private SharedPreferences mSharedPreferences;
public void readDeprecatedFromPref(Context context) {
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
if (mSharedPreferences.getInt(KEY_DEPRECATED_VERSION_CODE, 0) < BuildConfig.VERSION_CODE) {
mSharedPreferences.edit().remove(KEY_DEPRECATED_VERSION_CODE)
.putBoolean(KEY_DEPRECATED, false)
.apply();
}
mDeprecated = mSharedPreferences.getBoolean(KEY_DEPRECATED, false);
}
public void readDeprecatedFromPrefIfNeeded(Context context) {
if (mSharedPreferences == null) {
readDeprecatedFromPref(context);
}
}
public boolean isCurrentVersionDeprecated() {
return mDeprecated;
}
public UpdateChecker.UpdateInfo getUpdateInfo() {
return mUpdateInfo;
}
public String getCurrentVersionIssues() {
if (mUpdateInfo == null)
return null;
UpdateChecker.OldVersion oldVersion = mUpdateInfo.getOldVersion(BuildConfig.VERSION_CODE);
if (oldVersion == null)
return null;
return oldVersion.issues;
}
public void checkUpdateIfNeeded(Context context) {
if (mUpdateInfo == null) {
checkUpdateIfUsingWifi(context);
}
}
public void setOnReceiveUpdateResultCallback(OnReceiveUpdateResultCallback onReceiveUpdateResultCallback) {
mOnReceiveUpdateResultCallback = onReceiveUpdateResultCallback;
}
private void checkUpdateIfUsingWifi(Context context) {
if (NetworkUtils.isWifiAvailable(context)) {
checkUpdate(context);
}
}
public void checkUpdate(Context context) {
mReconnectCount = 0;
checkUpdateInner(context);
}
private void checkUpdateInner(final Context context) {
mReconnectCount++;
new UpdateChecker(context).check(new UpdateChecker.Callback() {
@Override
public void onSuccess(UpdateChecker.UpdateInfo result) {
if (result.isValid()) {
setUpdateInfo(result);
} else if (mReconnectCount < mReconnectTimes) {
checkUpdate(context);
}
}
@Override
public void onError(Exception exception) {
if (mReconnectCount < mReconnectTimes) {
checkUpdate(context);
}
}
});
}
private void setUpdateInfo(UpdateChecker.UpdateInfo result) {
mDeprecated = BuildConfig.VERSION_CODE <= result.deprecated;
mUpdateInfo = result;
if (mDeprecated) {
mSharedPreferences.edit().putBoolean(KEY_DEPRECATED, mDeprecated)
.putInt(KEY_DEPRECATED_VERSION_CODE, BuildConfig.VERSION_CODE)
.apply();
}
if (mOnReceiveUpdateResultCallback != null) {
mOnReceiveUpdateResultCallback.onReceive(result, mDeprecated);
}
}
}

View File

@@ -1,8 +1,10 @@
package com.stardust.scriptdroid.ui;
import android.app.Activity;
import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
@@ -10,8 +12,14 @@ import android.support.v7.widget.Toolbar;
import android.view.View;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.App;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.external.tasker.TaskPrefEditActivity;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.scriptdroid.tool.VersionInfo;
import com.stardust.scriptdroid.ui.update.UpdateCheckDialog;
import com.stardust.theme.ThemeColorManager;
import com.stardust.util.BackPressedHandler;
@@ -42,6 +50,20 @@ public abstract class BaseActivity extends AppCompatActivity {
if ((getWindow().getDecorView().getSystemUiVisibility() & View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0) {
ThemeColorManager.addActivityStatusBar(this);
}
}
@Override
protected void onResume() {
super.onResume();
}
@Override
protected void onPause() {
super.onPause();
VersionInfo.getInstance().setOnReceiveUpdateResultCallback(null);
}
@SuppressWarnings("unchecked")

View File

@@ -22,15 +22,19 @@ import timber.log.Timber;
public class TimberConsole implements Console {
static {
Timber.plant(new ConsoleTree.Builder()
.minPriority(Log.VERBOSE)
.verboseColor(0xff909090)
.debugColor(0xffc88b48)
.infoColor(0xffc9c9c9)
.warnColor(0xffa97db6)
.errorColor(0xffff534e)
.assertColor(0xffff5540)
.build());
try {
Timber.plant(new ConsoleTree.Builder()
.minPriority(Log.VERBOSE)
.verboseColor(0xff909090)
.debugColor(0xffc88b48)
.infoColor(0xffc9c9c9)
.warnColor(0xffa97db6)
.errorColor(0xffff534e)
.assertColor(0xffff5540)
.build());
} catch (Exception e) {
// FIXME: 2017/4/26 java.lang.NoClassDefFoundError: com.jraska.console.timber.ConsoleTree at android4.4
}
}
@Override

View File

@@ -11,6 +11,8 @@ import android.support.design.widget.Snackbar;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.inputmethod.InputMethod;
@@ -19,17 +21,24 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.autojs.engine.JavaScriptEngine;
import com.stardust.autojs.ScriptExecutionListener;
import com.stardust.autojs.script.FileScriptSource;
import com.stardust.autojs.script.JsBeautifier;
import com.stardust.autojs.script.ScriptSource;
import com.stardust.autojs.script.StringScriptSource;
import com.stardust.enhancedfloaty.ResizableFloatyService;
import com.stardust.pio.PFile;
import com.stardust.scriptdroid.Pref;
import com.stardust.scriptdroid.autojs.AutoJs;
import com.stardust.scriptdroid.external.floating_window.FloatingConsole;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.tool.JsBeautifierFactory;
import com.stardust.scriptdroid.tool.MaterialDialogFactory;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.console.ConsoleActivity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Activity;
import com.stardust.scriptdroid.ui.edit.editor920.Editor920Utils;
import com.stardust.scriptdroid.ui.edit.sidemenu.EditSideMenuFragment;
import com.stardust.scriptdroid.ui.edit.sidemenu.FunctionListRecyclerView;
import com.stardust.scriptdroid.ui.help.HelpCatalogueActivity;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.SparseArrayEntries;
import com.stardust.view.ViewBinding;
@@ -56,6 +65,7 @@ import timber.log.Timber;
public class EditActivity extends Editor920Activity {
public static class InputMethodEnhanceBarBridge implements InputMethodEnhanceBar.EditTextBridge {
private Editor920Activity mEditor920Activity;
@@ -152,6 +162,7 @@ public class EditActivity extends Editor920Activity {
}
}
};
private JsBeautifier mJsBeautifier = JsBeautifierFactory.getJsBeautify();
public void onCreate(Bundle b) {
super.onCreate(b);
@@ -314,6 +325,51 @@ public class EditActivity extends Editor920Activity {
menuItem.setEnabled(!disabled);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_editor, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_console:
startActivity(new Intent(getContext(), ConsoleActivity.class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
return true;
case R.id.action_help:
HelpCatalogueActivity.showMainCatalogue(this);
return true;
case R.id.action_beautify:
beautifyCode();
return true;
}
return super.onOptionsItemSelected(item);
}
private void beautifyCode() {
final MaterialDialog dialog = MaterialDialogFactory.showProgress(this);
mJsBeautifier.beautify(mEditorDelegate.getText(), new JsBeautifier.Callback() {
@Override
public void onSuccess(final String beautifiedCode) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mEditorDelegate.mEditText.setText(beautifiedCode);
dialog.dismiss();
}
});
}
@Override
public void onException(Exception e) {
e.printStackTrace();
}
});
}
@Override
public void finish() {
if (!mReadOnly && mEditorDelegate.isChanged()) {

View File

@@ -122,7 +122,7 @@ public class CodeCompletion implements TextWatcher {
}
private Collection<CodeCompletionItem> searchWordCompletion(String str) {
if (mEditText.getEditableText().length() < Pref.MaxTextLengthForCodeCompletion()) {
if (mEditText.getEditableText().length() < Pref.getMaxTextLengthForCodeCompletion()) {
return searchCodeCompletion(str, splitWord(mEditText.getEditableText().toString()));
}
return new TreeSet<>();

View File

@@ -0,0 +1,24 @@
package com.stardust.scriptdroid.ui.edit.sidemenu;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.stardust.app.Fragment;
import com.stardust.scriptdroid.R;
/**
* Created by Stardust on 2017/4/18.
*/
public class HelpSideMenuFragment extends Fragment {
@Nullable
@Override
public View createView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_help_side_menu, container, false);
}
}

View File

@@ -25,26 +25,27 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.app.FragmentPagerAdapterBuilder;
import com.stardust.app.NotAskAgainDialog;
import com.stardust.app.OnActivityResultDelegate;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.ScriptFile;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.service.AccessibilityWatchDogService;
import com.stardust.scriptdroid.tool.AccessibilityServiceTool;
import com.stardust.scriptdroid.tool.DrawableSaver;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.scriptdroid.ui.main.script_list.MyScriptListFragment;
import com.stardust.scriptdroid.ui.main.sample_list.SampleScriptListFragment;
import com.stardust.scriptdroid.ui.main.script_list.MyScriptListFragment;
import com.stardust.scriptdroid.ui.main.script_list.ScriptFileChooserDialogBuilder;
import com.stardust.scriptdroid.ui.main.task.TaskManagerFragment;
import com.stardust.scriptdroid.ui.settings.SettingsActivity;
import com.stardust.scriptdroid.ui.update.VersionGuard;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.BackPressedHandler;
import com.stardust.util.MessageEvent;
import com.stardust.view.ViewBinding;
import com.stardust.widget.SlidingUpPanel;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.view.ViewBinder;
import com.stardust.view.ViewBinding;
import com.stardust.view.accessibility.AccessibilityServiceUtils;
import com.stardust.widget.SlidingUpPanel;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
@@ -68,6 +69,7 @@ public class MainActivity extends BaseActivity {
private OnActivityResultDelegate.Intermediary mActivityResultIntermediary = new OnActivityResultDelegate.Intermediary();
private DrawableSaver mDrawerHeaderBackgroundSaver, mAppbarBackgroundSaver;
private VersionGuard mVersionGuard;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -77,8 +79,11 @@ public class MainActivity extends BaseActivity {
registerBackPressHandlers();
handleIntent(getIntent());
EventBus.getDefault().register(this);
mVersionGuard = new VersionGuard(this);
}
private void registerBackPressHandlers() {
registerBackPressedHandler(new BackPressedHandler() {
@Override
@@ -101,7 +106,7 @@ public class MainActivity extends BaseActivity {
private void showAccessibilitySettingPromptIfDisabled() {
if (!AccessibilityServiceUtils.isAccessibilityServiceEnabled(this, AccessibilityWatchDogService.class)) {
new NotAskAgainDialog.Builder(this, "showAccessibilitySettingPromptIfDisabled")
new NotAskAgainDialog.Builder(this, "Eating...love you...miss you...17.4.12")
.title(R.string.text_need_to_enable_accessibility_service)
.content(R.string.explain_accessibility_permission)
.positiveText(R.string.text_go_to_setting)
@@ -279,24 +284,6 @@ public class MainActivity extends BaseActivity {
return ((MyScriptListFragment) mPagerAdapter.getStoredFragment(0));
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mActivityResultIntermediary.onActivityResult(requestCode, resultCode, data);
}
public static void onActionRecordStopped(Context context, String script) {
Intent intent = new Intent(context, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED)
.putExtra(ARGUMENT_SCRIPT, script);
context.startActivity(intent);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
StorageScriptProvider.getDefault().notifyStoragePermissionGranted();
}
@ViewBinding.Click(R.id.toolbar)
public void OnToolbarClick() {
mAppbarBackgroundSaver.select(this, mActivityResultIntermediary);
@@ -310,9 +297,36 @@ public class MainActivity extends BaseActivity {
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
mActivityResultIntermediary.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
StorageScriptProvider.getDefault().notifyStoragePermissionGranted();
}
@Override
protected void onResume() {
super.onResume();
mVersionGuard.checkDeprecateAndUpdate();
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
public static void onRecordStop(Context context, String script) {
Intent intent = new Intent(context, MainActivity.class)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.putExtra(EXTRA_ACTION, ACTION_ON_ACTION_RECORD_STOPPED)
.putExtra(ARGUMENT_SCRIPT, script);
context.startActivity(intent);
}
}

View File

@@ -12,6 +12,7 @@ import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.tool.IntentTool;
import com.stardust.scriptdroid.ui.BaseActivity;
import com.stardust.theme.dialog.ThemeColorMaterialDialogBuilder;
import com.stardust.util.IntentUtil;
@@ -51,9 +52,7 @@ public class AboutActivity extends BaseActivity {
@ViewBinding.Click(R.id.github)
private void openGitHub() {
if (!IntentUtil.browse(this, getString(R.string.my_github))) {
Toast.makeText(this, R.string.text_no_brower, Toast.LENGTH_SHORT).show();
}
IntentTool.browse(this, getString(R.string.my_github));
}
@ViewBinding.Click(R.id.qq)

View File

@@ -1,7 +1,6 @@
package com.stardust.scriptdroid.ui.update;
import android.content.Context;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.widget.Toast;
@@ -12,8 +11,7 @@ import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.util.IntentUtil;
import java.util.Timer;
import java.util.TimerTask;
import java.util.LinkedList;
/**
* Created by Stardust on 2017/4/9.
@@ -21,7 +19,6 @@ import java.util.TimerTask;
public class UpdateCheckDialog implements UpdateChecker.Callback {
private MaterialDialog mResultDialog;
private MaterialDialog mProgressDialog;
private Context mContext;
private UpdateChecker mUpdateChecker;
@@ -29,70 +26,42 @@ public class UpdateCheckDialog implements UpdateChecker.Callback {
public UpdateCheckDialog(Context context) {
mContext = context;
mUpdateChecker = new UpdateChecker(context, this);
mUpdateChecker = new UpdateChecker(context);
}
public void show() {
if (mProgressDialog != null)
throw new IllegalStateException();
mProgressDialog = new MaterialDialog.Builder(mContext)
.content(mContext.getString(R.string.text_checking_update))
.progress(true, 0)
.cancelable(false)
.show();
mUpdateChecker.check();
mUpdateChecker.check(this);
}
@Override
public void onSuccess(UpdateChecker.CheckResult result) {
public void onSuccess(UpdateChecker.UpdateInfo result) {
mProgressDialog.dismiss();
if (BuildConfig.VERSION_CODE >= result.versionCode) {
Toast.makeText(mContext, R.string.text_is_latest_version, Toast.LENGTH_SHORT).show();
return;
}
mResultDialog = buildDialog(result);
mResultDialog.show();
String updateSite = result.downloads.get(0).name;
final String updateUrl = result.downloads.get(0).url;
mResultDialog = new MaterialDialog.Builder(mContext)
.title(mContext.getString(R.string.text_new_version) + " " + result.versionName)
.content(result.releaseNotes)
.positiveText(updateSite)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
IntentUtil.browse(mContext, updateUrl);
}
})
new UpdateInfoDialogBuilder(mContext, result)
.show();
}
private MaterialDialog buildDialog(final UpdateChecker.CheckResult result) {
String updateSite = result.downloads.get(0).name;
final String updateUrl = result.downloads.get(0).url;
MaterialDialog.Builder builder = new MaterialDialog.Builder(mContext)
.title(mContext.getString(R.string.text_new_version) + " " + result.versionName)
.content(result.releaseNotes)
.positiveText(updateSite)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
IntentUtil.browse(mContext, updateUrl);
}
});
if (result.downloads.size() > 1) {
builder.negativeText(result.downloads.get(1).name)
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
IntentUtil.browse(mContext, result.downloads.get(1).url);
}
});
}
return builder.build();
clear();
}
@Override
public void onError(Exception exception) {
mProgressDialog.dismiss();
Toast.makeText(mContext, R.string.text_check_update_error, Toast.LENGTH_SHORT).show();
clear();
}
private void clear() {
mProgressDialog = null;
mContext = null;
}
}

View File

@@ -0,0 +1,146 @@
package com.stardust.scriptdroid.ui.update;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.BuildConfig;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.scripts.StorageScriptProvider;
import com.stardust.scriptdroid.tool.IntentTool;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.util.DownloadTask;
import com.stardust.util.IntentUtil;
import com.stardust.widget.CommonMarkdownView;
/**
* Created by Stardust on 2017/4/9.
*/
public class UpdateInfoDialogBuilder extends MaterialDialog.Builder {
private static final String KEY_DO_NOT_ASK_AGAIN_FOR_VERSION = "I cannot forget you...cannot help missing you...";
private View mView;
private SharedPreferences mSharedPreferences;
private UpdateChecker.UpdateInfo mUpdateInfo;
public UpdateInfoDialogBuilder(@NonNull Context context, UpdateChecker.UpdateInfo info) {
super(context);
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
updateInfo(info);
}
public UpdateInfoDialogBuilder updateInfo(UpdateChecker.UpdateInfo info) {
mUpdateInfo = info;
mView = View.inflate(context, R.layout.dialog_update_info, null);
setReleaseNotes(mView, info);
setCurrentVersionIssues(mView, info);
setUpdateDownloadButtons(mView, info);
title(context.getString(R.string.text_new_version) + " " + info.versionName);
customView(mView, false);
return this;
}
public UpdateInfoDialogBuilder showDoNotAskAgain() {
mView.findViewById(R.id.do_not_ask_again_container).setVisibility(View.VISIBLE);
CheckBox checkBox = (CheckBox) mView.findViewById(R.id.do_not_ask_again);
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mSharedPreferences.edit().putBoolean(KEY_DO_NOT_ASK_AGAIN_FOR_VERSION + mUpdateInfo.versionCode, isChecked).apply();
}
});
return this;
}
@Override
public MaterialDialog show() {
if (mSharedPreferences.getBoolean(KEY_DO_NOT_ASK_AGAIN_FOR_VERSION + mUpdateInfo.versionCode, false)) {
return null;
}
return super.show();
}
private void setCurrentVersionIssues(View view, UpdateChecker.UpdateInfo info) {
TextView issues = (TextView) view.findViewById(R.id.issues);
UpdateChecker.OldVersion currentVersion = info.getOldVersion(BuildConfig.VERSION_CODE);
if (currentVersion == null) {
issues.setVisibility(View.GONE);
} else {
issues.setText(currentVersion.issues);
}
}
private void setUpdateDownloadButtons(View view, UpdateChecker.UpdateInfo info) {
LinearLayout downloads = (LinearLayout) view.findViewById(R.id.downloads);
setDirectlyDownloadButton(downloads, info);
for (final UpdateChecker.Download download : info.downloads) {
Button button = (Button) View.inflate(getContext(), R.layout.dialog_update_info_btn, null);
button.setText(download.name);
downloads.addView(button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
IntentTool.browse(v.getContext(), download.url);
}
});
}
}
private void setDirectlyDownloadButton(LinearLayout container, final UpdateChecker.UpdateInfo info) {
if (TextUtils.isEmpty(info.downloadUrl)) {
return;
}
Button button = (Button) View.inflate(getContext(), R.layout.dialog_update_info_btn, null);
button.setText(R.string.text_directly_download);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
directlyDownload(info.downloadUrl);
}
});
container.addView(button);
}
private void directlyDownload(String downloadUrl) {
final MaterialDialog dialog = new MaterialDialog.Builder(getContext())
.title(R.string.text_downloading)
.progress(false, 100)
.show();
final String path = StorageScriptProvider.DEFAULT_DIRECTORY_PATH + "AutoJs.apk";
final DownloadTask task = new DownloadTask() {
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
dialog.setProgress(values[0]);
}
@Override
protected void onPostExecute(Boolean result) {
super.onPostExecute(result);
dialog.dismiss();
if (!result) {
Toast.makeText(getContext(), R.string.text_download_failed, Toast.LENGTH_SHORT).show();
} else {
IntentUtil.installApk(getContext(), path);
}
}
};
task.execute(downloadUrl, path);
}
private void setReleaseNotes(View view, UpdateChecker.UpdateInfo info) {
CommonMarkdownView markdownView = (CommonMarkdownView) view.findViewById(R.id.release_notes);
markdownView.loadMarkdown(info.releaseNotes);
}
}

View File

@@ -0,0 +1,94 @@
package com.stardust.scriptdroid.ui.update;
import android.app.Activity;
import android.content.DialogInterface;
import android.support.annotation.NonNull;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.scriptdroid.R;
import com.stardust.scriptdroid.tool.UpdateChecker;
import com.stardust.scriptdroid.tool.VersionInfo;
/**
* Created by Stardust on 2017/4/12.
*/
public class VersionGuard {
private Activity mActivity;
private MaterialDialog mDeprecatedDialog;
private VersionInfo mVersionInfo = VersionInfo.getInstance();
public VersionGuard(Activity activity) {
mActivity = activity;
}
public void checkDeprecateAndUpdate() {
mVersionInfo.readDeprecatedFromPrefIfNeeded(mActivity);
if (mVersionInfo.isCurrentVersionDeprecated()) {
showDeprecatedDialogIfNeeded();
} else {
checkUpdateIfNeeded();
}
}
private void checkUpdateIfNeeded() {
if (mVersionInfo.getUpdateInfo() == null) {
mVersionInfo.setOnReceiveUpdateResultCallback(new VersionInfo.OnReceiveUpdateResultCallback() {
@Override
public void onReceive(UpdateChecker.UpdateInfo info, boolean isCurrentVersionDeprecated) {
mVersionInfo.setOnReceiveUpdateResultCallback(null);
if (isCurrentVersionDeprecated) {
showDeprecatedDialogIfNeeded();
} else {
showUpdateInfo(info);
}
}
});
mVersionInfo.checkUpdateIfNeeded(mActivity);
}
}
private void showUpdateInfo(UpdateChecker.UpdateInfo info) {
new UpdateInfoDialogBuilder(mActivity, info)
.showDoNotAskAgain()
.show();
}
private void showDeprecatedDialogIfNeeded() {
if (mDeprecatedDialog != null && mDeprecatedDialog.isShowing())
return;
String content = mActivity.getString(R.string.warning_version_too_old);
String issues = mVersionInfo.getCurrentVersionIssues();
if (issues != null) {
content += "\n" + issues;
}
mDeprecatedDialog = new MaterialDialog.Builder(mActivity)
.title(R.string.text_version_too_old)
.content(content)
.positiveText(R.string.text_update)
.negativeText(R.string.text_exit)
.cancelable(false)
.autoDismiss(false)
.onAny(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
if (which == DialogAction.POSITIVE) {
new UpdateCheckDialog(mActivity)
.show();
} else {
mActivity.finish();
}
}
})
.dismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mDeprecatedDialog = null;
}
})
.show();
}
}