init global config view and app list view
This commit is contained in:
@@ -34,6 +34,15 @@ dependencies {
|
|||||||
implementation 'com.google.android.material:material:1.10.0'
|
implementation 'com.google.android.material:material:1.10.0'
|
||||||
implementation 'androidx.activity:activity:1.8.0'
|
implementation 'androidx.activity:activity:1.8.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
|
|
||||||
|
// Fragment and Navigation dependencies
|
||||||
|
implementation 'androidx.fragment:fragment:1.6.2'
|
||||||
|
implementation 'androidx.navigation:navigation-fragment:2.7.5'
|
||||||
|
implementation 'androidx.navigation:navigation-ui:2.7.5'
|
||||||
|
|
||||||
|
// RecyclerView for app list
|
||||||
|
implementation 'androidx.recyclerview:recyclerview:1.3.2'
|
||||||
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<!-- 查询已安装应用的权限 -->
|
||||||
|
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
|||||||
73
configapp/src/main/java/com/jiqiu/configapp/AppInfo.java
Normal file
73
configapp/src/main/java/com/jiqiu/configapp/AppInfo.java
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package com.jiqiu.configapp;
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用程序信息数据模型
|
||||||
|
*/
|
||||||
|
public class AppInfo {
|
||||||
|
private String appName; // 应用名称
|
||||||
|
private String packageName; // 包名
|
||||||
|
private Drawable appIcon; // 应用图标
|
||||||
|
private boolean isSystemApp; // 是否为系统应用
|
||||||
|
private boolean isEnabled; // 是否启用注入
|
||||||
|
|
||||||
|
public AppInfo(String appName, String packageName, Drawable appIcon, boolean isSystemApp) {
|
||||||
|
this.appName = appName;
|
||||||
|
this.packageName = packageName;
|
||||||
|
this.appIcon = appIcon;
|
||||||
|
this.isSystemApp = isSystemApp;
|
||||||
|
this.isEnabled = false; // 默认不启用注入
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter 和 Setter 方法
|
||||||
|
public String getAppName() {
|
||||||
|
return appName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppName(String appName) {
|
||||||
|
this.appName = appName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPackageName() {
|
||||||
|
return packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPackageName(String packageName) {
|
||||||
|
this.packageName = packageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawable getAppIcon() {
|
||||||
|
return appIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppIcon(Drawable appIcon) {
|
||||||
|
this.appIcon = appIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSystemApp() {
|
||||||
|
return isSystemApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSystemApp(boolean systemApp) {
|
||||||
|
isSystemApp = systemApp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
isEnabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "AppInfo{" +
|
||||||
|
"appName='" + appName + '\'' +
|
||||||
|
", packageName='" + packageName + '\'' +
|
||||||
|
", isSystemApp=" + isSystemApp +
|
||||||
|
", isEnabled=" + isEnabled +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
125
configapp/src/main/java/com/jiqiu/configapp/AppListAdapter.java
Normal file
125
configapp/src/main/java/com/jiqiu/configapp/AppListAdapter.java
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
package com.jiqiu.configapp;
|
||||||
|
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.switchmaterial.SwitchMaterial;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用列表适配器
|
||||||
|
*/
|
||||||
|
public class AppListAdapter extends RecyclerView.Adapter<AppListAdapter.AppViewHolder> {
|
||||||
|
|
||||||
|
private List<AppInfo> appList;
|
||||||
|
private List<AppInfo> filteredAppList;
|
||||||
|
private OnAppToggleListener onAppToggleListener;
|
||||||
|
|
||||||
|
public interface OnAppToggleListener {
|
||||||
|
void onAppToggle(AppInfo appInfo, boolean isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppListAdapter() {
|
||||||
|
this.appList = new ArrayList<>();
|
||||||
|
this.filteredAppList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppList(List<AppInfo> appList) {
|
||||||
|
this.appList = appList;
|
||||||
|
this.filteredAppList = new ArrayList<>(appList);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnAppToggleListener(OnAppToggleListener listener) {
|
||||||
|
this.onAppToggleListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void filterApps(String query, boolean hideSystemApps) {
|
||||||
|
filteredAppList.clear();
|
||||||
|
|
||||||
|
for (AppInfo app : appList) {
|
||||||
|
// 过滤系统应用
|
||||||
|
if (hideSystemApps && app.isSystemApp()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 搜索过滤
|
||||||
|
if (query == null || query.isEmpty() ||
|
||||||
|
app.getAppName().toLowerCase().contains(query.toLowerCase()) ||
|
||||||
|
app.getPackageName().toLowerCase().contains(query.toLowerCase())) {
|
||||||
|
filteredAppList.add(app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public AppViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.item_app, parent, false);
|
||||||
|
return new AppViewHolder(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull AppViewHolder holder, int position) {
|
||||||
|
AppInfo appInfo = filteredAppList.get(position);
|
||||||
|
holder.bind(appInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return filteredAppList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
class AppViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private ImageView appIcon;
|
||||||
|
private TextView appName;
|
||||||
|
private TextView packageName;
|
||||||
|
private TextView systemAppLabel;
|
||||||
|
private SwitchMaterial switchEnable;
|
||||||
|
|
||||||
|
public AppViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
appIcon = itemView.findViewById(R.id.app_icon);
|
||||||
|
appName = itemView.findViewById(R.id.app_name);
|
||||||
|
packageName = itemView.findViewById(R.id.package_name);
|
||||||
|
systemAppLabel = itemView.findViewById(R.id.system_app_label);
|
||||||
|
switchEnable = itemView.findViewById(R.id.switch_enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(AppInfo appInfo) {
|
||||||
|
appIcon.setImageDrawable(appInfo.getAppIcon());
|
||||||
|
appName.setText(appInfo.getAppName());
|
||||||
|
packageName.setText(appInfo.getPackageName());
|
||||||
|
|
||||||
|
// 显示系统应用标签
|
||||||
|
if (appInfo.isSystemApp()) {
|
||||||
|
systemAppLabel.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
systemAppLabel.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置开关状态
|
||||||
|
switchEnable.setOnCheckedChangeListener(null); // 清除之前的监听器
|
||||||
|
switchEnable.setChecked(appInfo.isEnabled());
|
||||||
|
|
||||||
|
// 设置开关监听器
|
||||||
|
switchEnable.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
|
appInfo.setEnabled(isChecked);
|
||||||
|
if (onAppToggleListener != null) {
|
||||||
|
onAppToggleListener.onAppToggle(appInfo, isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
166
configapp/src/main/java/com/jiqiu/configapp/AppListFragment.java
Normal file
166
configapp/src/main/java/com/jiqiu/configapp/AppListFragment.java
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
package com.jiqiu.configapp;
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用列表Fragment
|
||||||
|
*/
|
||||||
|
public class AppListFragment extends Fragment implements AppListAdapter.OnAppToggleListener {
|
||||||
|
|
||||||
|
private RecyclerView recyclerView;
|
||||||
|
private AppListAdapter adapter;
|
||||||
|
private TextInputEditText searchEditText;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
|
||||||
|
private List<AppInfo> allApps;
|
||||||
|
private boolean hideSystemApps = false;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_app_list, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
initViews(view);
|
||||||
|
setupRecyclerView();
|
||||||
|
setupSearchView();
|
||||||
|
loadApps();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViews(View view) {
|
||||||
|
recyclerView = view.findViewById(R.id.recycler_view_apps);
|
||||||
|
searchEditText = view.findViewById(R.id.search_edit_text);
|
||||||
|
progressBar = view.findViewById(R.id.progress_bar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupRecyclerView() {
|
||||||
|
adapter = new AppListAdapter();
|
||||||
|
adapter.setOnAppToggleListener(this);
|
||||||
|
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupSearchView() {
|
||||||
|
searchEditText.addTextChangedListener(new TextWatcher() {
|
||||||
|
@Override
|
||||||
|
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
|
filterApps(s.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterTextChanged(Editable s) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadApps() {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
recyclerView.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
new LoadAppsTask().execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterApps(String query) {
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.filterApps(query, hideSystemApps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHideSystemApps(boolean hideSystemApps) {
|
||||||
|
this.hideSystemApps = hideSystemApps;
|
||||||
|
filterApps(searchEditText.getText().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAppToggle(AppInfo appInfo, boolean isEnabled) {
|
||||||
|
// 这里可以保存应用的启用状态到配置文件或数据库
|
||||||
|
// 暂时只是打印日志
|
||||||
|
android.util.Log.d("AppListFragment",
|
||||||
|
"App " + appInfo.getAppName() + " toggle: " + isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步加载应用列表
|
||||||
|
*/
|
||||||
|
private class LoadAppsTask extends AsyncTask<Void, Void, List<AppInfo>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected List<AppInfo> doInBackground(Void... voids) {
|
||||||
|
List<AppInfo> apps = new ArrayList<>();
|
||||||
|
PackageManager pm = getContext().getPackageManager();
|
||||||
|
|
||||||
|
List<ApplicationInfo> installedApps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
|
||||||
|
|
||||||
|
for (ApplicationInfo appInfo : installedApps) {
|
||||||
|
try {
|
||||||
|
String appName = pm.getApplicationLabel(appInfo).toString();
|
||||||
|
String packageName = appInfo.packageName;
|
||||||
|
boolean isSystemApp = (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
|
||||||
|
|
||||||
|
AppInfo app = new AppInfo(
|
||||||
|
appName,
|
||||||
|
packageName,
|
||||||
|
pm.getApplicationIcon(appInfo),
|
||||||
|
isSystemApp
|
||||||
|
);
|
||||||
|
|
||||||
|
apps.add(app);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 忽略无法获取信息的应用
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按应用名称排序
|
||||||
|
Collections.sort(apps, new Comparator<AppInfo>() {
|
||||||
|
@Override
|
||||||
|
public int compare(AppInfo o1, AppInfo o2) {
|
||||||
|
return o1.getAppName().compareToIgnoreCase(o2.getAppName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return apps;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(List<AppInfo> apps) {
|
||||||
|
allApps = apps;
|
||||||
|
adapter.setAppList(apps);
|
||||||
|
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// 应用当前的过滤设置
|
||||||
|
filterApps(searchEditText.getText().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,8 +7,17 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||||||
import androidx.core.graphics.Insets;
|
import androidx.core.graphics.Insets;
|
||||||
import androidx.core.view.ViewCompat;
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.core.view.WindowInsetsCompat;
|
import androidx.core.view.WindowInsetsCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity implements SettingsFragment.OnSettingsChangeListener {
|
||||||
|
|
||||||
|
private BottomNavigationView bottomNavigationView;
|
||||||
|
private AppListFragment appListFragment;
|
||||||
|
private SettingsFragment settingsFragment;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -20,5 +29,61 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||||
return insets;
|
return insets;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
initViews();
|
||||||
|
setupBottomNavigation();
|
||||||
|
|
||||||
|
// 默认显示应用列表
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
showAppListFragment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViews() {
|
||||||
|
bottomNavigationView = findViewById(R.id.bottom_navigation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupBottomNavigation() {
|
||||||
|
bottomNavigationView.setOnItemSelectedListener(item -> {
|
||||||
|
int itemId = item.getItemId();
|
||||||
|
if (itemId == R.id.navigation_apps) {
|
||||||
|
showAppListFragment();
|
||||||
|
return true;
|
||||||
|
} else if (itemId == R.id.navigation_settings) {
|
||||||
|
showSettingsFragment();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showAppListFragment() {
|
||||||
|
if (appListFragment == null) {
|
||||||
|
appListFragment = new AppListFragment();
|
||||||
|
}
|
||||||
|
showFragment(appListFragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSettingsFragment() {
|
||||||
|
if (settingsFragment == null) {
|
||||||
|
settingsFragment = new SettingsFragment();
|
||||||
|
settingsFragment.setOnSettingsChangeListener(this);
|
||||||
|
}
|
||||||
|
showFragment(settingsFragment);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showFragment(Fragment fragment) {
|
||||||
|
FragmentManager fragmentManager = getSupportFragmentManager();
|
||||||
|
FragmentTransaction transaction = fragmentManager.beginTransaction();
|
||||||
|
transaction.replace(R.id.nav_host_fragment, fragment);
|
||||||
|
transaction.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onHideSystemAppsChanged(boolean hideSystemApps) {
|
||||||
|
// 当设置改变时,通知应用列表Fragment更新过滤
|
||||||
|
if (appListFragment != null) {
|
||||||
|
appListFragment.setHideSystemApps(hideSystemApps);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
package com.jiqiu.configapp;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置Fragment
|
||||||
|
*/
|
||||||
|
public class SettingsFragment extends Fragment {
|
||||||
|
|
||||||
|
private static final String PREFS_NAME = "MyInjectorSettings";
|
||||||
|
private static final String KEY_HIDE_SYSTEM_APPS = "hide_system_apps";
|
||||||
|
|
||||||
|
private RadioGroup radioGroupFilter;
|
||||||
|
private RadioButton radioShowAll;
|
||||||
|
private RadioButton radioHideSystem;
|
||||||
|
|
||||||
|
private SharedPreferences sharedPreferences;
|
||||||
|
private OnSettingsChangeListener settingsChangeListener;
|
||||||
|
|
||||||
|
public interface OnSettingsChangeListener {
|
||||||
|
void onHideSystemAppsChanged(boolean hideSystemApps);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
return inflater.inflate(R.layout.fragment_settings, container, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
|
initViews(view);
|
||||||
|
initSharedPreferences();
|
||||||
|
loadSettings();
|
||||||
|
setupListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initViews(View view) {
|
||||||
|
radioGroupFilter = view.findViewById(R.id.radio_group_filter);
|
||||||
|
radioShowAll = view.findViewById(R.id.radio_show_all);
|
||||||
|
radioHideSystem = view.findViewById(R.id.radio_hide_system);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initSharedPreferences() {
|
||||||
|
sharedPreferences = getContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadSettings() {
|
||||||
|
boolean hideSystemApps = sharedPreferences.getBoolean(KEY_HIDE_SYSTEM_APPS, false);
|
||||||
|
|
||||||
|
if (hideSystemApps) {
|
||||||
|
radioHideSystem.setChecked(true);
|
||||||
|
} else {
|
||||||
|
radioShowAll.setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupListeners() {
|
||||||
|
radioGroupFilter.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onCheckedChanged(RadioGroup group, int checkedId) {
|
||||||
|
boolean hideSystemApps = (checkedId == R.id.radio_hide_system);
|
||||||
|
|
||||||
|
// 保存设置
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
editor.putBoolean(KEY_HIDE_SYSTEM_APPS, hideSystemApps);
|
||||||
|
editor.apply();
|
||||||
|
|
||||||
|
// 通知设置变化
|
||||||
|
if (settingsChangeListener != null) {
|
||||||
|
settingsChangeListener.onHideSystemAppsChanged(hideSystemApps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOnSettingsChangeListener(OnSettingsChangeListener listener) {
|
||||||
|
this.settingsChangeListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHideSystemApps() {
|
||||||
|
return sharedPreferences.getBoolean(KEY_HIDE_SYSTEM_APPS, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
6
configapp/src/main/res/drawable/system_app_badge.xml
Normal file
6
configapp/src/main/res/drawable/system_app_badge.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="#FF9800" />
|
||||||
|
<corners android:radius="12dp" />
|
||||||
|
</shape>
|
||||||
@@ -7,13 +7,26 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
<TextView
|
<!-- Fragment容器 -->
|
||||||
android:layout_width="wrap_content"
|
<androidx.fragment.app.FragmentContainerView
|
||||||
android:layout_height="wrap_content"
|
android:id="@+id/nav_host_fragment"
|
||||||
android:text="Hello World!"
|
android:layout_width="0dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
android:layout_height="0dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintEnd_toEndOf="parent" />
|
||||||
|
|
||||||
|
<!-- 底部导航栏 -->
|
||||||
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
|
android:id="@+id/bottom_navigation"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="0dp"
|
||||||
|
android:layout_marginEnd="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:menu="@menu/bottom_nav_menu" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
42
configapp/src/main/res/layout/fragment_app_list.xml
Normal file
42
configapp/src/main/res/layout/fragment_app_list.xml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp"
|
||||||
|
tools:context=".AppListFragment">
|
||||||
|
|
||||||
|
<!-- 搜索框 -->
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
android:hint="@string/search_apps">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/search_edit_text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="text"
|
||||||
|
android:maxLines="1" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<!-- 应用列表 -->
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view_apps"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:scrollbars="vertical" />
|
||||||
|
|
||||||
|
<!-- 加载进度条 -->
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
108
configapp/src/main/res/layout/fragment_settings.xml
Normal file
108
configapp/src/main/res/layout/fragment_settings.xml
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".SettingsFragment">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<!-- 全局设置标题 -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/global_settings"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="16dp" />
|
||||||
|
|
||||||
|
<!-- 过滤系统应用设置 -->
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/filter_system_apps"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/filter_system_apps_desc"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="@android:color/darker_gray"
|
||||||
|
android:layout_marginBottom="12dp" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/radio_group_filter"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/radio_show_all"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/show_all_apps"
|
||||||
|
android:checked="true" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/radio_hide_system"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/hide_system_apps" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
<!-- 其他设置可以在这里添加 -->
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/about"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:layout_marginBottom="8dp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/app_description"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="@android:color/darker_gray" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
75
configapp/src/main/res/layout/item_app.xml
Normal file
75
configapp/src/main/res/layout/item_app.xml
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="4dp"
|
||||||
|
app:cardCornerRadius="8dp"
|
||||||
|
app:cardElevation="2dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<!-- 应用图标 -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/app_icon"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:scaleType="centerCrop" />
|
||||||
|
|
||||||
|
<!-- 应用信息 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/app_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/package_name"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textColor="@android:color/darker_gray"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:layout_marginTop="2dp" />
|
||||||
|
|
||||||
|
<!-- 系统应用标签 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/system_app_label"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/system_app"
|
||||||
|
android:textSize="10sp"
|
||||||
|
android:textColor="@android:color/white"
|
||||||
|
android:background="@drawable/system_app_badge"
|
||||||
|
android:padding="4dp"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- 启用开关 -->
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/switch_enable"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="8dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
12
configapp/src/main/res/menu/bottom_nav_menu.xml
Normal file
12
configapp/src/main/res/menu/bottom_nav_menu.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/navigation_apps"
|
||||||
|
android:icon="@android:drawable/ic_menu_view"
|
||||||
|
android:title="@string/title_apps" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/navigation_settings"
|
||||||
|
android:icon="@android:drawable/ic_menu_preferences"
|
||||||
|
android:title="@string/title_settings" />
|
||||||
|
</menu>
|
||||||
@@ -1,3 +1,23 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">configapp</string>
|
<string name="app_name">MyInjector Config</string>
|
||||||
|
|
||||||
|
<!-- 底部导航 -->
|
||||||
|
<string name="title_apps">应用列表</string>
|
||||||
|
<string name="title_settings">全局设置</string>
|
||||||
|
|
||||||
|
<!-- 应用列表 -->
|
||||||
|
<string name="search_apps">搜索应用</string>
|
||||||
|
<string name="system_app">系统应用</string>
|
||||||
|
<string name="loading_apps">正在加载应用列表...</string>
|
||||||
|
|
||||||
|
<!-- 设置页面 -->
|
||||||
|
<string name="global_settings">全局设置</string>
|
||||||
|
<string name="filter_system_apps">过滤系统应用</string>
|
||||||
|
<string name="filter_system_apps_desc">选择是否在应用列表中显示系统应用</string>
|
||||||
|
<string name="show_all_apps">显示所有应用</string>
|
||||||
|
<string name="hide_system_apps">隐藏系统应用</string>
|
||||||
|
|
||||||
|
<!-- 关于 -->
|
||||||
|
<string name="about">关于</string>
|
||||||
|
<string name="app_description">MyInjector 配置应用,用于管理注入设置</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -17,3 +17,9 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
|||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
# Automatically convert third-party libraries to use AndroidX
|
# Automatically convert third-party libraries to use AndroidX
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
# Fix TLS handshake issues
|
||||||
|
systemProp.https.protocols=TLSv1.2,TLSv1.3
|
||||||
|
systemProp.http.proxyHost=
|
||||||
|
systemProp.http.proxyPort=
|
||||||
|
systemProp.https.proxyHost=
|
||||||
|
systemProp.https.proxyPort=
|
||||||
|
|||||||
Reference in New Issue
Block a user