This is the 11th day of my participation in the 14th Gwen Challenge. For details, see: The last Gwen Challenge 2021

preface

This article focuses on using intEnts to open third-party applications or invoke activities, which should be a common requirement during development

App entrance

By default, a normal application will have an entry for an Activity, which is written in androidmanifest.xml like this:

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

Only configured with a such Activity, the time of this application will click know which Activity to start, but if the category of value change for android. The intent. The category, the DEFAULT, then, the application will be on the desktop can’t see the icon, I can’t open it straight away.

Three ways to open another App or invoke an Activity with an Intent

If you only know the package name, invoke the App directly. If you know the entry Activity, you need the package name and configure Export = “true”

1)

1. UsePackageManager.getLaunchIntentForPackage()

String package_name="xx.xx.xx";
PackageManager packageManager = context.getPackageManager();
Intent it = packageManager.getLaunchIntentForPackage(package_name);
startActivity(it);
Copy the code

This method is used when you want to start the application knowing only the package name, and the only restriction on the application is the default entry Activity.

NullPointerException is raised when there is no default entry for an Activity:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Intent.toString()' on a null object reference
Copy the code

Look again at getLaunchIntentForPackage () method:

/**
     * Returns a "good" intent to launch a front-door activity in a package.
     * This is used, for example, to implement an "open" button when browsing
     * through packages.  The current implementation looks first for a main
     * activity in the category {@link Intent#CATEGORY_INFO}, and next for a
     * main activity in the category {@link Intent#CATEGORY_LAUNCHER}. Returns
     * <code>null</code> if neither are found.
     *
     * @param packageName The name of the package to inspect.
     *
     * @return A fully-qualified {@link Intent} that can be used to launch the
     * main activity in the package. Returns <code>null</code> if the package
     * does not contain such an activity, or if <em>packageName</em> is not
     * recognized.
     */
    public abstract Intent getLaunchIntentForPackage(String packageName);
Copy the code

Therefore, use this method to determine whether the Intent is null.

String package_name = "xx.xx.xx"; PackageManager packageManager = getPackageManager(); Intent it = packageManager.getLaunchIntentForPackage(package_name); if (it ! = null){ startActivity(it); }else{// There is no default entry Activity}Copy the code

2) useIntent.setComponent()

String package_name = "xx.xx.xx"; String activity_path = "xx.xx.xx.ab.xxActivity"; Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ComponentName comp = new ComponentName(package_name,activity_path); intent.setComponent(comp); startActivity(intent);Copy the code

This method can start an application-specific Activity, not limited to the default entry Activity. However, this method requires many conditions, as follows:

  1. Know the package name of the App and the full path of the Activity and its name

  2. The target Activity that needs to be launched has the attribute Export= “true” in androidmanifest.xml

How do you determine if the target Activity exists in this way?

Here are some very common usages circulating on the Internet:

String package_name = "xx.xx.xx"; String activity_path = "xx.xx.xx.ab.xxActivity"; Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // ComponentName cn = new ComponentName(package_name,activity_path); intent.setComponent(cn); if (intent.resolveActivity(getPackageManager()) ! = null) { startActivity(intent); } else {// Can not find the specified Activity}Copy the code

But will have a problem, is resolveActivity this method don’t know whether to invoke activity exists, if there is no error: Java. Lang. IllegalArgumentException: Unknown Component exception, causing the program to crash. Of course, there are types of methods to solve this problem: resolveActivityInfo ();

String package_name = "xx.xx.xx"; String activity_path = "xx.xx.xx.ab.xxActivity"; Intent intent = new Intent(); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // ComponentName cn = new ComponentName(package_name,activity_path); intent.setComponent(cn); if (intent.resolveActivityInfo(getPackageManager(), PackageManager.MATCH_DEFAULT_ONLY) ! = null) { startActivity(intent); } else {// Can not find the specified Activity}Copy the code

3) Implicit invocation

This method is used to launch functional applications on the system, such as making phone calls, sending emails, previewing images, and opening a web page using the default browser.

> Intent intent = new Intent();
> intent.setAction(action);
> intent.addCategory(category);
> intent.setDataAndType("abc://www.dfg.com","image/gif");
> startActivity(intent);
>
Copy the code
  • Condition 1: IntentFilter has at least one action and at least one Category, without Data and Type
  • Condition 2: If there is Data, Data in the parameter must comply with the Data rule
  • Condition 3: Action and Category must match the Activity of an Action and a Category (Category DEFAULT: android. Intent. The Category. The DEFAULT)

There are many functions of implicit launch, which are not listed one by one. If necessary, you can directly search the relevant code. Let’s open a web page as an example:

Uri uri = Uri.parse("http://www.abc.xyz");
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
Copy the code

In this case, there’s nothing wrong with using intent.resolveActivity () directly:

Uri uri = Uri.parse("http://www.abc.xyz"); Intent intent = new Intent(Intent.ACTION_VIEW, uri); if (intent.resolveActivity(getPackageManager()) ! = null) { startActivity(intent); } else {// The required application is not installedCopy the code

conclusion

The above is the Intent to open other applications or activities in several ways and precautions refer to PackageManager source, . You can also use the packageManager queryIntentActivities () method to determine if there is a resolution specified in the system the application of Intent.

public boolean isAvailable(Context context, Intent intent) {
  PackageManager packageManager = context.getPackageManager();
  List list = packageManager.queryIntentActivities(intent,
  PackageManager.MATCH_DEFAULT_ONLY);
  return list.size() > 0;
}

Copy the code

To sum up:

  • Methods aPackageManager.getLaunchIntentForPackage(), directly determine whether the returned Intent is null.
  • Way 2Intent.setComponent(), the use ofIntent.resolveActivityInfo()orpackageManager.queryIntentActivities()Two ways;
  • Mode three implicit start, useIntent.resolveActivity(),Intent.resolveActivityInfo() 、packageManager.queryIntentActivities()All three ways are ok.