diff --git a/configapp/build.gradle b/configapp/build.gradle index 3bac0e1..df3a7bd 100644 --- a/configapp/build.gradle +++ b/configapp/build.gradle @@ -34,6 +34,15 @@ dependencies { implementation 'com.google.android.material:material:1.10.0' implementation 'androidx.activity:activity:1.8.0' 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' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/configapp/src/main/AndroidManifest.xml b/configapp/src/main/AndroidManifest.xml index f7742fd..837a2c2 100644 --- a/configapp/src/main/AndroidManifest.xml +++ b/configapp/src/main/AndroidManifest.xml @@ -1,6 +1,9 @@ + + + > { + + @Override + protected List doInBackground(Void... voids) { + List apps = new ArrayList<>(); + PackageManager pm = getContext().getPackageManager(); + + List 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() { + @Override + public int compare(AppInfo o1, AppInfo o2) { + return o1.getAppName().compareToIgnoreCase(o2.getAppName()); + } + }); + + return apps; + } + + @Override + protected void onPostExecute(List apps) { + allApps = apps; + adapter.setAppList(apps); + + progressBar.setVisibility(View.GONE); + recyclerView.setVisibility(View.VISIBLE); + + // 应用当前的过滤设置 + filterApps(searchEditText.getText().toString()); + } + } +} diff --git a/configapp/src/main/java/com/jiqiu/configapp/MainActivity.java b/configapp/src/main/java/com/jiqiu/configapp/MainActivity.java index 907cbaf..65a401b 100644 --- a/configapp/src/main/java/com/jiqiu/configapp/MainActivity.java +++ b/configapp/src/main/java/com/jiqiu/configapp/MainActivity.java @@ -7,8 +7,17 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; 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 protected void onCreate(Bundle savedInstanceState) { @@ -20,5 +29,61 @@ public class MainActivity extends AppCompatActivity { v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); 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); + } } } \ No newline at end of file diff --git a/configapp/src/main/java/com/jiqiu/configapp/SettingsFragment.java b/configapp/src/main/java/com/jiqiu/configapp/SettingsFragment.java new file mode 100644 index 0000000..c8bedf5 --- /dev/null +++ b/configapp/src/main/java/com/jiqiu/configapp/SettingsFragment.java @@ -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); + } +} diff --git a/configapp/src/main/res/drawable/system_app_badge.xml b/configapp/src/main/res/drawable/system_app_badge.xml new file mode 100644 index 0000000..c9d729c --- /dev/null +++ b/configapp/src/main/res/drawable/system_app_badge.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/configapp/src/main/res/layout/activity_main.xml b/configapp/src/main/res/layout/activity_main.xml index 86a5d97..caa48f7 100644 --- a/configapp/src/main/res/layout/activity_main.xml +++ b/configapp/src/main/res/layout/activity_main.xml @@ -7,13 +7,26 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - + + app:layout_constraintEnd_toEndOf="parent" /> + + + \ No newline at end of file diff --git a/configapp/src/main/res/layout/fragment_app_list.xml b/configapp/src/main/res/layout/fragment_app_list.xml new file mode 100644 index 0000000..5ab2ffa --- /dev/null +++ b/configapp/src/main/res/layout/fragment_app_list.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + diff --git a/configapp/src/main/res/layout/fragment_settings.xml b/configapp/src/main/res/layout/fragment_settings.xml new file mode 100644 index 0000000..3270a17 --- /dev/null +++ b/configapp/src/main/res/layout/fragment_settings.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configapp/src/main/res/layout/item_app.xml b/configapp/src/main/res/layout/item_app.xml new file mode 100644 index 0000000..755d0a9 --- /dev/null +++ b/configapp/src/main/res/layout/item_app.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configapp/src/main/res/menu/bottom_nav_menu.xml b/configapp/src/main/res/menu/bottom_nav_menu.xml new file mode 100644 index 0000000..644622b --- /dev/null +++ b/configapp/src/main/res/menu/bottom_nav_menu.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/configapp/src/main/res/values/strings.xml b/configapp/src/main/res/values/strings.xml index 9a27d23..56e599b 100644 --- a/configapp/src/main/res/values/strings.xml +++ b/configapp/src/main/res/values/strings.xml @@ -1,3 +1,23 @@ - configapp + MyInjector Config + + + 应用列表 + 全局设置 + + + 搜索应用 + 系统应用 + 正在加载应用列表... + + + 全局设置 + 过滤系统应用 + 选择是否在应用列表中显示系统应用 + 显示所有应用 + 隐藏系统应用 + + + 关于 + MyInjector 配置应用,用于管理注入设置 \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 01b80d7..391a165 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,3 +17,9 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 android.useAndroidX=true # Automatically convert third-party libraries to use AndroidX 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=