You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现从已安装应用ListView向Blocked App页面ListView迁移条目

Implementing Dual ListViews for App Blocking with Password Verification

Got it, let's walk through building this feature step by step. We'll create a MainActivity showing all installed apps, a BlockedActivity with a list of blocked apps, and wire up the logic to move apps between lists plus add password verification for blocked apps.


1. MainActivity: Load Installed Apps & Handle Item Clicks

First, we'll complete your existing MainActivity code to fetch installed apps, display them in a ListView, and handle clicking items to move them to BlockedActivity.

public class MainActivity extends AppCompatActivity {
    private PackageManager packageManager = null;
    private List<ApplicationInfo> installedApps = new ArrayList<>();
    private ListView installedAppsListView;
    private AppListAdapter installedAdapter;
    private SharedPreferences sharedPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        packageManager = getPackageManager();
        installedAppsListView = findViewById(R.id.list_installed_apps);
        sharedPreferences = getSharedPreferences("BlockedApps", MODE_PRIVATE);

        // Fetch installed launchable apps (filter out system apps optionally)
        loadInstalledApps();

        // Set up adapter and click listener
        installedAdapter = new AppListAdapter(this, installedApps);
        installedAppsListView.setAdapter(installedAdapter);
        
        installedAppsListView.setOnItemClickListener((parent, view, position, id) -> {
            ApplicationInfo selectedApp = installedApps.get(position);
            String packageName = selectedApp.packageName;

            // Remove from current list
            installedApps.remove(position);
            installedAdapter.notifyDataSetChanged();

            // Add to blocked apps storage
            Set<String> blockedPackages = sharedPreferences.getStringSet("blocked_packages", new HashSet<>());
            blockedPackages.add(packageName);
            AppBlockAccessibilityService.updateBlockedPackages(this, blockedPackages);

            // Navigate to BlockedActivity
            Intent blockedIntent = new Intent(MainActivity.this, BlockedActivity.class);
            startActivity(blockedIntent);
        });
    }

    private void loadInstalledApps() {
        Intent launchIntent = new Intent(Intent.ACTION_MAIN, null);
        launchIntent.addCategory(Intent.CATEGORY_LAUNCHER);
        List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(launchIntent, 0);
        
        Set<String> blockedPackages = sharedPreferences.getStringSet("blocked_packages", new HashSet<>());

        for (ResolveInfo resolveInfo : resolveInfos) {
            ApplicationInfo appInfo = resolveInfo.activityInfo.applicationInfo;
            // Skip already blocked apps and system apps (adjust filter as needed)
            if (!blockedPackages.contains(appInfo.packageName) && (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
                installedApps.add(appInfo);
            }
        }
    }

    // Custom adapter for app list items
    private class AppListAdapter extends ArrayAdapter<ApplicationInfo> {
        public AppListAdapter(Context context, List<ApplicationInfo> apps) {
            super(context, 0, apps);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_app, parent, false);
            }

            ApplicationInfo appInfo = getItem(position);
            TextView appName = convertView.findViewById(R.id.tv_app_name);
            ImageView appIcon = convertView.findViewById(R.id.iv_app_icon);

            appName.setText(packageManager.getApplicationLabel(appInfo));
            appIcon.setImageDrawable(packageManager.getApplicationIcon(appInfo));

            return convertView;
        }
    }
}

2. BlockedActivity: Manage Blocked Apps List

This activity displays all blocked apps and lets users unblock them (move back to MainActivity's list).

public class BlockedActivity extends AppCompatActivity {
    private List<ApplicationInfo> blockedApps = new ArrayList<>();
    private ListView blockedAppsListView;
    private BlockedAppAdapter blockedAdapter;
    private PackageManager packageManager;
    private SharedPreferences sharedPreferences;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_blocked);
        setTitle("Blocked App");

        packageManager = getPackageManager();
        blockedAppsListView = findViewById(R.id.list_blocked_apps);
        sharedPreferences = getSharedPreferences("BlockedApps", MODE_PRIVATE);

        // Load blocked apps from storage
        loadBlockedApps();

        blockedAdapter = new BlockedAppAdapter(this, blockedApps);
        blockedAppsListView.setAdapter(blockedAdapter);

        // Handle unblocking apps
        blockedAppsListView.setOnItemClickListener((parent, view, position, id) -> {
            ApplicationInfo unblockedApp = blockedApps.get(position);
            String packageName = unblockedApp.packageName;

            // Remove from blocked list storage
            Set<String> blockedPackages = sharedPreferences.getStringSet("blocked_packages", new HashSet<>());
            blockedPackages.remove(packageName);
            AppBlockAccessibilityService.updateBlockedPackages(this, blockedPackages);

            // Update local list and adapter
            blockedApps.remove(position);
            blockedAdapter.notifyDataSetChanged();
        });
    }

    private void loadBlockedApps() {
        Set<String> blockedPackages = sharedPreferences.getStringSet("blocked_packages", new HashSet<>());
        for (String packageName : blockedPackages) {
            try {
                ApplicationInfo appInfo = packageManager.getApplicationInfo(packageName, 0);
                blockedApps.add(appInfo);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
                // Remove invalid package from storage
                blockedPackages.remove(packageName);
                AppBlockAccessibilityService.updateBlockedPackages(this, blockedPackages);
            }
        }
    }

    private class BlockedAppAdapter extends ArrayAdapter<ApplicationInfo> {
        public BlockedAppAdapter(Context context, List<ApplicationInfo> apps) {
            super(context, 0, apps);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item_app, parent, false);
            }

            ApplicationInfo appInfo = getItem(position);
            TextView appName = convertView.findViewById(R.id.tv_app_name);
            ImageView appIcon = convertView.findViewById(R.id.iv_app_icon);

            appName.setText(packageManager.getApplicationLabel(appInfo));
            appIcon.setImageDrawable(packageManager.getApplicationIcon(appInfo));

            return convertView;
        }
    }
}

3. Layout Files

Create these layout files to match the activities:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Installed Apps"
        android:textSize="18sp"
        android:padding="16dp"
        android:background="#f5f5f5"/>

    <ListView
        android:id="@+id/list_installed_apps"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

activity_blocked.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Blocked Apps"
        android:textSize="18sp"
        android:padding="16dp"
        android:background="#f5f5f5"/>

    <ListView
        android:id="@+id/list_blocked_apps"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

list_item_app.xml (for both lists)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:padding="12dp"
    android:gravity="center_vertical"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/iv_app_icon"
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:marginEnd="16dp"/>

    <TextView
        android:id="@+id/tv_app_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"/>

</LinearLayout>

4. Password Verification for Blocked Apps

To enforce password checks when blocked apps are launched, we'll use an Accessibility Service (the most reliable way to intercept app launches):

AppBlockAccessibilityService.java

public class AppBlockAccessibilityService extends AccessibilityService {
    private List<String> blockedPackages = new ArrayList<>();
    private SharedPreferences sharedPreferences;

    @Override
    protected void onServiceConnected() {
        super.onServiceConnected();
        sharedPreferences = getSharedPreferences("BlockedApps", MODE_PRIVATE);
        refreshBlockedPackages();
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            String packageName = event.getPackageName().toString();
            if (blockedPackages.contains(packageName)) {
                // Launch password verification screen
                Intent verifyIntent = new Intent(this, PasswordVerificationActivity.class);
                verifyIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                verifyIntent.putExtra("TARGET_PACKAGE", packageName);
                startActivity(verifyIntent);
            }
        }
    }

    @Override
    public void onInterrupt() {}

    public void refreshBlockedPackages() {
        Set<String> packageSet = sharedPreferences.getStringSet("blocked_packages", new HashSet<>());
        blockedPackages.clear();
        blockedPackages.addAll(packageSet);
    }

    public static void updateBlockedPackages(Context context, Set<String> newPackages) {
        SharedPreferences.Editor editor = context.getSharedPreferences("BlockedApps", MODE_PRIVATE).edit();
        editor.putStringSet("blocked_packages", newPackages);
        editor.apply();
        // Refresh the service if it's running
        AccessibilityManager manager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> services = manager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
        for (AccessibilityServiceInfo info : services) {
            if (info.getId().contains(AppBlockAccessibilityService.class.getName())) {
                ((AppBlockAccessibilityService) manager.getAccessibilityService(info.getId())).refreshBlockedPackages();
                break;
            }
        }
    }
}

PasswordVerificationActivity.java

public class PasswordVerificationActivity extends AppCompatActivity {
    private String targetPackage;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_password_verification);
        targetPackage = getIntent().getStringExtra("TARGET_PACKAGE");

        EditText passwordInput = findViewById(R.id.et_password);
        Button verifyBtn = findViewById(R.id.btn_verify);

        verifyBtn.setOnClickListener(v -> {
            String input = passwordInput.getText().toString().trim();
            // Replace with your actual password validation logic
            if ("your_secure_password".equals(input)) {
                Toast.makeText(this, "Verification successful", Toast.LENGTH_SHORT).show();
                finish();
            } else {
                Toast.makeText(this, "Incorrect password", Toast.LENGTH_SHORT).show();
                // Close the blocked app
                try {
                    Intent closeIntent = getPackageManager().getLaunchIntentForPackage(targetPackage);
                    if (closeIntent != null) {
                        closeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                        startActivity(closeIntent);
                    }
                    finish();
                } catch (PackageManager.NameNotFoundException e) {
                    e.printStackTrace();
                    finish();
                }
            }
        });
    }
}

Register Accessibility Service in Manifest

Add this to your AndroidManifest.xml:

<service
    android:name=".AppBlockAccessibilityService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService"/>
    </intent-filter>
    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/accessibility_service_config"/>
</service>

accessibility_service_config.xml (res/xml/)

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_service_desc"/>

Key Notes

  • Data Persistence: We use SharedPreferences to store blocked app package names, so the list survives app restarts.
  • Accessibility Permission: Users need to enable the accessibility service in system settings. Add a guide in your app to direct users there.
  • Performance: For large app lists, use background threads (Coroutines or AsyncTask) to fetch installed apps to avoid UI freezes.

内容的提问来源于stack exchange,提问作者ayoub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:18:06