本周早些时候,我问了一个类似的问题,但我仍然不明白如何获得所有已安装的应用程序的列表,然后选择一个运行。

我试过了:

Intent intent = new Intent(ACTION_MAIN);
intent.addCategory(CATEGORY_LAUNCHER);

这只显示预安装或可以运行ACTION_MAIN Intent类型的应用程序。

我也知道我可以使用PackageManager来获取所有已安装的应用程序,但我如何使用它来运行特定的应用程序呢?


当前回答

获取已安装的非系统应用程序列表

public static void installedApps()
{
    List<PackageInfo> packList = getPackageManager().getInstalledPackages(0);
    for (int i=0; i < packList.size(); i++)
    {
        PackageInfo packInfo = packList.get(i);
        if (  (packInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)
        {
            String appName = packInfo.applicationInfo.loadLabel(getPackageManager()).toString();
            Log.e("App № " + Integer.toString(i), appName);
        }
    }
}

其他回答

获取已安装的非系统应用程序列表

public static void installedApps()
{
    List<PackageInfo> packList = getPackageManager().getInstalledPackages(0);
    for (int i=0; i < packList.size(); i++)
    {
        PackageInfo packInfo = packList.get(i);
        if (  (packInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0)
        {
            String appName = packInfo.applicationInfo.loadLabel(getPackageManager()).toString();
            Log.e("App № " + Integer.toString(i), appName);
        }
    }
}

这个答案是正确的一个列表安装的应用程序显示和搜索功能添加。

科特林

activity_all_installed_app.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AllInstalledAppActivity">

    <TextView
        android:id="@+id/totalInstalledApp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/total_Installed_Apps"
        android:textStyle="bold"
        android:textAlignment="center"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/totalInstalledApp"
        tools:listitem="@layout/installed_app_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>

installed_app_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_margin="4dp"
    android:elevation="6dp"
    android:background="?attr/selectableItemBackground">
    <androidx.cardview.widget.CardView
        android:id="@+id/cardview"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        app:cardCornerRadius="5dp"
        app:cardUseCompatPadding="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/app_icon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:contentDescription="@string/todo"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/list_app_name"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:text="@string/app_name"
                android:textSize="16sp"
                android:textStyle="bold"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/app_icon"
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/app_package"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:text="@string/app_package_name"
                android:textStyle="bold"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/app_icon"
                app:layout_constraintTop_toBottomOf="@+id/list_app_name" />
        </androidx.constraintlayout.widget.ConstraintLayout>
    </androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>

AppModel.kt

import android.graphics.drawable.Drawable

class AppModel(private var name:String, private var icon: Drawable, private var packages:String) {
    fun getName(): String {
        return name
    }

    fun getIcon(): Drawable {
        return icon
    }

    fun getPackages(): String {
        return packages
    }
}

AppAdapter.kt


import android.app.AlertDialog
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.materialsouk.allcodeapp.R
import com.materialsouk.allcodeapp.models.AppModel
import java.util.ArrayList

import android.content.Intent
import android.net.Uri
import android.provider.Settings
import android.widget.Toast


class AppAdapter(private val context: Context, private var appModelList: ArrayList<AppModel>) :
    RecyclerView.Adapter<AppAdapter.ViewHolder>() {


    class ViewHolder(ItemView: View) : RecyclerView.ViewHolder(ItemView) {
        val appNameTxt: TextView = itemView.findViewById(R.id.list_app_name)
        val appPackageNameTxt: TextView = itemView.findViewById(R.id.app_package)
        val appIcon: ImageView = itemView.findViewById(R.id.app_icon)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val view: View =
            LayoutInflater.from(parent.context)
                .inflate(R.layout.installed_app_layout, parent, false)
        return ViewHolder(view)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.appNameTxt.text = appModelList[position].getName()
        holder.appIcon.setImageDrawable(appModelList[position].getIcon())
        holder.appPackageNameTxt.text = appModelList[position].getPackages()

        holder.itemView.setOnClickListener {
            val dialogListTitle = arrayOf("Open App", "App Info")
            val builder: AlertDialog.Builder = AlertDialog.Builder(context)
            builder.setTitle("Choose Action")
                .setItems(
                    dialogListTitle
                ) { _, which ->
                    when (which) {
                        0 -> {
                            val intent =
                                context.packageManager.getLaunchIntentForPackage(appModelList[position].getPackages())
                            if (intent != null) {
                                context.startActivity(intent)
                            }else{
                                Toast.makeText(context,"System app is not open for any reason.",Toast.LENGTH_LONG).show()
                            }
                        }
                        1 -> {
                            val intent = Intent()
                            intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                            intent.data =
                                Uri.parse("package:${appModelList[position].getPackages()}")
                            context.startActivity(intent)
                        }
                    }
                }
            builder.show()
        }

    }

    override fun getItemCount(): Int {
        return appModelList.size
    }
}

这是菜单 search_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/app_bar_search"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="@string/search"
        app:showAsAction="ifRoom|withText"
        app:actionViewClass="androidx.appcompat.widget.SearchView"/>
</menu>

AllInstalledAppActivity.kt


import android.annotation.SuppressLint
import android.app.Dialog
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.recyclerview.widget.RecyclerView
import com.materialsouk.allcodeapp.models.AppModel

import android.content.pm.PackageInfo

import android.content.pm.ApplicationInfo
import android.os.Handler
import android.os.Looper
import android.view.Menu
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.SearchView
import com.materialsouk.allcodeapp.adapters.AppAdapter
import java.util.*
import kotlin.collections.ArrayList


class AllInstalledAppActivity : AppCompatActivity() {
    private lateinit var recyclerView: RecyclerView
    private lateinit var installedAppsList: ArrayList<AppModel>
    private lateinit var installedAppAdapter: AppAdapter

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_all_installed_app)
        recyclerView = findViewById(R.id.recycler_view)
        val loadingDialog = Dialog(this)
        loadingDialog.setContentView(R.layout.loading)
        loadingDialog.window!!.setLayout(
            LinearLayout.LayoutParams.WRAP_CONTENT,
            LinearLayout.LayoutParams.WRAP_CONTENT
        )
        loadingDialog.setCancelable(false)
        installedAppsList = ArrayList()
        loadingDialog.show()
        Handler(Looper.getMainLooper()).postDelayed({
            getInstalledApps()
            loadingDialog.dismiss()
            findViewById<TextView>(R.id.totalInstalledApp).text =
                "${getString(R.string.total_Installed_Apps)} ${installedAppsList.size}"
            installedAppAdapter = AppAdapter(this, installedAppsList)
            recyclerView.adapter = installedAppAdapter
        }, 500)

    }

    @SuppressLint("QueryPermissionsNeeded")
    private fun getInstalledApps(): ArrayList<AppModel> {
        installedAppsList.clear()
        val packs = packageManager.getInstalledPackages(0)
        for (i in packs.indices) {
            val p = packs[i]
            if (!isSystemPackage(p)) {
                val appName = p.applicationInfo.loadLabel(packageManager).toString()
                val icon = p.applicationInfo.loadIcon(packageManager)
                val packages = p.applicationInfo.packageName
                installedAppsList.add(AppModel(appName, icon, packages))
            }
        }
        installedAppsList.sortBy { it.getName().capitalized() }
        return installedAppsList
    }
    private fun String.capitalized(): String {
        return this.replaceFirstChar {
            if (it.isLowerCase())
                it.titlecase(Locale.getDefault())
            else it.toString()
        }
    }
    private fun isSystemPackage(pkgInfo: PackageInfo): Boolean {
        return pkgInfo.applicationInfo.flags and ApplicationInfo.FLAG_SYSTEM != 0
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.search_menu, menu)
        val search = menu.findItem(R.id.app_bar_search)

        val searchView = search.actionView as SearchView
        searchView.maxWidth = android.R.attr.width
        searchView.queryHint = "Search app name or package"
        searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
            override fun onQueryTextSubmit(query: String?): Boolean {
                return false
            }

            @SuppressLint("NotifyDataSetChanged")
            override fun onQueryTextChange(newText: String?): Boolean {
                val appModelArrayList: ArrayList<AppModel> = ArrayList()

                for (i in installedAppsList) {
                    if (i.getName().lowercase(Locale.getDefault()).contains(
                            newText!!.lowercase(
                                Locale.getDefault()
                            )
                        )
                        ||
                        i.getPackages().lowercase(Locale.getDefault()).contains(
                            newText.lowercase(
                                Locale.getDefault()
                            )
                        )
                    ) {
                        appModelArrayList.add(i)
                    }
                }
                installedAppAdapter =
                    AppAdapter(this@AllInstalledAppActivity, appModelArrayList)

                recyclerView.adapter = installedAppAdapter
                installedAppAdapter.notifyDataSetChanged()
                return true
            }
        })

        return super.onCreateOptionsMenu(menu)
    }
}

