Add more options in the Select menu
Allow users to select all/none and automatically include new applications. Close #93 as completed. Co-authored-by: mywalk <66966897+mywalkb@users.noreply.github.com>
This commit is contained in:
parent
c5ff4c0e3a
commit
1339fc7d3c
|
|
@ -390,4 +390,23 @@ public class ConfigManager {
|
||||||
return ILSPManagerService.DEX2OAT_CRASHED;
|
return ILSPManagerService.DEX2OAT_CRASHED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean getAutoInclude(String packageName) {
|
||||||
|
try {
|
||||||
|
return LSPManagerServiceHolder.getService().getAutoInclude(packageName);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(App.TAG, Log.getStackTraceString(e));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean setAutoInclude(String packageName, boolean enable) {
|
||||||
|
try {
|
||||||
|
LSPManagerServiceHolder.getService().setAutoInclude(packageName, enable);
|
||||||
|
return true;
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(App.TAG, Log.getStackTraceString(e));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -292,6 +292,26 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
|
||||||
fragment.showHint(R.string.enable_documentui, true);
|
fragment.showHint(R.string.enable_documentui, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (itemId == R.id.select_all) {
|
||||||
|
var tmpChkList = new HashSet<ApplicationWithEquals>(ConfigManager.getModuleScope(module.packageName));
|
||||||
|
for (AppInfo info : searchList) {
|
||||||
|
if (info.packageName.equals("android")) {
|
||||||
|
fragment.showHint(R.string.reboot_required, true, R.string.reboot, v -> ConfigManager.reboot());
|
||||||
|
}
|
||||||
|
tmpChkList.add(info.application);
|
||||||
|
}
|
||||||
|
ConfigManager.setModuleScope(module.packageName, module.legacy, tmpChkList);
|
||||||
|
} else if (itemId == R.id.select_none) {
|
||||||
|
var tmpChkList = new HashSet<ApplicationWithEquals>(ConfigManager.getModuleScope(module.packageName));
|
||||||
|
for (AppInfo info : searchList) {
|
||||||
|
if (tmpChkList.remove(info.application) && info.packageName.equals("android")) {
|
||||||
|
fragment.showHint(R.string.reboot_required, true, R.string.reboot, v -> ConfigManager.reboot());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConfigManager.setModuleScope(module.packageName, module.legacy, tmpChkList);
|
||||||
|
} else if (itemId == R.id.auto_include) {
|
||||||
|
item.setChecked(!item.isChecked());
|
||||||
|
ConfigManager.setAutoInclude(module.packageName, item.isChecked());
|
||||||
} else if (!AppHelper.onOptionsItemSelected(item, preferences)) {
|
} else if (!AppHelper.onOptionsItemSelected(item, preferences)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -371,6 +391,7 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
|
||||||
}
|
}
|
||||||
case 0 -> menu.findItem(R.id.item_sort_by_name).setChecked(true);
|
case 0 -> menu.findItem(R.id.item_sort_by_name).setChecked(true);
|
||||||
}
|
}
|
||||||
|
menu.findItem(R.id.auto_include).setChecked(ConfigManager.getAutoInclude(module.packageName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -28,33 +28,45 @@
|
||||||
android:showAsAction="ifRoom|collapseActionView"
|
android:showAsAction="ifRoom|collapseActionView"
|
||||||
android:title="@android:string/search_go" />
|
android:title="@android:string/search_go" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="@string/menu_select">
|
||||||
|
<menu>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/use_recommended"
|
android:id="@+id/use_recommended"
|
||||||
android:title="@string/use_recommended" />
|
android:title="@string/use_recommended" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/select_all"
|
||||||
|
android:title="@string/menu_select_all" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/select_none"
|
||||||
|
android:title="@string/menu_select_none" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/auto_include"
|
||||||
|
android:checkable="true"
|
||||||
|
android:title="@string/menu_auto_include" />
|
||||||
|
</menu>
|
||||||
|
</item>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:showAsAction="never"
|
android:showAsAction="never"
|
||||||
android:title="@string/menu_hide">
|
android:title="@string/menu_hide">
|
||||||
<menu>
|
<menu>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/item_filter_games"
|
android:id="@+id/item_filter_games"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:title="@string/menu_show_games" />
|
android:title="@string/menu_show_games" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/item_filter_modules"
|
android:id="@+id/item_filter_modules"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:title="@string/menu_show_modules" />
|
android:title="@string/menu_show_modules" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/item_filter_system"
|
android:id="@+id/item_filter_system"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:title="@string/menu_show_system_apps" />
|
android:title="@string/menu_show_system_apps" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/item_filter_denylist"
|
android:id="@+id/item_filter_denylist"
|
||||||
android:checkable="true"
|
android:checkable="true"
|
||||||
|
|
|
||||||
|
|
@ -141,9 +141,13 @@
|
||||||
<string name="menu_show_denylist">Denylist</string>
|
<string name="menu_show_denylist">Denylist</string>
|
||||||
<string name="failed_to_save_scope_list">Failed to save scope list</string>
|
<string name="failed_to_save_scope_list">Failed to save scope list</string>
|
||||||
<string name="app_version">Version: %1$s</string>
|
<string name="app_version">Version: %1$s</string>
|
||||||
|
<string name="menu_select">Select</string>
|
||||||
<string name="use_recommended">Recommended</string>
|
<string name="use_recommended">Recommended</string>
|
||||||
<string name="no_scope_selected_has_recommended">You did not select any app. Select recommended apps?</string>
|
<string name="no_scope_selected_has_recommended">You did not select any app. Select recommended apps?</string>
|
||||||
<string name="use_recommended_message">Select recommended apps?</string>
|
<string name="use_recommended_message">Select recommended apps?</string>
|
||||||
|
<string name="menu_select_all">All</string>
|
||||||
|
<string name="menu_select_none">None</string>
|
||||||
|
<string name="menu_auto_include">Auto-Include</string>
|
||||||
<string name="module_is_not_activated_yet">Xposed module is not activated yet</string>
|
<string name="module_is_not_activated_yet">Xposed module is not activated yet</string>
|
||||||
<string name="requested_by_module">Recommended</string>
|
<string name="requested_by_module">Recommended</string>
|
||||||
<string name="update_available">Update available: %1$s</string>
|
<string name="update_available">Update available: %1$s</string>
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageParser;
|
import android.content.pm.PackageParser;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
|
import android.database.sqlite.SQLiteException;
|
||||||
import android.database.sqlite.SQLiteStatement;
|
import android.database.sqlite.SQLiteStatement;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
@ -141,7 +142,9 @@ public class ConfigManager {
|
||||||
"module_pkg_name text NOT NULL UNIQUE," +
|
"module_pkg_name text NOT NULL UNIQUE," +
|
||||||
"apk_path text NOT NULL, " +
|
"apk_path text NOT NULL, " +
|
||||||
"enabled BOOLEAN DEFAULT 0 " +
|
"enabled BOOLEAN DEFAULT 0 " +
|
||||||
"CHECK (enabled IN (0, 1))" +
|
"CHECK (enabled IN (0, 1))," +
|
||||||
|
"auto_include BOOLEAN DEFAULT 0 " +
|
||||||
|
"CHECK (auto_include IN (0, 1))" +
|
||||||
");");
|
");");
|
||||||
private final SQLiteStatement createScopeTable = db.compileStatement("CREATE TABLE IF NOT EXISTS scope (" +
|
private final SQLiteStatement createScopeTable = db.compileStatement("CREATE TABLE IF NOT EXISTS scope (" +
|
||||||
"mid integer," +
|
"mid integer," +
|
||||||
|
|
@ -420,6 +423,20 @@ public class ConfigManager {
|
||||||
db.compileStatement("UPDATE scope SET app_pkg_name = 'system' WHERE app_pkg_name = 'android';").execute();
|
db.compileStatement("UPDATE scope SET app_pkg_name = 'system' WHERE app_pkg_name = 'android';").execute();
|
||||||
db.setVersion(3);
|
db.setVersion(3);
|
||||||
});
|
});
|
||||||
|
case 3:
|
||||||
|
try {
|
||||||
|
executeInTransaction(() -> {
|
||||||
|
db.compileStatement("ALTER TABLE modules ADD COLUMN auto_include BOOLEAN DEFAULT 0 CHECK (auto_include IN (0, 1));").execute();
|
||||||
|
db.setVersion(4);
|
||||||
|
});
|
||||||
|
} catch (SQLiteException ex) {
|
||||||
|
// Fix wrong init code for new column auto_include
|
||||||
|
if (ex.getMessage().startsWith("duplicate column name: auto_include")) {
|
||||||
|
db.setVersion(4);
|
||||||
|
} else {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -894,20 +911,7 @@ public class ConfigManager {
|
||||||
|
|
||||||
|
|
||||||
public String[] enabledModules() {
|
public String[] enabledModules() {
|
||||||
try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"}, "enabled = 1", null, null, null, null)) {
|
return listModules("enabled");
|
||||||
if (cursor == null) {
|
|
||||||
Log.e(TAG, "query enabled modules failed");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int modulePkgNameIdx = cursor.getColumnIndex("module_pkg_name");
|
|
||||||
HashSet<String> result = new HashSet<>();
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
var pkgName = cursor.getString(modulePkgNameIdx);
|
|
||||||
if (pkgName.equals("lspd")) continue;
|
|
||||||
result.add(pkgName);
|
|
||||||
}
|
|
||||||
return result.toArray(new String[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeModule(String packageName) {
|
public boolean removeModule(String packageName) {
|
||||||
|
|
@ -1223,4 +1227,41 @@ public class ConfigManager {
|
||||||
synchronized SharedMemory getPreloadDex() {
|
synchronized SharedMemory getPreloadDex() {
|
||||||
return ConfigFileManager.getPreloadDex(dexObfuscate);
|
return ConfigFileManager.getPreloadDex(dexObfuscate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean getAutoInclude(String packageName) {
|
||||||
|
try (Cursor cursor = db.query("modules", new String[]{"auto_include"},
|
||||||
|
"module_pkg_name = ? and auto_include = 1", new String[]{packageName}, null, null, null, null)) {
|
||||||
|
return cursor == null || cursor.moveToNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean setAutoInclude(String packageName, boolean enable) {
|
||||||
|
boolean changed = executeInTransaction(() -> {
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
values.put("auto_include", enable ? 1 : 0);
|
||||||
|
return db.update("modules", values, "module_pkg_name = ?", new String[]{packageName}) > 0;
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getAutoIncludeModules() {
|
||||||
|
return listModules("auto_include");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] listModules(String column) {
|
||||||
|
try (Cursor cursor = db.query("modules", new String[]{"module_pkg_name"}, column + " = 1", null, null, null, null)) {
|
||||||
|
if (cursor == null) {
|
||||||
|
Log.e(TAG, "query " + column + " modules failed");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int modulePkgNameIdx = cursor.getColumnIndex("module_pkg_name");
|
||||||
|
HashSet<String> result = new HashSet<>();
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
var pkgName = cursor.getString(modulePkgNameIdx);
|
||||||
|
if (pkgName.equals("lspd")) continue;
|
||||||
|
result.add(pkgName);
|
||||||
|
}
|
||||||
|
return result.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -556,4 +556,14 @@ public class LSPManagerService extends ILSPManagerService.Stub {
|
||||||
public boolean isLogWatchdogEnabled() {
|
public boolean isLogWatchdogEnabled() {
|
||||||
return ConfigManager.getInstance().isLogWatchdogEnabled();
|
return ConfigManager.getInstance().isLogWatchdogEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean setAutoInclude(String packageName, boolean enabled) {
|
||||||
|
return ConfigManager.getInstance().setAutoInclude(packageName, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getAutoInclude(String packageName) {
|
||||||
|
return ConfigManager.getInstance().getAutoInclude(packageName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ import android.telephony.TelephonyManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.lsposed.daemon.BuildConfig;
|
import org.lsposed.daemon.BuildConfig;
|
||||||
|
import org.lsposed.lspd.models.Application;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -151,8 +152,10 @@ public class LSPosedService extends ILSPosedService.Stub {
|
||||||
if (moduleName != null) {
|
if (moduleName != null) {
|
||||||
LSPNotificationManager.cancelNotification(UPDATED_CHANNEL_ID, moduleName, userId);
|
LSPNotificationManager.cancelNotification(UPDATED_CHANNEL_ID, moduleName, userId);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
case Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_CHANGED -> {
|
case Intent.ACTION_PACKAGE_ADDED, Intent.ACTION_PACKAGE_CHANGED -> {
|
||||||
|
var configManager = ConfigManager.getInstance();
|
||||||
// make sure that the change is for the complete package, not only a
|
// make sure that the change is for the complete package, not only a
|
||||||
// component
|
// component
|
||||||
String[] components = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
|
String[] components = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST);
|
||||||
|
|
@ -164,10 +167,32 @@ public class LSPosedService extends ILSPosedService.Stub {
|
||||||
// module to send a broadcast when modules that have not been activated are
|
// module to send a broadcast when modules that have not been activated are
|
||||||
// uninstalled.
|
// uninstalled.
|
||||||
// If cache not updated, assume it's not xposed module
|
// If cache not updated, assume it's not xposed module
|
||||||
isXposedModule = ConfigManager.getInstance().updateModuleApkPath(moduleName, ConfigManager.getInstance().getModuleApkPath(applicationInfo), false);
|
isXposedModule = configManager.updateModuleApkPath(moduleName, ConfigManager.getInstance().getModuleApkPath(applicationInfo), false);
|
||||||
} else if (ConfigManager.getInstance().isUidHooked(uid)) {
|
} else {
|
||||||
// it will auto update obsolete scope from database
|
if (configManager.isUidHooked(uid)) {
|
||||||
ConfigManager.getInstance().updateAppCache();
|
// it will automatically remove obsolete app from database
|
||||||
|
configManager.updateAppCache();
|
||||||
|
}
|
||||||
|
if (intentAction.equals(Intent.ACTION_PACKAGE_ADDED) && !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
|
||||||
|
for (String xposedModule : configManager.getAutoIncludeModules()) {
|
||||||
|
// For Xposed modules with auto_include set, we always add new applications
|
||||||
|
// to its scope
|
||||||
|
var list = configManager.getModuleScope(xposedModule);
|
||||||
|
if (list != null) {
|
||||||
|
Application scope = new Application();
|
||||||
|
scope.packageName = moduleName;
|
||||||
|
scope.userId = userId;
|
||||||
|
list.add(scope);
|
||||||
|
try {
|
||||||
|
if (!configManager.setModuleScope(xposedModule, list)) {
|
||||||
|
Log.e(TAG, "failed to set scope for " + xposedModule);
|
||||||
|
}
|
||||||
|
} catch(RemoteException re) {
|
||||||
|
Log.e(TAG, "failed to set scope for " + xposedModule, re);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
broadcastAndShowNotification(moduleName, userId, intent, isXposedModule);
|
broadcastAndShowNotification(moduleName, userId, intent, isXposedModule);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,4 +91,8 @@ interface ILSPManagerService {
|
||||||
void setLogWatchdog(boolean enable) = 49;
|
void setLogWatchdog(boolean enable) = 49;
|
||||||
|
|
||||||
boolean isLogWatchdogEnabled() = 50;
|
boolean isLogWatchdogEnabled() = 50;
|
||||||
|
|
||||||
|
boolean getAutoInclude(String packageName) = 51;
|
||||||
|
|
||||||
|
boolean setAutoInclude(String packageName, boolean enable) = 52;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue