“This is the 19th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021”

In chapter 23 of the Definitive Guide to Android Programming, we’ll create a new application called NerdLauncher, and the technical point is about implicit intents and intent filters. This chapter on apps will show you other apps on your device, and you can launch other apps.

Create the NerdLauncher project

Create a project and add RecyclerView to display the list of apps.

<? The XML version = "1.0" encoding = "utf-8"? > <androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" />Copy the code
class MainActivity : AppCompatActivity() {

    private lateinit var mBinding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        mBinding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(mBinding.root)

        mBinding.recyclerView.layoutManager = LinearLayoutManager(this)
    }
}
Copy the code

Intent intent intent intent intent intent

The PackageManager can be used to get all the main activities that can be started. The MAIN activity can be launched with an Intent filter that contains the MAIN action and the LAUNCHER category. As follows:

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
Copy the code

Add the setupAdapter() function and call it from onCreate() :

private fun setupAdapter(){ val startupIntent = Intent(Intent.ACTION_MAIN).apply { addCategory(Intent.CATEGORY_LAUNCHER)  } val activities = packageManager.queryIntentActivities(startupIntent,0) Log.i(TAG, "Found ${activities.size} activities") }Copy the code

This code creates an implicit intent with an action set to ACTION_MAIN and category CATEGORY_LAUNCHER.

PackageManager. QueryIntentActivities (Intent, Int) will be returned contains all the activity (with matching target Intent filters) ResolveInfo information. The 0 parameter indicates that the query result is not modified.

Next you need to display the list using the activity tag name “Application Name.” First, the activity labels in the ResolveInfo object are sorted alphabetically using the resolveInfo.loadLabel (PackageManager) function.

Add code below the above method:

activities.sortWith(Comparator { a, b -> 
            String.CASE_INSENSITIVE_ORDER.compare(
                a.loadLabel(packageManager).toString(),
                b.loadLabel(packageManager).toString()
            )
        })
Copy the code

Then, define a ViewHolder to display the activity tag name. Use member variables to store ResolveInfo.

    private class ActivityHolder(itemView: View):RecyclerView.ViewHolder(itemView){
        
        private val tvName = itemView as TextView
        private lateinit var resolveInfo:ResolveInfo
        
        fun bindActivity(resolveInfo: ResolveInfo){
            this.resolveInfo = resolveInfo
            val packageManager = itemView.context.packageManager
            val appName = resolveInfo.loadLabel(packageManager).toString()
            tvName.text = appName
        }
    }
Copy the code

Then realize RecyclerView.Adapter:

    private class ActivityAdapter(val activities:List<ResolveInfo>):RecyclerView.Adapter<ActivityHolder>(){
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ActivityHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val view =layoutInflater.inflate(android.R.layout.simple_list_item_1,parent,false)
                 return ActivityHolder(view)
            }

        override fun onBindViewHolder(holder: ActivityHolder, position: Int) {
            val resolveInfo = activities[position]
            holder.bindActivity(resolveInfo)
        }

        override fun getItemCount(): Int {
            return activities.size
        }
    }
Copy the code

Finally, configure adapter instance to RecyclerView, add at the end of setupAdapter:

 mBinding.recyclerView.adapter = ActivityAdapter(activities)
Copy the code

Running results:

Create an explicit intent at runtime

Next, do the click list, launching the activity with the intent.

To create an explicit intent that starts the activity, you need to get the package name and class name of the activity from the ResolveInfo object.

Update the ActivityHolder class to implement a click listener and get the necessary information from activityInfo to create a display intent to start the target activity.

    private class ActivityHolder(itemView: View) : RecyclerView.ViewHolder(itemView),
        View.OnClickListener {
       ...
        init {
            tvName.setOnClickListener(this)
        }
       ...
        override fun onClick(v: View) {
            val activityInfo = resolveInfo.activityInfo
            val intent = Intent(Intent.ACTION_MAIN).apply {
                setClassName(activityInfo.applicationInfo.packageName, activityInfo.name)
            }
            val context = v.context
            context.startActivity(intent)
        }
    }
Copy the code

Then run the project, click the list item, you can jump to the corresponding App.

other

Hey hey, continue to cent two, weekend need to play, go out to relax relax!

ResolveInfo also provides other information. For details, see:

Developer.android.com/reference/a…

NerdLauncher project Demo

Github.com/visiongem/A…


🌈 follow me ac~ ❤️

Public account: Ni K Ni K