下面是使用PackageManager的一种更简洁的方式

final PackageManager pm = getPackageManager();
//get a list of installed apps.
List<ApplicationInfo> packages = pm.getInstalledApplications(PackageManager.GET_META_DATA);

for (ApplicationInfo packageInfo : packages) {
    Log.d(TAG, "Installed package :" + packageInfo.packageName);
    Log.d(TAG, "Source dir : " + packageInfo.sourceDir);
    Log.d(TAG, "Launch Activity :" + pm.getLaunchIntentForPackage(packageInfo.packageName)); 
}
// the getLaunchIntentForPackage returns an intent that you can use with startActivity() 

更多信息请点击这里http://qtcstation.com/2011/02/how-to-launch-another-app-from-your-app/

干净的解决方案,过滤成功的系统应用程序

这个解决方案背后的思想是,每个系统应用程序的主活动都没有一个自定义的活动图标。这个方法给了我一个很好的结果:

 public static Set<PackageInfo> getInstalledApps(Context ctx) {
    final PackageManager packageManager = ctx.getPackageManager();

    final List<PackageInfo> allInstalledPackages = packageManager.getInstalledPackages(PackageManager.GET_META_DATA);
    final Set<PackageInfo> filteredPackages = new HashSet();

    Drawable defaultActivityIcon = packageManager.getDefaultActivityIcon();

    for(PackageInfo each : allInstalledPackages) {
        if(ctx.getPackageName().equals(each.packageName)) {
            continue;  // skip own app
        }

        try {
            // add only apps with application icon
            Intent intentOfStartActivity = packageManager.getLaunchIntentForPackage(each.packageName);
            if(intentOfStartActivity == null)
                continue;

            Drawable applicationIcon = packageManager.getActivityIcon(intentOfStartActivity);
            if(applicationIcon != null && !defaultActivityIcon.equals(applicationIcon)) {
                filteredPackages.add(each);
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.i("MyTag", "Unknown package name " + each.packageName);
        }
    }

    return filteredPackages;
}

@Jas: 我没有那个代码了,但我找到了一些接近的东西。我已经做了这个来搜索我的应用程序的“组件”,它们只是具有给定类别的活动。

private List<String> getInstalledComponentList() {
    Intent componentSearchIntent = new Intent();
    componentSearchIntent.addCategory(Constants.COMPONENTS_INTENT_CATEGORY);
    componentSearchIntent.setAction(Constants.COMPONENTS_INTENT_ACTION_DEFAULT);
    List<ResolveInfo> ril = getPackageManager().queryIntentActivities(componentSearchIntent, PackageManager.MATCH_DEFAULT_ONLY);
    List<String> componentList = new ArrayList<String>();
    Log.d(LOG_TAG, "Search for installed components found " + ril.size() + " matches.");
    for (ResolveInfo ri : ril) {
        if (ri.activityInfo != null) {
            componentList.add(ri.activityInfo.packageName);// + ri.activityInfo.name);
            Log.d(LOG_TAG, "Found installed: " + componentList.get(componentList.size()-1));
        }
    }
    return componentList;
}

我已经注释了它获取活动名称的部分,但它非常简单。