This commit is contained in:
hyb1996
2018-10-11 10:11:38 +08:00
69 changed files with 929 additions and 304 deletions

Binary file not shown.

View File

@@ -1,19 +1,27 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
def AAVersion = '4.3.1' def AAVersion = '4.4.0'
def SupportLibVersion = '28.0.0'
configurations.all {
resolutionStrategy {
force "com.android.support:appcompat-v7:${SupportLibVersion}"
force "com.android.support:support-v4:${SupportLibVersion}"
}
}
android { android {
compileSdkVersion 27 compileSdkVersion versions.compile
buildToolsVersion '27.0.3' buildToolsVersion versions.buildTool
defaultConfig { defaultConfig {
applicationId "org.autojs.autojs" applicationId "org.autojs.autojs"
minSdkVersion 17 minSdkVersion versions.mini
targetSdkVersion 23 targetSdkVersion versions.target
versionCode 421 versionCode versions.appVersionCode
versionName "4.0.3 Alpha2" versionName versions.appVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
ndk { ndk {
abiFilters 'armeabi-v7a' abiFilters 'armeabi-v7a', 'x86'
} }
} }
buildTypes { buildTypes {
@@ -24,7 +32,7 @@ android {
} }
release { release {
shrinkResources false shrinkResources false
minifyEnabled true minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
} }
} }
@@ -62,6 +70,7 @@ android {
repositories { repositories {
flatDir { flatDir {
dirs 'libs' dirs 'libs'
@@ -70,83 +79,83 @@ repositories {
} }
dependencies { dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
// Android Annotations // Android Annotations
annotationProcessor "org.androidannotations:androidannotations:$AAVersion" annotationProcessor "org.androidannotations:androidannotations:$AAVersion"
compile "org.androidannotations:androidannotations-api:$AAVersion" implementation "org.androidannotations:androidannotations-api:$AAVersion"
// ButterKnife // ButterKnife
compile('com.jakewharton:butterknife:8.6.0', { implementation('com.jakewharton:butterknife:8.8.1', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
// Android supports // Android supports
compile 'com.android.support:appcompat-v7:27.1.1' implementation "com.android.support:appcompat-v7:${SupportLibVersion}"
compile 'com.android.support:cardview-v7:27.1.1' implementation "com.android.support:cardview-v7:${SupportLibVersion}"
compile 'com.android.support:design:27.1.1' implementation "com.android.support:design:${SupportLibVersion}"
compile 'com.android.support:multidex:1.0.3' implementation 'com.android.support:multidex:1.0.3'
// Personal libraries // Personal libraries
compile 'com.github.hyb1996:MutableTheme:0.2.2' implementation 'com.github.hyb1996:MutableTheme:0.2.2'
// Material Dialogs // Material Dialogs
compile('com.afollestad.material-dialogs:core:0.9.2.3', { implementation('com.afollestad.material-dialogs:core:0.9.2.3', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
// Common Markdown // Common Markdown
compile 'com.github.atlassian:commonmark-java:commonmark-parent-0.9.0' implementation 'com.github.atlassian:commonmark-java:commonmark-parent-0.9.0'
// Android issue reporter (a github issue reporter) // Android issue reporter (a github issue reporter)
compile('com.heinrichreimersoftware:android-issue-reporter:1.3.1', { implementation('com.heinrichreimersoftware:android-issue-reporter:1.3.1', {
exclude group: 'com.afollestad.material-dialogs' exclude group: 'com.afollestad.material-dialogs'
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
//MultiLevelListView //MultiLevelListView
compile 'com.github.hyb1996:android-multi-level-listview:1.1' implementation 'com.github.hyb1996:android-multi-level-listview:1.1'
//Licenses Dialog //Licenses Dialog
compile 'de.psdev.licensesdialog:licensesdialog:1.8.1' implementation 'de.psdev.licensesdialog:licensesdialog:1.8.1'
//Expandable RecyclerView //Expandable RecyclerView
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1' implementation 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
//FlexibleDivider //FlexibleDivider
compile 'com.yqritc:recyclerview-flexibledivider:1.4.0' implementation 'com.yqritc:recyclerview-flexibledivider:1.4.0'
//??? //???
compile 'com.wang.avi:library:2.1.3' implementation 'com.wang.avi:library:2.1.3'
//Commons-lang //Commons-lang
compile 'org.apache.commons:commons-lang3:3.6' implementation 'org.apache.commons:commons-lang3:3.6'
//Expandable RecyclerView //Expandable RecyclerView
compile 'com.thoughtbot:expandablerecyclerview:1.3' implementation 'com.thoughtbot:expandablerecyclerview:1.3'
compile('com.github.hyb1996:FloatingCircularActionMenu:0.0.4') implementation('com.github.hyb1996:FloatingCircularActionMenu:0.0.4')
compile 'com.github.hyb1996:Auto.js-ApkBuilder:1.0.1' implementation 'com.github.hyb1996:Auto.js-ApkBuilder:1.0.1'
// RxJava // RxJava
compile "io.reactivex.rxjava2:rxjava:2.1.2" implementation "io.reactivex.rxjava2:rxjava:2.1.2"
compile 'io.reactivex.rxjava2:rxandroid:2.0.1' implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
// Retrofit // Retrofit
compile 'com.squareup.retrofit2:retrofit:2.3.0' implementation 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0' implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
//Glide //Glide
compile('com.github.bumptech.glide:glide:4.2.0', { implementation('com.github.bumptech.glide:glide:4.8.0', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
annotationProcessor 'com.github.bumptech.glide:compiler:4.2.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
//joda time //joda time
compile 'joda-time:joda-time:2.9.9' implementation 'joda-time:joda-time:2.9.9'
// Tasker Plugin // Tasker Plugin
compile 'com.twofortyfouram:android-plugin-client-sdk-for-locale:4.0.3' implementation 'com.twofortyfouram:android-plugin-client-sdk-for-locale:4.0.3'
// Flurry // Flurry
compile 'com.flurry.android:analytics:7.0.0@aar' implementation 'com.flurry.android:analytics:7.0.0@aar'
// Bugly // Bugly
compile 'com.tencent.bugly:crashreport:2.6.6' implementation 'com.tencent.bugly:crashreport:2.6.6'
// MaterialDialogCommon // MaterialDialogCommon
compile('com.afollestad.material-dialogs:commons:0.9.2.3', { implementation('com.afollestad.material-dialogs:commons:0.9.2.3', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1' debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.1'
releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1' releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.1'
// Optional, if you use support library fragments: // Optional, if you use support library fragments:
debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.1' debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.1'
compile project(':automator') implementation project(':automator')
compile project(':common') implementation project(':common')
compile project(':autojs') implementation project(':autojs')
implementation (name: 'ads8', ext: 'aar') implementation (name: 'ads8', ext: 'aar')
} }

View File

@@ -23,6 +23,7 @@
<!-- Ad SDK Permissions --> <!-- Ad SDK Permissions -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<application <application
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:name=".App" android:name=".App"
@@ -34,6 +35,10 @@
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:replace="android:label, android:icon, android:allowBackup"> tools:replace="android:label, android:icon, android:allowBackup">
<meta-data
android:name="android.max_aspect"
android:value="2.1" />
<activity <activity
android:name=".ui.splash.SplashActivity" android:name=".ui.splash.SplashActivity"
android:hardwareAccelerated="true" android:hardwareAccelerated="true"
@@ -64,7 +69,7 @@
</activity> </activity>
<provider <provider
android:name="android.support.v4.content.FileProvider" android:name=".external.fileprovider.AppFileProvider"
android:authorities="org.autojs.autojs.fileprovider" android:authorities="org.autojs.autojs.fileprovider"
android:exported="false" android:exported="false"
android:grantUriPermissions="true"> android:grantUriPermissions="true">
@@ -139,11 +144,6 @@
<action android:name="android.intent.action.QUICKBOOT_POWERON" /> <action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.TIME_SET"/> <action android:name="android.intent.action.TIME_SET"/>
<action android:name="android.intent.action.TIMEZONE_CHANGED"/> <action android:name="android.intent.action.TIMEZONE_CHANGED"/>
<action android:name="android.intent.action.PACKAGE_ADDED"/>
<action android:name="android.intent.action.PACKAGE_CHANGED"/>
<action android:name="android.intent.action.PACKAGE_DATA_CLEARED"/>
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
<action android:name="android.intent.action.PACKAGE_RESTARTED"/>
<action android:name="android.intent.action.UID_REMOVED"/> <action android:name="android.intent.action.UID_REMOVED"/>
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/> <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>

View File

@@ -18,6 +18,7 @@ import com.stardust.autojs.core.ui.inflater.ImageLoader;
import com.stardust.autojs.core.ui.inflater.util.Drawables; import com.stardust.autojs.core.ui.inflater.util.Drawables;
import com.stardust.theme.ThemeColor; import com.stardust.theme.ThemeColor;
import com.stardust.theme.ThemeColorManager; import com.stardust.theme.ThemeColorManager;
import com.tencent.bugly.Bugly;
import com.tencent.bugly.crashreport.CrashReport; import com.tencent.bugly.crashreport.CrashReport;
import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.autojs.AutoJs;

View File

@@ -48,14 +48,18 @@ public class AutoJsApkBuilder extends ApkBuilder {
Callable<Bitmap> icon; Callable<Bitmap> icon;
public static AppConfig fromProjectConfig(String projectDir, ProjectConfig projectConfig) { public static AppConfig fromProjectConfig(String projectDir, ProjectConfig projectConfig) {
return new AppConfig() String icon = projectConfig.getIcon();
AppConfig appConfig = new AppConfig()
.setAppName(projectConfig.getName()) .setAppName(projectConfig.getName())
.setPackageName(projectConfig.getPackageName()) .setPackageName(projectConfig.getPackageName())
.ignoreDir(new File(projectDir, projectConfig.getBuildDir())) .ignoreDir(new File(projectDir, projectConfig.getBuildDir()))
.setVersionCode(projectConfig.getVersionCode()) .setVersionCode(projectConfig.getVersionCode())
.setVersionName(projectConfig.getVersionName()) .setVersionName(projectConfig.getVersionName())
.setIcon(projectConfig.getIcon())
.setSourcePath(projectDir); .setSourcePath(projectDir);
if (icon != null) {
appConfig.setIcon(new File(projectDir, icon).getPath());
}
return appConfig;
} }

View File

@@ -0,0 +1,16 @@
package org.autojs.autojs.external.fileprovider;
import android.content.Context;
import android.net.Uri;
import android.support.v4.content.FileProvider;
import java.io.File;
public class AppFileProvider extends FileProvider {
public static final String AUTHORITY = "org.autojs.autojs.fileprovider";
public static Uri getUriForFile(Context context, File file){
return FileProvider.getUriForFile(context, AUTHORITY, file);
}
}

View File

@@ -13,11 +13,12 @@ import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.stardust.app.GlobalAppContext;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.ui.main.MainActivity_; import org.autojs.autojs.ui.main.MainActivity_;
import java.lang.reflect.Array;
import java.util.Arrays;
public class ForegroundService extends Service { public class ForegroundService extends Service {
@@ -64,6 +65,7 @@ public class ForegroundService extends Service {
.setWhen(System.currentTimeMillis()) .setWhen(System.currentTimeMillis())
.setContentIntent(contentIntent) .setContentIntent(contentIntent)
.setChannelId(CHANEL_ID) .setChannelId(CHANEL_ID)
.setVibrate(new long[0])
.build(); .build();
} }

View File

@@ -4,10 +4,15 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.os.Build; import android.os.Build;
import android.support.design.widget.TabLayout;
import android.util.Log;
import android.util.Pair;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -18,61 +23,110 @@ import static android.content.Intent.ACTION_PACKAGES_SUSPENDED;
import static android.content.Intent.ACTION_PACKAGES_UNSUSPENDED; import static android.content.Intent.ACTION_PACKAGES_UNSUSPENDED;
import static android.content.Intent.ACTION_SCREEN_OFF; import static android.content.Intent.ACTION_SCREEN_OFF;
import static android.content.Intent.ACTION_SCREEN_ON; import static android.content.Intent.ACTION_SCREEN_ON;
import static android.content.Intent.ACTION_TIME_TICK;
public class DynamicBroadcastReceivers { public class DynamicBroadcastReceivers {
private static final List<String> DEFAULT_ACTIONS = new ArrayList<>(Arrays.asList( private static final String LOG_TAG = "DynBroadcastReceivers";
ACTION_TIME_TICK,
ACTION_SCREEN_OFF,
ACTION_SCREEN_ON,
ACTION_BATTERY_CHANGED,
ACTION_CONFIGURATION_CHANGED
));
static {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
DEFAULT_ACTIONS.addAll(Arrays.asList(
ACTION_PACKAGES_SUSPENDED,
ACTION_PACKAGES_UNSUSPENDED
));
}
}
private final Set<String> mActions = new LinkedHashSet<>(); private final Set<String> mActions = new LinkedHashSet<>();
private final List<BroadcastReceiver> mReceivers = new ArrayList<>(); private final List<ReceiverRegistry> mReceiverRegistries = new ArrayList<>();
private final BaseBroadcastReceiver mDefaultActionReceiver = new BaseBroadcastReceiver();
private final BaseBroadcastReceiver mPackageActionReceiver = new BaseBroadcastReceiver();
private final Context mContext; private final Context mContext;
public DynamicBroadcastReceivers(Context context) { public DynamicBroadcastReceivers(Context context) {
mContext = context; mContext = context;
register(DEFAULT_ACTIONS); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mContext.registerReceiver(mDefaultActionReceiver, createIntentFilter(StaticBroadcastReceiver.ACTIONS));
IntentFilter filter = createIntentFilter(StaticBroadcastReceiver.PACKAGE_ACTIONS);
filter.addDataScheme("package");
mContext.registerReceiver(mPackageActionReceiver, filter);
}
} }
public void register(String action) { public void register(String action) {
register(Collections.singletonList(action)); register(Collections.singletonList(action));
} }
public void register(List<String> actions) { public synchronized void register(List<String> actions) {
IntentFilter filter = new IntentFilter(); LinkedHashSet<String> newActions = new LinkedHashSet<>();
for (String action : actions) { for (String action : actions) {
if (!StaticBroadcastReceiver.ACTIONS.contains(action) if (!StaticBroadcastReceiver.ACTIONS.contains(action)
&& !StaticBroadcastReceiver.PACKAGE_ACTIONS.contains(action)
&& !mActions.contains(action)) { && !mActions.contains(action)) {
mActions.add(action); newActions.add(action);
filter.addAction(action);
} }
} }
if (filter.countActions() == 0) { if (newActions.isEmpty()) {
return; return;
} }
BaseBroadcastReceiver receiver = new BaseBroadcastReceiver(); ReceiverRegistry receiverRegistry = new ReceiverRegistry(newActions);
mContext.registerReceiver(receiver, filter); receiverRegistry.register();
mReceiverRegistries.add(receiverRegistry);
} }
public void unregisterAll() { public synchronized void unregister(String action) {
for (BroadcastReceiver receiver : mReceivers) { if (!mActions.contains(action)) {
return;
}
mActions.remove(action);
Iterator<ReceiverRegistry> iterator = mReceiverRegistries.iterator();
while (iterator.hasNext()) {
ReceiverRegistry receiverRegistry = iterator.next();
if (!receiverRegistry.actions.contains(action)) {
continue;
}
receiverRegistry.actions.remove(action);
receiverRegistry.unregister();
if (!receiverRegistry.register()) {
iterator.remove();
}
break;
}
}
public synchronized void unregisterAll() {
for (ReceiverRegistry registry : mReceiverRegistries) {
registry.unregister();
}
mReceiverRegistries.clear();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mContext.unregisterReceiver(mDefaultActionReceiver);
mContext.unregisterReceiver(mPackageActionReceiver);
}
}
static IntentFilter createIntentFilter(Collection<String> actions) {
IntentFilter filter = new IntentFilter();
for (String action : actions) {
filter.addAction(action);
}
return filter;
}
private class ReceiverRegistry {
BroadcastReceiver receiver;
LinkedHashSet<String> actions;
ReceiverRegistry(LinkedHashSet<String> actions) {
this.actions = actions;
receiver = new BaseBroadcastReceiver();
}
void unregister() {
mContext.unregisterReceiver(receiver); mContext.unregisterReceiver(receiver);
} }
mReceivers.clear();
boolean register() {
if (actions.isEmpty())
return false;
IntentFilter intentFilter = createIntentFilter(actions);
mContext.registerReceiver(receiver, intentFilter);
Log.d(LOG_TAG, "register: " + actions);
return true;
}
} }
} }

View File

@@ -37,4 +37,12 @@ public class StaticBroadcastReceiver extends BaseBroadcastReceiver {
"android.net.conn.CONNECTIVITY_CHANGE" "android.net.conn.CONNECTIVITY_CHANGE"
)); ));
static final List<String> PACKAGE_ACTIONS = new ArrayList<>(Arrays.asList(
"android.intent.action.PACKAGE_ADDED",
"android.intent.action.PACKAGE_CHANGED",
"android.intent.action.PACKAGE_DATA_CLEARED",
"android.intent.action.PACKAGE_REMOVED",
"android.intent.action.PACKAGE_RESTARTED"
));
} }

View File

@@ -1,6 +1,7 @@
package org.autojs.autojs.model.explorer; package org.autojs.autojs.model.explorer;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import com.stardust.util.ObjectHelper;
import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.ScriptFile;
@@ -9,6 +10,7 @@ import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
public class ExplorerFileItem implements ExplorerItem { public class ExplorerFileItem implements ExplorerItem {
private static final Set<String> sEditableFileExts = new HashSet<>(Arrays.asList( private static final Set<String> sEditableFileExts = new HashSet<>(Arrays.asList(
@@ -19,6 +21,7 @@ public class ExplorerFileItem implements ExplorerItem {
private final ExplorerPage mParent; private final ExplorerPage mParent;
public ExplorerFileItem(PFile file, ExplorerPage parent) { public ExplorerFileItem(PFile file, ExplorerPage parent) {
ObjectHelper.requireNonNull(file, "file");
mFile = file; mFile = file;
mParent = parent; mParent = parent;
} }

View File

@@ -12,11 +12,13 @@ import com.stardust.autojs.execution.ScriptExecutionListener;
import com.stardust.autojs.execution.SimpleScriptExecutionListener; import com.stardust.autojs.execution.SimpleScriptExecutionListener;
import com.stardust.autojs.runtime.exception.ScriptInterruptedException; import com.stardust.autojs.runtime.exception.ScriptInterruptedException;
import com.stardust.autojs.script.ScriptSource; import com.stardust.autojs.script.ScriptSource;
import com.stardust.util.IntentUtil;
import org.autojs.autojs.Pref; import org.autojs.autojs.Pref;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.autojs.AutoJs; import org.autojs.autojs.autojs.AutoJs;
import org.autojs.autojs.external.ScriptIntents; import org.autojs.autojs.external.ScriptIntents;
import org.autojs.autojs.external.fileprovider.AppFileProvider;
import org.autojs.autojs.external.shortcut.Shortcut; import org.autojs.autojs.external.shortcut.Shortcut;
import org.autojs.autojs.external.shortcut.ShortcutActivity; import org.autojs.autojs.external.shortcut.ShortcutActivity;
import org.autojs.autojs.ui.edit.EditActivity; import org.autojs.autojs.ui.edit.EditActivity;
@@ -71,8 +73,7 @@ public class Scripts {
public static void openByOtherApps(String path) { public static void openByOtherApps(String path) {
Uri uri = Uri.parse("file://" + path); IntentUtil.viewFile(GlobalAppContext.get(), path, "text/plain", AppFileProvider.AUTHORITY);
GlobalAppContext.get().startActivity(new Intent(Intent.ACTION_VIEW).setDataAndType(uri, "text/plain").addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} }
public static void openByOtherApps(File file) { public static void openByOtherApps(File file) {
@@ -111,8 +112,8 @@ public class Scripts {
public static ScriptExecution run(ScriptSource source) { public static ScriptExecution run(ScriptSource source) {
try { try {
return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig() return AutoJs.getInstance().getScriptEngineService().execute(source, new ExecutionConfig()
.executePath(Pref.getScriptDirPath()) .executePath(Pref.getScriptDirPath())
.requirePath(Pref.getScriptDirPath())); .requirePath(Pref.getScriptDirPath()));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
Toast.makeText(GlobalAppContext.get(), e.getMessage(), Toast.LENGTH_LONG).show(); Toast.makeText(GlobalAppContext.get(), e.getMessage(), Toast.LENGTH_LONG).show();

View File

@@ -8,11 +8,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader; import java.io.StringReader;
import java.net.Socket;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -23,7 +19,6 @@ import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import okhttp3.WebSocket; import okhttp3.WebSocket;
import okhttp3.WebSocketListener; import okhttp3.WebSocketListener;
import okio.ByteString;
public class JsonWebSocket extends WebSocketListener { public class JsonWebSocket extends WebSocketListener {

View File

@@ -94,7 +94,12 @@ public class TimedTaskManager {
@SuppressLint("CheckResult") @SuppressLint("CheckResult")
public void removeTask(IntentTask intentTask) { public void removeTask(IntentTask intentTask) {
mIntentTaskDatabase.delete(intentTask) mIntentTaskDatabase.delete(intentTask)
.subscribe(EmptyObservers.consumer(), Throwable::printStackTrace);; .subscribe(i -> {
if(!TextUtils.isEmpty(intentTask.getAction())){
App.getApp().getDynamicBroadcastReceivers()
.unregister(intentTask.getAction());
}
}, Throwable::printStackTrace);
} }
public Flowable<TimedTask> getAllTasks() { public Flowable<TimedTask> getAllTasks() {

View File

@@ -291,14 +291,14 @@ public class ScriptOperations {
} }
public void delete(final ScriptFile scriptFile) { public void delete(final ScriptFile scriptFile) {
new ThemeColorMaterialDialogBuilder(mContext) DialogUtils.showDialog(new ThemeColorMaterialDialogBuilder(mContext)
.title(mContext.getString(R.string.text_are_you_sure_to_delete, scriptFile.getName())) .title(mContext.getString(R.string.text_are_you_sure_to_delete, scriptFile.getName()))
.positiveText(R.string.cancel) .positiveText(R.string.cancel)
.negativeText(R.string.ok) .negativeText(R.string.ok)
.onNegative((dialog, which) -> { .onNegative((dialog, which) -> {
deleteWithoutConfirm(scriptFile); deleteWithoutConfirm(scriptFile);
}) })
.show(); .build());
} }

View File

@@ -6,6 +6,7 @@ import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log;
import android.view.ActionMode; import android.view.ActionMode;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
@@ -48,6 +49,7 @@ public class
EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, PermissionRequestProxyActivity { EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHost, PermissionRequestProxyActivity {
private OnActivityResultDelegate.Mediator mMediator = new OnActivityResultDelegate.Mediator(); private OnActivityResultDelegate.Mediator mMediator = new OnActivityResultDelegate.Mediator();
private static final String LOG_TAG = "EditActivity";
@ViewById(R.id.editor_view) @ViewById(R.id.editor_view)
EditorView mEditorView; EditorView mEditorView;
@@ -125,6 +127,7 @@ EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHo
@Override @Override
public boolean onPrepareOptionsMenu(Menu menu) { public boolean onPrepareOptionsMenu(Menu menu) {
Log.d(LOG_TAG, "onPrepareOptionsMenu: " + menu);
boolean isScriptRunning = mEditorView.getScriptExecutionId() != ScriptExecution.NO_ID; boolean isScriptRunning = mEditorView.getScriptExecutionId() != ScriptExecution.NO_ID;
MenuItem forceStopItem = menu.findItem(R.id.action_force_stop); MenuItem forceStopItem = menu.findItem(R.id.action_force_stop);
forceStopItem.setEnabled(isScriptRunning); forceStopItem.setEnabled(isScriptRunning);
@@ -132,6 +135,7 @@ EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHo
} }
public boolean onPrepareActionMode(Menu menu) { public boolean onPrepareActionMode(Menu menu) {
Log.d(LOG_TAG, "onPrepareActionMode: " + menu);
boolean isScriptRunning = mEditorView.getScriptExecutionId() != ScriptExecution.NO_ID; boolean isScriptRunning = mEditorView.getScriptExecutionId() != ScriptExecution.NO_ID;
MenuItem forceStopItem = menu.findItem(R.id.action_force_stop); MenuItem forceStopItem = menu.findItem(R.id.action_force_stop);
forceStopItem.setEnabled(isScriptRunning); forceStopItem.setEnabled(isScriptRunning);
@@ -140,6 +144,7 @@ EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHo
@Override @Override
public void onActionModeStarted(ActionMode mode) { public void onActionModeStarted(ActionMode mode) {
Log.d(LOG_TAG, "onActionModeStarted: " + mode);
Menu menu = mode.getMenu(); Menu menu = mode.getMenu();
MenuItem item = menu.getItem(menu.size() - 1); MenuItem item = menu.getItem(menu.size() - 1);
menu.add(item.getGroupId(), R.id.action_delete_line, 10000, R.string.text_delete_line); menu.add(item.getGroupId(), R.id.action_delete_line, 10000, R.string.text_delete_line);
@@ -147,6 +152,31 @@ EditActivity extends BaseActivity implements OnActivityResultDelegate.DelegateHo
super.onActionModeStarted(mode); super.onActionModeStarted(mode);
} }
@Override
public void onSupportActionModeStarted(@NonNull android.support.v7.view.ActionMode mode) {
Log.d(LOG_TAG, "onSupportActionModeStarted: mode = " + mode);
super.onSupportActionModeStarted(mode);
}
@Nullable
@Override
public android.support.v7.view.ActionMode onWindowStartingSupportActionMode(@NonNull android.support.v7.view.ActionMode.Callback callback) {
Log.d(LOG_TAG, "onWindowStartingSupportActionMode: callback = " + callback);
return super.onWindowStartingSupportActionMode(callback);
}
@Override
public ActionMode startActionMode(ActionMode.Callback callback, int type) {
Log.d(LOG_TAG, "startActionMode: callback = " + callback + ", type = " + type);
return super.startActionMode(callback, type);
}
@Override
public ActionMode startActionMode(ActionMode.Callback callback) {
Log.d(LOG_TAG, "startActionMode: callback = " + callback );
return super.startActionMode(callback);
}
@Override @Override
public void onBackPressed() { public void onBackPressed() {
if (!mEditorView.onBackPressed()) { if (!mEditorView.onBackPressed()) {

View File

@@ -532,7 +532,7 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
return mEditor; return mEditor;
} }
public void find(String keywords, boolean usingRegex) { public void find(String keywords, boolean usingRegex) throws CodeEditor.CheckedPatternSyntaxException {
mEditor.find(keywords, usingRegex); mEditor.find(keywords, usingRegex);
showSearchToolbar(false); showSearchToolbar(false);
} }
@@ -547,12 +547,12 @@ public class EditorView extends FrameLayout implements CodeCompletionBar.OnHintC
.commit(); .commit();
} }
public void replace(String keywords, String replacement, boolean usingRegex) { public void replace(String keywords, String replacement, boolean usingRegex) throws CodeEditor.CheckedPatternSyntaxException {
mEditor.replace(keywords, replacement, usingRegex); mEditor.replace(keywords, replacement, usingRegex);
showSearchToolbar(true); showSearchToolbar(true);
} }
public void replaceAll(String keywords, String replacement, boolean usingRegex) { public void replaceAll(String keywords, String replacement, boolean usingRegex) throws CodeEditor.CheckedPatternSyntaxException {
mEditor.replaceAll(keywords, replacement, usingRegex); mEditor.replaceAll(keywords, replacement, usingRegex);
} }

View File

@@ -10,8 +10,11 @@ import android.widget.CheckBox;
import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.app.GlobalAppContext;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
import org.autojs.autojs.ui.edit.editor.CodeEditor;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
@@ -43,20 +46,16 @@ public class FindOrReplaceDialogBuilder extends ThemeColorMaterialDialogBuilder
private EditorView mEditorView; private EditorView mEditorView;
public FindOrReplaceDialogBuilder(@NonNull Context context, EditorView editorView) { public FindOrReplaceDialogBuilder(@NonNull Context context, EditorView editorView) {
super(context); super(context);
mEditorView = editorView; mEditorView = editorView;
setupViews(); setupViews();
restoreState(); restoreState();
onPositive(new MaterialDialog.SingleButtonCallback() { autoDismiss(false);
onNegative((dialog, which)-> dialog.dismiss());
@Override onPositive((dialog, which) -> {
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { storeState();
storeState(); findOrReplace(dialog);
findOrReplace();
}
}); });
} }
@@ -96,21 +95,27 @@ public class FindOrReplaceDialogBuilder extends ThemeColorMaterialDialogBuilder
} }
} }
private void findOrReplace() { private void findOrReplace(MaterialDialog dialog) {
String keywords = mKeywordsEditText.getText().toString(); String keywords = mKeywordsEditText.getText().toString();
if (keywords.isEmpty()) { if (keywords.isEmpty()) {
return; return;
} }
boolean usingRegex = mRegexCheckBox.isChecked(); try {
if (!mReplaceCheckBox.isChecked()) { boolean usingRegex = mRegexCheckBox.isChecked();
mEditorView.find(keywords, usingRegex); if (!mReplaceCheckBox.isChecked()) {
} else { mEditorView.find(keywords, usingRegex);
String replacement = mReplacementEditText.getText().toString();
if (mReplaceAllCheckBox.isChecked()) {
mEditorView.replaceAll(keywords, replacement, usingRegex);
} else { } else {
mEditorView.replace(keywords, replacement, usingRegex); String replacement = mReplacementEditText.getText().toString();
if (mReplaceAllCheckBox.isChecked()) {
mEditorView.replaceAll(keywords, replacement, usingRegex);
} else {
mEditorView.replace(keywords, replacement, usingRegex);
}
} }
dialog.dismiss();
} catch (CodeEditor.CheckedPatternSyntaxException e) {
e.printStackTrace();
mKeywordsEditText.setError(getContext().getString(R.string.error_pattern_syntax));
} }
} }

View File

@@ -19,6 +19,7 @@ import com.stardust.util.TextUtils;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import io.reactivex.Observable; import io.reactivex.Observable;
@@ -41,6 +42,11 @@ import io.reactivex.Observable;
*/ */
public class CodeEditor extends HVScrollView { public class CodeEditor extends HVScrollView {
public static class CheckedPatternSyntaxException extends Exception {
public CheckedPatternSyntaxException(PatternSyntaxException cause) {
super(cause);
}
}
public interface CursorChangeCallback { public interface CursorChangeCallback {
@@ -222,9 +228,13 @@ public class CodeEditor extends HVScrollView {
mTextViewRedoUndo.redo(); mTextViewRedoUndo.redo();
} }
public void find(String keywords, boolean usingRegex) { public void find(String keywords, boolean usingRegex) throws CheckedPatternSyntaxException {
if (usingRegex) { if (usingRegex) {
mMatcher = Pattern.compile(keywords).matcher(mCodeEditText.getText()); try {
mMatcher = Pattern.compile(keywords).matcher(mCodeEditText.getText());
}catch (PatternSyntaxException e){
throw new CheckedPatternSyntaxException(e);
}
mKeywords = null; mKeywords = null;
} else { } else {
mKeywords = keywords; mKeywords = keywords;
@@ -233,17 +243,21 @@ public class CodeEditor extends HVScrollView {
findNext(); findNext();
} }
public void replace(String keywords, String replacement, boolean usingRegex) { public void replace(String keywords, String replacement, boolean usingRegex) throws CheckedPatternSyntaxException {
mReplacement = replacement == null ? "" : replacement; mReplacement = replacement == null ? "" : replacement;
find(keywords, usingRegex); find(keywords, usingRegex);
} }
public void replaceAll(String keywords, String replacement, boolean usingRegex) { public void replaceAll(String keywords, String replacement, boolean usingRegex) throws CheckedPatternSyntaxException {
if (!usingRegex) { if (!usingRegex) {
keywords = Pattern.quote(keywords); keywords = Pattern.quote(keywords);
} }
String text = mCodeEditText.getText().toString(); String text = mCodeEditText.getText().toString();
text = text.replaceAll(keywords, replacement); try {
text = text.replaceAll(keywords, replacement);
}catch (PatternSyntaxException e){
throw new CheckedPatternSyntaxException(e);
}
setText(text); setText(text);
} }

View File

@@ -40,6 +40,12 @@ public class JavaScriptHighlighter implements SimpleTextWatcher.AfterTextChanged
} }
public void addToken(int tokenStart, int tokenEnd, int color) { public void addToken(int tokenStart, int tokenEnd, int color) {
if(mCount < tokenStart){
int c = mCount > 0 ? colors[mCount - 1] : color;
for (int i = mCount; i < tokenStart; i++) {
colors[i] = c;
}
}
for (int i = tokenStart; i < tokenEnd; i++) { for (int i = tokenStart; i < tokenEnd; i++) {
colors[i] = color; colors[i] = color;
} }

View File

@@ -6,7 +6,6 @@ import android.support.annotation.StringRes;
import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.MaterialDialog;
import com.stardust.pio.PFile; import com.stardust.pio.PFile;
import com.tencent.bugly.crashreport.BuglyLog;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.model.explorer.Explorer; import org.autojs.autojs.model.explorer.Explorer;

View File

@@ -3,6 +3,7 @@ package org.autojs.autojs.ui.floating;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.Gravity;
import android.view.OrientationEventListener; import android.view.OrientationEventListener;
import android.view.View; import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
@@ -94,8 +95,10 @@ public class CircularMenuWindow implements FloatyWindow {
} }
private WindowManager.LayoutParams createWindowLayoutParams() { private WindowManager.LayoutParams createWindowLayoutParams() {
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(-2, -2, 2003, 520, -3); WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
layoutParams.gravity = 51; WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
FloatyWindowManger.getWindowType(), 520, -3);
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
return layoutParams; return layoutParams;
} }

View File

@@ -2,6 +2,8 @@ package org.autojs.autojs.ui.floating;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build;
import android.view.WindowManager;
import android.widget.Toast; import android.widget.Toast;
import com.stardust.app.GlobalAppContext; import com.stardust.app.GlobalAppContext;
@@ -9,9 +11,11 @@ import com.stardust.autojs.util.FloatingPermission;
import com.stardust.enhancedfloaty.FloatyService; import com.stardust.enhancedfloaty.FloatyService;
import com.stardust.enhancedfloaty.FloatyWindow; import com.stardust.enhancedfloaty.FloatyWindow;
import com.stardust.enhancedfloaty.util.FloatingWindowPermissionUtil; import com.stardust.enhancedfloaty.util.FloatingWindowPermissionUtil;
import org.autojs.autojs.App; import org.autojs.autojs.App;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.ui.floating.CircularMenu; import org.autojs.autojs.ui.floating.CircularMenu;
import com.stardust.util.IntentUtil; import com.stardust.util.IntentUtil;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@@ -74,4 +78,12 @@ public class FloatyWindowManger {
menu.close(); menu.close();
sCircularMenu = null; sCircularMenu = null;
} }
public static int getWindowType() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
return WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
}
} }

View File

@@ -176,6 +176,8 @@ public class MainActivity extends BaseActivity implements OnActivityResultDelega
} }
private void setUpViewPagerFragmentBehaviors() { private void setUpViewPagerFragmentBehaviors() {
mPagerAdapter.setOnFragmentInstantiateListener((pos, fragment) -> { mPagerAdapter.setOnFragmentInstantiateListener((pos, fragment) -> {
((ViewPagerFragment) fragment).setFab(mFab); ((ViewPagerFragment) fragment).setFab(mFab);
if (pos == mViewPager.getCurrentItem()) { if (pos == mViewPager.getCurrentItem()) {

View File

@@ -63,7 +63,7 @@ public class CommunityFragment extends ViewPagerFragment implements BackPressedH
@AfterViews @AfterViews
void setUpViews() { void setUpViews() {
mWebView = mEWebView.getWebView(); mWebView = mEWebView.getWebView();
String url = "http://www.autojs.org/"; String url = "https://www.autojs.org/";
Bundle savedWebViewState = getArguments().getBundle("savedWebViewState"); Bundle savedWebViewState = getArguments().getBundle("savedWebViewState");
if (savedWebViewState != null) { if (savedWebViewState != null) {
mWebView.restoreState(savedWebViewState); mWebView.restoreState(savedWebViewState);

View File

@@ -239,9 +239,9 @@ public class DrawerFragment extends android.support.v4.app.Fragment {
SettingsActivity.selectThemeColor(getActivity()); SettingsActivity.selectThemeColor(getActivity());
} }
@SuppressLint("CheckResult")
private void enableAccessibilityServiceByRootIfNeeded() { private void enableAccessibilityServiceByRootIfNeeded() {
Observable.fromCallable(() -> Pref.shouldEnableAccessibilityServiceByRoot() && !isAccessibilityServiceEnabled()) Observable.fromCallable(() -> Pref.shouldEnableAccessibilityServiceByRoot() && !isAccessibilityServiceEnabled())
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe(needed -> { .subscribe(needed -> {
if (needed) { if (needed) {

View File

@@ -5,10 +5,8 @@ import android.os.Bundle;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.RecyclerView;
import com.stardust.app.GlobalAppContext; import com.stardust.app.GlobalAppContext;
import com.stardust.util.BackPressedHandler;
import com.stardust.util.IntentUtil; import com.stardust.util.IntentUtil;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
@@ -16,6 +14,7 @@ import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.ViewById; import org.androidannotations.annotations.ViewById;
import org.autojs.autojs.Pref; import org.autojs.autojs.Pref;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.external.fileprovider.AppFileProvider;
import org.autojs.autojs.model.explorer.ExplorerDirPage; import org.autojs.autojs.model.explorer.ExplorerDirPage;
import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.model.script.Scripts; import org.autojs.autojs.model.script.Scripts;
@@ -28,7 +27,6 @@ import org.autojs.autojs.ui.main.ViewPagerFragment;
import org.autojs.autojs.ui.project.ProjectConfigActivity; import org.autojs.autojs.ui.project.ProjectConfigActivity;
import org.autojs.autojs.ui.project.ProjectConfigActivity_; import org.autojs.autojs.ui.project.ProjectConfigActivity_;
import org.autojs.autojs.ui.viewmodel.ExplorerItemList; import org.autojs.autojs.ui.viewmodel.ExplorerItemList;
import org.autojs.autojs.ui.widget.ExpandableRecyclerView;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.Subscribe;
@@ -66,7 +64,7 @@ public class MyScriptListFragment extends ViewPagerFragment implements FloatingA
if (item.isEditable()) { if (item.isEditable()) {
Scripts.edit(item.toScriptFile()); Scripts.edit(item.toScriptFile());
} else { } else {
IntentUtil.viewFile(GlobalAppContext.get(), item.getPath()); IntentUtil.viewFile(GlobalAppContext.get(), item.getPath(), AppFileProvider.AUTHORITY);
} }
}); });
} }

View File

@@ -25,10 +25,12 @@ import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Click; import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity; import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById; import org.androidannotations.annotations.ViewById;
import org.autojs.autojs.App;
import org.autojs.autojs.Pref; import org.autojs.autojs.Pref;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.autojs.build.AutoJsApkBuilder; import org.autojs.autojs.autojs.build.AutoJsApkBuilder;
import org.autojs.autojs.build.ApkBuilderPluginHelper; import org.autojs.autojs.build.ApkBuilderPluginHelper;
import org.autojs.autojs.external.fileprovider.AppFileProvider;
import org.autojs.autojs.model.script.ScriptFile; import org.autojs.autojs.model.script.ScriptFile;
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
import org.autojs.autojs.tool.BitmapTool; import org.autojs.autojs.tool.BitmapTool;
@@ -53,6 +55,8 @@ import io.reactivex.schedulers.Schedulers;
@EActivity(R.layout.activity_build) @EActivity(R.layout.activity_build)
public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.ProgressCallback { public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.ProgressCallback {
private static final int REQUEST_CODE = 44401;
public static final String EXTRA_SOURCE = BuildActivity.class.getName() + ".extra_source_file"; public static final String EXTRA_SOURCE = BuildActivity.class.getName() + ".extra_source_file";
private static final String LOG_TAG = "BuildActivity"; private static final String LOG_TAG = "BuildActivity";
@@ -194,7 +198,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
@Click(R.id.icon) @Click(R.id.icon)
void selectIcon() { void selectIcon() {
ShortcutIconSelectActivity_.intent(this) ShortcutIconSelectActivity_.intent(this)
.startForResult(31209); .startForResult(REQUEST_CODE);
} }
@Click(R.id.fab) @Click(R.id.fab)
@@ -299,7 +303,7 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
.positiveText(R.string.text_install) .positiveText(R.string.text_install)
.negativeText(R.string.cancel) .negativeText(R.string.cancel)
.onPositive((dialog, which) -> .onPositive((dialog, which) ->
IntentUtil.installApk(BuildActivity.this, outApk.getPath()) IntentUtil.installApk(BuildActivity.this, outApk.getPath(), AppFileProvider.AUTHORITY)
) )
.show(); .show();
@@ -333,27 +337,13 @@ public class BuildActivity extends BaseActivity implements AutoJsApkBuilder.Prog
if (resultCode != RESULT_OK) { if (resultCode != RESULT_OK) {
return; return;
} }
String packageName = data.getStringExtra(ShortcutIconSelectActivity.EXTRA_PACKAGE_NAME); ShortcutIconSelectActivity.getBitmapFromIntent(getApplicationContext(), data)
if (packageName != null) { .subscribeOn(Schedulers.io())
try {
mIcon.setImageDrawable(getPackageManager().getApplicationIcon(packageName));
mIsDefaultIcon = false;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return;
}
if (data.getData() == null)
return;
Observable.fromCallable(() -> BitmapFactory.decodeStream(getContentResolver().openInputStream(data.getData())))
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe((bitmap -> { .subscribe(bitmap -> {
mIcon.setImageBitmap(bitmap); mIcon.setImageBitmap(bitmap);
mIsDefaultIcon = false; mIsDefaultIcon = false;
}), error -> { }, Throwable::printStackTrace);
Log.e(LOG_TAG, "decode stream", error);
});
} }

View File

@@ -1,6 +1,8 @@
package org.autojs.autojs.ui.project; package org.autojs.autojs.ui.project;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.TextInputEditText; import android.support.design.widget.TextInputEditText;
@@ -12,7 +14,6 @@ import android.widget.ImageView;
import android.widget.Toast; import android.widget.Toast;
import com.stardust.autojs.project.ProjectConfig; import com.stardust.autojs.project.ProjectConfig;
import com.stardust.autojs.runtime.api.Dialogs;
import com.stardust.pio.PFiles; import com.stardust.pio.PFiles;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
@@ -22,14 +23,18 @@ import org.androidannotations.annotations.ViewById;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.model.explorer.ExplorerDirPage; import org.autojs.autojs.model.explorer.ExplorerDirPage;
import org.autojs.autojs.model.explorer.ExplorerFileItem; import org.autojs.autojs.model.explorer.ExplorerFileItem;
import org.autojs.autojs.model.explorer.ExplorerItem;
import org.autojs.autojs.model.explorer.Explorers; import org.autojs.autojs.model.explorer.Explorers;
import org.autojs.autojs.model.project.ProjectTemplate; import org.autojs.autojs.model.project.ProjectTemplate;
import org.autojs.autojs.network.GlideApp;
import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder; import org.autojs.autojs.theme.dialog.ThemeColorMaterialDialogBuilder;
import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.BaseActivity;
import org.autojs.autojs.ui.shortcut.ShortcutIconSelectActivity;
import org.autojs.autojs.ui.shortcut.ShortcutIconSelectActivity_;
import org.autojs.autojs.ui.widget.SimpleTextWatcher; import org.autojs.autojs.ui.widget.SimpleTextWatcher;
import java.io.File; import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -44,6 +49,8 @@ public class ProjectConfigActivity extends BaseActivity {
public static final String EXTRA_DIRECTORY = "directory"; public static final String EXTRA_DIRECTORY = "directory";
private static final int REQUEST_CODE = 12477;
@ViewById(R.id.project_location) @ViewById(R.id.project_location)
EditText mProjectLocation; EditText mProjectLocation;
@@ -70,6 +77,7 @@ public class ProjectConfigActivity extends BaseActivity {
private File mParentDirectory; private File mParentDirectory;
private ProjectConfig mProjectConfig; private ProjectConfig mProjectConfig;
private boolean mNewProject; private boolean mNewProject;
private Bitmap mIconBitmap;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -118,6 +126,12 @@ public class ProjectConfigActivity extends BaseActivity {
mVersionName.setText(mProjectConfig.getVersionName()); mVersionName.setText(mProjectConfig.getVersionName());
mMainFileName.setText(mProjectConfig.getMainScriptFile()); mMainFileName.setText(mProjectConfig.getMainScriptFile());
mProjectLocation.setVisibility(View.GONE); mProjectLocation.setVisibility(View.GONE);
String icon = mProjectConfig.getIcon();
if (icon != null) {
GlideApp.with(this)
.load(new File(mDirectory, icon))
.into(mIcon);
}
} }
} }
@@ -128,9 +142,22 @@ public class ProjectConfigActivity extends BaseActivity {
if (!checkInputs()) { if (!checkInputs()) {
return; return;
} }
if (mIconBitmap != null) {
saveIcon(mIconBitmap)
.subscribe(ignored -> saveProjectConfig(), e -> {
e.printStackTrace();
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
});
} else {
saveProjectConfig();
}
}
@SuppressLint("CheckResult")
private void saveProjectConfig() {
if (mNewProject) { if (mNewProject) {
String location = mProjectLocation.getText().toString(); new ProjectTemplate(mProjectConfig, mDirectory)
new ProjectTemplate(mProjectConfig, new File(location))
.newProject() .newProject()
.subscribe(ignored -> { .subscribe(ignored -> {
Explorers.workspace().notifyChildrenChanged(new ExplorerDirPage(mParentDirectory, null)); Explorers.workspace().notifyChildrenChanged(new ExplorerDirPage(mParentDirectory, null));
@@ -158,12 +185,22 @@ public class ProjectConfigActivity extends BaseActivity {
} }
} }
@Click(R.id.icon)
void selectIcon() {
ShortcutIconSelectActivity_.intent(this)
.startForResult(REQUEST_CODE);
}
private void syncProjectConfig() { private void syncProjectConfig() {
mProjectConfig.setName(mAppName.getText().toString()); mProjectConfig.setName(mAppName.getText().toString());
mProjectConfig.setVersionCode(Integer.parseInt(mVersionCode.getText().toString())); mProjectConfig.setVersionCode(Integer.parseInt(mVersionCode.getText().toString()));
mProjectConfig.setVersionName(mVersionName.getText().toString()); mProjectConfig.setVersionName(mVersionName.getText().toString());
mProjectConfig.setMainScriptFile(mMainFileName.getText().toString()); mProjectConfig.setMainScriptFile(mMainFileName.getText().toString());
mProjectConfig.setPackageName(mPackageName.getText().toString()); mProjectConfig.setPackageName(mPackageName.getText().toString());
if (mNewProject) {
String location = mProjectLocation.getText().toString();
mDirectory = new File(location);
}
//mProjectConfig.getLaunchConfig().setHideLogs(true); //mProjectConfig.getLaunchConfig().setHideLogs(true);
} }
@@ -184,4 +221,43 @@ public class ProjectConfigActivity extends BaseActivity {
editText.setError(hint + getString(R.string.text_should_not_be_empty)); editText.setError(hint + getString(R.string.text_should_not_be_empty));
return false; return false;
} }
@SuppressLint("CheckResult")
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) {
return;
}
ShortcutIconSelectActivity.getBitmapFromIntent(getApplicationContext(), data)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(bitmap -> {
mIcon.setImageBitmap(bitmap);
mIconBitmap = bitmap;
},
Throwable::printStackTrace);
}
@SuppressLint("CheckResult")
private Observable<String> saveIcon(Bitmap b) {
return Observable.just(b)
.map(bitmap -> {
String iconPath = mProjectConfig.getIcon();
if (iconPath == null) {
iconPath = "res/logo.png";
}
File iconFile = new File(mDirectory, iconPath);
PFiles.ensureDir(iconFile.getPath());
FileOutputStream fos = new FileOutputStream(iconFile);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.close();
return iconPath;
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnNext(iconPath -> mProjectConfig.setIcon(iconPath));
}
} }

View File

@@ -6,6 +6,7 @@ import android.content.pm.PackageManager;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.drawable.Icon; import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.PersistableBundle; import android.os.PersistableBundle;
@@ -131,6 +132,7 @@ public class ShortcutCreateActivity extends AppCompatActivity {
} }
@SuppressLint("CheckResult")
@Override @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) { if (resultCode != RESULT_OK) {
@@ -146,7 +148,11 @@ public class ShortcutCreateActivity extends AppCompatActivity {
} }
return; return;
} }
Observable.fromCallable(() -> BitmapFactory.decodeStream(getContentResolver().openInputStream(data.getData()))) Uri uri = data.getData();
if(uri == null){
return;
}
Observable.fromCallable(() -> BitmapFactory.decodeStream(getContentResolver().openInputStream(uri)))
.subscribeOn(Schedulers.computation()) .subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.subscribe((bitmap -> { .subscribe((bitmap -> {

View File

@@ -5,7 +5,10 @@ import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ShortcutManager; import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -16,6 +19,7 @@ import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.tool.BitmapTool;
import org.autojs.autojs.ui.BaseActivity; import org.autojs.autojs.ui.BaseActivity;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
@@ -24,6 +28,7 @@ import org.androidannotations.annotations.ViewById;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -97,6 +102,23 @@ public class ShortcutIconSelectActivity extends BaseActivity {
} }
} }
public static Observable<Bitmap> getBitmapFromIntent(Context context, Intent data) {
String packageName = data.getStringExtra(EXTRA_PACKAGE_NAME);
if (packageName != null) {
return Observable.fromCallable(() -> {
Drawable drawable = context.getPackageManager().getApplicationIcon(packageName);
return BitmapTool.drawableToBitmap(drawable);
});
}
Uri uri = data.getData();
if (uri == null) {
return Observable.error(new IllegalArgumentException("invalid intent"));
}
return Observable.fromCallable(() ->
BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri))
);
}
private class AppItem { private class AppItem {
Drawable icon; Drawable icon;
ApplicationInfo info; ApplicationInfo info;

View File

@@ -3,19 +3,16 @@ package org.autojs.autojs.ui.splash;
import android.Manifest; import android.Manifest;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import com.stardust.autojs.core.image.OpenCVHelper;
import com.xcy8.ads.listener.LoadAdListener; import com.xcy8.ads.listener.LoadAdListener;
import com.xcy8.ads.view.FullScreenAdView; import com.xcy8.ads.view.FullScreenAdView;
import com.xcy8.ads.view.skipview.OnFullScreenListener;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ViewById;
import org.autojs.autojs.Constants; import org.autojs.autojs.Constants;
import org.autojs.autojs.Pref; import org.autojs.autojs.Pref;
import org.autojs.autojs.R; import org.autojs.autojs.R;
@@ -33,6 +30,7 @@ public class SplashActivity extends BaseActivity {
public static final String FORCE_SHOW_AD = "forceShowAd"; public static final String FORCE_SHOW_AD = "forceShowAd";
private static final String LOG_TAG = SplashActivity.class.getSimpleName(); private static final String LOG_TAG = SplashActivity.class.getSimpleName();
private static final long INIT_TIMEOUT = 1500;
private boolean mCanEnterNextActivity = false; private boolean mCanEnterNextActivity = false;
@@ -47,19 +45,31 @@ public class SplashActivity extends BaseActivity {
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mHandler = new Handler(); init();
mNotStartMainActivity = getIntent().getBooleanExtra(NOT_START_MAIN_ACTIVITY, false);
boolean forceShowAd = getIntent().getBooleanExtra(FORCE_SHOW_AD, false); boolean forceShowAd = getIntent().getBooleanExtra(FORCE_SHOW_AD, false);
setContentView(R.layout.activity_splash); final long millis = SystemClock.uptimeMillis();
mFullScreenAdView = findViewById(R.id.full_screen_view);
if (!forceShowAd && !Pref.shouldShowAd()) { if (!forceShowAd && !Pref.shouldShowAd()) {
mFullScreenAdView.setVisibility(View.INVISIBLE); mFullScreenAdView.setVisibility(View.INVISIBLE);
mHandler.postDelayed(this::enterNextActivity, 1500);
} else { } else {
if(checkPermission(Manifest.permission.READ_PHONE_STATE)){ if (checkPermission(Manifest.permission.READ_PHONE_STATE)) {
fetchSplashAD(); fetchSplashAD();
} }
} }
OpenCVHelper.initIfNeeded(this, () -> {
long delay = INIT_TIMEOUT - (SystemClock.uptimeMillis() - millis);
if (delay <= 0) {
enterNextActivity();
return;
}
mHandler.postDelayed(SplashActivity.this::enterNextActivity, delay);
});
}
private void init() {
setContentView(R.layout.activity_splash);
mFullScreenAdView = findViewById(R.id.full_screen_view);
mHandler = new Handler();
mNotStartMainActivity = getIntent().getBooleanExtra(NOT_START_MAIN_ACTIVITY, false);
} }
void enterNextActivity() { void enterNextActivity() {
@@ -116,7 +126,7 @@ public class SplashActivity extends BaseActivity {
}); });
mHandler.postDelayed(() -> { mHandler.postDelayed(() -> {
if (mAdLoading) { if (mAdLoading) {
enterNextActivity(); enterNextActivity();
} }
}, 2000); }, 2000);
mFullScreenAdView.loadAd(getAdId(), false); mFullScreenAdView.loadAd(getAdId(), false);

View File

@@ -20,6 +20,7 @@ import com.stardust.util.IntentUtil;
import org.autojs.autojs.BuildConfig; import org.autojs.autojs.BuildConfig;
import org.autojs.autojs.Pref; import org.autojs.autojs.Pref;
import org.autojs.autojs.R; import org.autojs.autojs.R;
import org.autojs.autojs.external.fileprovider.AppFileProvider;
import org.autojs.autojs.network.download.DownloadManager; import org.autojs.autojs.network.download.DownloadManager;
import org.autojs.autojs.network.entity.VersionInfo; import org.autojs.autojs.network.entity.VersionInfo;
import org.autojs.autojs.tool.IntentTool; import org.autojs.autojs.tool.IntentTool;
@@ -118,7 +119,7 @@ public class UpdateInfoDialogBuilder extends MaterialDialog.Builder {
final String path = new File(Pref.getScriptDirPath(), "AutoJs.apk").getPath(); final String path = new File(Pref.getScriptDirPath(), "AutoJs.apk").getPath();
DownloadManager.getInstance().downloadWithProgress(getContext(), downloadUrl, path) DownloadManager.getInstance().downloadWithProgress(getContext(), downloadUrl, path)
.subscribeOn(AndroidSchedulers.mainThread()) .subscribeOn(AndroidSchedulers.mainThread())
.subscribe(file -> IntentUtil.installApk(getContext(), file.getPath()), .subscribe(file -> IntentUtil.installApk(getContext(), file.getPath(), AppFileProvider.AUTHORITY),
error -> { error -> {
error.printStackTrace(); error.printStackTrace();
Toast.makeText(getContext(), R.string.text_download_failed, Toast.LENGTH_SHORT).show(); Toast.makeText(getContext(), R.string.text_download_failed, Toast.LENGTH_SHORT).show();

View File

@@ -71,6 +71,7 @@
</android.support.design.widget.CoordinatorLayout> </android.support.design.widget.CoordinatorLayout>
<fragment <fragment
android:id="@+id/fragment_drawer"
android:name="org.autojs.autojs.ui.main.drawer.DrawerFragment_" android:name="org.autojs.autojs.ui.main.drawer.DrawerFragment_"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@@ -421,4 +421,5 @@
<string name="text_run_on_headset_plug">耳机插拔时</string> <string name="text_run_on_headset_plug">耳机插拔时</string>
<string name="text_run_on_time_tick">每分钟一次</string> <string name="text_run_on_time_tick">每分钟一次</string>
<string name="text_run_on_config_change">某些设置(屏幕方向,地区等)更改时</string> <string name="text_run_on_config_change">某些设置(屏幕方向,地区等)更改时</string>
<string name="error_pattern_syntax">正则表达式错误</string>
</resources> </resources>

View File

@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android"> <paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/> <external-path name="external_files" path="."/>
<files-path name="sample" path="sample"/>
<root-path name="root_files" path="." />
</paths> </paths>

View File

@@ -1,12 +1,12 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
android { android {
compileSdkVersion 27 compileSdkVersion versions.compile
buildToolsVersion '27.0.3' buildToolsVersion versions.buildTool
defaultConfig { defaultConfig {
minSdkVersion 17 minSdkVersion versions.mini
targetSdkVersion 25 targetSdkVersion versions.target
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@@ -35,35 +35,34 @@ repositories {
} }
dependencies { dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
compile fileTree(dir: 'libs', include: ['*.jar']) api fileTree(dir: 'libs', include: ['*.jar'])
compile 'org.greenrobot:eventbus:3.0.0' api 'org.greenrobot:eventbus:3.0.0'
compile 'net.lingala.zip4j:zip4j:1.3.2' api 'net.lingala.zip4j:zip4j:1.3.2'
compile('com.afollestad.material-dialogs:core:0.9.2.3', { api('com.afollestad.material-dialogs:core:0.9.2.3', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
compile 'com.android.support:design:25.4.0' api 'com.android.support:design:28.0.0'
compile 'com.android.support:appcompat-v7:25.4.0' api 'com.github.hyb1996:EnhancedFloaty:0.21'
compile 'com.github.hyb1996:EnhancedFloaty:0.21' api 'com.github.hyb1996:OpenCvLib:2.4.13.4-imgproc'
compile 'com.github.hyb1996:OpenCvLib:2.4.13.4-imgproc' api 'com.makeramen:roundedimageview:2.3.0'
compile 'com.makeramen:roundedimageview:2.3.0'
// OkHttp // OkHttp
compile 'com.squareup.okhttp3:okhttp:3.9.0' api 'com.squareup.okhttp3:okhttp:3.10.0'
//JDeferred //JDeferred
compile 'org.jdeferred:jdeferred-android-aar:1.2.6' api 'org.jdeferred:jdeferred-android-aar:1.2.6'
//RootShell //RootShell
compile 'com.github.Stericson:RootShell:1.6' api 'com.github.Stericson:RootShell:1.6'
// Gson // Gson
compile 'com.google.code.gson:gson:2.8.0' api 'com.google.code.gson:gson:2.8.2'
// Terminal emulator // Terminal emulator
compile(name: 'libtermexec-release', ext: 'aar') api(name: 'libtermexec-release', ext: 'aar')
compile(name: 'emulatorview-release', ext: 'aar') api(name: 'emulatorview-release', ext: 'aar')
compile(name: 'term-debug', ext: 'aar') api(name: 'term-debug', ext: 'aar')
compile files('libs/rhino-1.7.7.2.jar') api files('libs/rhino-1.7.7.2.jar')
compile project(path: ':common') api project(path: ':common')
compile project(path: ':automator') api project(path: ':automator')
} }

View File

@@ -7,6 +7,7 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.VIBRATE"/> <uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.WRITE_SETTINGS"/> <uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<application <application

View File

@@ -109,6 +109,10 @@ module.exports = function(runtime, global){
"fast": 1 "fast": 1
} }
const flagsMap = {
"findOnUiThread": 1
};
var auto = function(mode){ var auto = function(mode){
if(mode){ if(mode){
global.auto.setMode(mode); global.auto.setMode(mode);
@@ -120,14 +124,33 @@ module.exports = function(runtime, global){
runtime.accessibilityBridge.waitForServiceEnabled(); runtime.accessibilityBridge.waitForServiceEnabled();
} }
auto.setMode = function(mode){ auto.setMode = function(modeStr){
if(typeof(mode) !== "string"){ if(typeof(mode) !== "string"){
throw new TypeError("mode should be a string"); throw new TypeError("mode should be a string");
} }
mode = modes[mode.toLowerCase()] || 0; let mode = modes[modeStr];
if(mode == undefined){
throw new Error("unknown mode for auto.setMode(): " + modeStr)
}
runtime.accessibilityBridge.setMode(mode); runtime.accessibilityBridge.setMode(mode);
} }
auto.setFlags = function(flags){
if(typeof(flags) !== "string"){
throw new TypeError("flags should be a string");
}
let flagsInt = 0;
let flagStrings = flags.split("|");
for(let i = 0; i < flagStrings.length; i++){
let flag = flagsMap[flagStrings[i]];
if(flag == undefined){
throw new Error("unknown flag for auto.setFlags(): " + flagStrings[i]);
}
flagsInt |= flag;
}
runtime.accessibilityBridge.setFlags(flagsInt);
}
auto.getService = function(){ auto.getService = function(){
return runtime.accessibilityBridge.getService(); return runtime.accessibilityBridge.getService();
} }

View File

@@ -13,6 +13,7 @@ import com.stardust.app.SimpleActivityLifecycleCallbacks;
import com.stardust.autojs.core.accessibility.AccessibilityBridge; import com.stardust.autojs.core.accessibility.AccessibilityBridge;
import com.stardust.autojs.core.console.GlobalStardustConsole; import com.stardust.autojs.core.console.GlobalStardustConsole;
import com.stardust.autojs.core.console.StardustConsole; import com.stardust.autojs.core.console.StardustConsole;
import com.stardust.autojs.core.image.OpenCVHelper;
import com.stardust.autojs.core.image.capture.ScreenCaptureRequestActivity; import com.stardust.autojs.core.image.capture.ScreenCaptureRequestActivity;
import com.stardust.autojs.core.image.capture.ScreenCaptureRequester; import com.stardust.autojs.core.image.capture.ScreenCaptureRequester;
import com.stardust.autojs.core.record.accessibility.AccessibilityActionRecorder; import com.stardust.autojs.core.record.accessibility.AccessibilityActionRecorder;
@@ -76,8 +77,6 @@ public abstract class AutoJs {
protected void init() { protected void init() {
addAccessibilityServiceDelegates(); addAccessibilityServiceDelegates();
registerActivityLifecycleCallbacks(); registerActivityLifecycleCallbacks();
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_13, mContext, new BaseLoaderCallback(mContext) {
});
} }
public abstract void ensureAccessibilityServiceEnabled(); public abstract void ensureAccessibilityServiceEnabled();
@@ -111,7 +110,7 @@ public abstract class AutoJs {
return new ScriptRuntime.Builder() return new ScriptRuntime.Builder()
.setConsole(new StardustConsole(mUiHandler, mGlobalConsole)) .setConsole(new StardustConsole(mUiHandler, mGlobalConsole))
.setScreenCaptureRequester(mScreenCaptureRequester) .setScreenCaptureRequester(mScreenCaptureRequester)
.setAccessibilityBridge(new AccessibilityBridgeImpl()) .setAccessibilityBridge(new AccessibilityBridgeImpl(mUiHandler))
.setUiHandler(mUiHandler) .setUiHandler(mUiHandler)
.setAppUtils(mAppUtils) .setAppUtils(mAppUtils)
.setEngineService(mScriptEngineService) .setEngineService(mScriptEngineService)
@@ -183,8 +182,8 @@ public abstract class AutoJs {
private class AccessibilityBridgeImpl extends AccessibilityBridge { private class AccessibilityBridgeImpl extends AccessibilityBridge {
public AccessibilityBridgeImpl() { public AccessibilityBridgeImpl(UiHandler uiHandler) {
super(createAccessibilityConfig()); super(createAccessibilityConfig(), uiHandler);
} }
@Override @Override

View File

@@ -7,11 +7,10 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo; import android.view.accessibility.AccessibilityWindowInfo;
import com.stardust.autojs.runtime.accessibility.AccessibilityConfig; import com.stardust.autojs.runtime.accessibility.AccessibilityConfig;
import com.stardust.automator.UiObject; import com.stardust.util.UiHandler;
import com.stardust.view.accessibility.AccessibilityInfoProvider; import com.stardust.view.accessibility.AccessibilityInfoProvider;
import com.stardust.view.accessibility.AccessibilityNotificationObserver; import com.stardust.view.accessibility.AccessibilityNotificationObserver;
import com.stardust.view.accessibility.AccessibilityService; import com.stardust.view.accessibility.AccessibilityService;
import com.stardust.view.accessibility.NotificationListener;
/** /**
@@ -27,12 +26,17 @@ public abstract class AccessibilityBridge {
public static final int MODE_NORMAL = 0; public static final int MODE_NORMAL = 0;
public static final int MODE_FAST = 1; public static final int MODE_FAST = 1;
private int mMode = MODE_NORMAL; public static final int FLAG_FIND_ON_UI_THREAD = 1;
private AccessibilityConfig mConfig;
private WindowFilter mWindowFilter;
public AccessibilityBridge(AccessibilityConfig config) { private int mMode = MODE_NORMAL;
private int mFlags = 0;
private final AccessibilityConfig mConfig;
private WindowFilter mWindowFilter;
private final UiHandler mUiHandler;
public AccessibilityBridge(AccessibilityConfig config, UiHandler uiHandler) {
mConfig = config; mConfig = config;
mUiHandler = uiHandler;
mConfig.seal(); mConfig.seal();
} }
@@ -40,6 +44,10 @@ public abstract class AccessibilityBridge {
public abstract void waitForServiceEnabled(); public abstract void waitForServiceEnabled();
public void post(Runnable r) {
mUiHandler.post(r);
}
@Nullable @Nullable
public abstract AccessibilityService getService(); public abstract AccessibilityService getService();
@@ -62,7 +70,7 @@ public abstract class AccessibilityBridge {
return activeWindow.getRoot(); return activeWindow.getRoot();
} }
} }
if (mMode == MODE_FAST) { if ((mMode & MODE_FAST) != 0) {
return service.fastRootInActiveWindow(); return service.fastRootInActiveWindow();
} }
return service.getRootInActiveWindow(); return service.getRootInActiveWindow();
@@ -75,11 +83,18 @@ public abstract class AccessibilityBridge {
@NonNull @NonNull
public abstract AccessibilityInfoProvider getInfoProvider(); public abstract AccessibilityInfoProvider getInfoProvider();
public void setMode(int mode) { public void setMode(int mode) {
mMode = mode; mMode = mode;
} }
public int getFlags() {
return mFlags;
}
public void setFlags(int flags) {
mFlags = flags;
}
@NonNull @NonNull
public abstract AccessibilityNotificationObserver getNotificationObserver(); public abstract AccessibilityNotificationObserver getNotificationObserver();

View File

@@ -1,5 +1,6 @@
package com.stardust.autojs.core.accessibility; package com.stardust.autojs.core.accessibility;
import android.os.Looper;
import android.os.SystemClock; import android.os.SystemClock;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.util.Log; import android.util.Log;
@@ -13,6 +14,7 @@ import com.stardust.automator.UiGlobalSelector;
import com.stardust.automator.UiObject; import com.stardust.automator.UiObject;
import com.stardust.automator.UiObjectCollection; import com.stardust.automator.UiObjectCollection;
import com.stardust.automator.filter.DfsFilter; import com.stardust.automator.filter.DfsFilter;
import com.stardust.concurrent.VolatileBox;
import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator; import com.stardust.view.accessibility.AccessibilityNodeInfoAllocator;
import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS; import static android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS;
@@ -72,6 +74,18 @@ public class UiSelector extends UiGlobalSelector {
@ScriptInterface @ScriptInterface
public UiObjectCollection find() { public UiObjectCollection find() {
ensureAccessibilityServiceEnabled(); ensureAccessibilityServiceEnabled();
if((mAccessibilityBridge.getFlags() & AccessibilityBridge.FLAG_FIND_ON_UI_THREAD)!=0
&& Looper.myLooper() != Looper.getMainLooper()){
VolatileBox<UiObjectCollection> result = new VolatileBox<>();
mAccessibilityBridge.post(() -> result.setAndNotify(findImpl()));
return result.blockedGet();
}
return findImpl();
}
@NonNull
@ScriptInterface
protected UiObjectCollection findImpl() {
AccessibilityNodeInfo root = mAccessibilityBridge.getRootInCurrentWindow(); AccessibilityNodeInfo root = mAccessibilityBridge.getRootInCurrentWindow();
if (BuildConfig.DEBUG) if (BuildConfig.DEBUG)
Log.d(TAG, "find: root = " + root); Log.d(TAG, "find: root = " + root);
@@ -98,6 +112,7 @@ public class UiSelector extends UiGlobalSelector {
return regex; return regex;
} }
@Override @Override
public UiGlobalSelector classNameMatches(String regex) { public UiGlobalSelector classNameMatches(String regex) {
return super.classNameMatches(convertRegex(regex)); return super.classNameMatches(convertRegex(regex));

View File

@@ -80,7 +80,7 @@ public class ConsoleFloaty extends ResizableExpandableFloaty.AbstractResizableEx
} }
private void initConsoleTitle(View view) { private void initConsoleTitle(View view) {
mTitleView = (TextView) view.findViewById(R.id.title); mTitleView = view.findViewById(R.id.title);
if (mTitle != null) { if (mTitle != null) {
mTitleView.setText(mTitle); mTitleView.setText(mTitle);
} }
@@ -91,7 +91,7 @@ public class ConsoleFloaty extends ResizableExpandableFloaty.AbstractResizableEx
} }
private void setUpConsole(View view, ResizableExpandableFloatyWindow window) { private void setUpConsole(View view, ResizableExpandableFloatyWindow window) {
ConsoleView consoleView = (ConsoleView) view.findViewById(R.id.console); ConsoleView consoleView = view.findViewById(R.id.console);
consoleView.setConsole(mConsole); consoleView.setConsole(mConsole);
consoleView.setWindow(window); consoleView.setWindow(window);
initConsoleTitle(view); initConsoleTitle(view);

View File

@@ -66,10 +66,16 @@ public class RawWindow implements FloatyWindow {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
} }
int type;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
}
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, type,
flags, flags,
PixelFormat.TRANSLUCENT); PixelFormat.TRANSLUCENT);
layoutParams.gravity = Gravity.TOP | Gravity.START; layoutParams.gravity = Gravity.TOP | Gravity.START;

View File

@@ -93,10 +93,6 @@ public class ScriptCanvas {
return mCanvas.save(); return mCanvas.save();
} }
public int save(int saveFlags) {
return mCanvas.save(saveFlags);
}
public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, int saveFlags) { public int saveLayer(@Nullable RectF bounds, @Nullable Paint paint, int saveFlags) {
return mCanvas.saveLayer(bounds, paint, saveFlags); return mCanvas.saveLayer(bounds, paint, saveFlags);
} }

View File

@@ -1,8 +1,14 @@
package com.stardust.autojs.core.image; package com.stardust.autojs.core.image;
import android.app.Activity;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.Log; import android.util.Log;
import com.afollestad.materialdialogs.MaterialDialog;
import org.opencv.android.InstallCallbackInterface;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat; import org.opencv.core.Mat;
/** /**
@@ -11,8 +17,12 @@ import org.opencv.core.Mat;
public class OpenCVHelper { public class OpenCVHelper {
public interface InitializeCallback {
void onInitFinish();
}
private static final String LOG_TAG = "OpenCv"; private static final String LOG_TAG = "OpenCVHelper";
private static boolean mInitialized = false;
public static void release(@Nullable Mat mat) { public static void release(@Nullable Mat mat) {
if (mat == null) if (mat == null)
@@ -20,4 +30,103 @@ public class OpenCVHelper {
mat.release(); mat.release();
} }
public static void initIfNeeded(Activity activity, InitializeCallback callback) {
if (mInitialized) {
callback.onInitFinish();
return;
}
mInitialized = true;
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_13, activity.getApplicationContext(), new LoaderCallback(activity) {
@Override
protected void finish() {
callback.onInitFinish();
}
});
}
public static class LoaderCallback implements LoaderCallbackInterface {
private Activity mActivity;
public LoaderCallback(Activity activity) {
this.mActivity = activity;
}
public void onManagerConnected(int status) {
switch (status) {
case 0:
finish();
break;
case 1:
default:
Log.e(LOG_TAG, "OpenCV loading failed!");
new MaterialDialog.Builder(mActivity)
.title("OpenCV error")
.content("OpenCV was not initialised correctly. Application will be shut down")
.cancelable(false)
.positiveText("OK")
.onPositive((dialog, which) -> finish())
.show();
break;
case 2:
Log.e(LOG_TAG, "Package installation failed!");
new MaterialDialog.Builder(mActivity)
.title("OpenCV Manager")
.content("Package installation failed!")
.cancelable(false)
.positiveText("OK")
.onPositive((dialog, which) -> finish())
.show();
break;
case 3:
Log.d(LOG_TAG, "OpenCV library instalation was canceled by user");
finish();
break;
case 4:
Log.d(LOG_TAG, "OpenCV Manager Service is uncompatible with this app!");
new MaterialDialog.Builder(mActivity)
.title("OpenCV Manager")
.content("OpenCV Manager service is incompatible with this app. Try to update it via Google Play.")
.cancelable(false)
.positiveText("OK")
.onPositive((dialog, which) -> finish())
.show();
}
}
public void onPackageInstall(int operation, final InstallCallbackInterface callback) {
switch (operation) {
case 0:
new MaterialDialog.Builder(mActivity)
.title("Package not found")
.content(callback.getPackageName() + " package was not found! Try to install it?")
.cancelable(false)
.positiveText("Yes")
.onPositive((dialog, which) -> callback.install())
.negativeText("No")
.onNegative(((dialog, which) -> callback.cancel()))
.show();
break;
case 1:
new MaterialDialog.Builder(mActivity)
.title("OpenCV is not ready")
.content("Installation is in progress. Wait or exit?")
.cancelable(false)
.positiveText("Wait")
.onPositive((dialog, which) -> callback.wait_install())
.negativeText("Exit")
.onNegative(((dialog, which) -> callback.cancel()))
.show();
default:
finish();
}
}
protected void finish() {
mActivity.finish();
}
}
} }

View File

@@ -19,6 +19,12 @@ public class LinearLayoutInflater<V extends LinearLayout> extends ViewGroupInfla
.map("vertical", LinearLayout.VERTICAL) .map("vertical", LinearLayout.VERTICAL)
.map("horizontal", LinearLayout.HORIZONTAL); .map("horizontal", LinearLayout.HORIZONTAL);
static final ValueMapper<Integer> SHOW_DIVIDERS = new ValueMapper<Integer>("showDividers")
.map("beginning", LinearLayout.SHOW_DIVIDER_BEGINNING)
.map("middle", LinearLayout.SHOW_DIVIDER_MIDDLE)
.map("end", LinearLayout.SHOW_DIVIDER_END)
.map("none", LinearLayout.SHOW_DIVIDER_NONE);
public LinearLayoutInflater(ResourceParser resourceParser) { public LinearLayoutInflater(ResourceParser resourceParser) {
super(resourceParser); super(resourceParser);
} }
@@ -44,6 +50,9 @@ public class LinearLayoutInflater<V extends LinearLayout> extends ViewGroupInfla
case "orientation": case "orientation":
view.setOrientation(ORIENTATIONS.get(value)); view.setOrientation(ORIENTATIONS.get(value));
break; break;
case "showDividers":
view.setShowDividers(SHOW_DIVIDERS.split(value));
break;
case "weightSum": case "weightSum":
view.setWeightSum(Float.valueOf(value)); view.setWeightSum(Float.valueOf(value));
break; break;

View File

@@ -39,7 +39,7 @@ public class TextViewInflater<V extends TextView> extends BaseViewInflater<V> {
.map("web", Linkify.WEB_URLS); .map("web", Linkify.WEB_URLS);
private static final ValueMapper<TextUtils.TruncateAt> ELLIPSIZE = new ValueMapper<TextUtils.TruncateAt>("ellipsize") private static final ValueMapper<TextUtils.TruncateAt> ELLIPSIZE = new ValueMapper<TextUtils.TruncateAt>("ellipsize")
.map("end", TextUtils.TruncateAt.END) .map("end", TextUtils.TruncateAt.END)
.map("marquee", TextUtils.TruncateAt.MIDDLE) .map("marquee", TextUtils.TruncateAt.MARQUEE)
.map("none", null) .map("none", null)
.map("start", TextUtils.TruncateAt.START) .map("start", TextUtils.TruncateAt.START)
.map("middle", TextUtils.TruncateAt.MIDDLE); .map("middle", TextUtils.TruncateAt.MIDDLE);

View File

@@ -2,6 +2,7 @@ package com.stardust.autojs.core.ui.widget;
import android.content.Context; import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.support.v4.view.ViewPager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;

View File

@@ -4,7 +4,9 @@ import android.content.Context;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout; import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.Gravity;
import com.stardust.autojs.runtime.api.UI; import com.stardust.autojs.runtime.api.UI;

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.MessageQueue; import android.os.MessageQueue;
import android.util.Log;
import com.stardust.autojs.core.looper.LooperHelper; import com.stardust.autojs.core.looper.LooperHelper;
import com.stardust.autojs.script.JavaScriptSource; import com.stardust.autojs.script.JavaScriptSource;
@@ -44,6 +45,7 @@ public class LoopBasedJavaScriptEngine extends RhinoJavaScriptEngine {
if (callback != null) if (callback != null)
callback.onResult(o); callback.onResult(o);
} catch (Exception e) { } catch (Exception e) {
Log.d("DDDDD", "execute: " + e.getMessage());
if (callback == null) { if (callback == null) {
throw e; throw e;
} else { } else {

View File

@@ -205,6 +205,7 @@ public class RhinoJavaScriptEngine extends JavaScriptEngine {
@Override @Override
protected void observeInstructionCount(Context cx, int instructionCount) { protected void observeInstructionCount(Context cx, int instructionCount) {
if (Thread.currentThread().isInterrupted() && Looper.myLooper() != Looper.getMainLooper()) { if (Thread.currentThread().isInterrupted() && Looper.myLooper() != Looper.getMainLooper()) {
Log.d("DDDDD", "thread interrupt: " + Thread.currentThread());
throw new ScriptInterruptedException(); throw new ScriptInterruptedException();
} }
} }

View File

@@ -140,9 +140,11 @@ public class ScriptExecuteActivity extends AppCompatActivity {
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
Log.d(LOG_TAG, "onDestroy"); Log.d(LOG_TAG, "onDestroy");
mScriptEngine.put("activity", null); if(mScriptEngine != null){
mScriptEngine.setTag("activity", null); mScriptEngine.put("activity", null);
mScriptEngine.destroy(); mScriptEngine.setTag("activity", null);
mScriptEngine.destroy();
}
mScriptExecution = null; mScriptExecution = null;
} }

View File

@@ -3,7 +3,8 @@ package com.stardust.autojs.rhino;
import android.util.Log; import android.util.Log;
import com.android.dx.command.dexer.Main; import com.android.dx.command.dexer.Main;
import com.android.dx.dex.file.DexFile; import com.stardust.pio.PFiles;
import com.stardust.util.MD5;
import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.exception.ZipException;
@@ -16,6 +17,7 @@ import java.io.ByteArrayInputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -42,7 +44,11 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa
public AndroidClassLoader(ClassLoader parent, File dir) { public AndroidClassLoader(ClassLoader parent, File dir) {
this.parent = parent; this.parent = parent;
mCacheDir = dir; mCacheDir = dir;
dir.mkdirs(); if (dir.exists()) {
PFiles.deleteFilesOfDir(dir);
} else {
dir.mkdirs();
}
} }
/** /**
@@ -53,13 +59,13 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa
Log.d(LOG_TAG, "defineClass: name = " + name + " data.length = " + data.length); Log.d(LOG_TAG, "defineClass: name = " + name + " data.length = " + data.length);
File classFile = null; File classFile = null;
try { try {
classFile = generateTempClassFile(name, false); classFile = generateTempFile(name, false);
final ZipFile zipFile = new ZipFile(classFile); final ZipFile zipFile = new ZipFile(classFile);
final ZipParameters parameters = new ZipParameters(); final ZipParameters parameters = new ZipParameters();
parameters.setFileNameInZip(name.replace('.', '/') + ".class"); parameters.setFileNameInZip(name.replace('.', '/') + ".class");
parameters.setSourceExternalStream(true); parameters.setSourceExternalStream(true);
zipFile.addStream(new ByteArrayInputStream(data), parameters); zipFile.addStream(new ByteArrayInputStream(data), parameters);
return dexJar(classFile).loadClass(name); return dexJar(classFile, null).loadClass(name);
} catch (IOException | ZipException | ClassNotFoundException e) { } catch (IOException | ZipException | ClassNotFoundException e) {
throw new FatalLoadingException(e); throw new FatalLoadingException(e);
} finally { } finally {
@@ -69,7 +75,7 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa
} }
} }
private File generateTempClassFile(String name, boolean create) throws IOException { private File generateTempFile(String name, boolean create) throws IOException {
File file = new File(mCacheDir, name.hashCode() + System.currentTimeMillis() + ".jar"); File file = new File(mCacheDir, name.hashCode() + System.currentTimeMillis() + ".jar");
if (create) { if (create) {
if (!file.exists()) { if (!file.exists()) {
@@ -83,8 +89,16 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa
public void loadJar(File jar) throws IOException { public void loadJar(File jar) throws IOException {
Log.d(LOG_TAG, "loadJar: jar = " + jar); Log.d(LOG_TAG, "loadJar: jar = " + jar);
if (!jar.exists() || !jar.canRead()) {
throw new FileNotFoundException("File does not exist or readable: " + jar.getPath());
}
File dexFile = new File(mCacheDir, generateDexFileName(jar));
if (dexFile.exists()) {
loadDex(dexFile);
return;
}
try { try {
final File classFile = generateTempClassFile(jar.getPath(), false); final File classFile = generateTempFile(jar.getPath(), false);
final ZipFile zipFile = new ZipFile(classFile); final ZipFile zipFile = new ZipFile(classFile);
final ZipFile jarFile = new ZipFile(jar); final ZipFile jarFile = new ZipFile(jar);
//noinspection unchecked //noinspection unchecked
@@ -96,12 +110,22 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa
zipFile.addStream(jarFile.getInputStream(header), parameters); zipFile.addStream(jarFile.getInputStream(header), parameters);
} }
} }
dexJar(classFile); dexJar(classFile, dexFile);
classFile.delete();
} catch (ZipException e) { } catch (ZipException e) {
throw new IOException(e); throw new IOException(e);
} }
} }
private String generateDexFileName(File jar) {
String message = jar.getPath() + "_" + jar.lastModified();
try {
return MD5.md5(message);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
public DexClassLoader loadDex(File file) throws FileNotFoundException { public DexClassLoader loadDex(File file) throws FileNotFoundException {
Log.d(LOG_TAG, "loadDex: file = " + file); Log.d(LOG_TAG, "loadDex: file = " + file);
if (!file.exists()) { if (!file.exists()) {
@@ -112,15 +136,20 @@ public class AndroidClassLoader extends ClassLoader implements GeneratedClassLoa
return loader; return loader;
} }
private DexClassLoader dexJar(File classFile) throws IOException { private DexClassLoader dexJar(File classFile, File dexFile) throws IOException {
final Main.Arguments arguments = new Main.Arguments(); final Main.Arguments arguments = new Main.Arguments();
arguments.fileNames = new String[]{classFile.getPath()}; arguments.fileNames = new String[]{classFile.getPath()};
File dexFile = generateTempClassFile("dex-" + classFile.getPath(), true); boolean isTmpDex = dexFile == null;
if (isTmpDex) {
dexFile = generateTempFile("dex-" + classFile.getPath(), true);
}
arguments.outName = dexFile.getPath(); arguments.outName = dexFile.getPath();
arguments.jarOutput = true; arguments.jarOutput = true;
Main.run(arguments); Main.run(arguments);
DexClassLoader loader = loadDex(dexFile); DexClassLoader loader = loadDex(dexFile);
dexFile.delete(); if (isTmpDex) {
dexFile.delete();
}
return loader; return loader;
} }

View File

@@ -7,9 +7,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.webkit.MimeTypeMap;
import com.stardust.autojs.annotation.ScriptInterface; import com.stardust.autojs.annotation.ScriptInterface;
import com.stardust.util.IntentUtil; import com.stardust.util.IntentUtil;
@@ -18,8 +16,6 @@ import com.stardust.util.MimeTypes;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.List; import java.util.List;
import static com.stardust.pio.PFiles.getExtension;
/** /**
* Created by Stardust on 2017/4/2. * Created by Stardust on 2017/4/2.
*/ */
@@ -28,9 +24,16 @@ public class AppUtils {
private Context mContext; private Context mContext;
private volatile WeakReference<Activity> mCurrentActivity = new WeakReference<>(null); private volatile WeakReference<Activity> mCurrentActivity = new WeakReference<>(null);
private final String mFileProviderAuthority;
public AppUtils(Context context) { public AppUtils(Context context) {
mContext = context; mContext = context;
mFileProviderAuthority = null;
}
public AppUtils(Context context, String fileProviderAuthority) {
mContext = context;
mFileProviderAuthority = fileProviderAuthority;
} }
@ScriptInterface @ScriptInterface
@@ -99,22 +102,14 @@ public class AppUtils {
public void viewFile(String path) { public void viewFile(String path) {
if (path == null) if (path == null)
throw new NullPointerException("path == null"); throw new NullPointerException("path == null");
path = "file://" + path; IntentUtil.viewFile(mContext, path, mFileProviderAuthority);
String mimeType = MimeTypes.fromFileOr(path, "*/*");
mContext.startActivity(new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse(path), mimeType)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} }
@ScriptInterface @ScriptInterface
public void editFile(String path) { public void editFile(String path) {
if (path == null) if (path == null)
throw new NullPointerException("path == null"); throw new NullPointerException("path == null");
path = "file://" + path; IntentUtil.editFile(mContext, path, mFileProviderAuthority);
String mimeType = MimeTypes.fromFileOr(path, "*/*");
mContext.startActivity(new Intent(Intent.ACTION_EDIT)
.setDataAndType(Uri.parse(path), mimeType)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
} }
@ScriptInterface @ScriptInterface

View File

@@ -1,12 +1,12 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
android { android {
compileSdkVersion 25 compileSdkVersion versions.compile
buildToolsVersion '26.0.2' buildToolsVersion versions.buildTool
defaultConfig { defaultConfig {
minSdkVersion 17 minSdkVersion versions.mini
targetSdkVersion 25 targetSdkVersion versions.target
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@@ -33,10 +33,10 @@ repositories {
} }
dependencies { dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.4.0' api 'com.android.support:appcompat-v7:28.0.0'
compile project(path: ':common') api project(path: ':common')
} }

View File

@@ -1,12 +1,14 @@
import groovy.json.JsonSlurper
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
repositories { repositories {
jcenter()
google() google()
jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.1' classpath 'com.android.tools.build:gradle:3.1.4'
} }
} }
@@ -18,9 +20,14 @@ allprojects {
url "https://jitpack.io" url "https://jitpack.io"
} }
google() google()
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
} }
} }
task clean(type: Delete) { task clean(type: Delete) {
delete rootProject.buildDir delete rootProject.buildDir
} }
ext {
versions = new JsonSlurper().parse(file('./project-versions.json'))
}

View File

@@ -1,12 +1,12 @@
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
android { android {
compileSdkVersion 25 compileSdkVersion versions.compile
buildToolsVersion '26.0.2' buildToolsVersion versions.buildTool
defaultConfig { defaultConfig {
minSdkVersion 17 minSdkVersion versions.mini
targetSdkVersion 25 targetSdkVersion versions.target
versionCode 1 versionCode 1
versionName "1.0" versionName "1.0"
@@ -23,10 +23,10 @@ android {
} }
dependencies { dependencies {
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
compile 'com.android.support:support-annotations:25.4.0' api 'com.android.support:support-annotations:28.0.0'
compile 'com.github.hyb1996:settingscompat:1.1.5' api 'com.github.hyb1996:settingscompat:1.1.5'
} }

View File

@@ -1 +1 @@
[{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":421},"path":"commonRelease-4.0.3 Alpha2.apk","properties":{"packageId":"org.autojs.autojs","split":"","minSdkVersion":"17"}}] [{"outputType":{"type":"APK"},"apkInfo":{"type":"MAIN","splits":[],"versionCode":424,"versionName":"4.0.3 Alpha5","enabled":true,"outputFile":"commonRelease-4.0.3 Alpha5.apk","fullName":"commonRelease","baseName":"common-release"},"path":"commonRelease-4.0.3 Alpha5.apk","properties":{}}]

View File

@@ -4,6 +4,7 @@ import android.app.Activity;
import android.app.Dialog; import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.content.ContextWrapper; import android.content.ContextWrapper;
import android.os.Build;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
@@ -15,10 +16,17 @@ public class DialogUtils {
public static <T extends Dialog> T showDialog(T dialog) { public static <T extends Dialog> T showDialog(T dialog) {
Context context = dialog.getContext(); Context context = dialog.getContext();
if (!isActivityContext(context)) { if (!isActivityContext(context)) {
Window window = dialog.getWindow(); Window window = dialog.getWindow();
int type;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
} else {
type = WindowManager.LayoutParams.TYPE_PHONE;
}
if (window != null) if (window != null)
window.setType(WindowManager.LayoutParams.TYPE_PHONE); window.setType(type);
} }
dialog.show(); dialog.show();
return dialog; return dialog;

View File

@@ -395,6 +395,19 @@ public class PFiles {
return file.delete(); return file.delete();
} }
public static boolean deleteFilesOfDir(File dir) {
if (!dir.isDirectory())
throw new IllegalArgumentException("not a directory: " + dir);
File[] children = dir.listFiles();
if (children != null) {
for (File child : children) {
if (!deleteRecursively(child))
return false;
}
}
return true;
}
public static boolean remove(String path) { public static boolean remove(String path) {
return new File(path).delete(); return new File(path).delete();
} }

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import java.io.File; import java.io.File;
@@ -84,20 +85,47 @@ public class IntentUtil {
return goToAppDetailSettings(context, context.getPackageName()); return goToAppDetailSettings(context, context.getPackageName());
} }
// FIXME: 2018/7/11 Permission denial public static void installApk(Context context, String path, String fileProviderAuthority) {
public static void installApk(Context context, String path) { Uri uri = getUriOfFile(context, path, fileProviderAuthority);
Intent intent = new Intent(Intent.ACTION_VIEW); Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.setDataAndType(Uri.fromFile(new File(path)), "application/vnd.android.package-archive"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
context.startActivity(intent); context.startActivity(intent);
} }
public static void viewFile(Context context, String path) { public static void viewFile(Context context, String path, String fileProviderAuthority) {
path = "file://" + path;
String mimeType = MimeTypes.fromFileOr(path, "*/*"); String mimeType = MimeTypes.fromFileOr(path, "*/*");
viewFile(context, path, mimeType, fileProviderAuthority);
}
public static Uri getUriOfFile(Context context, String path, String fileProviderAuthority) {
Uri uri;
if (fileProviderAuthority == null) {
uri = Uri.parse("file://" + path);
} else {
uri = FileProvider.getUriForFile(context, fileProviderAuthority, new File(path));
}
return uri;
}
public static void viewFile(Context context, String path, String mimeType, String fileProviderAuthority) {
Uri uri = getUriOfFile(context, path, fileProviderAuthority);
context.startActivity(new Intent(Intent.ACTION_VIEW) context.startActivity(new Intent(Intent.ACTION_VIEW)
.setDataAndType(Uri.parse(path), mimeType) .setDataAndType(uri, mimeType)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
}
public static void editFile(Context context, String path, String fileProviderAuthority) {
String mimeType = MimeTypes.fromFileOr(path, "*/*");
Uri uri = getUriOfFile(context, path, fileProviderAuthority);
context.startActivity(new Intent(Intent.ACTION_EDIT)
.setDataAndType(uri, mimeType)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
} }
} }

View File

@@ -0,0 +1,26 @@
package com.stardust.util;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
public static byte[] md5Bytes(String message) throws NoSuchAlgorithmException {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(message.getBytes());
return md5.digest();
}
public static String md5(String message) throws NoSuchAlgorithmException {
byte[] bytes = md5Bytes(message);
StringBuilder hexString = new StringBuilder(32);
for (byte b : bytes) {
String hex = Integer.toHexString(0xFF & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
}

View File

@@ -0,0 +1,16 @@
package com.stardust.util;
public class ObjectHelper {
public static void requireNonNull(Object obj, String name){
if(obj == null){
throw new NullPointerException(name + " should not be null");
}
}
public static void requireNonNull(Object obj){
if(obj == null){
throw new NullPointerException();
}
}
}

View File

@@ -1,6 +1,6 @@
#Mon Nov 27 21:40:02 CST 2017 #Fri Oct 05 23:57:16 CST 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

View File

@@ -1,15 +1,15 @@
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
android { android {
compileSdkVersion 25 compileSdkVersion versions.compile
buildToolsVersion '26.0.2' buildToolsVersion versions.buildTool
defaultConfig { defaultConfig {
applicationId "com.stardust.auojs.inrt" applicationId "com.stardust.auojs.inrt"
minSdkVersion 17 minSdkVersion versions.mini
targetSdkVersion 23 targetSdkVersion versions.target
versionCode 210 versionCode versions.appVersionCode - 200
versionName "4.0.2 Alpha5" versionName versions.appVersionName
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk { ndk {
abiFilters 'armeabi-v7a' abiFilters 'armeabi-v7a'
@@ -36,6 +36,39 @@ android {
} }
} }
task buildApkPlugin {
doLast {
def pluginProjectDirPath = '..\\..\\AutoJsApkBuilderPlugin'
def pluginProjectDir = file(pluginProjectDirPath)
if(!pluginProjectDir.exists() || !pluginProjectDir.isDirectory()){
println 'pluginProjectDir not exists'
return
}
copy {
from file('build\\outputs\\apk\\release\\')
into new File(pluginProjectDir, 'app\\src\\main\\assets')
include "inrt-release-unsigned.apk"
rename "inrt-release-unsigned.apk", 'template.apk'
}
exec {
workingDir pluginProjectDir
commandLine 'gradlew.bat', 'assembleRelease'
}
copy {
from new File(pluginProjectDir, 'app\\build\\outputs\\apk\\release')
into file('..\\common\\release')
include '*-release.apk'
}
}
}
tasks.whenTaskAdded { task ->
if (task.name == 'assembleRelease') {
task.finalizedBy 'buildApkPlugin'
}
}
repositories { repositories {
flatDir { flatDir {
dirs 'libs' dirs 'libs'
@@ -44,17 +77,16 @@ repositories {
} }
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
}) })
compile 'com.android.support:appcompat-v7:25.4.0'
//Glide //Glide
compile('com.github.bumptech.glide:glide:4.2.0', { implementation('com.github.bumptech.glide:glide:4.2.0', {
exclude group: 'com.android.support' exclude group: 'com.android.support'
}) })
testCompile 'junit:junit:4.12' testImplementation 'junit:junit:4.12'
compile project(':automator') implementation project(':automator')
compile project(':common') implementation project(':common')
compile project(':autojs') implementation project(':autojs')
} }

View File

@@ -26,7 +26,8 @@
android:label="inrt" android:label="inrt"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme"
tools:replace="android:label, android:allowBackup"> tools:replace="android:label, android:allowBackup"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".LogActivity"> <activity android:name=".LogActivity">
</activity> </activity>

View File

@@ -43,9 +43,9 @@ public class LogActivity extends AppCompatActivity {
private void setupView() { private void setupView() {
setContentView(R.layout.activity_main); setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar); setSupportActionBar(toolbar);
ConsoleView consoleView = (ConsoleView) findViewById(R.id.console); ConsoleView consoleView = findViewById(R.id.console);
consoleView.setConsole((StardustConsole) AutoJs.getInstance().getGlobalConsole()); consoleView.setConsole((StardustConsole) AutoJs.getInstance().getGlobalConsole());
consoleView.findViewById(R.id.input_container).setVisibility(View.GONE); consoleView.findViewById(R.id.input_container).setVisibility(View.GONE);
} }

View File

@@ -6,6 +6,7 @@ import android.graphics.Typeface;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi; import android.support.annotation.RequiresApi;
@@ -14,6 +15,7 @@ import android.widget.TextView;
import com.stardust.auojs.inrt.launch.AssetsProjectLauncher; import com.stardust.auojs.inrt.launch.AssetsProjectLauncher;
import com.stardust.auojs.inrt.launch.GlobalProjectLauncher; import com.stardust.auojs.inrt.launch.GlobalProjectLauncher;
import com.stardust.autojs.core.image.OpenCVHelper;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@@ -29,18 +31,24 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
public class SplashActivity extends AppCompatActivity { public class SplashActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CODE = 11186; private static final int PERMISSION_REQUEST_CODE = 11186;
private static final long INIT_TIMEOUT = 2500;
@Override @Override
protected void onCreate(@Nullable Bundle savedInstanceState) { protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
if (!Pref.isFirstUsing()) {
main();
return;
}
setContentView(R.layout.activity_splash); setContentView(R.layout.activity_splash);
TextView slug = (TextView) findViewById(R.id.slug); TextView slug = findViewById(R.id.slug);
slug.setTypeface(Typeface.createFromAsset(getAssets(), "roboto_medium.ttf")); slug.setTypeface(Typeface.createFromAsset(getAssets(), "roboto_medium.ttf"));
new Handler().postDelayed(this::main, 2500); final long millis = SystemClock.uptimeMillis();
OpenCVHelper.initIfNeeded(this, () -> {
long delay = INIT_TIMEOUT - (SystemClock.uptimeMillis() - millis);
if (!Pref.isFirstUsing() || delay <= 0) {
main();
return;
}
new Handler().postDelayed(SplashActivity.this::main, delay);
});
} }
private void main() { private void main() {
@@ -67,9 +75,7 @@ public class SplashActivity extends AppCompatActivity {
runScript(); runScript();
} }
} else { } else {
int[] grantResults = new int[permissions.length]; runScript();
Arrays.fill(grantResults, PERMISSION_GRANTED);
onRequestPermissionsResult(PERMISSION_REQUEST_CODE, permissions, grantResults);
} }
} }

8
project-versions.json Normal file
View File

@@ -0,0 +1,8 @@
{
"appVersionCode": 424,
"appVersionName": "4.0.3 Alpha5",
"target": 28,
"mini": 17,
"compile": 28,
"buildTool": "28.0.3"
}