mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-02-25 20:47:24 +00:00
Improve MagiskHide app listing
- Prevent platform apps from showing up - Add new option to toggle whether to show system apps
This commit is contained in:
parent
a60710e3bb
commit
da13b5dbf2
@ -66,6 +66,7 @@ public class Config {
|
|||||||
public static final String DARK_THEME = "dark_theme";
|
public static final String DARK_THEME = "dark_theme";
|
||||||
public static final String ETAG_KEY = "ETag";
|
public static final String ETAG_KEY = "ETag";
|
||||||
public static final String REPO_ORDER = "repo_order";
|
public static final String REPO_ORDER = "repo_order";
|
||||||
|
public static final String SHOW_SYSTEM_APP = "show_system";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Value {
|
public static class Value {
|
||||||
@ -108,16 +109,17 @@ public class Config {
|
|||||||
|
|
||||||
// prefs bool
|
// prefs bool
|
||||||
defs.putBoolean(Key.CHECK_UPDATES, true);
|
defs.putBoolean(Key.CHECK_UPDATES, true);
|
||||||
// defs.putBoolean(Const.Key.DARK_THEME, false);
|
// defs.putBoolean(Key.DARK_THEME, false);
|
||||||
// defs.putBoolean(Const.Key.SU_REAUTH, false);
|
// defs.putBoolean(Key.SU_REAUTH, false);
|
||||||
// defs.putBoolean(Const.Key.MAGISKHIDE, false);
|
// defs.putBoolean(Key.MAGISKHIDE, false);
|
||||||
// defs.putBoolean(Const.Key.COREONLY, false);
|
// defs.putBoolean(Key.COREONLY, false);
|
||||||
|
// defs.putBoolean(Key.SHOW_SYSTEM_APP, false);
|
||||||
|
|
||||||
// prefs string
|
// prefs string
|
||||||
defs.putString(Key.CUSTOM_CHANNEL, "");
|
defs.putString(Key.CUSTOM_CHANNEL, "");
|
||||||
defs.putString(Key.BOOT_FORMAT, ".img");
|
defs.putString(Key.BOOT_FORMAT, ".img");
|
||||||
defs.putString(Key.LOCALE, "");
|
defs.putString(Key.LOCALE, "");
|
||||||
// defs.putString(Const.Key.ETAG_KEY, null);
|
// defs.putString(Key.ETAG_KEY, null);
|
||||||
|
|
||||||
// db int
|
// db int
|
||||||
defs.putInt(Key.ROOT_ACCESS, Value.ROOT_ACCESS_APPS_AND_ADB);
|
defs.putInt(Key.ROOT_ACCESS, Value.ROOT_ACCESS_APPS_AND_ADB);
|
||||||
@ -125,10 +127,10 @@ public class Config {
|
|||||||
defs.putInt(Key.SU_MULTIUSER_MODE, Value.MULTIUSER_MODE_OWNER_ONLY);
|
defs.putInt(Key.SU_MULTIUSER_MODE, Value.MULTIUSER_MODE_OWNER_ONLY);
|
||||||
|
|
||||||
// db bool
|
// db bool
|
||||||
// defs.putBoolean(Const.Key.SU_FINGERPRINT, false);
|
// defs.putBoolean(Key.SU_FINGERPRINT, false);
|
||||||
|
|
||||||
// db strings
|
// db strings
|
||||||
// defs.putString(Const.Key.SU_MANAGER, null);
|
// defs.putString(Key.SU_MANAGER, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadMagiskInfo() {
|
public static void loadMagiskInfo() {
|
||||||
@ -245,6 +247,7 @@ public class Config {
|
|||||||
case Key.CHECK_UPDATES:
|
case Key.CHECK_UPDATES:
|
||||||
case Key.MAGISKHIDE:
|
case Key.MAGISKHIDE:
|
||||||
case Key.COREONLY:
|
case Key.COREONLY:
|
||||||
|
case Key.SHOW_SYSTEM_APP:
|
||||||
return PREF_BOOL;
|
return PREF_BOOL;
|
||||||
|
|
||||||
case Key.CUSTOM_CHANNEL:
|
case Key.CUSTOM_CHANNEL:
|
||||||
|
@ -2,14 +2,13 @@ package com.topjohnwu.magisk.adapters;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.CheckBox;
|
import android.widget.CheckBox;
|
||||||
import android.widget.Filter;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@ -18,6 +17,7 @@ import com.topjohnwu.magisk.R;
|
|||||||
import com.topjohnwu.magisk.utils.Topic;
|
import com.topjohnwu.magisk.utils.Topic;
|
||||||
import com.topjohnwu.magisk.utils.Utils;
|
import com.topjohnwu.magisk.utils.Utils;
|
||||||
import com.topjohnwu.superuser.Shell;
|
import com.topjohnwu.superuser.Shell;
|
||||||
|
import com.topjohnwu.superuser.internal.UiThreadHandler;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -25,22 +25,30 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.WorkerThread;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
|
|
||||||
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> {
|
public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.ViewHolder> {
|
||||||
|
|
||||||
private List<ApplicationInfo> fullList, showList;
|
private static PackageInfo PLATFORM;
|
||||||
|
|
||||||
|
private List<PackageInfo> fullList, showList;
|
||||||
private List<String> hideList;
|
private List<String> hideList;
|
||||||
private PackageManager pm;
|
private PackageManager pm;
|
||||||
private ApplicationFilter filter;
|
private boolean showSystem;
|
||||||
|
|
||||||
public ApplicationAdapter(Context context) {
|
public ApplicationAdapter(Context context) {
|
||||||
fullList = showList = Collections.emptyList();
|
fullList = showList = Collections.emptyList();
|
||||||
hideList = Collections.emptyList();
|
hideList = Collections.emptyList();
|
||||||
filter = new ApplicationFilter();
|
|
||||||
pm = context.getPackageManager();
|
pm = context.getPackageManager();
|
||||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps);
|
showSystem = false;
|
||||||
|
if (PLATFORM == null) {
|
||||||
|
try {
|
||||||
|
PLATFORM = pm.getPackageInfo("android", PackageManager.GET_SIGNATURES);
|
||||||
|
} catch (PackageManager.NameNotFoundException ignored) {}
|
||||||
|
}
|
||||||
|
AsyncTask.SERIAL_EXECUTOR.execute(this::loadApps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ -50,12 +58,17 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
return new ViewHolder(v);
|
return new ViewHolder(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
private void loadApps() {
|
private void loadApps() {
|
||||||
fullList = pm.getInstalledApplications(0);
|
fullList = pm.getInstalledPackages(PackageManager.GET_SIGNATURES);
|
||||||
hideList = Shell.su("magiskhide --ls").exec().getOut();
|
hideList = Shell.su("magiskhide --ls").exec().getOut();
|
||||||
for (Iterator<ApplicationInfo> i = fullList.iterator(); i.hasNext(); ) {
|
for (Iterator<PackageInfo> i = fullList.iterator(); i.hasNext(); ) {
|
||||||
ApplicationInfo info = i.next();
|
PackageInfo info = i.next();
|
||||||
if (Const.HIDE_BLACKLIST.contains(info.packageName) || !info.enabled || info.uid == 1000) {
|
if (Const.HIDE_BLACKLIST.contains(info.packageName) ||
|
||||||
|
/* Do not show disabled apps */
|
||||||
|
!info.applicationInfo.enabled ||
|
||||||
|
/* Never show platform apps */
|
||||||
|
PLATFORM.signatures[0].equals(info.signatures[0])) {
|
||||||
i.remove();
|
i.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +76,8 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
boolean ah = hideList.contains(a.packageName);
|
boolean ah = hideList.contains(a.packageName);
|
||||||
boolean bh = hideList.contains(b.packageName);
|
boolean bh = hideList.contains(b.packageName);
|
||||||
if (ah == bh) {
|
if (ah == bh) {
|
||||||
return Utils.getAppLabel(a, pm).compareToIgnoreCase(Utils.getAppLabel(b, pm));
|
return Utils.getAppLabel(a.applicationInfo, pm)
|
||||||
|
.compareToIgnoreCase(Utils.getAppLabel(b.applicationInfo, pm));
|
||||||
} else if (ah) {
|
} else if (ah) {
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
@ -73,9 +87,13 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
Topic.publish(false, Topic.MAGISK_HIDE_DONE);
|
Topic.publish(false, Topic.MAGISK_HIDE_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setShowSystem(boolean b) {
|
||||||
|
showSystem = b;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||||
ApplicationInfo info = showList.get(position);
|
ApplicationInfo info = showList.get(position).applicationInfo;
|
||||||
|
|
||||||
holder.appIcon.setImageDrawable(info.loadIcon(pm));
|
holder.appIcon.setImageDrawable(info.loadIcon(pm));
|
||||||
holder.appName.setText(Utils.getAppLabel(info, pm));
|
holder.appName.setText(Utils.getAppLabel(info, pm));
|
||||||
@ -99,8 +117,37 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
return showList.size();
|
return showList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean contains(String s, String filter) {
|
||||||
|
return s.toLowerCase().contains(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show if have launch intent or not system app
|
||||||
|
private boolean systemFilter(PackageInfo info) {
|
||||||
|
if (showSystem)
|
||||||
|
return true;
|
||||||
|
return (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
|
||||||
|
pm.getLaunchIntentForPackage(info.packageName) != null;
|
||||||
|
}
|
||||||
|
|
||||||
public void filter(String constraint) {
|
public void filter(String constraint) {
|
||||||
filter.filter(constraint);
|
AsyncTask.SERIAL_EXECUTOR.execute(() -> {
|
||||||
|
showList = new ArrayList<>();
|
||||||
|
if (constraint == null || constraint.length() == 0) {
|
||||||
|
for (PackageInfo info : fullList) {
|
||||||
|
if (systemFilter(info))
|
||||||
|
showList.add(info);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String filter = constraint.toLowerCase();
|
||||||
|
for (PackageInfo info : fullList) {
|
||||||
|
if ((contains(Utils.getAppLabel(info.applicationInfo, pm), filter) ||
|
||||||
|
contains(info.packageName, filter)) && systemFilter(info)) {
|
||||||
|
showList.add(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UiThreadHandler.run(this::notifyDataSetChanged);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
@ -119,33 +166,4 @@ public class ApplicationAdapter extends RecyclerView.Adapter<ApplicationAdapter.
|
|||||||
new ApplicationAdapter$ViewHolder_ViewBinding(this, itemView);
|
new ApplicationAdapter$ViewHolder_ViewBinding(this, itemView);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ApplicationFilter extends Filter {
|
|
||||||
|
|
||||||
private boolean lowercaseContains(String s, CharSequence filter) {
|
|
||||||
return !TextUtils.isEmpty(s) && s.toLowerCase().contains(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected FilterResults performFiltering(CharSequence constraint) {
|
|
||||||
if (constraint == null || constraint.length() == 0) {
|
|
||||||
showList = fullList;
|
|
||||||
} else {
|
|
||||||
showList = new ArrayList<>();
|
|
||||||
String filter = constraint.toString().toLowerCase();
|
|
||||||
for (ApplicationInfo info : fullList) {
|
|
||||||
if (lowercaseContains(Utils.getAppLabel(info, pm), filter)
|
|
||||||
|| lowercaseContains(info.packageName, filter)) {
|
|
||||||
showList.add(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void publishResults(CharSequence constraint, FilterResults results) {
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,12 @@ import android.os.Bundle;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.SearchView;
|
import android.widget.SearchView;
|
||||||
|
|
||||||
|
import com.topjohnwu.magisk.Config;
|
||||||
import com.topjohnwu.magisk.R;
|
import com.topjohnwu.magisk.R;
|
||||||
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
|
import com.topjohnwu.magisk.adapters.ApplicationAdapter;
|
||||||
import com.topjohnwu.magisk.components.BaseFragment;
|
import com.topjohnwu.magisk.components.BaseFragment;
|
||||||
@ -23,10 +25,9 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
|||||||
|
|
||||||
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||||
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
@BindView(R.id.recyclerView) RecyclerView recyclerView;
|
||||||
SearchView search;
|
|
||||||
|
|
||||||
private ApplicationAdapter appAdapter;
|
|
||||||
|
|
||||||
|
private SearchView search;
|
||||||
|
private ApplicationAdapter adapter;
|
||||||
private SearchView.OnQueryTextListener searchListener;
|
private SearchView.OnQueryTextListener searchListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -41,22 +42,22 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
|||||||
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
|
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
|
||||||
unbinder = new MagiskHideFragment_ViewBinding(this, view);
|
unbinder = new MagiskHideFragment_ViewBinding(this, view);
|
||||||
|
|
||||||
appAdapter = new ApplicationAdapter(requireActivity());
|
adapter = new ApplicationAdapter(requireActivity());
|
||||||
recyclerView.setAdapter(appAdapter);
|
recyclerView.setAdapter(adapter);
|
||||||
|
|
||||||
mSwipeRefreshLayout.setRefreshing(true);
|
mSwipeRefreshLayout.setRefreshing(true);
|
||||||
mSwipeRefreshLayout.setOnRefreshListener(appAdapter::refresh);
|
mSwipeRefreshLayout.setOnRefreshListener(adapter::refresh);
|
||||||
|
|
||||||
searchListener = new SearchView.OnQueryTextListener() {
|
searchListener = new SearchView.OnQueryTextListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextSubmit(String query) {
|
public boolean onQueryTextSubmit(String query) {
|
||||||
appAdapter.filter(query);
|
adapter.filter(query);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextChange(String newText) {
|
public boolean onQueryTextChange(String newText) {
|
||||||
appAdapter.filter(newText);
|
adapter.filter(newText);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -71,6 +72,21 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
|||||||
inflater.inflate(R.menu.menu_magiskhide, menu);
|
inflater.inflate(R.menu.menu_magiskhide, menu);
|
||||||
search = (SearchView) menu.findItem(R.id.app_search).getActionView();
|
search = (SearchView) menu.findItem(R.id.app_search).getActionView();
|
||||||
search.setOnQueryTextListener(searchListener);
|
search.setOnQueryTextListener(searchListener);
|
||||||
|
boolean showSystem = Config.get(Config.Key.SHOW_SYSTEM_APP);
|
||||||
|
menu.findItem(R.id.show_system).setChecked(showSystem);
|
||||||
|
adapter.setShowSystem(showSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
if (item.getItemId() == R.id.show_system) {
|
||||||
|
boolean showSystem = !item.isChecked();
|
||||||
|
item.setChecked(showSystem);
|
||||||
|
Config.set(Config.Key.SHOW_SYSTEM_APP, showSystem);
|
||||||
|
adapter.setShowSystem(showSystem);
|
||||||
|
adapter.filter(search.getQuery().toString());
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -81,6 +97,6 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
|
|||||||
@Override
|
@Override
|
||||||
public void onPublish(int topic, Object[] result) {
|
public void onPublish(int topic, Object[] result) {
|
||||||
mSwipeRefreshLayout.setRefreshing(false);
|
mSwipeRefreshLayout.setRefreshing(false);
|
||||||
appAdapter.filter(search.getQuery().toString());
|
adapter.filter(search.getQuery().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,10 @@
|
|||||||
android:title=""
|
android:title=""
|
||||||
app:actionViewClass="android.widget.SearchView"
|
app:actionViewClass="android.widget.SearchView"
|
||||||
app:showAsAction="always"/>
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/show_system"
|
||||||
|
android:title="@string/show_system_app"
|
||||||
|
android:checkable="true"/>
|
||||||
|
|
||||||
</menu>
|
</menu>
|
@ -232,4 +232,7 @@
|
|||||||
<string name="target_uid">Target UID: %1$d</string>
|
<string name="target_uid">Target UID: %1$d</string>
|
||||||
<string name="command">Command: %1$s</string>
|
<string name="command">Command: %1$s</string>
|
||||||
|
|
||||||
|
<!-- MagiskHide -->
|
||||||
|
<string name="show_system_app">Show system apps</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user